System Information: Memory Addresses: $00000 ROMSIZE-1 Rom WORKRAM WORKRAM+$3fff RaM $B0000 $B0001 IRQ Line $BC000 $BC001 Sprite Control $C0000 $C03FF Ram (Read) $C0000 $C03FF Sprite Ram (Write) $C8000 $C8BFF Palette 1 $CC000 $CCBFF Palette 2 $D0000 $D3FFF Video Ram 1 $D8000 $DBFFF Video Ram 2 $E0000 $EFFFF Sound Ram Sizes: ROMSIZE WORKRAM R Type $40000 $40000 M72 $80000 $a0000 XMultipl $80000 $80000 DBreed $80000 $90000 IO Ports: (Write) $00 $01 Sound Command $02 $03 Coin counters, reset sound cpu, other stuff? $04 $05 Sprite Control $06 $07 IRQ Line $80 $81 Scroll Y1 $82 $83 Scroll X1 $84 $85 Scroll Y2 $86 $87 Scroll X2 $c0 $c0 Trigger sample, filled by init_ function */ IO Ports: (Read) $00 ? $01 ? $02 ? $03 ? $04 ? $05 ? Sound Memory: $0000 $ffff Ram Sound Ports (Read): $01 YM2151 Status Port $02 Sound Latch $84 Sample Sound Ports (Write): $00 YM2151 Register Port $01 YM2151 Data Port $06 Sound IRQ Ack $82 Sample Sample playback: In the later games, the sound CPU can program the start offset of the PCM samples, but it seems the earlier games have them hardcoded somewhere (maybe a PROM?). So, here I provided some tables with the start offset precomputed. They could be built automatically for the most part (00 marks the end of a sample), but some games have holes in the numbering so we would have to do some alterations anyway. Protection simulation: Most of the games running on this board have an 8751 protection mcu. It is not known how it works in detail, however it's pretty clear that it shares RAM at b0000-b0fff. On startup, the game writes a pattern to the whole RAM, then reads it back expecting it to be INVERTED. If it isn't, it reports a RAM error. If the RAM passes the test, the program increments every byte up to b0ffb, then calls a subroutine at b0000, which has to be provided by the mcu. It seems that this routine is not supposed to RET, but instead it should jump directly to the game entry point. The routine should also write some bytes here and there in RAM (different in every game); those bytes are checked at various points during the game, causing a crash if they aren't right. Note that the program keeps incrementing b0ffe while the game is running, maybe this is done to keep the 8751 alive. We don't bother with that. Finally, to do the ROM test the program asks the mcu to provide the correct values. This is done only in service, so doesn't seem to be much of a protection. Here we have provided the correct crcs for the available dumps, of course there is no guarantee that they are actually good. Sound: The sound CPU runs in interrup mode 0. IRQ is shared by two sources: the YM2151 (bit 4 of the vector), and the main CPU (bit 5). Since the vector can be changed from different contexts (the YM2151 timer callback, the main CPU context, and the sound CPU context), it's important to accurately arbitrate the changes to avoid out-of-order execution. We do that by handling all vector changes in a single timer callback. Input: $01 Right $02 Left $04 Down $08 Up $10 Button 4 $20 Button 3 $40 Button 2 $80 Button 1 Graphics: 8 * 8 characters RGN_FRAC(1,4) NUM characters */ 0x8(1-4bits)(4-4bits)[23 bits] 4 bits per pixel RGN_FRAC(3,4) RGN_FRAC(2,4) RGN_FRAC(1,4) RGN_FRAC(0,4) 0 1 2 3 4 5 6 7 0*8 1*8 2*8 3*8 4*8 5*8 6*8 7*8 Every char takes 8 consecutive bytes 16 * 16 sprites RGN_FRAC(1,4) NUM characters See above 4 bits per pixel RGN_FRAC(3,4) RGN_FRAC(2,4) RGN_FRAC(1,4) RGN_FRAC(0,4) 0 1 2 3 4 5 6 7 16*8+0 16*8+1 16*8+2 16*8+3 16*8+4 16*8+5 16*8+6 16*8+7 0*8 1*8 2*8 3*8 4*8 5*8 6*8 7*8 8*8 9*8 10*8 11*8 12*8 13*8 14*8 15*8 Every sprite takes 32 consecutive bytes Foreground Tilemap: Attribute = Video Ram1[Tile + 1] Tile = Video Ram1[Tile] + ((Attribute & $3f) << 8) Palette = Video Ram1[Tile + 2] & $0f FlipXY = Attribute & $c0 Priority = Video Ram1[Tile + 2] & $80 Background Tilemap: Attribute = Video Ram2[Tile + 1] Tile = Video Ram2[Tile] + ((Attribute & $3f) << 8) Palette = Video Ram2[Tile + 2] & $0f FlipXY = Attribute & $c0 Tilemap can be 256x64, but seems to be used at 128x64 (scroll wraparound) Palette: Palette Stored in planar format. ($400 per color) SpriteRam: $BC001 $40 Clears Sprite Ram Tile = Sprite Ram[offs+2] | (Sprite Ram[offs+3] << 8) Color = Sprite Ram[offs+4] & $0f x = -256 + Sprite Ram[offs+6] | ((Sprite Ram[offs+7] & $03) << 8)) y = 512 - (Sprite Ram[offs+0] | ((Sprite Ram[offs+1] & $01) << 8)) Flipx = Sprite Ram[offs+5] & $08; Flipy = Sprite Ram[offs+5] & $04; Width = 1 << ((Sprite Ram[offs+5] & $c0) >> 6); Height = 1 << ((Sprite Ram[offs+5] & $30) >> 4); y -= 16 * Height; IRQs: