User Tools

Site Tools


sd:how_to_write_retro_games_on_the_sd-8516

This is an old revision of the document!


How to Write Retro Games on the SD-8516

Introduction

Retro game enthusiasts know that the key to the retro games experience is the constraints that programmers had to work around to write games on older hardware. As they say, an animal is most dangerous when cornered; and it is precisely when we are restrained by hardware can we realize our vision in the most creative way possible.

Each system has it's fingerprint; From the 128 bytes of RAM on the Atari 2600 to the register pressure of the 6502, to the superscalar sprites of a Sega System 32; it is the particular set of restraints that hardware places upon us that most strongly evokes the feel of retro gaming. These are not arbitrary restraints like “128×128 graphics” or “32 colors”, but they had real meaning, deriving from the hardware of the time.

This guide explains how to constrain the SD-8516 to era-authentic specs. Now your games will not merely be awesome – they will be awesome and they will look and feel exactly like in your vision, in your dream.

The cheat sheet:

Era Computer RAM Speed Graphics Sound
1985 8-bit computer/console 256k 1 MIPS Mode 1, 2, 3 (320×200, INT 18h) INT 11h
1990 16-bit console/PC 1MB 8 MIPS Mode 3, Mode 4 (256×224), PPU sparingly INT 11h / ASU
1991 32-bit computer 2MB 32 MIPS 640×480 + PPU ASU
1996 N64 8MB 125 MIPS 320×240, 480×360, 640×480 + PPU ASU

Early Consoles

For pre-1982 hardware (Atari 2600, ColecoVision, Intellivision, VIC-20), drop the speed to 0.3 MIPS and follow that system's RAM and cartridge budget. Use only CORE-I and CORE-II opcodes, and only use the KERNAL for memory-mapped I/O. Don't use the PPU or the APU.

