https://www.infochunk.com/schannel/index.html
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 # Bit Item Description
(0-indexed) Length
0 27 Unknown Not added by NSF, maybe added at
transmission by the server?
27 2 Padding Always 0.
1 when the GameTimeBit field
29 1 GameTimeSync contains bit 15 of the game
time-out value.
Contains one bit of the game
time-out value (how long to allow
30 1 GameTimeBit the game to be played in
10-second intervals), clocked out
for a given file in reverse bit
order (highest bit first).
This is usually 1. May have
something to do with Express
31 7 ServiceID Games (new titles that had to be
individually ordered from a cable
operator for an additional fee).
Uniquely identifies each file in
38 14 FileID 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
* Chessmaster, The
* Klondike
* Olympic Summer Games - Test Drive
* Sega Channel Game Guide
New Builds
* Bugs Bunny in Double Trouble
* OutRunners
* Super Volleyball
* World Series Baseball '96
Known Dumps with Different Padding
* Flashback - The Quest for Identity (USA) (En,Fr)
* Phantasy Star II (USA, Europe) (Rev A)
* Punisher, The (USA)
Known Dumps with Watermarks Added
* Alex Kidd in the Enchanted Castle (USA)
* Berenstain Bears' Camping Adventure, The (USA)
* Ecco - The Tides of Time (USA)
* Richard Scarry's Busytown (USA)
* Sonic & Knuckles (World)
* Strider (USA, Europe)
* World Series Baseball (USA)
Match Known Dumps
* Aaahh!!! Real Monsters (USA)
* Arcus Odyssey (USA)
* B.O.B. (USA, Europe)
* Ballz 3D - The Battle of the Ballz (USA, Europe)
* Castlevania - Bloodlines (USA)
* College Football's National Championship II (USA)
* Dr. Robotnik's Mean Bean Machine (USA)
* Fatal Labyrinth (USA, Europe) (En,Ja)
* G-LOC - Air Battle (World)
* Generations Lost (USA, Europe)
* Granada (Japan, USA) (En) (Rev A)
* Hard Drivin' (World)
* Junction (Japan, USA) (En)
* Jungle Strike (USA, Europe)
* M-1 Abrams Battle Tank (USA, Europe)
* Marsupilami (USA) (En,Fr,De,Es,It)
* Mega Bomberman (USA)
* NCAA Football (USA)
* Pele! (USA, Europe)
* PGA Tour Golf III (USA, Europe)
* Rugby World Cup 95 (USA, Europe) (En,Fr,It)
* Saint Sword (USA)
* Shinobi III - Return of the Ninja Master (USA)
* Space Harrier II (World)
* Streets of Rage 2 (USA)
* Taz-Mania (World)
* ToeJam & Earl (USA, Europe, Korea) (En)
* Ultimate QIX (USA)
* Valis (USA)
* Vectorman (USA) (Sega Smash Pack)
* X-Men (USA)
* Ys III (USA)
* Zoop (USA)
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
* Unique ROMs from the game image file
* Sega Channel September 1996 menu demo ROM
* Sega Channel September 1996 game instructions ROM
Back