Skip to content

Latest commit

 

History

History
1207 lines (891 loc) · 50 KB

README-en.md

File metadata and controls

1207 lines (891 loc) · 50 KB

Video Game System - Zero suzukiplan

Language: Japanese, English

logo

The Video Game System - Zero (VGS-Zero) is a game console that runs on a RaspberryPi Zero 2W bare-metal environment.

This repository provides the VGS-Zero body code, distribution images, SDK, and an emulator that runs on a PC (Linux or macOS).

Table of Content

  1. VGS-Zero Feature
  2. First Step Guide
  3. How to Execute
  4. config.sys
  5. game.pkg
  6. Game Development Tools
  7. Programming Guide
  8. How to Sell Your Game
  9. Examples
  10. License

VGS-Zero Feature

First Step Guide

The recommended OS for the VGS-Zero game development environment is Ubuntu Desktop.

More precisely, Ubuntu Desktop installed on a 2013 MacBook Air is the baseline environment in which you can comfortably focus on game development without any inconvenience.

With VGS-Zero, you don't need a strong PC or a huge SDK download of tens of GB to develop games.

Below is a step-by-step guide to running VGS-Zero's Hello, World! (Z80) on Ubuntu Desktop with nothing installed:

# Install middleware needed to build toolchain
sudo apt update
sudo apt install build-essential libsdl2-dev libasound2 libasound2-dev

# Download the VGS-Zero repository
git clone https://github.com/suzukiplan/vgszero

# Move directory
cd vgszero/example/01_hello-asm

# Build and Execute
make

If you follow the above steps, the SDL2 version of the VGS-Zero emulator will start Hello, World.

preview

The toolsets available in VGS-Zero for drawing graphics, creating sound effects, composing music, etc. are listed in detail in the Game Development Tools chapter.

How to Execute

This section describes the procedure for running the game on the actual device (RaspberryPi Zero 2W).

Required Hardware

The following hardware is required:

  • RaspberryPi Zero 2W
  • HDMI cable (mini HDMI Type C → HDMI Type A)
  • USB joypad(D-Pad+A/B+Start/Select)+ Type A to B convert adapter
  • USB power supply
  • micro SD card (need 20MB empty)
  • Displays that meet the following requirements:
    • HDMI input
    • Refresh rate 60Hz
    • Resolution 480x384 pixels or higher
    • Audio output

(Joypad)

VGS-Zero only supports input via the 8-button USB joypad with cursor (D-PAD), A button, B button, SELECT button, and START button.

joypad.png

The button assignments (key config) of the USB joypad connected to the RaspberryPi Zero 2W can be freely customized by the user via the config.sys file.

The key assignments for the PC (SDL2 version) are as follows:

  • D-Pad: cursor key
  • A button: X key
  • B button: Z key
  • START button: SPACE key
  • SELECT button: ESC key

The input status can be obtained from the program by inputting the 0xA0 port.

(Supported USB Joypad)

The following is a list of USB joypad support in VGS-Zero:

Product name Support Supplementary info.
HXBE37823 (XINYUANSHUNTONG) OK Works perfectly
suily USB controller for NES games(wired model) OK Works perfectly
Elecom JC-U3312 OK Works perfectly
HORI Real Arcade Pro V3SA for PS3 OK Works perfectly
HORI Grip Controller Attachment Set for Nintendo Switch NG The four-way controller is not usable.
Logicool (Logitech) F310 NG No connection
Kiwitata gamepad NG Circle is unsupported
Xbox 360 wired gamepad clone NG Circle is unsupported

A standard HID-compliant joypad (game controller) is likely to work.

We do not recommend the use of game controllers that require a dedicated device driver for use on a PC, or game controllers that support XInput (relatively new game controllers), as many of them tend to not be recognized at all, or even if they are recognized, some key input does not work.

SUZUKIPLAN primarily uses the Elecom JC-U3312 and HXBE37823; the Elecom JC-U3312 is an EOL product and may be difficult to find. The HXBE37823 is available inexpensively from Aliexpress and Amazon and is recommended, but may have slightly more oblique input misdetection. (It is not considered to be of high quality, so there may be individual variability issues.)

Games like Battle Marine can be played comfortably on the HXBE37823 if the direction of movement is focused to the left or right.

(GPIO Joypad)

You can also connect buttons directly to the GPIOs of the RaspberryPi Zero 2W with the following pin assignments:

Button GPIO
Up 22
Down 5
Left 26
Right 6
A 24
B 25
Start 4
Select 23

RaspberryPi Zero 2W Pin Map

joypad_pin.jpeg

NOTE: GND connection is also required.

For more technical details on GPIO connections, please refer to this article (Japanese).

VGS-Zero compatible joysticks and joypads can be developed and sold freely without a license from SUZUKIPLAN, regardless of whether they are for companies (commercial hardware) or individuals (doujin hardware). No license is required, but our support is not provided, so it is the responsibility of the distributor to provide support to consumers.