C64, Apple ][, NES and SNES

These are all based around a 6502 and 64k to 128k RAM. But the big issue is the ability to package games on cartridge. The Apple ][ didn't have carts but was a higher end machine in other ways. For everything else, you need to increase the RAM to match the cartridge.

The reasoning: the SNES had 128k RAM but several megabytes of cartridge ROM, so 1MB is a fair budget for period-accurate games – depending on the cart. Games like Chrono Triger came on 4mb cartridges, so if you have to load in from disk and do extra processing, the extra MIPS will help with that, but 1mb should be enough to port a game like Chrono Trigger. On the other hand, games like Street Fighter Alpha II really needed the fast RAM access. They even came with special co-processor chips to stream data in as fast as possible. For games like this you might even want to bump the ram to 2mb or 3mb. It's in cases like this that the 8 MIPS will really pull it's weight. But for most SNES titles, 5 mips and 1mb ram will be more than enough.

The 8 MIPS rate will also account for the PPU and ASU running in parallel on real hardware; the SD-8516 emulates everything on a single thread, including user input, so the CPU has to work harder to keep things smooth.

Amiga/PC Gaming to N64

The four tiers above are calibrated to reproduce the look and feel of their eras as closely as a single-threaded emulator allows. The logic for the post-SNES era is the same. Give yourself about 50% breathing room in terms of CPU speed and RAM, accounting for all extras like a graphics chip, ROM space, and so on.

Where you will start to run into trouble is in 3d emulation; games like Doom, Quake, and Ocarina of Time. Whereas a ~50 MIPS 486 or Pentium could run Doom at 30fps, you would need at least 90 MIPS to run it on the SD-8516; there is simply no 3d emulation, you would need to do it in software.

The N64 is the theoretical upper limit; and then, only if 3d acceleration was enabled. I may add something to enable “a decent port” of a game like Ocarina of Time, but that really would be the theoretical max. In my opinion, some 3d games are good but most are not. This machine is intended for the pre-3d acceleration era. The N64, much like the PS1, was a polygon machine. You will notice, all the extra RAM and CPU went towards 3d acceleration, not game depth. Case in point, Ocarina of Time was not a significantly larger game than “A Link to the Past”. The SNES Zelda had more dungeons; the N64 had longer dungeons, and was a little larger; but not what you would expect from a machine literally 100 times as powerful as a SNES. A game like GTA 3, Tomb Raider or Ocarina of Time would be the theoretical upper limit for this system, and not for quite some time.

For 2d/2.5d however, the SD-8516 has everything you could ask for.

Limit System Speed

The first thing you can consider is limiting the system speed (or increasing it) to match your era.

INT $19, AH=$02 sets the CPU rate. B holds the desired speed in MIPS × 100.

  LDAH $02
  LDB #128         ; 1.28 MIPS
  INT $19
  LDAH $02
  LDB #1           ; 0.01 MIPS = 10,000 instructions/sec
  INT $19
  LDAH $02
  LDB #1250        ; 12.5 MIPS
  INT $19
  LDAH $02
  LDB #12500       ; 125 MIPS
  INT $19

Values above 65000 are “unlocked.” This will probably matter around 2050, by which point we'll be on the SD-9532.

Practical Considerations

If you want to write an Elite clone, you have to do it in assembly. But if you increase the system speed to 10-20 MIPS, suddenly you can write one in BASIC (at 15-20fps, maybe, just like the original!) as now you can do over 1000 DRAWLINE commands per frame. The problem is, you're running the game in BASIC. If you have enough RAM, you can do it. (Note: I will add MEMCOPY and MEMLOAD/MEMSAVE commands later, enabling hot-loading things like game data). But at a certain point, you will lose the feel of the original game.

If things become too easy, the goalposts are lost.

Another example is Ultima 4 and 5. These games had a world map that was 256×256 wide. That means your location fit in an 8 byte register or memory location. Ultima 6, designed for 16 bit systems, had a map that was 1024×1024. Notably, the full game could not be ported to the C64. If you allow yourself to use more RAM and CPU speed to fit something into an era where it does not belong, it will not feel authentic. You must be realistic with your constraints.

I think, it is acceptable to increase system speed by 2 to 5 times to get a game to run in BASIC. But if you are going to go 10x faster just to get a game running in BASIC, the question becomes, do you really understand the constraints of the system? Games written in BASIC on a C64 had a certain feel that games written in assembly didn't have. If you are doing a pure ELITE clone in BASIC, sure, why not, as long as it is a faithful clone. But if you're writing a new game, and you are increasing system speed and RAM just to get it done in BASIC, you are probably making a mistake.

Conclusions over limiting speed

Many original games had no frame timer because the hardware was the timer. They ran as fast as the system could go, and that was the gameplay speed. Writing under that specific constraint produces a specific feel. Games feel platform-authentic because you feel that same heartbeat. That's part of the secret magic retro sauce. Messing with this and upping system speed destroys this feeling. When games run too fast, we as programmers tend to lean on speed instead of writing tight code. Era-authentic games came from era-authentic constraints.

Run at 0.5 MIPS with 64k RAM and the constraints will write themselves.

Limit RAM

The system boots with 4 banks of 64k each (256k total) laid out as:

  • Bank 0: free space (64k)
  • Bank 1: KERNAL
  • Bank 2: framebuffer
  • Bank 3: audio

If you don't use a graphics mode and don't call any KERNAL functions, you can reclaim most of banks 1, 2, and 3, though a few KERNAL-space addresses (the keyboard buffer, for example) are written by hardware regardless. Realistic budgets:

  • Text mode without touching KERNAL: 192k usable across banks 0, 2, and 3.
  • Mode 3 (graphics): 128k across banks 0 and 3, and 32k free in bank 2.
  • C64 / Apple ][ feel: just use bank 0. 64k is plenty.
  • Older consoles/VIC-20 (4k-32k programs): Stick to the hardware + cartridge limitations.

For Amiga/PC or SNES-era games, request more RAM. 640k to 1MB is appropriate for Amiga 500/SNES-tier, and 4MB is a safe upper limit for larger machines. However, above 4MB and you are leaving the comfortable constraints of retro gaming behind. By 8mb you will be looking for 3d graphics acceleration; the system is not designed to support that yet. What are you going to do with all that RAM? :)

