Table of Contents
How to write Retro Games on the SD-8516
Introduction
Would you like to write cool retro games? Would you like them to be “really” retro? Not “fake retro”? Well, this is the guide you should follow.
Here is the cheat sheet; the numbers will be explained below.
| Era | Computer | RAM Size | Speed Settings | Graphics Settings | Sound Settings |
|---|---|---|---|---|---|
| 1985 | 8-bit computer/console | 256k | 1 MIPS | Mode 1, 2, 3 (320×200, Use INT 18h) | Int 11h |
| 1990 | 16-bit console/PC | 1mb | 10 MIPS | Mode 3 (320×200), Mode 4(256×224), use PPU sparingly | Int 11h/ASU |
| 1991 | 32-bit computer | 2mb | 40 MIPS | 640×480 + PPU | ASU |
| 1996 | N64 | 8mb | 125 MIPS | 320×240, 480×360, 640×480 + PPU | ASU |
The above modes will help you constrain the system to era-authentic specs considering this is an emulator.
What this means is, considering things like the SNES had 128k RAM, but several megabytes of ROM and on a cartridge, 1mb might be fair. And, upping the speed to 10 MIPS because it had a PPU and an ASU that ran independently; as well as co-processors included on some chips. Also consider, we are locked to a single thread for everything, including processing user input. Given extensive research and thought, the above four levels are very close to what you would need to replicate the look and feel of those eras accurately.
If you wanted to try and replicate an early console game (Intellivision, Atari 2600, ColecoVision or even a VIC-20) you are advised to drop the system speed to 0.5 MIPS and follow that system's RAM guideline + cartridge size. As a starting point, try to fit your entire program in 16k and don't use the KERNAL for anything other than the memory-mapped IO.
Limit your System Speed
You can alter the run speed of the CPU using INT 0x19, AH=$02. The number in B is the desired system speed in MIPS, divided by 100.
LDAH $02 LDB #128 ; Set system speed to 1.28 MIPS. INT 0x19
To run the system at 10,000 instructions per second, you could do:
LDAH $02 LDB #1 INT 0x19
This sets the system speed to 0.01 MIPS, or, 10,000 instructions per second.
To run the system at 12.5 or 125 mips:
LDAH $02 LDB #1250 ; Set system speed to 12.5 MIPS. INT 0x19
LDAH $02 LDB #12500 ; Set CPU to 125 MIPS INT 0x19
Numbers above 65000 are considered “unlocked”. It is expected that this will become a realistic concern in 2050 but by then I'll sure we will be using the SD-9532!
Why Limit System Speed?
Why not run in 125 MIPS mode (or unlocked) all the time? This is a good question. There are two reasons. One, if you want to write era-authentic games, what is the point of running at 100 mips when 1 MIPS is already fast enough? Some games went up against the hardware limitations of the time and were designed without frame timers. The game speed was the limit of what the computer could do. So for retro, era-authentic games, it's actually harder to code them if the system is too fast. You have to start writing timer code. And if you get lazy and start to rely on that speed, your games will not have the look and feel that era-authentic games had.
Limit your RAM usage
The system boots up with a certain amount of RAM which cannot be changed. Based on this you are responsible for limiting your own RAM usage based on what you are trying to emulate. This is a stern warning; do NOT get lazy and write unbounded structs using megabytes of RAM when you're emulating an Atari 2600! Your games will NOT have the look and feel, and you will be wasting your time.
Now, here's how the RAM is used.
- Bank 0 is free space. 64k.
- Bank 1 is reserved for the KERNAL.
- Bank 2 is reserved for the framebuffer.
- Bank 3 is reserved for audio.
Given this layout, if you are not using a graphics mode, and if you don't plan on using any KERNAL functions, you can use the majority of banks 1, 2 and 3; there are however some special memory locations in kernal space you should be aware of, such as the keyboard buffer, which are modified by the “hardware”. Still, with banks 0, 2 and 3, that's 192k of RAM to play with in text mode, or 128k in MODE 3. Seeing as how you can use BANK 0 and BANK 3 for your games, the standard 256k layout covers most games prior to the SNES era. If you want to emulate the C64/Apple ][ era, just use bank 0. It's a bit larger, but you will have essentially the same space; You can limit yourself to 32k if you really wanted to, but this just means you have to swap out to DISK for larger programs. Everyone knows this technique, so you might as well make your life easier and use the 64k. Your call.
For larger games you want more RAM but the system is not designed to boot this way. Later I will add a memory.grow function connecting to the WASM system but for now, you're stuck with 256k. It's a lot of space.
But, if you want to do Amiga/PC era stuff, even SNES level stuff, you will want to increase RAM to 1MB. Anything higher, 4MB is your safe bet, 8MB if you want lots of breathing room. But 4MB is a safe upper limit. if you are pushing more than 4MB memory usage, your game will not have an era-authentic look and feel.
Limit your use of the PPU and ASU
For some games do not use the PPU and ASU. For early consoles, don't use it. For the microcomputer era, 1.28 MIPS is fast enough to do software sprites. If you do decide to use the PPU, limit yourself to at most eight sprites, and no larger than 16×16 each.
For the NES/SNES era, you can use 64 or 128 sprites in the PPU and use the ASU at 4 to 8 channels.
For the early 32-bit PC and N64 era, you can feel free to go to SNK Neo Geo levels; 200-400 sprites. and 16 channel ASU. But if you go above this you will break the look and feel of that era.
Use Specific Graphics Modes
Graphics modes 1, 2 and 6 are for early OS/text games and bsdgames-like terminal mode games.
Graphics mode 3 is 320x200x16 and covers the standard C64/Apple ][ era. To do 160×200 just treat each byte as 2 pixels and poke the same color into both nibbles; ex color 2, use $22. Color 9, use $99. This will roughly cover the Intellivision and Atari 2600; for a 160×96 mode just write two pixels in the Y dimension at the same time, creating the illusion of 160×100. Close enough.
Graphics mode 5 is 256x224x256 and covers the SNES era. To do ColecoVision or NES just limit yourself to 16 colors here.
Graphics mode 8 is 128×128 and is a poke of fun at PICO-8, but you could use it for early console games if you like.
At some point I will do some N64 or VGA style modes; but I am working on many things at once here and will need to find the time. Maybe in June?
BONUS: Limit the ISA
Appendix 4 Instruction Set Architecture organizes every instruction in the ISA into four groups:
- Core-I
- Core-II
- Extended, and,
- CISC
If you are writing early console games, limit yourself to CORE-I opcodes.
If you are writing 80s microcomputer games, limit yourself to CORE-I and II opcodes.
The EXTENDED opcodes are mainly quality-of-life, but do include some nice indexed-addressing and auto-step loads and stores. Some of those opcodes compress 3 to 5 steps into a single opcode.
It is the CISC opcodes you must be careful with. Operations like CVTAN, CASE, SKPC and INSQUE vastly increase the power of the CPU. Including the CISC instructions will easily double the total power of the system by making certain tasks like jumptables, tokenization, and ATOI/ITOA trivial. As tempting as it can be to use these opcodes, avoid them when writing for earlier systems.
It really is important! We already have what amounts to a single-cycle MUL. The system is dangerously fast as it is!
Conclusion
If you want to write a period-accurate game, do a de-make, or just have the correct look and feel of an era-authentic retro game, you must work within the proper constraints. Not random, nonsensical constraints; but the constraints of the era.
- Use the correct graphics mode
- Limit your RAM usage
- Limit the system speed (MIPS)
- Limit your use of the PPU and ASU.
- Limit against extended and CISC level instructions on systems that didn't use them.