Although more difficult to implement than a USB joypad, it has the following advantages:

  • No compatibility issues
  • Faster response time than USB joypads

If you are selling hardware that can play VGS-Zero games, we recommend that you basically implement it with a GPIO joypad.

Note that when both USB and GPIO joypads are connected, the USB joypad input has priority and the GPIO joypad input does not.

Launch Sequence

The startup procedure is as follows:

  1. Prepare a FAT32 formatted SD card.
  2. Add ./image to the root directory of the SD card.
  3. Replace game.pkg with the game you wish to boot.
  4. Insert the SD card into the RaspberryPi Zero 2W.
  5. Connect the USB joypad to the RaspberryPi Zero 2W.
  6. Connect the RaspberryPi Zero 2W to the TV with the HDMI cable
  7. Connect power to RaspberryPi Zero 2W and turn it ON

config.sys

Various customizations can be made by placing the config.sys file in the root directory of the SD card inserted into the RaspberryPi Zero 2W.

Joypad Button Assign

#--------------------
# JoyPad settings
#--------------------
A BUTTON_1
B BUTTON_0
SELECT BUTTON_8
START BUTTON_9
UP AXIS_1 < 64
DOWN AXIS_1 > 192
LEFT AXIS_0 < 64
RIGHT AXIS_0 > 192

Specification:

# Button Settings
key_name △ BUTTON_{0-31}

# AXIS Settings
key_name △ AXIS_{0-1} △ {<|>} △ {0-255}

key_name:

  • A A button
  • B B button
  • START START button
  • SELECT SELECT button
  • UP Up cursor
  • DOWN Down cursor
  • LEFT Left cursor
  • RIGHT Right cursor

You can also assign BUTTON_ to a cursor or AXIS_ to a button.

You can use tools/joypad can be used to check the button contents of your USB joypad.

game.pkg

game.pkg is a VGS-Zero game executable file that can be generated with the makepkg command.

makepkg  -o /path/to/output.pkg
         -r /path/to/game.rom
        [-b /path/to/bgm.dat]
        [-s /path/to/se.dat]

The maximum size of game.pkg is 16MB (128Mbits).

game.rom

game.rom is a ROM data set in 8KB units that is loaded into the ROM bank and can be generated with the makerom command in the toolchain.

usage: makerom output input1 input2 ... input256
  • 8KB (64KBit) = 1 bank
  • game.rom can store up to 256 banks (16MBit)
  • If the input file exceeds 8KB, it is automatically divided into multiple banks and stored in game.rom.
  • If the input file is not divisible by 8KB, padding data is automatically inserted.
  • The bank number is determined by the order in which the input files are specified (the first 8KB of the first file specified is bank 0).
  • When VGS-Zero starts, banks 0 to 3 are loaded into ROM Bank 0 to 3 of the CPU Memory Map.
  • Bank 0 must be program code.

bgm.dat

bgm.dat is a data set containing one or more songs and can be generated by the makebgm command.

Music data supports the following two data formats:

The VGS-Zero automatically identifies the type of BGM data that has been Playback instruction (0xE0) in the Z80 program.

(Compile MML)

usage: vgsmml /path/to/file.mml /path/to/file.bgm

(NSF)

  • NSF; NES Sound Format background music data can be created using a DAW; Digital Audio Workstation that supports the NSF format, such as FamiStudio
  • Please check example/15_nsf for details.
  • For extended sound sources, only VRC6 is supported (VRC7, FME7, FDS, N106, and MMC5 are not supported).
  • Reference article: https://note.com/suzukiplan/n/n94ea503ff2c8
  • NSF only supports playback of the default track (specified by the 8th byte of the NSF header)
    • If you wish to use NSF data in multi-track format, incorporate multiple identical NSF files with rewritten default tracks into bgm.dat.

(Make bgm.dat)

makebgm bgm.dat song1.bgm [song2.bgm [song3.bgm...]]

Up to 256 BGM or NSF files can be specified.

se.dat

se.dat is a sound effect data set that can be generated with the makese command.

makese se.dat se1.wav [se2.wav [se3.wav...]]

The .wav file that can be specified to the makese command must be in the following format:

  • Uncompressed RIFF format
  • Sampling rate: 44100Hz
  • Bit rate: 16bits
  • Number of channels: 1 (monaural)

Up to 256 .wav files may be specified.

Game Development Tools

This section contains information on the tools necessary for VGS-Zero game development.

Recommended Game Development Tools

The table below lists recommended development tools:

Name Type Information
Ubuntu Desktop OS All tools listed in this table can also run on Ubuntu
Visual Studio Code Coding Writing programs, MMLs, scripts, etc.
An extension for vgsasm is available.
SDCC C compiler Recommended for use when developing games in C
(but only version 4.1.0 can work)
aseprite Graphics Editor Graphics editor supporting 256-color Bitmap format
Tiled Map Editor Map Editor Examples of Use: example/08_map-scroll
Jfxr Sound Effects Editor Creating game sound effects in the browser
FamiStudio BGM Editor DAW that can produce background music in NSF format