How to Add RAM

INT $19, AH=$05 grows system RAM. B holds the desired total bank count.

  LDAH $05
  LDB #16          ; grow to 16 banks (1MB)
  INT $19

RAM can grow up to 256 banks (16MB, the 24-bit address ceiling). It cannot shrink. Request only what you need. A BERZERK clone that runs in 512k RAM will look and feel vastly different than an actual Atari 2600 game.

Limit PPU and ASU Use

For early consoles, don't use either. At 1.28 MIPS, software sprites are fast enough for the microcomputer era; if you do use the PPU there, cap at 8 sprites of 16×16 or smaller.

For NES/SNES-era games: 64 max sprites, (or 128 for SNES. ASU at 4–8 channels. You very rarely this many. Super Mario Bros. and Super Mario World would typically use 20-30 sprites at a time, going over 40 only in very rare situations. Flicker was more due to sprite-per-scanline limitations that don't exist here. Limiting yourself to 20-40 sprites is very NES/SNES authentic. Even R-Type III rarely had more than 80 sprites on the screen at once.

Some games, notably Contra III, Gradius III, would push the 128 sprite limit. But those games are known for composite sprites, busy scenes, lots of bullets flying around.

For early 32-bit and N64-era games; the Sega X-board (Outrun, Afterburner) and SNK Neo Geo could do over 300 sprites per frame. For sample playback, 16 channels is probably going to be your limit. Beyond this and you have left the era.

Choose the Right Graphics Mode

  • Modes 1, 2, 6 for text. Use for early OS-style and bsdgames-style terminal games.
  • Mode 3 (320×200×16) — C64 / Apple ][ era. For 160×200, write two pixels per byte by poking the same nibble into both halves (color 2 = $22, color 9 = $99). For 160×100, write each pair of Y rows together. Close enough for Atari 2600 and Intellivision.
  • Mode 4 (256×224×256) is the SNES era. For ColecoVision or NES feel, restrict yourself to 16 colors.
  • Mode 8 (128×128) – a Pico-8 nod. Also workable for early-console-style games.

VGA- and N64-style modes are on the roadmap. These may include the following modes:

  • 320x240x256
  • 480x360x256
  • 640x480x16 and x256
  • Beyond these modes I am not sure the system will be able to keep up.

Bonus: Limit the ISA

Appendix 4 Instruction Set Architecture groups every instruction into four tiers:

  • Core-I
  • Core-II
  • Extended
  • CISC

For early console games, try to use Core-I instructions only. For 80s microcomputer games, Core-I and Core-II should form the base. Extended adds quality-of-life such as per-flag set commands, indexed addressing, auto-stepping loads and stores. You will mainly find this on more expensive and powerful processors like a 680×0 or a Z80. Not needed for earlier games.

CISC is the dangerous tier. CVTAN, CASE, SKPC, INSQUE and friends roughly double the system's effective power: jump tables, tokenization, and ATOI/ITOA become trivial. They're tempting. Avoid them on systems that didn't have anything like them. The SD-8516 already has effectively single-cycle MUL — it's already dangerously fast for retro work without piling more wood on the fire.

Conclusion

To produce a period-accurate game, a de-make, or anything with the genuine feel of its era, work inside the era's constraints, not arbitrary ones, the real ones:

  • The right graphics mode
  • The right RAM budget
  • The right CPU speed
  • The right level of PPU and ASU use
  • The right ISA tier

If you constrain it, the era will come.-Field of Dreams

sd/how_to_write_retro_games_on_the_sd-8516.1778069799.txt.gz · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki