Skip to content

Commit

Permalink
Add mapper ocornut#43 MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF for "Su…
Browse files Browse the repository at this point in the history
…per Game Gear 9 in 1 [Sonic II] (Unl)"

I've been calling it "Super Game Gear 9 in 1 [Sonic II] (Unl)" but the actual names are different:

GEAR 9 IN 1 CARD [English menu]
9 in 1 [splash screen before menu]
9 IN 1 [cartridge label, box front]
SUPER GAME [cartridge label, box front (twice), box back]
SUPER 9 IN 1 GAME LIST [box edges, box back]

I have two copies of this cartridge, only one of which works correctly in real hardware. The broken one came with a box, the working one came loose.

Description of the broken cartridge:

This is a Super Game Gear 9-in-1 GG multi I have that doesn't work even in real hardware (well, occasionally the menu works and even more rarely I can start Columns, but the other games never boot successfully.) I suspect one or more of the electrically-erasable programmable logic devices on the PCB may have forgotten its programming, or there is a bad trace or something. Anyhow, with persistence I was still able to use dumping hardware to extract the menu, figure out the likely mapper writes, and read out the first 512 KB, and to determine that the total size of a complete dump would be 2MB. I thought I would share what I learned because it seems likely somebody else will have the same one, and maybe theirs will still work well enough for complete dumping.

Dumping process was very simple, I just wrote the same bytes the menu writes to the same addresses, then read out the game. The bigger games seem to use Sega mapper, but that part of my cartridge is quite dead so I instead just used FFF7 with even numbers (0x00, 0x02, … 0x1E) to dump it 32KB at a time.

The bottom of the box has a US/CA UPC_A barcode on it. The printed number and barcode both say 010086025118. However, that barcode is literally copied from the box of Game Gear Jurassic Park.

The back of the box has a game list:

```
1. SONIC 2
2. COLUMNS
3. SUPER GOLF
4. BARE KNUCKLE 2
5. SUPER TETRIS
6. BAT MAN 2
7. DEVILISH
8. BASE BALL
9. JURASSIC PARK
```

The double-sided PCB has:

60-Z [marking on the back]

1× COB mystery IC (likely a memory) with somewhere around 40 traces emerging in all directions from beneath the blob of epoxy

3× DIP-20 AMI 18CV8PC-25 Programmable Electrically Erasable Logic (PEEL) devices

1× DIP-16 National Semiconductor DM74S133N single NAND gate

Though the DIP components appear to be through-hole versions, their leads have been trimmed and they are bonded directly to pads on the parts side, SOIC-style.

The newest IC date codes seem to be from week 29 of 1993

Description of the working cartridge:

This 2MB cartridges boots and runs all 9 games, including: [GG] Sonic The Hedgehog 2, Columns, Super Golf, Bare Knuckle/Streets of Rage, Batman Returns, Devilish, Hyper Pro Yakyuu '92, Jurassic Park, [GG-SMS] Super Tetris

The Sega mapper works, and using it I was able to read out the first 512KB of the cartridge, which are identical to the broken one, as well as the remaining 1.5MB.