With the above tools, you can develop all the programs and assets (graphics, sound effects, music) needed for your game, and all the tools are free to use. All of the tools are free to use. Some of them are paid, but you can use them for free if you download and build the source code yourself.

It does not necessarily mean that only the above tools can be used for development.

Official Toolchain

The tools provided in this repository are as follows:

Name Path Type Information
vgs0 ./src/sdl2 Emulator VGS-Zero emulator & debugger for PC (Linux, macOS)
vgsasm ./tools/vgsasm CLI Z80 Assembler
bmp2chr ./tools/bmp2chr CLI Convert 256-color Bitmap file to character-pattern format
csv2bin ./tools/csv2bin CLI Tiled Map Editor csv to binary format
makepkg ./tools/makepkg CLI Generate game.pkg
makerom ./tools/makerom CLI Generate game.rom
makese ./tools/makese CLI Generate se.dat
makebgm ./tools/makebgm CLI Generate bgm.dat
vgsmml ./tools/vgsmml CLI MML Compiler
vgsplay ./tools/vgsplay CLI Playback MML
joypad ./tools/joypad RPi Test tool for USB joypad

Programming Guide

Programming Language

vgsasm is recommended for programming.

You can program comfortably by using the “vgsasm” extension for Visual Studio Code.

API Manual for Programming Language C

See the vgs0lib.h implementation.

Although deprecated because it would be quicker to look at the implementation, you can view the manual in HTML format by running the following command:

sudo apt install doxygen build-essential
git clone https://github.com/suzukiplan/vgszero
cd vgszero/lib/sdcc
make doc
open doc/html/index.html

Create Sound Data

Joypad Recommended Usage

Games developed for VGS-Zero are intended to be played by game users without reading the documentation as much as possible, so the buttons on the joypad are fixed to a simple 8-button system D-PAD, A/B, Select/Start.

  • D-PAD usage
    • Use it to move the character or cursor.
  • B button usage
    • These buttons are suitable for operations that are expected to be often tapped (repeatedly tapped) by the user.
    • Examples of use: shooting shots, plumber firing fireballs, dash by pressing and holding cursor input, etc.
    • It is preferable to use the B button for canceling command operations such as RPG.
  • A button usage
    • These buttons are suitable for operations where the user is expected to carefully tap.
    • Examples of use: shooting bombers, jumps, sniping shots, etc.
    • It is preferable to use the A button to make decisions for RPG and other command operations.
  • START button usage
    • Buttons that are expected to be pressed during system operations.
    • Examples: game start, pause, open command, etc.
  • SELECT button usage
    • It is not a button that is expected to be used very often, so it is best to avoid its active use.
    • Example of use: coin drop in arcade-like games, etc.

How to Debug

  • For debugging, an SDL2 version emulator running on a PC (Linux or macOS) (./src/sdl2) running on a PC (Linux or macOS).
  • The SDL2 version of the emulator breaks when it detects a NOP instruction and displays a register and memory dump debug function

CPU Memory Map

The memory map visible from the main program (Z80) is as follows:

CPU address Map
0x0000 ~ 0x1FFF ROM Bank 0
0x2000 ~ 0x3FFF ROM Bank 1
0x4000 ~ 0x5FFF ROM Bank 2
0x6000 ~ 0x7FFF ROM Bank 3
0x8000 ~ 0x9FFF VRAM
0xA000 ~ 0xBFFF Extra RAM Bank
0xC000 ~ 0xFFFF Main RAM (16KB)
  • The ROM data of the program is divided into 8KB blocks and can have up to 256 banks.
  • After power-on or reset, ROM Bank is set to 0 to 3, and bank-switch is available via I/O on ports B0 to B3.
  • The stack area is used from 0xFFFE toward 0xC000
  • When using global variables, use them in order from 0xC000, and be careful not to destroy the stack when programming.

RAM Scheme

The RAM in VGS-Zero can be broadly classified into three types of RAM compartments:

  1. VRAM (0x8000 ~ 0x9FFF) = 8KB
  2. Extra RAM Bank (0xA000 ~ 0xBFFF) = 8KB x 256 Banks (2MB)
  3. Main RAM (0xC000 ~ 0xFFFF) = 16KB

VRAM is a memory area used for graphics display and control functions such as Name Table, Attribute Table, OAM, Palette and VDP registers. VDP registers and other functions related to graphics display and control.

And Main RAM is a memory section used to hold data such as variables (0xC000~) and stack (~0xFFFF).

The Extra RAM Bank is a slightly special memory block unique to VGS-Zero that can be used as a Character Pattern Table for VRAM (similar to TMS9918A). It can also be used for other purposes.

VGS-Video can use data in ROM directly as character patterns by using DPM; Direct Pattern Mapping or OAM Bank, This eliminates the need to expand the character pattern into RAM (VRAM).

If there is no need to expand character patterns into RAM (VRAM), the Extra RAM Bank can be used as a vast data area for roguelike RPG map data, for example.

