Reverse engineering the Sega Channel game image file format


Introduction

Sega Channel was a games-on-demand service that gave cable subscribers access to a library of around 50 Sega Genesis games per month in exchange for a monthly fee (typically $10-$15/month depending on the cable provider). It operated between June 1994 (with a nationwide rollout in December 1994) and June 1998. Cable subscribers would be given an adapter cartridge that would connect their Genesis to a cable TV line. On boot, the cartridge would search for the Sega Channel signal, then download the game menu. This process typically took around 20 seconds. The user would then pick a game and wait about a minute for it to be downloaded to the adapter's RAM. At this point, the game would function exactly the same as a retail cartridge. Turning the system off or pressing the menu button on the adapter would erase the downloaded game, but game save data was retained unless the user downloaded a different game. Besides retail games, Sega Channel offered a "Test Drives" section where users could play time or content restricted versions of games before they got a retail release. There were also a number of games that were only available via Sega Channel, although it seems that most of them were titles where either Sega or the publisher weren't confident enough in their quality to give them a physical cartridge release. Sega Channel was a modest success, peaking at around 250,000 subscribers.

photograph of a Sega Channel adapter

Sega Channel data was delivered to cable customers through a somewhat long-winded process. First, Sega Channel employees would select the game line-up and other content (game hints, manuals, news, digitized fan-art, etc.) for a given month. They would then send everything to a company called Foley Hi-Tech, who would create the game menu graphics/animations and insert all the monthly content. They ended up with a ~60MB file called a "game image", which was burnt to a CD and sent to a satellite uplink facility in Denver, Colorado. The CD would then be installed in the uplink game server computer, which would continuously transmit the game data in a loop over satellite. Cable headends all over the US would receive the satellite transmission and send it to cable subscribers. The data being sent in a continuous loop is how the service's "interactivity" was achieved at a time when cable TV providers could only transmit data to all subscribers and couldn't receive data (i.e. what game a given subscriber wants to download). When a user chose a game from the menu, their adapter was instructed to look through the Sega Channel data stream and pick out the data for the game they selected. The ~60MB game image file was transmitted at a rate of about 12Mbps using two 6Mbps carriers. Assuming that there were no signal problems, the user always got to play whatever game they picked in less than a minute (one loop of the data). The menu downloaded faster than this because additional redundant copies of it were added to the data stream to speed up downloads.

Diagram showing how Sega Channel service worked

Game Image

In November 2024, the user RisingFromRuins on the Sonic Retro forum announced that he had found a Sega Channel game image CD for September 1996 while he was going through a lot of PC equipment he had bought years earlier. He posted pictures of the CD and uploaded a copy of the game image file on the disc. I thought it would be a fun project to see if I could extract the data from the game image file to see if there were any exclusive or prototype games on there. It's always neat to see games that nobody's been able to play for over 25 years.

photograph of a Sega Channel game image CD case photograph of a Sega Channel game image CD

Process

My first idea was to check out the image file's contents in a hex editor. Genesis games all have a standardized ASCII header, and I figured the game hints/downloadable manuals would be readable as well. Unfortunately, when I scrolled through the image file, there wasn't anything readable. My best guess was that the image file was either scrambled or encrypted.

screenshot of a portion of the image file being displayed in a hex editor

At this point, I hit a lucky break. In 2017, someone with the username tdijital had uploaded a backup CD from Foley Hi-Tech (company I mentioned earlier that made the Sega Channel menus) containing Sega Channel development materials. People had previously gone over some of the CD's contents and found some interesting stuff, including contest versions of Primal Rage, a couple quiz games from the Japanese version of Sega Channel, and standalone menu demo ROMs for December 1994 - January 1996 that could be run in an emulator and acted as time capsules for what was on the service that month. However, as far as I was aware, nobody had looked at any of the development tooling on the disc. My point of view was that if I wanted to extract the data from the game image file, it would be easier to reverse engineer the tooling that created the game image than to reverse engineer the Genesis-side downloading code and hope that the image file remained mostly intact during the data transmission process.

After a bit of trial and error, I figured out how the image files were created. First, developers would add all the games, descriptions, news text, art, music, etc. using a program called MENUMAKR. They'd end up with a menu binary file and a script file (misleadingly named MENUSPIN.BAT despite not being a batch file) containing the ROM file paths, data offsets, how many copies of the ROM to include, and other metadata for each game.

screenshot of MENUMAKR program

Next, they'd run a program written by Scientific Atlanta (a cable equipment company that Sega partnered with to create the Sega Channel broadcast equipment and cartridge adapter) called PKSPREAD. This would validate the contents of the MENUSPIN.BAT file and output a binary file called PMAP.DAT, which contained instructions on how to split up and process the menu and game data for transmission.

screenshot of PKSPREAD program

Finally, they'd run another program written by Scientific Atlanta called NSF, which would use the PMAP.DAT file to encode all the input files and create the game image file. I decided that if I wanted to decode the image file, this was the program I should focus on.

screenshot of NSF program

At this point, I hit another lucky break. I found that NSF.EXE had been compiled in debug mode, with optimizations turned off and with symbols embedded into the EXE. This meant that it would be easy to reverse engineer. Unfortunately, IDA Pro didn't automatically pick up the debug symbols from the executable, so I had to open NSF in Turbo Debugger (it was compiled with Borland C++ 4.1) and manually copy them over. Fortunately, the program was pretty small so this didn't take too long.

screenshot of portion of NSF code in Turbo Debugger screenshot of portion of NSF code in IDA