Dumping script snippet: (did a lot of write spamming as without it the mapper would not reliably respond)
```
// Super Game Gear 9 in 1 [Sonic II] (Unl)

// dumped 512kb at a time, disconnected between dumps since writes to 0xFFF7 are cumulative (OR'ed with any previous writes)

local game_number = 0x40; // one of 0x00 0x20 0x40 0x60
local reps = 5;
for (local reg = 0xfff0; reg <= 0xFFFF; reg += 1) {
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * reg, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * reg, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * reg, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0x8000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * (reg - 0x8000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0x8000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0x4000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * (reg - 0x4000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0x4000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0xC000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * (reg - 0xC000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * (reg - 0xC000), game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * reg, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * reg, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, 1 + address_scale_factor * reg, game_number);
    }
}
for (local orep = 0; orep < reps; orep += 1) {
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xFFFE, 0x01);
        cpu_write(d, 1 + address_scale_factor * 0xFFFE, 0x01);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xDFFE, 0x00);
        cpu_write(d, 1 + address_scale_factor * 0xDFFE, 0x00);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xFFFE, 0x00);
        cpu_write(d, 1 + address_scale_factor * 0xFFFE, 0x00);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xFFF7, game_number);
        cpu_write(d, 1 + address_scale_factor * 0xFFF7, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xDFF7, game_number);
        cpu_write(d, 1 + address_scale_factor * 0xDFF7, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xFFFE, 0x01);
        cpu_write(d, 1 + address_scale_factor * 0xFFFE, 0x01);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xDFFE, 0x01);
        cpu_write(d, 1 + address_scale_factor * 0xDFFE, 0x01);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0x7FFE, 0x01);
        cpu_write(d, 1 + address_scale_factor * 0x7FFE, 0x01);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0x7FFE, 0x00);
        cpu_write(d, 1 + address_scale_factor * 0x7FFE, 0x00);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0x7FF7, game_number);
        cpu_write(d, 1 + address_scale_factor * 0x7FF7, game_number);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0x7FFE, 0x01);
        cpu_write(d, 1 + address_scale_factor * 0x7FFE, 0x01);
    }
}
cpu_read(d, address_scale_factor * 0x0000, address_scale_factor * 0x4000);
for (local page = 1; (page * address_scale_factor * 0x4000) < rom_size; page += 1) {
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0xFFFF, page);
        cpu_write(d, 1 + address_scale_factor * 0xFFFF, page);
    }
    for (local rep = 0; rep < reps; rep += 1) {
        cpu_write(d, address_scale_factor * 0x7FFF, page);
        cpu_write(d, 1 + address_scale_factor * 0x7FFF, page);
    }
    cpu_read(d, address_scale_factor * 0x8000, address_scale_factor * 0x4000);
}
```

The menu appears to be made by using Pengo as a starting point and then hacking it until it works as a menu; Pengo is not actually a playable game in the multicart, though, and parts of the game have been replaced with menu code and data.

The menu is available in both English and Traditional Chinese versions.

On startup, the initialization code writes [0xFFFE=0x01] and briefly shows a "9 in 1" splash screen.

English menu contents: (">" is the cursor and is movable; possible mapper writes are shown bracketed)
```
 ******************
 *GEAR 9 IN 1 CARD*
********************

>1*SONIC II         [0xFFF7=0x60]; it's [GG] part-60-sonic-the-hedgehog-2-512k.gg
  2*COLUMNS          [0xFFF7=0x02]; it's [GG] part-02-columns-32k.gg
  3*SUPER GOLF       [0xFFF7=0x18]; it's [GG] part-18-Super Golf (JP)-128k.gg
  4*BARE KNUCKLE 2   [0xFFF7=0x20]; it's [GG] part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
  5*SUPER TETRIS     [0xFFF7=0x05]; it's [GG-SMS] part-05-super-tetris-64k.sms
  6*BATMAN II        [0xFFF7=0x30]; it's [GG] part-30-batman-returns-256k.gg
  7*DEVILISH         [0xFFF7=0x10]; it's [GG] part-10-Devilish (JP)-128k.gg
  8*92'BASEBALL      [0xFFF7=0x08]; it's [GG] part-08-hyper-pro-yakyuu-92-128k.gg
  9*JURASSIC PARK    [0xFFF7=0x40]; it's [GG] part-40-Jurassic Park (Japan)-512kb.gg

  [↑↓]:SELECT GAME
  [START]:RUN GAME
 [1&2]:ENGLISH ↔中文
```

Before each mapper write 0xFFFE is set to 0x00. After each mapper write, bit 5 is set in a write to 0x0A7E which appears to reset the Game Gear with the new mapping taking effect.