VRAM Memory Map

CPU address VRAM address Map
0x8000 ~ 0x83FF 0x0000 ~ 0x03FF BG Name Table (32 x 32)
0x8400 ~ 0x87FF 0x0400 ~ 0x07FF BG Attribute Table (32 x 32)
0x8800 ~ 0x8BFF 0x0800 ~ 0x0BFF FG Name Table (32 x 32)
0x8C00 ~ 0x8FFF 0x0C00 ~ 0x0FFF FG Attribute Table (32 x 32)
0x9000 ~ 0x97FF 0x1000 ~ 0x17FF OAM; Object Attribute Memory (8 x 256)
0x9800 ~ 0x99FF 0x1800 ~ 0x19FF Palette Table (2 x 16 x 16)
0x9A00 ~ 0x9DFF 0x1A00 ~ 0x1DFF OAM16
0x9F00 0x1F00 Register #0: Vertical Scanline Counter (read only)
0x9F01 0x1F01 Register #1: Horizontal Scanline Counter (read only)
0x9F02 0x1F02 Register #2: BG Scroll X
0x9F03 0x1F03 Register #3: BG Scroll Y
0x9F04 0x1F04 Register #4: FG Scroll X
0x9F05 0x1F05 Register #5: FG Scroll Y
0x9F06 0x1F06 Register #6: IRQ scanline position (NOTE: 0 is disable)
0x9F07 0x1F07 Register #7: Status (read only)
0x9F08 0x1F08 Register #8: Direct Pattern Maaping for BG
0x9F09 0x1F09 Register #9: Direct Pattern Maaping for FG
0x9F0A 0x1F0A Register #10: Direct Pattern Maaping for Sprite
0x9F0B 0x1F0B Register #11: 1024 pattern mode setting for BG/FG
0xA000 ~ $BFFF 0x2000 ~ 0x3FFF Character Pattern Table (32 x 256)

Unlike general VDP, access to VRAM can be easily performed by load/store to CPU address (e.g., LD instruction).

(BG)

  • BG (Background Graphics) is the basic background image
  • It is displayed behind sprite and FG.
  • It is intended to be used as the background graphics for games.
  • Can be displayed by specifying character-pattern-table and attribute in name-table
  • Transparent color does not exist
  • The drawing cannot be hidden by specifying attribute.
  • Supports hardware-scroll, which is independent of FG.

(FG)

  • FG (Foreground Graphics) is the foremost image displayed
  • It is displayed in front of the BG and sprite.
  • It is intended to be used for displaying game scores, message windows, etc.
  • Can be displayed by specifying character-pattern-table and attribute in name-table
  • Color number 0 in palette is transparent color.
  • Attribute can be used to hide the drawing, which is set to hidden by default.
  • Supports hardware-scroll, which is independent of BG.

(Sprite)

  • Sprite is an image of a character moving around on the screen
  • It is displayed on the front of BG & the back of FG.
  • Intended for use in game character display
  • Up to 256 images can be displayed simultaneously.
  • Up to 256 characters can be displayed at the same time.
  • The drawing can be hidden by specifying attribute.
  • The default size is 1x1 pattern (8x8 pixels), but a maximum of 16x16 pattern (128x128 pixels) can be displayed as a single sprite (see the description of widthMinus1 and heightMinus1 in OAM for details)

(Name Table)

  • VGS-Zero displays graphics by writing 8x8 pixel rectangle character pattern numbers to a name table.
  • The name table is a two-dimensional array of 32 rows and 32 columns (common to BG/FG).

(Attribute)

Attributes are character pattern display attributes common to BG, FG, and sprites.

Bit-7 Bit-6 Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0
VI LR UD PTN P3 P2 P1 P0
  • VI: 0 = hidden, 1 = shown (*only for BG, 0 is also shown)
  • LR: If 1, left-right flip is shown.
  • UD: If 1, it is displayed upside down.
  • PTN: If 1, the bank number will +1 when Direct Pattern Mapping is enabled.
  • P0~P3: palette number (0 ~ 15).

(Palette)

  • VGS-Zero allows up to 16 palettes
  • Each palette can contain 16 colors in RGB555 format
  • For FG and sprites, color number 0 is the transparent color

(OAM)

OAM is a structure with the following elements:

  1. display coordinates of sprite.
  2. Character pattern number.
  3. Attribute
  4. Size
  5. Bank number by OAM
struct OAM {
    unsigned char y;
    unsigned char x;
    unsigned char pattern;
    unsigned char attribute;
    unsigned char heightMinus1;
    unsigned char widthMinus1;
    unsigned char bank;
    unsigned char reserved;
} oam[256];

VGS-Zero can display up to 256 sprites simultaneously, with no upper limit to the number of sprites displayed horizontally.

(OAM Pattern Size)

The widthMinus1 and heightMinus1 of OAM can be specified in the range of 0 to 15, and a value of 1 or more will display multiple character-patterns side by side.

