From the NES to the PC Engine!
So, after completing Aspect Star “N” for the NES, I went back to my JavaScript dungeon and continued to work on my games there. But the sweet sound of retro homebrew has called me again, and this time I’ve ended up in the world of the TurboGrafx-16, called the PC Engine by its friends, assuming its friends live in Japan (or France, apparently). Why did I betray Nintendo like this? Let’s take a technical look at the system.
The new project?!
Not going to go into too much detail on the new project. That’s because it’s just barely started; it’s going to be a sequel to Space Ava. If you want updates on that, check out my Twitter.
Back when I did my post on coding for the NES, it kind of combined both Aspect Star-specific things and technical details about the NES. Instead, I’m going to do two things differently on this project:
- I’m going to write the technical blogpost first
- I’m going to write it before I’ve actually finished the project
The second means that all my nice assumptions will be laid out publicly, so when the inevitable mistake or misunderstanding bites me, I will have to admit to it. It might be interesting for me rereading this blog a few years down the line. I mean, it might be interesting for other readers too, if they existed
Let’s talk about the NES some more
The first thing that appealed to me about the PC Engine is that technically, it’s a lot like the NES, which I was already familiar with. But it’s not quite like the NES as I knew it. As a quick summary, the NES expects cartridges with 32KB of program ROM, and 8KB of character ROM, which is on its own bus.
The PC Engine was developed by Hudson Soft, who were very familiar wit the NES. Since it was released in 1987, and the chipset was unsuccessfully pitched to Nintendo before it was developed into a console with NEC, we can imagine the idea may have started around 1985. What did the “state of the art” of NES games look like in 1985?
In America, the NES had just been released, but in Japan, it had been out since 1983. Pure NROM games, like Aspect Star “N” were becoming less common as developers wanted more space, and more flexibility. They got that by putting hardware in the cartridges. (This isn’t to say that NROM was dead; Super Mario Bros., probably the biggest hit of 1985, was one!)
This circuitboard may not be that different to you than the one I used in the making of Aspect Star “N” cartridges. But look closer at the board and there are some key differences.
The lockout chip is the same as any NES game, so no need to worry about that. But the rest has some key differences.
- 8KB SRAM - Instead of the 8KB of CHR-ROM, there are 8KB of static RAM. (SRAM, or static RAM, simply means that the RAM only needs power to maintain its state, rather than also a refresh circuit) This setup, called “CHR-RAM”, means that the contents of the video memory can be changed on the fly, rather than being set in stone at the time the ROM chip is burned. This also means that to display any graphics, the game program will need to copy the graphics from somewhere else (the program ROM) into RAM. From the perspective of the PPU (the NES’ graphics chip, the Picture Processing Unit), it can read RAM just as easily as ROM.
- 128KB ROM - Compared to Aspect Star “N”, that’s a huge amount of ROM! But of course it is; it needs to handle all of the graphics that will be copied into static RAM. But remember, the NES console can only see 32KB at a time. Essentially, the CPU only has a 32KB “window” it can see data from the program ROM in. So what’s the point of having 128KB?
- Discrete switching logic - This is what the point is. How these are wired depends on the particular board, and in cartridges using the MMC series of chips, aren’t discrete logic chips at all. But in any case, what these allow the cartridge to do is change out what part of the ROM is being seen at any given time through the 32KB window. Specifically, this particular layout, called UNROM, gives a 16KB base program that sits at the bottom of memory, and the rest of the 128KB ROM is divided into 16KB “banks” which can be switched into the remaining 16KB of the window. This is called “bank-switching”.
Now, the astute among you might note that Rush ‘n’ Attack, our guinea pig game here, started out on the Famicom Disk System. And that’s true; the Famicom Disk System, though, is outside the scope of this discussion, except to note that it also included CHR-RAM, and also included PRG-RAM, since code can’t run directly from floppy disks. Remember that.
So, now that we know what a “cutting-edge” NES game looked like in 1985, we can now understand better some of the decisions that led to the PC Engine’s design.
It’s worth noting that this also explains what the architecture of an NES followup to Aspect Star “N” would’ve looked like; I was considering switching to UNROM to get more space and to play with character RAM. However, at the moment I don’t have any plans for that.
The TurboGrafx-16 / PC Engine
Confession: I don’t own a TurboGrafx-16 or PC Engine. The original model, at least. What I own are two later models; a Turbo Duo that won’t spin up discs, and the console I use most of the time, an RGB and region-modded PC Engine Duo R.
We’ll get into the CD system later in this post, so that won’t be covered here; just the standard base system. And in that base system, the PC Engine is a lot like the NES. I’ll try to go into some detail here, but note that I’ll focus on comparisons first.
Controllers
This one’s easy. Both have two face buttons, a D-pad, and two small buttons in the middle. Sure, the buttons have different names (except for “Select”, which is eternal), and Nintendo’s cross-shaped D-pad patent was still valid at the time, but overall the family resemblance is undeniable. The turbo switches, which were very common on this console, are part of the controller. (In fact, the first PC Engine controller in Japan didn’t have them, and so the PC Engine Mini also doesn’t)
They also work the same way internally, using a shift register to minimize the number of wires needed. It’s true that the PC Engine had 6-button controllers later in its life, but they were only used for Street Fighter 2’ and a small number of other games, and in any case, you could have done the same thing on the NES. Of course, no games exist that would take advantage of it if you did. (Might be a fun thing to mess around with, though)
Graphics
Background graphics on the NES are made up of the “nametables”, which were described more in detail in my last blog post. These are essentially sets of 8x8 tile indices, along with palette blocks. Sitting on top of them are 64 sprites which are either 8x8, or 8x16 pixels, and use their own block of CHR. (Which, as noted above, can be ROM or RAM, but must be provided by the cartridge)
The graphics chip on the TurboGrafx-16 is the HuC6270 “Video Display Controller”, or VDC. This is backed by 64kB of video RAM. Like UNROM, data needs to be copied from the program to the video RAM. No prepopulated CHR-ROM here.
At the top of RAM is the Background Attribute Table (BAT), which is similar to the nametables in that it maps 8x8 tiles in a grid, but is more flexible, since the size can be adjusted to free up RAM for other uses if needed. Additionally, each 8x8 tile can have its own palette index of 15 colors (and 1 for the background, which is shared), with 16 background and 16 sprite palettes.
The HuC6270 is an entirely 16-bit beast, and also has 64 sprites, which can range in size from 16x16 up to 32x64. (These don’t live in the main VRAM, but in their own dedicated RAM called the “Sprite Attribute Table”, or SATB) These giant, colorful sprites were probably the biggest advantage the PC Engine had over its life. Unlike the NES, which was limited to an odd set of colors, PC Engine palettes used 9-bit RGB and were much more flexible. (Palettes on the PC Engine are technically handled by the CPU and the “Video Color Encoder”, the HuC6260, and are never seen by the VDC)
And that’s why TurboGrafx-16 had the 16 in its name. Because as we’ll see, nothing else is 16-bit. They did the math.
Work RAM
The NES has a meager 2KB of “work RAM”, which is the RAM the program has accessible for storing game variables and the like. Since the program mostly runs directly from ROM, this small amount of RAM isn’t as bad as it sounds. (Cartridges could add a little bit more RAM, within the window they were provided. By adding more RAM, along with a battery, we also got saved games)
The PC Engine is also paltry with the work RAM, upping it to 8KB. By comparison, this is the same amount of work RAM the Sega Master System had. (Though the Sega Master System had much less VRAM) Much like the NES, though, you pretty much never need to run your code from RAM if you’re a HuCard game.
CPU
The NES and Famicom use the Ricoh 2A03 CPU running at 1.79 MHz. This is a clone of the popular MOS 6502 CPU, with the patented binary-coded decimal mode disabled. Additionally, the sound hardware of the system is included on the CPU, providing two square waves, one triangle wave, and one noise channel.
As a quick refresher, the 6502 is an aggressively 8-bit processor. While its competitor the Zilog Z80 can do some 16-bit math by combining registers, the 6502 can only do 8-bit math, period. It does have a 16-bit data bus (giving 64KB of addressable space). It also only has one general-purpose register A (for Accumulator), as well as two index registers, X and Y.
The PC Engine CPU, the HuC6280, is also based off of the MOS 6502 core. (Specifically, it’s based off of the later CMOS 65C02, which added some neat new opcodes, but didn’t change anything fundamental) I think it even has binary-coded decimal this time. (Pachi-Com programmer, rejoice) Therefore, internally it also sees a flat 64KB address space, and can only do 8-bit math. It can run as fast a 7MHz though, which is blazing fast for a 6502.
How do they manage this? The entire 64KB address set is divided into 8KB “pages” that function just like the switchable memory bank in UNROM, and since the CPU is a custom Hudson Soft chip, they added new commands to the assembly language to switch these internal registers. To the outside world, therefore, the HuC6280 has 21 address lines, giving it access to 2MB of memory at a time. Like the NES design, this address space includes not only ROM and RAM, but also memory-mapped IO, and registers for audio. The PC Engine’s built-in sound processor is also included on the processor die, just like the NES.
Putting it all together
Since it includes all the cartridge hardware onboard the system, the games for the TurboGrafx-16 came on ultra-thin cards known as HuCards. (For Hudson Cards). In America they called them TurboChips because they were all-in on being Turbo. Most HuCard are basically just a program ROM chip, though a few, such as Street Fighter 2’, did include on-cartridge hardware. Street Fighter 2’ included a memory mapper to access an even larger amount of ROM space, making it one of the most impressive cartridge games on the console.
Hopefully it’s clear now why I see the TurboGrafx-16 as essentially an overclocked NES with a built-in UNROM mapper, and a souped up graphics chip. Since I was considering an UNROM game, it definitely seemed like a promising alternative.
Oh, and it plays CDs
The TurboGrafx-16 had something else that I wanted to try my hand at: it was the first console to play games on CD-ROM, using the CD-ROM2 system. (Pronounced “CD ROM ROM” in Japan, and “CD ROM” in America, where we’re boring)
The CD-ROM format opens a lot of interesting possibilities. Manufacturing CDs is something that still happens, which means unlike my messy hand-soldered buggy Aspect Star “N” cartridges, I could make something that I might not be ashamed to actually sell. And even if I don’t reach that point, 650MB on an 8-bit console is nothing to sneeze at, and the CD-ROM brings with it a host of new features.
ADPCM sound
The CD-ROM also adds ADPCM (adaptive differential pulse-code modulation) for sound effects. The exact details of how it works aren’t important (read: I don’t know the details myself) but it can provide high-quality (up to a 32kHz sampling rate) output. Only 64kB of RAM exist for the ADPCM chip, but more data can be loaded from the CD at any time. (Taking into account that the CD is not fast and there will be a noticeable pause)
CD-quality audio
Have you ever put a video game CD in a CD audio player, ignoring the warning telling you not to? Early 90’s systems like this and the Sega CD will usually have all the games audio as CD tracks. This basically means the sky is the limit for music quality.
Limited program RAM
Wait, that one doesn’t sound so good.
So, this is where we run into a hiccup. As noted above, the PC Engine only has 8kB of RAM accessible to the CPU at a time. For a game running from a HuCard, that’s not necessarily a huge problem. But code can’t run from a CD; even by the standards of a 1MHz processor, they’re ungodly slow. The code needs to be copied from the CD into RAM first.
The first release, the CD-ROM2 (also known as the TurboGrafx-CD in the US, until later where they decided to call it the CD-ROM2 after all, because NEC USA and Turbo Technologies had a hard time), provided only 64kB of work RAM.
What this means is that at any given time, only 64kB of code and data from the CD is accessible to the CPU. And remember, loading more data is slow. The user will notice, whereas bank-switching is almost instant. (And you still need to bankswitch anyway)
This really makes games like Ys I & II even more impressive. This is a pretty painful limitation, caused by the high expense of RAM in the 1980s.
As RAM prices went down, NEC made two upgrades:
- The Super CD-ROM2 System - This simply upped the program RAM to 256kB. This is mapped in the same address space, all accessible to the CPU. You can identify these games because they require the “Super System Card”.
- The Arcade CD-ROM2 System - This is an interesting one; it provides a massive 2MB of RAM on top of the Super CD-ROM2’s 256kB, but the 2MB aren’t accessible directly to the CPU. Instead, it has narrow windows; the design is instead to load large amounts of data from the CD up-front, and then take advantage of the faster loading of data from RAM. This allowed for some pretty good Neo Geo ports.
In the latter part of the console’s life (say, from 1992 or 1993 onwards), nearly all releases were on one of these two formats, mostly on the Super one. In fact, all the “Duo” systems, including my Duo-R, come with the 256kB needed for Super format games built-in.
Plan of Attack
So, I decided I wanted to make a TurboGrafx-CD game. Or a CD-ROM2 game. Or a Super or Arcade CD-ROM2 game, I hadn’t decided yet. But one other thing I wanted to do was to try using a higher-level language. 6502 assembly is one of the easiest variants to pick up, but bit-twiddling CD registers didn’t sound like much fun.
Enter HuC. It’s a C compiler that runs on an 8-bit CPU. Unlike the more well-known cc65, it’s focused solely for the PC Engine, and is less dedicated to reimplementing standard C. Instead, it uses the “Small C” dialect. It’s an open source project that now has a number of forks out there. It also makes it easy to add inline ASM blocks, though I haven’t used that feature yet.
With the decision made to use HuC, any hope of supporting the 64kB CD-ROM2 System went out the window. It’s a good compiler, but higher-level languages are just less efficient and eat up more space. Since I didn’t plan on creating enough graphics to need the Arcade space, I decided to target the Super CD-ROM2 system. (Remember, always make your project scope achievable) I imagine anyone who plays PC Engine CD games these days has access to it.
It’s worth noting that HuC makes things easier, but there’s still a pretty steep learning curve. There are a few basic tutorials, but generally I had to dig into the examples included with HuC, which are themselves buggy and occasionally use compiler features that don’t actually work (for example, the MML music). So this isn’t as simple as simply picking up GCC. HuC in general is more oriented towards HuCard, though the CD features it does have are invaluable.
One thing that I’ve had to build a lot of tooling on my own is for graphics. A few years ago, I coded my own editor for paletted graphics. I don’t necessarily recommend anyone else use it, but I’m very comfortable with it and wanted to use it here. Ideally, I wanted to use it directly; HuC can convert PNG and PCX files to the PC Engine’s internal formats, but I found it limiting, and also a poor fit for the CD, where you want to keep image data separate from your code overlay.
To give an example of a challenge I didn’t expect to run into: the background tiles (called “CG”, for character generator) and the sprite tiles don’t use the same format in memory! This is a pretty big difference from the NES, which in 8x16 sprite mode can use any background tile as a sprite, though not vice-versa. This has made some of the conversion code a bit complicated, but it’s workable. (And since it’s done at compile time, I can just use Python)
Right now the code isn’t uploaded anywhere; however, much like how Aspect Star “N” has had its code released, I’m sure I’ll do the same for this. Watch this space!
Ava you can't have had enough of this already pic.twitter.com/xQZzl72lyy
— Nicole Express (@nicole_express) June 26, 2020