Traditional Chinese menu contents: (reversed angle "⦣" is the cursor and is movable)
```
     ⦣音速Ⅱ代  (i.e. "Sonic II")
 ╔══╗ 魔法宝石 (魔法寶石, i.e. "magic gem", a Chinese name for Columns)
 ║遊║ 高爾夫球 (i.e. "golf")
 ║戲║ 格鬥二人 (i.e. "fighting duo", a Chinese name for Bare Knuckle 2)
 ║目║ 超級方塊 (i.e. "super box"/"super Tetris")
 ║錄║ 蝙蝠俠Ⅱ  (i.e. "Batman II")
 ╚══╝ 魔珠歷劫 (i.e. "magic beads tribulation", a Chinese name for Devilish/Bad Omen)
      92棒球   (i.e. "92 baseball")
      侏儸公園 (same pronunciation as 侏羅公園, i.e. "Jura[ssic] Park")
```

Notes:
- Transcription and/or translation errors are entirely my own, and no I don't yet understand or read Chinese
- Chinese characters are drawn double-width/double-height compared to English text
- The Chinese menu heading 遊戲目錄 (i.e. "Game Menu") is written vertically spaced apart and enclosed with a box, and parts are half-character aligned compared to the rest of the text
- The chinese menu items are written horizontally spaced apart
- Some characters are drawn partly or wholly simplified to be more legible in 16px × 16px character cells, e.g. "宝" rather than "寶"
- "魔" (twice) is a guess for a character I can't read properly, which may be an informal or colloquial simplification omitting the 甶 and 𣏟 character components for reasons of space efficiency
- Names of some games seem to be shortened by omission of less-important characters for reasons of limited space too
- 俄羅斯方塊 (i.e. "Russia cube"/"Tetris") is sometimes abbreviated 俄羅方塊 (i.e. "Russia box"), so 超級方塊 seems like a plausible shortening for "super Tetris"
- 侏羅紀公園 (i.e. "Jurassic Park") is sometimes abbreviated 侏羅公園 (i.e. "Jura Park")
- Mapper writes for each game are the same in the Chinese and English versions of the menu

Mapper register 0xFFF7 seems to control base page (bits 0x7E) and GG-SMS mode switching (bit 0x01). Sega mapper works after that for game sizes up to 512KB. In fact all parts of the ROM can be dumped in four 512KB chunks using Sega paging inside each chunk.

ROM fingerprint info:

2.0M Super Game Gear 9 in 1 [Sonic II] (Unl).gg
Checking for export header with matching CRC... NO
sha256:aac0a7941ed21f4bc8157207b094c38ed5abeda93266e7c49a5c2e5c2aa53943 Super Game Gear 9 in 1 [Sonic II] (Unl).gg
sha1:1d1266ae173790df6e6289817c2fe8667f775f40 Super Game Gear 9 in 1 [Sonic II] (Unl).gg
md5:4aba56dbe111af08d62098dbfbee35fe Super Game Gear 9 in 1 [Sonic II] (Unl).gg
mekacrc:6727345FC46B6C44 Super Game Gear 9 in 1 [Sonic II] (Unl).gg
crc32:7cc51c51 Super Game Gear 9 in 1 [Sonic II] (Unl).gg

32K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg
Checking for export header with matching CRC... NO
sha256:33f3176801ff6a4596c1863ad1c2d578d0cbd658e6a41fbea544d36ba2b6d277 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg
sha1:063c1c3a53efc57716b8aa07b1a4a60f6c149c98 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg
md5:a5348e8e00436cbb7610e0065bf2134f Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg
mekacrc:6DB69D4B61508EB6 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg
crc32:51ab7f7d Super Game Gear 9 in 1 [Sonic II] (Unl)/part-00-menu-and-pengo-remnants-32k.gg

32K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg
Checking for export header with matching CRC... NO
sha256:81d062c901f29d83debc8bd384ff90389deab8a8e8790f31ca3b1d58a40ed212 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg
sha1:fe8b888abb2c995e6e805e96879805068d2b4f66 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg
md5:68e9356200da717b117295c614761dc7 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg
mekacrc:16E74B045730022B Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg
crc32:a1567576 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-02-columns-32k.gg

64K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms
Checking for export header with matching CRC... NO
sha256:72a8221df16d47e73a0c8db9781a90cce61b13d65f7b98786dddbb0e4452f4cb Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms
sha1:92431c60251b959f5d59633eb2677c8fc48edf0a Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms
md5:acb1f9cb12da34ec79f17cbd440a033d Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms
mekacrc:140E652C362B3BB1 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms
crc32:89ead431 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-05-super-tetris-64k.sms

128K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg
Checking for export header with matching CRC... NO
sha256:35fe7f955d9af26d72f52f5628e49d4d973d24d386a6f274b0889e201330ee9b Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg
sha1:b06c4e2f265a3e46aafa9af45d9612434b73d297 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg
md5:087b024e6ae0c875b6504006ad02128e Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg
mekacrc:128F79A1AEDD6B4F Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg
crc32:3c0d9105 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-08-hyper-pro-yakyuu-92-128k.gg

128K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg
Checking for export header with matching CRC... NO
sha256:52864086826e79caa6da91c929cd4017838ee64e2d7458c607413bf32b1e2059 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg
sha1:5b1d4295920ebe4d6d9b9610764939b2aaa6c598 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg
md5:bc3b402b546b9561c79e3373aee97a9c Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg
mekacrc:FED59D64601210AA Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg
crc32:25db174f Super Game Gear 9 in 1 [Sonic II] (Unl)/part-10-Devilish (JP)-128k.gg

128K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg
Checking for export header with matching CRC... NO
sha256:5f1af799fcbaa55430fd298140db28f943e8a731a94ecbac9e2e4dac506afe5a Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg
sha1:9ecb48513621086ec6d5bffa1375914f21f393e4 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg
md5:f2b5123b3614388677c9c15adaaa8d64 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg
mekacrc:FAE75543A7740E5E Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg
crc32:528cbbce Super Game Gear 9 in 1 [Sonic II] (Unl)/part-18-Super Golf (JP)-128k.gg

256K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
Checking for export header with matching CRC... NO
sha256:10e871fc673f4f54b53fd17d3f1117e68cdf5de41a5041aa474bacbe96686f79 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
sha1:ca8c8a00ee838e994b2fa17e595ddd40d898cf42 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
md5:1ece7480d21fb862a65233ba126282d3 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
mekacrc:5AD835BF116EC299 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg
crc32:3d8bcf1d Super Game Gear 9 in 1 [Sonic II] (Unl)/part-20-Bare Knuckle ~ Streets of Rage (JP,US,EU,BR)-256k.gg

256K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg
Checking for export header with matching CRC... NO
sha256:335a56ca637fb03ffc2b1e1dabe8d5b403730bbc0c2a2f9c972dcc63adb69d64 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg
sha1:77bb03d7828e9dce5558dc31688645246df90dab Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg
md5:d04a59808e44417272ce03ef17ad1bbb Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg
mekacrc:616AF5501BA3E052 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg
crc32:837120ec Super Game Gear 9 in 1 [Sonic II] (Unl)/part-30-batman-returns-256k.gg

512K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg
Checking for export header with matching CRC... NO
sha256:7c6bb90371f15fcc843bbff4667c366cc4d35f8ff90f42b24dc57017fca8db42 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg
sha1:89486678a6a065c56102296eebc7b25c5ef32d21 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg
md5:5797a3efc5bd691a29cd52e8315da9b9 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg
mekacrc:2192332A14FC845C Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg
crc32:2f536ae3 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-40-Jurassic Park (Japan)-512kb.gg

512K Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
Checking for export header with matching CRC... NO
sha256:1619d0851f992a615285f2987534de1b6abbf7b31da93405ce9ed98393f5822e Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
sha1:a07cba7124114a2ea5eb4fd5de79f0eae6f105d0 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
md5:5fcbee2f4bc35b49f1d2f1ca9b4dba40 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
mekacrc:EA5D1F63E150F214 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
crc32:e9a816f1 Super Game Gear 9 in 1 [Sonic II] (Unl)/part-60-sonic-the-hedgehog-2-512k.gg
  • Loading branch information
bsittler committed Apr 13, 2023
1 parent 7d1ffc1 commit c8b7657
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 4 deletions.
3 changes: 2 additions & 1 deletion meka/compat.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,7 @@
Super Battletank Ok
Super Columns Ok
Super Columns (JP) Ok
Super Game Gear 9 in 1 [Sonic II] *Ok
Super Golf (JP) Ok
Super Kick Off [SMS-GG] Ok
Superman - The Man of Steel Ok
Expand Down Expand Up @@ -1498,7 +1499,7 @@
Zoop (US) Ok
Zoop [Proto] (US) Ok
-----------------------------------------------------------------------------
517 games tested - 506 are "Ok" - Compatibility rate: 97.63%
518 games tested - 507 are "Ok" - Compatibility rate: 97.88%
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions meka/meka.nam
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,7 @@ GG b421c057 96BD12C62621B8D6 Striker/COUNTRY=EU/PRODUCT_NO=2551-50
GG 73d6745a 18CC99C9849C9901 Super Battletank/COUNTRY=US/PRODUCT_NO=1239
GG 8ba43af3 DAA4C785B7042952 Super Columns/COUNTRY=US,EU/PRODUCT_NO=2449,2449-50
GG 2a100717 E7260408CEC8EE63 Super Columns/COUNTRY=JP/PRODUCT_NO=G-3226
GG 7cc51c51 6727345FC46B6C44 Super Game Gear 9 in 1 [Sonic II]/EMU_MAPPER=43
GG 528cbbce FAE75543A7740E5E Super Golf/COUNTRY=JP/PRODUCT_NO=T-26017,T-26027
GG 73df5a15 43574420E8CF212A Superman - The Man of Steel/COUNTRY=EU/PRODUCT_NO=T-70068,70068-00
GG aa3f2172 0A5C6040EBCF152B Superman - The Man of Steel [Proto]/FLAGS=PROTO/COMMENT=Prototype version of the game.
Expand Down
34 changes: 34 additions & 0 deletions meka/srcs/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "tvtype.h"
#include "sound/fmunit.h"
#include "sound/psg.h"
#include "app_game.h"

//-----------------------------------------------------------------------------
// Data
Expand Down Expand Up @@ -196,6 +197,9 @@ void Machine_Set_Handler_MemRW(void)
case MAPPER_SMS_Korean_MSX_32KB_2000:
WrZ80 = WrZ80_NoHook = Write_Mapper_SMS_Korean_MSX_32KB_2000;
break;
case MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF:
WrZ80 = WrZ80_NoHook = Write_Mapper_GG_Super_9_in_1_FFFE_FFF7_FFFF;
break;
}
}

Expand Down Expand Up @@ -485,6 +489,24 @@ void Machine_Set_Mapping (void)
g_machine.mapper_regs[0] = 0;
break;

case MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF:
Map_8k_ROM(0, 0 & tsms.Pages_Mask_8k);
Map_8k_ROM(1, 1 & tsms.Pages_Mask_8k);
Map_8k_ROM(2, 0 & tsms.Pages_Mask_8k);
Map_8k_ROM(3, 1 & tsms.Pages_Mask_8k);
Map_8k_ROM(4, 0 & tsms.Pages_Mask_8k);
Map_8k_ROM(5, 1 & tsms.Pages_Mask_8k);
Map_8k_RAM(6, 0);
Map_8k_RAM(7, 0);
g_machine.mapper_regs_count = 3;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
g_machine.mapper_regs[i] = 0;
drv_set(DRV_GG);
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
break;