character-pattern-table numbers are incremented by +1 in the horizontal direction and +16 (+0x10) in the vertical direction.

For example, if widthMinus1 is 2 and heightMinus is 3, the character-pattern group in the table below is displayed as one sprite:

\ 0 1 2
0 pattern+0x00 pattern+0x01 pattern+0x02
1 pattern+0x10 pattern+0x11 pattern+0x12
2 pattern+0x20 pattern+0x21 pattern+0x22
3 pattern+0x30 pattern+0x31 pattern+0x32

(OAM Bank)

If bank in OAM is 0, the character pattern of the sprite is taken from the character-pattern in VRAM or the bank specified by Direct Pattern Mapping.

If a value greater than or equal to 1 is specified, then the bank number of the specified value is used as the character pattern for the OAM.

Configuration priority:

  1. OAM Bank (highest priority)
  2. Direct Pattern Mapping (#direct-pattern-mapping)
  3. Character Pattern on VRAM

By using OAM Bank, a different bank character pattern can be used for each OAM.

(OAM16)

OAM16 is an area where the sprite coordinates can be 16-bit values.

struct OAM16 {
    unsigned short y;
    unsigned short x;
} oam16[256];

Valid for non-zero x or y values in OAM16.

By using this function, sprites larger than 24px can be clipped.

OAM OAM16
oam oam16

For details on how to use example/17_clip for details.

(Scanline Counter)

  • The scanline counter is a read-only VDP register that can identify the pixel rendering position of the VDP
  • Vertical is 0x9F00 and horizontal is 0x9F01.
  • By waiting for the vertical value, processes such as raster scrolling can be implemented without interrupts.
  • Horizontal values are not useful because of the high speed of switching.

(Hardware Scroll)

  • BG allows you to specify 0x9F02 as X-coordinate and 0x9F03 as Y-coordinate starting point.
  • FG: 0x9F04 with X-coordinate and 0x9F05 with Y-coordinate starting point.
  • You can also get the current scroll position by reading 0x9F02 ~ 0x9F05.

(VDP Status)

Bit-7 Bit-6 Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0
BL - - - - - - -
  • BL: 1 = start vblank

The BL flag is set at the timing when the drawing of the 192nd line of the visible area (the 200th line of the scan line) is completed.

bl_timing.png

NOTE: Status register always reset after read.

(Direct Pattern Mapping)

Normally, BG, FG, and Sprite refer to a common [character-pattern-table], but by writing a value other than 0 to 0x9F08, 0x9F09, and/or 0x9F0A, the ROM bank corresponding to that value can be used as the respective character-pattern-table.

  • 0x9F08: DPM for BG
  • 0x9F09: DPM for FG
  • 0x9F0A: DPM for Sprite
LD HL, 0x9F08
LD (HL), 0x10   # BG = Bank 16
INC HL
LD (HL), 0x11   # FG = Bank 17
INC HL
LD (HL), 0x12   # Sprite = Bank 18

If you want to do bank-switching animations, you can save CPU resources by using DPM rather than switching character-pattern-table with DMA.

(1024 Patterns Mode)

The number of patterns available for BG/FG can be expanded to 1024 by setting 0x9F0B.

Note that the DPM setting in BG/FG is required to use this function.

Bit-7 Bit-6 Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0
- - - - - - F1k B1k
  • F1k Number of FG patterns (0: 256, 1: 1024)
  • B1k Number of BG patterns (0: 256, 1: 1024)

If B1k and/or F1k are set, then row÷8 + DPM in name-table is the pattern bank number to be applied.

  • Lines 0〜7: Pattern Bank = DPM + 0
  • Lines 8〜15: Pattern Bank = DPM + 1
  • Lines 16〜23: Pattern Bank = DPM + 2
  • Lines 24〜31: Pattern Bank = DPM + 3

By entering a 256x256 pixel .bmp file into bmp2chr, you can easily generate 4 banksets of chr data for this mode by entering a 256x256 pixel .bmp file.

For more information, see ./example/14_1024ptn

(Character Pattern Table)

  • The character pattern table can contain up to 256 character patterns of 8x8 pixel
  • The size of one character is 32 bytes
  • The total table size is 32 x 256 = 8192 bytes, exactly the size of a bank
  • A high-speed DMA function is provided to transfer the contents of a specific bank to the character pattern table

The bit layout of the character pattern table is as follows:

px0 px1 px2 px3 px4 px5 px6 px7 Line number
H00 L00 H01 L01 H02 L02 H03 L03 Line 0
H04 L04 H05 L05 H06 L06 H07 L07 Line 1
H08 L08 H09 L09 H10 L10 H11 L11 Line 2
H12 L12 H13 L13 H14 L14 H15 L15 Line 3
H16 L16 H17 L17 H18 L18 H19 L19 Line 4
H20 L20 H21 L21 H22 L22 H23 L23 Line 5
H24 L24 H25 L25 H26 L26 H27 L27 Line 6
H28 L28 H29 L29 H30 L30 H31 L31 Line 7
  • Hxx : Upper 4 bits (0 ~ 15 = color number) *xx indicates byte position.
  • Lxx : Lower 4 bits (0 ~ 15 = color number) *xx is byte position.
  • For FG and sprites, color number 0 is always a transparent color.
  • The palette number to be used is specified in attribute

The memory area of the Character Pattern Table (0xA000 to 0xBFFF) can be made equivalent to 8KB RAM by setting all of BG, FG, and sprite to Direct Pattern Mapping, the area can be set to be equivalent to 8KB of RAM. Furthermore, since this area supports high-speed bank loading by DMA, it may be suitable as a destination area for large map data (up to 64x128 chips for 1 byte per chip!) in shooting games and RPGs.

I/O Map

Port I O Description
0xA0 o - Joypad
0xB0 o o ROM Bank 0 (default: 0x00)
0xB1 o o ROM Bank 1 (default: 0x01)
0xB2 o o ROM Bank 2 (default: 0x02)
0xB3 o o ROM Bank 3 (default: 0x03)
0xB4 o o Extra RAM Bank (default: 0x00)
0xB5 - o Duplicate Extra RAM Bank
0xC0 - o ROM to Character DMA
0xC1 - o ROM to Memory DMA
0xC2 - o memset DMA
0xC3 - o memcpy DMA
0xC4 o - Collision Detection
0xC5 - o Multiplication, division, and remainder
0xC6 - o Hardware sin table
0xC7 - o Hardware cos table
0xC8 o - Hardware atan2 table
0xC9 o o Hardware Random (8-bits)
0xCA o o Hardware Random (16-bits)
0xCB - o Perlin noise seeding
0xCC - o Set X-coordinate scale for perlin noise
0xCD - o Set Y-coordinate scale for perlin noise
0xCE o - Get perlin noise
0xCF o - Get perlin noise (with octave)
0xDA o o Save / Load
0xE0 - o Playback BGM
0xE1 - o Pause, Resume or Fadeout BGM
0xF0 - o Play Sound Effect
0xF1 - o Interrupted Sound Effect
0xF2 - o Check if sound effects are playing.

(JoyPad)

IN A, (0xA0)
Bit-7 Bit-6 Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0
Up Down Left Right Start Select A B
  • 0: Entered
  • 1: Not entered

(Bank Switch)

# Read current bank of ROM Bank 0
IN A, (0xB0)

# Switch ROM Bank 1 to No.17
LD A, 0x11
OUT (0xB1), A

(Extra RAM Bank)

By setting port number 0xB4 to OUT, the Extra RAM Bank (0xA000 to 0xBFFF = RAM area (8KB) of Character Pattern Table) can be switched to use up to 2MB (8KB x 256) RAM.

# Read Current Extra RAM Bank
IN A, (0xB4)

# Switch Extra RAM Bank to No.3
LD A, 0x03
OUT (0xB4), A

(Duplicate Extra RAM Bank)

The contents of the current Extra RAM Bank can be duplicated to another Extra RAM Bank by setting port number 0xB5 to OUT.

; 現在の Extra RAM Bank = 0x00
XOR A
OUT (0xB4), A

; 0x00 の内容を 0x03 へ複製
LD A, 0x03
OUT (0xB5), A

(ROM to Character DMA)

By setting port number 0xC0 to OUT, the contents of a specific bank can be DMA-transferred to the Character Pattern Table in the VRAM.

# Transfer bank number = 0x22 to character pattern table
LD A, 0x22
OUT (0xC0), A

(ROM to Memory DMA)

By setting port number 0xC1 to OUT, the contents of a specific size of a specific bank can be DMA transferred to an arbitrary address.

This instruction sets BC, DE, and HL to the following:

  • BC: Offset in the source bank (0x0000 to 0x1FFF)
  • DE: Transfer size (8192 - BC or less)
  • HL: Destination address

The following example shows a DMA transfer of 512 bytes from 0x1234 of bank number 0x23 to 0xCE00 (RAM):

LD A, 0x23
LD BC, 0x1234
LD DE, 512
LD HL, 0xCE00
OUT (0xC1), A

(memset DMA)

LD BC, 0xC000   # Forwarding address
LD HL, 0x2000   # Number of bytes transferred
LD A,  0xFF     # Value to be transferred
OUT (0xC2), A   # Execute memset

(memcpy DMA)

LD BC, 0xC000   # Forwarding address (RAM)
LD DE, 0x6000   # Source address (ROM Bank 3)
LD HL, 0x2000   # Number of bytes transferred (8KB)
OUT (0xC3), A   # Execute memcpy (*Values written are ignored.)

(Collision Detection)

The following 8 bytes structure is stored in the HL and 0xC4 is set to IN to determine if a hit has occurred.

struct rect {
    uint8_t x;      // X-coordinate
    uint8_t y;      // Y-coordinate
    uint8_t width;  // width
    uint8_t height; // height
} chr[2];           // For 2 characters of them(8bytes)
LD HL, 0xC000   # First address of the structure
IN A, (0xC4)    # Perform collision determination
AND A           # Zero check
JNZ DETECT_HIT  # Collision Detection
JZ NOT_HIT      # Collision Not Detection

(Hardware Calculation)

The OUT of 0xC5 enables high-speed execution of multiplication, division, and remainder operations, which Z80 is not good at.

# 8bit arithmetic instruction (unsigned)
OUT (0xC5), 0x00 ... HL = H * L
OUT (0xC5), 0x01 ... HL = H / L
OUT (0xC5), 0x02 ... HL = H % L

# 8bit arithmetic instruction (signed)
OUT (0xC5), 0x40 ... HL = H * L
OUT (0xC5), 0x41 ... HL = H / L

# 16bit arithmetic instruction (unsigned)
OUT (0xC5), 0x80 ... HL = HL * C (HL: operation-result mod 65536)
OUT (0xC5), 0x81 ... HL = HL / C
OUT (0xC5), 0x82 ... HL = HL % C

# 16bit arithmetic instruction (Signed)
OUT (0xC5), 0xC0 ... HL = HL * C (HL: operation-result mod 65536)
OUT (0xC5), 0xC1 ... HL = HL / C

NOTE: HL is 0xFFFF if division by zero is performed.

(Hardware SIN table)

LD A, 123      # Specify the table element number to be sought in A
OUT (0xC6), A  # A = sin(A × π ÷ 128.0)

(Hardware COS table)

LD A, 123      # Specify the table element number to be sought in A
OUT (0xC7), A  # A = cos(A × π ÷ 128.0)

(Hardware ATAN2 table)

LD H, <<<y1 - y2>>>   # Set the difference of Y-coordinates to H
LD L, <<<x1 - x2>>>   # Set the difference of X-coordinates to L
IN A, (0xC8)          # Find the angles (x1, y1) and (x2, y2) in A

(Hardware Random)

You can obtain convergence-guaranteed random numbers.

Guaranteed convergence means that if 8 bits are called 256 times, the numbers 0 to 255 will always appear once, and if 16 bits are called 65536 times, the numbers 0 to 65535 will always appear once.

# 8 bits Set random number seed
LD L, 123
LD A, L
OUT (0xC9), A

# Obtain 8 bits random numbers (note that random numbers are also stored in the L)
IN A, (0xC9)

# 16 bits Sets the random number seed (any value specified for OUT is ignored, so anything is OK)
LD HL, 12345
OUT (0xCA), A

# Obtain 16 bits random number (note that random numbers are also stored in the HL)
IN A, (0xCA)

(Hardware Perlin Noise)

Perlin noise can be obtained.

For more information, see ./example/13_perlin.

# Set random number seed
LD HL, 12345
OUT (0xCB), A

# Set the scale in the x-direction (the smaller the scale, the larger the scale)
LD HL, 123
OUT (0xCC), A

# Set the scale in the Y direction (the smaller the scale, the larger the scale)
LD HL, 456
OUT (0xCD), A

# Get perlin noise
LD HL, 789 # X-coordinate
LD DE, 123 # Y-coordinate
IN A, (0xCE)

# Obtain perlin noise by specifying octave.
LD HL, 789 # X-coordinate
LD DE, 123 # Y-coordinate
LD A, 10   # Octave
IN A, (0xCF)

(Save Data)

  • Save (OUT) and load (IN) can be done with I/O on port 0xDA.
  • The save data file name is fixed to save.dat in the SD card root directory (current directory for SDL2).
  • It is intended to be used as a save function for RPGs and a high score save function for STGs.

Save implementation example:

LD BC, 0xC000   # Specify the address of the data to be saved (only RAM area can be specified)
LD HL, 0x2000   # Specify size of data to be saved (max 16 KB = 0x4000)
OUT (0xDA), A   # Save (*Written values are ignored, so anything can be saved)
AND 0xFF        # The save result is stored in A
JZ SAVE_SUCCESS # 0 on success
JNZ SAVE_FAILED # On failure, not 0

Load implementation example:

LD BC, 0xC000   # Specify load destination address (only RAM area can be specified)
LD HL, 0x2000   # Specify data size to load (max 16 KB = 0x4000)
IN A, (0xDA)    # Load (*Written values are ignored, so anything is OK)
JZ LOAD_SUCCESS # 0 on success
JNZ LOAD_FAILED # On failure, not 0 (*Load destination is filled with 0x00)

RaspberryPi specific notes:

  • Saving to the SD card is done asynchronously, so the save will return success even if the SD card is not inserted or in some other incorrect state (at this time, a system message will appear on the screen indicating that the SD card write has failed).
  • save.dat is written only when changes are made to the contents of the saved data in order to prevent SD card deterioration.
  • The LED lamp will be lit during saving and will blink 3 times if a write failure occurs.
  • Powering off the SD card while saving may damage the card.
  • The kernel mounts the SD card when save and load are performed and unmounts it automatically when the process is complete

Common notes:

  • Even if save.dat is smaller than the size (HL) specified at load time, the load will succeed, and the area where no data exists will be filled with 0x00.
  • Loading into the stack area may cause the program to run out of control.
  • It is advisable to take into account the possibility that users may be running with saved data from different games

(Play BGM)

LD A, 0x01      # Specify BGM bank number to be played
OUT (0xE0), A   # Start playing background music

(Pause BGM)

LD A, 0x00      # Operation ID: Pause
OUT (0xE1), A   # Interruption of background music performance.

(Resume BGM)

LD A, 0x01      # Operation ID: Resume
OUT (0xE1), A   # Resume playing background music.

(Fadeout BGM)

LD A, 0x02      # Operation ID: Fadeout
OUT (0xE1), A   # Fade out background music performance.

(Play Sound Effect)

LD A, 0x01      # Specify the number of the sound effect to be played.
OUT (0xF0), A   # Execute

(Stop Sound Effect)

LD A, 0x02      # Specify the number of the sound effect to be stopped.
OUT (0xF1), A   # Execute

(Check Sound Effect)

LD A, 0x03      # Specify the number of the sound effect to be checked if it is playing.
OUT (0xF2), A   # Execute (A=0: Stopped, A=1: Playing)
AND 0x01
JNZ EFF03_IS_PILAYING
JZ  EFF03_IS_NOT_PLAYING

How to Sell Your Game

RaspberryPi Zero 2W

When selling games for VGS-Zero at comic markets (events) or by mail order, the following procedure is recommended:

  1. Prepare a micro SD card formatted in FAT32
  2. Create a new micro SD card in ./image to the root directory of the micro SD card.
  3. Replace game.pkg
  4. Delete README
  5. Store README.txt (text describing how to play the game)
  6. Store micro-SD card in case etc.
  7. Apply game label to the case

Legend of README.txt description:

================================================================================
<<<Game Title>>>
<<<Copyright>>>
================================================================================

Thank you very much for purchasing “<<<game title>>>”.
This document describes how to play this game, etc.
Please read it before playing.

(Hardware Required)

- RaspberryPi Zero 2W
- HDMI Cable (mini HDMI Type C → HDMI Type A)
- USB Joypad(D-Pad+A/B+Start/Select)+ Conversion Adapter
- USB power supply
- Television, etc. (with the following conditions)
  - HDMI input support
  - Refresh rate 60Hz
  - Resolution 480x384 pixels or higher
  - Audio output supported

(How to Start-up)

- Insert this product (micro SD card) into RaspberryPi Zero 2W.
- Turn on the power of RaspberryPi Zero 2W

(How to change button assignments)

The joypad button assignments can be customized in config.sys.
The following tools can be used to check what should be set in config.sys.

https://github.com/suzukiplan/vgszero/tree/master/tools/joypad


(How to Play)

<<<Describe how you play your game>>>

(Contact us)

<<<Include Twitter (aka X) account, etc.>>>

For mail-order sales, consignment sales at doujin stores may be a good option if the lot size is large, but for small lots (100 or less), Mercari may be a good and easy option in Japan.

No payback (license fee) to SUZUKIPLAN is required for any proceeds from sales.

Steam

  • With VGS-Zero SDK for Steam you can easily create Steam (Windows & SteamDeck) versions
  • VGS-Zero SDK for Steam requires a subscription to Steamworks and the purchase of App Credits.
  • No payback (license fee) to SUZUKIPLAN is required for any revenue generated from the sale of VGS-Zero SDK for Steam.

Nintendo Switch

We hope to address this in the future.

Examples

Name Language Description
01_hello Z80, C Show HELLO,WORLD!
02_global Z80, C Example of Global Variable Usage
03_sound Z80, C Examples of background music and sound effects
04_heavy C Examples of background music and sound effects
05_sprite256 Z80, C Example of displaying and moving 256 sprites
06_save Z80, C Example of Save Function Usage
07_palette Z80, C Example using all 16 palettes
08_map-scroll Z80, C Scrolling map data created with the Tiled Map Editor
09_joypad Z80, C Preview joypad input results
10_chr720 Z80, C Example of displaying a single picture in Direct Pattern Mapping
11_bigsprite Z80, C Example of displaying a huge sprite by specifying widthMinus1, heightMinus1, and bank in OAM
12_angle Z80, C Example of implementing complete self-targeting using atan2
13_perlin Z80, C Example usage of Perlin Noise
14_1024ptn Z80, C 1024-patterns-mode usage example
15_nsf Z80, C Example usage of NSF
16_ptn-plus1 Z80, C Example usage of ptn in Attribute
17_clip Z80, C Example usage of OAM16

License

The copyright of game.pkg developed by you belongs to you and you are free to use it, including commercial use.

Only VGS-Zero Library for Z80 may be embedded in game.pkg, but all other OSS is used on the kernel (VGS-Zero itself) side and does not affect the license of the developed game.

However, if you wish to include it when redistributing ./image/README, please check the contents carefully.