a collection of tools and code (with a very presumptuous name) for SEGA Master System, Game Gear, SG-1000/SC-3000 and ColecoVision homebrew development using 'C' language (and the SDCC compiler).
- download SDCC - version 4.2.0 or newer required
- install it ("include files" and "Z80 library" are the only components required, you shouldn't need anything else)
- read its manual
- make sure that your installation works - details are at page 20 of the PDF manual
- place the
makesms(.exe),makecvmc(.exe)andassets2banks.exe(orassets2banks.pyif you're using a Python interpreter) tools from this package into your SDCCbinfolder
note: if you're on Linux or on Windows, all binaries are supplied in the Linux or Windows subfolders of each tool. If you're on a Mac, binaries are kindly provided by Carl-Dixon here. You can also compile the tools yourself from the provided sources.
- for SMS/GG: place
crt0_sms.relfrom this package in a crt0 folder in your projects root (or directly into your project folder if you prefer doing so) - for SMS: place
SMSlib.handSMSlib.libin a SMSlib folder in your projects root (or directly into your project folder if you prefer doing so) - for GG: place
SMSlib.handSMSlib_GG.libin a SMSlib folder in your projects root (or directly into your project folder if you prefer doing so) - for SG-1000/SC-3000: place
crt0_sg.relfrom this package in a crt0 folder in your projects root (or directly into your project folder if you prefer doing so) - for SG-1000/SC-3000: place
SGlib.handSGlib.libin a SGlib folder in your projects root (or directly into your project folder if you prefer doing so) - for ColecoVision: place
crt0_cv.relfrom this package in a crt0 folder in your projects root (or directly into your project folder if you prefer doing so) - for ColecoVision: place
SGlib.handSGlib_CV.libin a SGlib folder in your projects root (or directly into your project folder if you prefer doing so) - (optional) if you plan to use PSG music/SFX, place
PSGlib.handPSGlib.lib(orPSGlib_CV.libfor ColecoVision) in a PSGlib folder in your projects root (or directly into your project folder if you prefer doing so) - (optional) if you plan to use MoonBlaster modules for FM music, place
MBMlib.handMBMlib.relin a MBMlib folder in your projects root (or directly into your project folder if you prefer doing so)
- include
SMSlib.hin your sources - compile your program:
sdcc -c -mz80 --peep-file peep-rules.txt your_program.c
- link your program with
crt0_sms.relandSMSlib.lib(the SMS library):
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 crt0_sms.rel your_program.rel SMSlib.lib
note that you should put crt0_sms.rel first, and you should put the library after your code.
- build the final .sms file with the makesms utility included (the input file is the ihx generated by SDCC linker, the output file is the generated ROM). For example:
makesms your_program.ihx your_program.sms
The size of the ROM will be a multiple of 16 KiB. The utility also calculates the ROM checksum for the output file if the SEGA header has been included in your program. You can read makesms' documentation for additional command line switches.
- include
SMSlib.hin your sources - compile your program using the
TARGET_GGdefine:
sdcc -c -mz80 --peep-file peep-rules.txt -D TARGET_GG your_program.c
- link your program with
crt0_sms.relandSMSlib_GG.lib(the SMS library for GameGear):
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 crt0_sms.rel your_program.rel SMSlib_GG.lib
note that you should put crt0_sms.rel first, and you should put the library after your code.
- build the final .gg file with the makesms utility included (the input file is the ihx generated by SDCC linker, the output file is the generated ROM). For example:
makesms your_program.ihx your_program.gg
The size of the ROM will be a multiple of 16 KiB. The utility also calculates the ROM checksum for the output file if the SEGA header has been included in your program. You can read makesms' documentation for additional command line switches.
- include
SGlib.hin your sources - compile your program:
sdcc -c -mz80 your_program.c
- link your program with
crt0_sg.relandSGlib.lib(a.k.a. "the SG library"):
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 crt0_sg.rel your_program.rel SGlib.lib
note that you should put crt0_sg.rel first, and you should put SGlib.lib after your code.
- build the final .sg/.sc file with the makesms utility included (the input file is the ihx generated by SDCC linker, the output file is the generated ROM). For example:
makesms your_program.ihx your_program.sg
The size of the ROM will be a multiple of 16 KiB. You can read makesms' documentation for additional command line switches.
Software written with SGlib can be loaded to a BASIC cartridge on the SC-3000.
The BASIC LOAD command loads the program over the cassette interface to address 0x9800.
Once loaded, the program can be run with the CALL &H9800 command.
- Link with
crt0_BASIC.relinstead ofcrt0_sg.rel, and used--code-loc 0x90a0to place the code after the interrupt handler.
sdcc -o your_program.ihx -mz80 --no-std-crt0 --code-loc 0x98a0 --data-loc 0xC000 crt0_BASIC.rel your_program.rel SGlib.lib
- Convert the compiler's hex output to binary
objcopy -Iihex -Obinary your_program.ihx your_program.bin
-
Convert the binary into an SC-3000 formatted audio file using a tool such as SC-TapeWave
-
Note that the program size is limited. BASIC IIIa has 12 KiB of RAM following the load address. BASIC IIIb has 26 KiB.
- include
PSGlib.hin your sources - compile your program as explained above
- link your program with proper crt0 and libraries, adding
PSGlib.libtoo after the proper library:
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 crt0_sms.rel your_program.rel SMSlib.lib PSGlib.lib
- build the final .sms/.gg/.sg/.sc file with the makesms utility included (the input file is the ihx generated by SDCC linker, the output file is the generated ROM). For example:
makesms your_program.ihx your_program.sms
The size of the ROM will be a multiple of 16 KiB. You can read makesms' documentation for additional command line switches.
- use the assets2banks utility included. Read its documentation. It's quite powerful.
-
in your program, use the SMSlib provided macro
SMS_mapROMBank(n)(or the SGlib provided macroSG_mapROMBank(n)) to map the bank you need. Note that your code should be restrained to the first 32 KiB as the last 16 KiB will be paged out and any code there won't be accessible unless the bank is manually mapped in the address space. If you need more than 32 KiB of code, read the section titled "How to use more than 32 KiB of code in your SMS/GG/SG/SC ROM" below in this document. -
put your data into a separate .c file for each 16 KiB ROM bank starting from bank2, for example bank2.c, bank3.c etc... (you can use the assets2banks utility described above to achieve this easily) compiling each one with a different CONST segment name, I suggest using
BANK#for descriptiveness:
sdcc -c -mz80 --constseg BANK2 bank2.c
sdcc -c -mz80 --constseg BANK3 bank3.c
- compile your program:
sdcc -c -mz80 --peep-file peep-rules.txt your_program.c
- link all the objects together adding a custom parameter instructing the linker to place all your data banks at address 0x8000 + the virtual address of the bank, which is banknumber×2¹⁶ (so segment BANK2 goes at 0x28000, segment BANK3 goes at 0x38000 and so on...) Note: proper crt0 file goes always first) then all the bank#.rel files last, in ascending order:
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK2=0x28000 -Wl-b_BANK3=0x38000 crt0_sms.rel your_program.rel SMSlib.lib bank2.rel bank3.rel
- build the final .sms/.gg/.sg/.sc file with the makesms utility included (the input file is the ihx generated by SDCC linker, the output file is the generated ROM). For example:
makesms your_program.ihx your_program.sms
The size of the ROM will be a multiple of 16 KiB. You can read makesms' documentation for additional command line switches.
- include
SGlib.hin your sources - compile your program using the
TARGET_CVdefine:
sdcc -c -mz80 -D TARGET_CV your_program.c
- link your program with
crt0_cv.relandSGlib_CV.lib(a.k.a. "the SG library for ColecoVision"):
sdcc -o your_program.ihx -mz80 --no-std-crt0 --code-loc 0x8080 --data-loc 0x6000 crt0_cv.rel your_program.rel SGlib_CV.lib
note that you should put crt0_cv.rel first, and you should put SGlib_CV.lib after your code.
- build the final .col file using SDCC's
sdobjcopyfor the final step. Your input file is the ihx generated by the SDCC linker and the output file is the generated .col ROM file:
sdobjcopy --input-target=ihex --output-target=binary --pad-to 0x10000 your_program.ihx your_program.col
(you may want to to use --pad-to 0xC000 if your program and data can fit in 16 KiB, or you could use --pad-to 0xA000 if your program and data can fit in 8 KiB).
(regular ColecoVision ROMs are 32 KiB at most, see the section "How to use more than 32 KiB in your ColecoVision ROM" if you need more)
- include
PSGlib.hin your sources - compile your program as explained above
- link your program with with
crt0_cv.relandSGlib_CV.liband thePSGlib_CV.liblibrary too:
sdcc -o your_program.ihx -mz80 --no-std-crt0 --code-loc 0x8080 --data-loc 0x6000 crt0_cv.rel your_program.rel SGlib_CV.lib PSGlib_CV.lib
- build the final .col file using SDCC's
sdobjcopyfor the final step. Your input file is the ihx generated by the SDCC linker and the output file is the generated .col ROM file:
sdobjcopy --input-target=ihex --output-target=binary --pad-to 0x10000 your_program.ihx your_program.col
(you may want to to use --pad-to 0xC000 if your program and data can fit in 16 KiB, or you could use --pad-to 0xA000 if your program and data can fit in 8 KiB).
-
in your program, use the SGlib provided
SG_mapROMBank(n)macro to map the bank you need (your code should be restrained to 16 KiB as the second half of address space will be paged out) -
put your data into a separate .c file for each 16 KiB ROM bank starting from bank1, for example bank1.c, bank2.c etc... (you can use the assets2banks utility described above to achieve this easily) compiling each one with a different CONST segment name, I suggest using
BANK#for descriptiveness. Note that only 16,320 bytes (16 KiB - 64 bytes) are available in each ROM bank.
sdcc -c -mz80 --constseg BANK1 bank1.c
sdcc -c -mz80 --constseg BANK2 bank2.c
- compile your program using the
TARGET_CVdefine:
sdcc -c -mz80 -D TARGET_CV your_program.c
- link all the objects together adding a custom parameter instructing the linker to place all your data banks at address 0xC000 + the virtual address of the bank, which is banknumber×2¹⁶ (so segment BANK1 goes at 0x1C000, segment BANK2 goes at 0x2C000 and so on...) Note: proper crt0 file goes always first) then all the bank#.rel files last, in ascending order:
sdcc -o your_program.ihx -mz80 --no-std-crt0 --code-loc 0x8080 --data-loc 0x6000 -Wl-b_BANK1=0x1C000 -Wl-b_BANK2=0x2C000 crt0_cv.rel your_program.rel SGlib_CV.lib bank1.rel bank2.rel
- use the included makecvmc converter utility to create a ColecoVision MegaCart ROM. The input file is the ihx generated by SDCC linker, the output file is the generated ROM:
makecvmc your_program.ihx your_program.rom
The size of the final ROM file will be either 128, 256, 512 or 1024 KiB, as these are the only supported sizes for a ColecoVision MegaCart ROM.
SDCC 4.x supports banked code and this means that it's now possible to page in and out code in a transparent manner. To achieve this, banked code should be written in separate source files that have to get allocated in separate code banks. Upon calling a banked function the code will trigger a slot-1 bank change (using trampolines that are 'hidden' in bank 0 code) and will restore the previous bank upon returning from called function. This means that only code in bank 0 won't ever be paged out, but that means that total code won't be restricted to the 32 KiB maximum size.
You need to:
- put banked code in separate source files, marking banked functions as such using the
__bankedSDCC keyword, as in
void some_function (void) __banked {
// your code here
}
- compile each banked code source file into a specific separate code segment, for instance as in:
sdcc -c -mz80 --codeseg BANK1 banked_code_1.c
sdcc -c -mz80 --codeseg BANK2 banked_code_2.c
-
use the provided
crt0_sms.rel(orcrt0_sg.rel) as the first module in your linker call -
instruct the linker to place all the banked code at address 0x4000 + the virtual address of the bank, which is banknumber×2¹⁶ (so code segment BANK1 goes at 0x14000, code segment BANK2 goes at 0x24000 and so on...) and the compiled banked code modules in ascending order as in:
sdcc -o your_program.ihx -mz80 --no-std-crt0 --data-loc 0xC000 -Wl-b_BANK1=0x14000 -Wl-b_BANK2=0x24000 crt0_sms.rel SMSlib.lib main.rel banked_code_1.rel banked_code_2.rel
- use the
makesmstool to convert the ihx file into the sms ROM format. Usage is very simple:
makesms your_program.ihx your_program.sms
A few additional third-party libraries are available and can be used with devkitSMS:
- Raphnet's inlib - inlib is an input library for SMS supporting standard controllers, Genesis/MegaDrive controllers (3 and 6 buttons), the Light Phaser, and less common controllers such as the Paddle, the Sports Pad, and even the Mega Mouse (a mouse for megadrive) or the SEGA Graphic Board.
- Psidum's GSlib - GSlib is a general purpose 8 way scrolling engine for background, supporting 16×16 pixel metatiles (Development of this library is abandoned but I aim to fix any bug that is found. The link brings you to my forked repository that already has a few fixes).
- Joe's Banjo - a FM+PSG (YM2413+SN76489) sound driver supporting furnace tracker modules.
Once your game is done and tested, you might want to consider releasing it on a cartridge. There are a few options available at the moment:
- Raphnet's reprogrammable 4Mbit cartridge has complete SEGA Mapper support and can also come with its plastic shell. It's also available for the Game Gear.
- Retrocircuits's reprogrammable 4Mbit cartridge has complete SEGA Mapper support and can also be expanded to 8Mbit or have SRAM/FRAM added. There's also a 4Mbit cartridge available for the Game Gear and there's even a variant with SRAM.
- doragasu's FrugalMapper supports up to 4Mbit too, but the SEGA Mapper support is limited to slot-2 only which means it will work with devkitSMS programs that don't use banked code. It's a cheap solution but you have to order the printed circuit boards yourself from JLC (or a similar PCB factory) and you'll have to provide plastic shells too (you can buy new shells here or here for instance).
- the ModestMapper. This is a solution very similar to doragasu's FrugalMapper, as it's a derivate of that. It supports the SEGA mapper slot-1 & slot-2 which means it can be also used for devkitSMS programs that use banked code.
Using any of these, your ROM needs to be programmed onto each cartridge. For Raphnet's solution you can use for instance its cartridge reader/programmer and for doragasu's solution you can use its MegaWiFi programmer. Regarding the ModestMapper cartridge, either programmer should work. Retrocircuit's solution instead has its own programmer and there's a version of that that also supports the Game Gear cartridges.
Publishers like 2Minds are also a nice option, but they're currently shutting down operations. Côté Gamers released a few games too. We hope there will be other publishers soon.
Check SUPPORT.md to see how you can contribute to development.
- armixer24's Tetris4GG for the SEGA Game Gear
- badcomputer's Road Fighter, Astro Climber, Razing Core, Frontier Force, Blast Arena
- cireza's the Sword of Stone for the SEGA Game Gear
- Cyttorak's Gemitas
- dark's Akalabeth and Yawi for the SEGA SG-1000
- Digital Fluff's Arpabet Speech Synthesizer for the SEGA SG-1000
- Disjointed Studio's Weka Invaders
- Dr.Ludos' Dangerous Demolition
- Eruiz's Fridge Fury, Lunar Skirmish, Galactic Revenge, Astro Force, Bomb Jack Remake, Green Beret Remake, Crazy Pinball, Electronic Dreams, Dead Gunner, Mini MSX, Silver Valley
- Guy's Egle in Parallel Worlds, Grail of the Gods, Deathtrap Dungeon, Nyle - Lyne in SokobanLand
- haroldoop's Stalactites
- Integer Max Games' Knight Shift
- Jean Monos' Little Sokoban
- JoppyFurr's Snepzhen Solitaire, Ants
- Louis the SEGA Nerd's Monaco Master, Sub Assault
- Mojon Twins' Cheril Perils Classic, Jet Paco and Jet Puri, Che Man, Sgt. Helmet Training Day and Super Uwol for the SEGA SG-1000
- Naarshakta's Stygian Quest
- offgame's Pixner II
- old_pirate's Iron Man
- PSCD Games' Alien Cat 2
- raphnet's Capture GO, SKBN, Extreme Volleyball Infernal League, Goblin Kart Rescue
- Ricco's Where Is It?, Do The Same
- slogra's Jumping Jack'son
- SteveProXNA's Skazka, Simpsons Trivia
- TheGouldFish's Atoms
- Tuxedo Games' Alter Ego, Gotris
- undeveloper's Intergalactic Prophylactic, Land on my Base, Eggie Chuck, Primates
- x7r's Sutoroku
- xfixium's Castlevania, Ms. Pac-Man Classic
More games/demos can be found here