case MAPPER_SC3000_Survivors_Multicart:
g_machine.mapper_regs_count = 1;
for (int i = 0; i != MAPPER_REGS_MAX; i++)
Expand Down Expand Up @@ -582,6 +604,18 @@ void Machine_Set_TV_Lines(void)
g_machine.TV_lines = g_machine.TV->screen_lines;
}

// RESET EMULATED CPU ---------------------------------------------------------
void Machine_Reset_Z80(void)
{
#ifdef MARAT_Z80
ResetZ80 (&sms.R);
#elif MAME_Z80
z80_reset (NULL);
#elif RAZE_Z80
z80_reset();
#endif
}

// RESET EMULATED MACHINE -----------------------------------------------------
void Machine_Reset(void)
{
Expand Down
1 change: 1 addition & 0 deletions meka/srcs/machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void Machine_Pause (void);
void Machine_Debug_Start (void);
void Machine_Debug_Stop (void);
void Machine_Reset (void);
void Machine_Reset_Z80 (void);

void Machine_Set_Mapper (void);
void Machine_Set_Mapping (void);
Expand Down
63 changes: 63 additions & 0 deletions meka/srcs/mappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include "shared.h"
#include "mappers.h"
#include "eeprom.h"
#include "vdp.h"
#include "video.h"
#include "app_game.h"

//-----------------------------------------------------------------------------
// Data
Expand Down Expand Up @@ -952,6 +955,66 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000)
Write_Error (Addr, Value);
}

