Language: Japanese, English
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).
- VGS-Zero Feature
- First Step Guide
- How to Execute
- config.sys
- game.pkg
- Game Development Tools
- Programming Guide
- How to Sell Your Game
- Examples
- License
- CPU: Z80 16MHz (16,777,216Hz)
- Programmable in Z80 assembly language (see Programming Guide)
- Can also be programmed in C with SDCC (see Programming Guide)
- The game executable file game.pkg has a maximum size of 128 megabits.
- Up to 2MB (8KB x 256banks) of programs and data (*excluding voice data)
- RAM size 16KB (PV16相当!)
- Extended RAM size 2MB
- Built-in RAM save functionに対応
- VDP; VGS-Video (Video Display Processor)
- VRAM size 16KB
- Screen resolution: 240x192 pixels
- 16 x 16-color palettes available(Simultaneous 256 out of 32,768 colors)
- Up to 256 (8KB) 8x8 pixel character-pattern can be defined
- Name table size for BG and FG: 32x32 (256x256 pixels)
- Support for hardware scroll (BG, FG each)
- Capable of displaying up to 256 sprites (no horizontal limit)
- Supports Direct Pattern Mapping function to set different character patterns for BG, FG, and sprites.
- BG and FG support 1024 patterns mode.
- Provides a hardware function (OAM Pattern Size) that allows multiple character pattern to be displayed side by side on a sprite.
- Provides a hardware function (OAM Bank) to specify a different bank for each OAM record of sprite.
- Provides OAM16 which can make the coordinate system of sprite 16bit.
- DMA (Direct Memory Access)
- High-speed transfer of the contents of a specific ROM bank to the character pattern table
- Capable of transferring the contents of a specific ROM bank to any memory in any size
- High-speed DMA transfer functionality equivalent to
memset
in C is available - High-speed DMA transfer functionality equivalent to
memcpy
in C is available
- HAGe (High-speed Accumulator for Game)
- BGM
- SE (Sound Effect)
- Input Devices:
- USB joypad
- Supports joypad in 8-button format (cursor keys, A/B, START/SELECT)
- Button assignments can be customized via config.sys
- GPIO joypad
- Support for joypads that connect directly to RaspberryPi GPIOs
- USB joypad
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
.
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.
This section describes the procedure for running the game on the actual device (RaspberryPi Zero 2W).
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
VGS-Zero only supports input via the 8-button USB joypad with cursor (D-PAD), A button, B button, SELECT button, and START button.
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.
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.
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
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.
The startup procedure is as follows:
- Prepare a FAT32 formatted SD card.
- Add ./image to the root directory of the SD card.
- Replace game.pkg with the game you wish to boot.
- Insert the SD card into the RaspberryPi Zero 2W.
- Connect the USB joypad to the RaspberryPi Zero 2W.
- Connect the RaspberryPi Zero 2W to the TV with the HDMI cable
- Connect power to RaspberryPi Zero 2W and turn it ON
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 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 buttonB
B buttonSTART
START buttonSELECT
SELECT buttonUP
Up cursorDOWN
Down cursorLEFT
Left cursorRIGHT
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 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 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 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:
- BGM data in VGS; Video Game Sound format compiled by vgsmml command
- BGM data in NSF format
The VGS-Zero automatically identifies the type of BGM data that has been Playback instruction (0xE0) in the Z80 program.
usage: vgsmml /path/to/file.mml /path/to/file.bgm
- MML of Touhou BGM on VGS is available for all songs, so you may find it useful for practical use.
- MML files can be playback with the toolchain vgsplay command in the toolchain on your PC.
- 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.
makebgm bgm.dat song1.bgm [song2.bgm [song3.bgm...]]
Up to 256 BGM or NSF files can be specified.
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.
This section contains information on the tools necessary for VGS-Zero game development.
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.
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 |
- VGS-Zero games can be written in Z80 assembly language or C.
- If written in Z80:
- Recommended assembler: vgsasm
- Any Z80-compatible assembler can be used.
- If written in C:
- SDCC (Small Device C Compiler) can be used as a cross-compiler
- VGS-Zero supports SDCC version 4.1.0 only.
- Standard libraries are not available.
- vgs0.lib can be used.
vgsasm is recommended for programming.
You can program comfortably by using the “vgsasm” extension for Visual Studio Code.
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 music data in VGS Music Macro Language (MML) or NSF format (e.g. FamiStudio)
- Create sound effect data as 44100Hz 16bits 1ch (mono) wav files.
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.
- 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
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.
The RAM in VGS-Zero can be broadly classified into three types of RAM compartments:
- VRAM (0x8000 ~ 0x9FFF) = 8KB
- Extra RAM Bank (0xA000 ~ 0xBFFF) = 8KB x 256 Banks (2MB)
- 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.
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 (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 (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 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
andheightMinus1
in OAM for details)
- 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).
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
: If1
, left-right flip is shown.UD
: If1
, it is displayed upside down.PTN
: If1
, the bank number will +1 when Direct Pattern Mapping is enabled.P0~P3
: palette number (0 ~ 15).
- 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 is a structure with the following elements:
- display coordinates of sprite.
- Character pattern number.
- Attribute
- Size
- 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.
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 |
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:
- OAM Bank (highest priority)
- Direct Pattern Mapping (#direct-pattern-mapping)
- Character Pattern on VRAM
By using OAM Bank, a different bank character pattern can be used for each OAM.
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 |
---|---|
For details on how to use example/17_clip for details.
- The scanline counter is a read-only VDP register that can identify the pixel rendering position of the VDP
- Vertical is
0x9F00
and horizontal is0x9F01
. - 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.
- BG allows you to specify
0x9F02
as X-coordinate and0x9F03
as Y-coordinate starting point. - FG:
0x9F04
with X-coordinate and0x9F05
with Y-coordinate starting point. - You can also get the current scroll position by reading
0x9F02
~0x9F05
.
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.
NOTE: Status register always reset after read.
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.
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.
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
- 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.
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. |
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
# Read current bank of ROM Bank 0
IN A, (0xB0)
# Switch ROM Bank 1 to No.17
LD A, 0x11
OUT (0xB1), A
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
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
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
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
LD BC, 0xC000 # Forwarding address
LD HL, 0x2000 # Number of bytes transferred
LD A, 0xFF # Value to be transferred
OUT (0xC2), A # Execute memset
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.)
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
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.
LD A, 123 # Specify the table element number to be sought in A
OUT (0xC6), A # A = sin(A × π ÷ 128.0)
LD A, 123 # Specify the table element number to be sought in A
OUT (0xC7), A # A = cos(A × π ÷ 128.0)
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
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)
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 (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
LD A, 0x01 # Specify BGM bank number to be played
OUT (0xE0), A # Start playing background music
LD A, 0x00 # Operation ID: Pause
OUT (0xE1), A # Interruption of background music performance.
LD A, 0x01 # Operation ID: Resume
OUT (0xE1), A # Resume playing background music.
LD A, 0x02 # Operation ID: Fadeout
OUT (0xE1), A # Fade out background music performance.
LD A, 0x01 # Specify the number of the sound effect to be played.
OUT (0xF0), A # Execute
LD A, 0x02 # Specify the number of the sound effect to be stopped.
OUT (0xF1), A # Execute
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
When selling games for VGS-Zero at comic markets (events) or by mail order, the following procedure is recommended:
- Prepare a micro SD card formatted in FAT32
- Create a new micro SD card in ./image to the root directory of the micro SD card.
- Replace game.pkg
- Delete README
- Store README.txt (text describing how to play the game)
- Store micro-SD card in case etc.
- 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.
- 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.
We hope to address this in the future.
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 |
- VGS-Zero is GPLv3 OSS: LICENSE-VGS0.txt
- The VGS-Zero distribution image includes a RaspberryPi bootloader: LICENCE.broadcom
- VGS-Zero itself includes Circle (GPLv3): LICENSE-CIRCLE.txt
- VGS-Zero itself includes SUZUKI PLAN - Z80 Emulator (MIT): LICENSE-Z80.txt
- VGS-Zero itself includes NEZplug (Free Software): LICENSE-NEZplug.txt
- VGS-Zero itself includes Modified NSFPlay (GPLv3): LICENSE-NSFPlay-alter.txt
- VGS-Zero itself includes KM6502 (Free Software): LICENSE-km6502.txt
- VGS-Zero Library for Z80 is MIT licensed OSS: LICENSE-VGS0LIB.txt
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.