I could have gone straight to writing a decoder program here, but I thought it would be a better idea to first write an equivalent program to NSF.EXE. That way, if I was able to make a byte-for-byte identical image file to one created by the DOS NSF.EXE utility, I knew I had the algorithm figured out correctly. I created a test game image file (what the above screenshots of PKSPREAD and NSF show) and set about trying to match it. It took me a day of work and another couple evenings of debugging, but I wrote an equivalent C program to NSF.EXE and got the output to match. My basic process was I had IDA open on one monitor and Visual Studio open on the other, and I tried to match the assembly as closely as possible. This led to a couple interesting insights. Whoever wrote NSF was likely a novice C programmer. They also spent considerable effort on making everything 1-indexed rather than 0-indexed (maybe they were a Pascal fan?). Note that I made no effort to try to get the compiled binary to match the original. In fact, it likely won't even compile as a C file under Borland C++ 4, as I used C99 declarations and stdint.h types everywhere.

Simplified overview of what NSF does (click to expand)
  1. The GetData function pulls information such as what file to open for a given packet, where to seek into the file for the packet, and Sega Channel specific metadata (file ID, how long the game should be playable for if it's a time-limited demo, etc.) from the PMAP.DAT file. It then loads a 246-byte chunk of data from the data file.
  2. The LoadFrame function adds a header to the start of the data packet and reverses all the data bytes (not sure if this is some data transmission thing, or if it was just to obfuscate the packet contents). It also intersperses BCH error-correcting codes and parity bits throughout the game data. After this, 288 bytes are now used to hold the 246 bytes of data. Here's what the header structure looks like: (all multi-bit fields are in reverse bit order):
    Bit # (0-indexed) Bit Length Item Description
    0 27 Unknown Not added by NSF, maybe added at transmission by the server?
    27 2 Padding Always 0.
    29 1 GameTimeSync 1 when the GameTimeBit field contains bit 15 of the game time-out value.
    30 1 GameTimeBit Contains one bit of the game time-out value (how long to allow the game to be played in 10-second intervals), clocked out for a given file in reverse bit order (highest bit first).
    31 7 ServiceID This is usually 1. May have something to do with Express Games (new titles that had to be individually ordered from a cable operator for an additional fee).
    38 14 FileID Uniquely identifies each file in the game image. The menu is always file 0.
    52 15 Address Where in RAM the adapter should download the file to.
    67 16 HeaderCRC 16-bit CRC of bits 27-66 of the header.
    83 56 Header Copy Copy of bits 27-82 of the header.
  3. The InterLeave function splits the packet into 450-bit chunks and scrambles the bits around for each chunk. I think this has to have been done to obfuscate the data stream, as I can't think of a practical reason for this.
  4. The above steps are repeated for another 9 packets.
  5. All 10 packets are bundled up into a 2880 byte frame, and the data is woven together such that the first two bytes are from packet 0, the next two are from packet 1, and so on. The frame is then written to disk.
  6. This process repeats until the entire image file has been created.

Once I figured out how NSF works, it was fairly easy to write a decoder program that would undo all these steps in reverse and spit out a bunch of individual data files. However, the data my decoder program output still wasn't valid Genesis ROM data:

screenshot of a game from an image file compared to a regular ROM

Thankfully, this was just because the game data was compressed before transmission. The tool used to compress ROMS was in the Foley Hi-Tech CD (GAMEEDIT.EXE) but I didn't have to reverse engineer it because a GitHub user named Octocontrabass had already done so. I used his/her "unsa" tool to decompress all the .SA files into standard ROM files.

Findings

The most notable games from the image file are the two exclusive games that were broadcast in September 1996, Chessmaster and Klondike. Chessmaster is a chess game that was available on many platforms in the 90s (but not Genesis) and Klondike is a solitaire game commissioned by Sega for Sega Channel and programmed by David Crane of Pitfall fame.

Chessmaster title screen Klondike title screen

Here's a categorized full list of all the games from the image file (list by ICEknight):

Sega Channel September 1996 game list (click to expand)

Exclusives

New Builds

Known Dumps with Different Padding

Known Dumps with Watermarks Added

Match Known Dumps

After I posted my findings, Black Squirrel on Sonic Retro found that it was possible to get the September 1996 menu running in an emulator by copying bytes 0-0x1003FF from one of the Sega Channel demo cartridge ROMs and appending the menu data from the game image to the end. Obviously the download functionality doesn't work, but it's still fun to look around in the menu.

Sega Channel September 1996 menu screenshot

The final bit of content from the image file was the game instructions ROM. It looked like a normal Genesis ROM file, but when I tried to run it in an emulator I just got a black screen. The problem here turned out to be that the ROM was linked with a base address of 0x100000 rather than 0 like a normal cartridge. It seems like it was meant to be run directly out of the Sega Channel adapter's memory without it getting mapped to the normal cartridge address space. My best guess is this had something to do with the functionality for jumping into the manual for a specific game from the game menu. I got it working in an emulator by adding zeroes after the header until the code lined up correctly with the vectors in the header. When it's started like this, at boot you see a menu intended for developers with all the internal names for each game. At this point, all of the content from the game image file was now able to be run in an emulator.

Sega Channel September 1996 manual index screenshot Sega Channel September 1996 manual screenshot

Conclusion

I have to thank Tdijital for releasing the Sega Channel development backup CD, Octocontrabass for reverse engineeering the .SA compression format, and whoever at Scientific Atlanta compiled NSF.EXE in debug mode. This project would have been much harder without all of their assistance. Most of all, I have to thank RisingFromRuins for releasing the game image file. I hope if anyone else has a Sega Channel game image disc, they follow his example.

Downloads


Back