// Mapper #43
// Super Game Gear 9 in 1 [Sonic II]
WRITE_FUNC(Write_Mapper_GG_Super_9_in_1_FFFE_FFF7_FFFF)
{
if (((Addr == 0x0A7E) && (Value & 0x20)) || (Addr == 0xFFF7) || (Addr == 0xFFFE) || (Addr == 0xFFFF)) // Configurable segment -----------------------------------------------
{
if (Addr == 0xFFF7)
{
if (! (g_machine.mapper_regs[2])) {
g_machine.mapper_regs[0] |= Value;
}
}
else if (Addr == 0xFFFF)
{
g_machine.mapper_regs[1] = Value;
}
else if (Addr == 0xFFFE)
{
g_machine.mapper_regs[2] = Value;
}
bool force_reset = false;
if ((Addr == 0x0A7E) && (Value & 0x20)) {
// This seems to force a reset and apply the mapping
g_machine.mapper_regs[1] = 0;
g_machine.mapper_regs[2] = 1;
force_reset = true;
}
if (force_reset || (Addr == 0xFFFE) || (Addr == 0xFFFF)) {
int mapbase = g_machine.mapper_regs[0] & 0xFE;
Map_8k_ROM(0, (mapbase * 2) & tsms.Pages_Mask_8k);
Map_8k_ROM(1, ((mapbase * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(2, ((mapbase * 2) | ((g_machine.mapper_regs[2] & 0x1F) * 2)) & tsms.Pages_Mask_8k);
Map_8k_ROM(3, ((mapbase * 2) | ((g_machine.mapper_regs[2] & 0x1F) * 2) | 1) & tsms.Pages_Mask_8k);
Map_8k_ROM(4, ((mapbase * 2) | ((g_machine.mapper_regs[1] & 0x1F) * 2)) & tsms.Pages_Mask_8k);
Map_8k_ROM(5, ((mapbase * 2) | ((g_machine.mapper_regs[1] & 0x1F) * 2) | 1) & tsms.Pages_Mask_8k);
}
if (g_machine.mapper_regs[0] & 0x01) {
drv_set(DRV_SMS);
} else {
drv_set(DRV_GG);
}
gamebox_resize_all();
VDP_UpdateLineLimits();
Video_GameMode_UpdateBounds();
if (force_reset) {
Machine_Reset_Z80();
return;
}
}

switch (Addr >> 13)
{
// RAM [0xC000] = [0xE000] ------------------------------------------------
case 6: Mem_Pages[6][Addr] = Value; return;
case 7: Mem_Pages[7][Addr] = Value; return;
}

Write_Error(Addr, Value);
}

// Based on MSX ASCII 8KB mapper? http://bifi.msxnet.org/msxnet/tech/megaroms.html#ascii8
// - This mapper requires 4 registers to save bank switching state.
// However, all other mappers so far used only 3 registers, stored as 3 bytes.
Expand Down
2 changes: 2 additions & 0 deletions meka/srcs/mappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#define MAPPER_SMS_Korean_MD_FFF5 (25) // Registers at 0xFFF5 and 0xFFFF (Jaemiissneun Game Mo-eumjip 42/65 Hap [SMS-MD], Pigu Wang Hap ~ Jaemiiss-neun Game Mo-eumjip [SMS-MD])
#define MAPPER_SMS_Korean_MD_FFFA (26) // Registers at 0xFFFA and 0xFFFF (Game Jiphap 30 Hap [SMS-MD])
#define MAPPER_SMS_Korean_MSX_32KB_2000 (27) // Register at 0x2000 (2 Hap in 1 (Moai-ui bomul, David-2))
#define MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF (43) // Registers at 0xFFFE, 0xFFF7, and 0xFFFF (Super Game Gear 9 in 1 [Sonic II])

#define READ_FUNC(_NAME) u8 _NAME(register u16 Addr)
#define WRITE_FUNC(_NAME) void _NAME(register u16 Addr, register u8 Value)
Expand Down Expand Up @@ -96,6 +97,7 @@ WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF0);
WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFF5);
WRITE_FUNC (Write_Mapper_SMS_Korean_MD_FFFA);
WRITE_FUNC (Write_Mapper_SMS_Korean_MSX_32KB_2000);
WRITE_FUNC (Write_Mapper_GG_Super_9_in_1_FFFE_FFF7_FFFF);
//-----------------------------------------------------------------------------
void Out_SC3000_SurvivorsMulticarts_DataWrite(u8 v);

Expand Down
17 changes: 14 additions & 3 deletions meka/srcs/saves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void Load_Game_Fixup(void)
{
int i;
u8 b;
bool sms_gg_mode_in_mapper = false;

// CPU
#ifdef MARAT_Z80
Expand Down Expand Up @@ -144,13 +145,21 @@ void Load_Game_Fixup(void)
case MAPPER_SMS_Korean_MSX_32KB_2000:
WrZ80_NoHook(0x2000, g_machine.mapper_regs[0]);
break;
case MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF:
// rewriting these will automatically read and apply the hidden register's state
WrZ80_NoHook(0xFFFF, g_machine.mapper_regs[1]);
WrZ80_NoHook(0xFFFE, g_machine.mapper_regs[2]);
sms_gg_mode_in_mapper = true;
break;
}
}

// VDP/Graphic related
tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_ALL;
VDP_UpdateLineLimits();
// FALSE!!! // tsms.VDP_Line = 224;
if (!sms_gg_mode_in_mapper) {
tsms.VDP_Video_Change |= VDP_VIDEO_CHANGE_ALL;
VDP_UpdateLineLimits();
// FALSE!!! // tsms.VDP_Line = 224;
}

// Rewrite all VDP registers (we can do that since it has zero side-effect)
for (i = 0; i < 16; i ++)
Expand Down Expand Up @@ -339,6 +348,7 @@ int Save_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFF5:
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF:
default:
fwrite (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down Expand Up @@ -518,6 +528,7 @@ int Load_Game_MSV(FILE *f)
case MAPPER_SMS_Korean_MD_FFF5:
case MAPPER_SMS_Korean_MD_FFFA:
case MAPPER_SMS_Korean_MSX_32KB_2000:
case MAPPER_GG_Super_9_in_1_FFFE_FFF7_FFFF:
default:
fread (RAM, 0x2000, 1, f); // Do not use g_driver->ram because of g_driver video mode change
break;
Expand Down

0 comments on commit c8b7657

Please sign in to comment.