/*** Tecmo Bowl (c)1987 Tecmo driver by David Haywood wip 20/01/2002 Tecmo Bowl was a popular 4 player American Football game with two screens and attractive graphics --- Current Issues Might be some priority glitches ***/ #include "driver.h" #include "cpu/z80/z80.h" #include "sound/3812intf.h" #include "sound/msm5205.h" #include "rendlay.h" /* in video/tbowl.c */ extern UINT8 *tbowl_txvideoram, *tbowl_bgvideoram, *tbowl_bg2videoram; extern UINT8 *tbowl_spriteram; WRITE8_HANDLER (tbowl_bg2videoram_w); WRITE8_HANDLER (tbowl_bgvideoram_w); WRITE8_HANDLER (tbowl_txvideoram_w); WRITE8_HANDLER (tbowl_bg2xscroll_lo); WRITE8_HANDLER (tbowl_bg2xscroll_hi); WRITE8_HANDLER (tbowl_bg2yscroll_lo); WRITE8_HANDLER (tbowl_bg2yscroll_hi); WRITE8_HANDLER (tbowl_bgxscroll_lo); WRITE8_HANDLER (tbowl_bgxscroll_hi); WRITE8_HANDLER (tbowl_bgyscroll_lo); WRITE8_HANDLER (tbowl_bgyscroll_hi); VIDEO_START( tbowl ); VIDEO_UPDATE( tbowl ); static WRITE8_HANDLER( tbowl_coin_counter_w ) { coin_counter_w(0, data & 1); } /*** Banking note: check this, its borrowed from tecmo.c / wc90.c at the moment and could well be wrong ***/ static WRITE8_HANDLER( tbowlb_bankswitch_w ) { int bankaddress; UINT8 *RAM = memory_region(REGION_CPU1); bankaddress = 0x10000 + ((data & 0xf8) << 8); memory_set_bankptr(1,&RAM[bankaddress]); } static WRITE8_HANDLER( tbowlc_bankswitch_w ) { int bankaddress; UINT8 *RAM = memory_region(REGION_CPU2); bankaddress = 0x10000 + ((data & 0xf8) << 8); memory_set_bankptr(2,&RAM[bankaddress]); } /*** Shared Ram Handlers ***/ static UINT8 *shared_ram; static READ8_HANDLER( shared_r ) { return shared_ram[offset]; } static WRITE8_HANDLER( shared_w ) { shared_ram[offset] = data; } static WRITE8_HANDLER( tbowl_sound_command_w ) { soundlatch_w(offset,data); cpunum_set_input_line(2,INPUT_LINE_NMI,PULSE_LINE); } /*** Memory Structures Board B is the main board, reading inputs, and in control of the 2 bg layers & text layer etc. Board C is the sub board, main job is the sprites Board A is for the sound ***/ /* Board B */ static ADDRESS_MAP_START( readmem_6206B, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x7fff) AM_READ(MRA8_ROM) AM_RANGE(0x8000, 0x9fff) AM_READ(MRA8_RAM) /* RAM 1 */ AM_RANGE(0xa000, 0xbfff) AM_READ(MRA8_RAM) /* RAM 1 */ AM_RANGE(0xc000, 0xdfff) AM_READ(MRA8_RAM) AM_RANGE(0xe000, 0xefff) AM_READ(MRA8_RAM) AM_RANGE(0xf000, 0xf7ff) AM_READ(MRA8_BANK1) /* Banked ROM */ AM_RANGE(0xf800, 0xfbff) AM_READ(shared_r) /* RAM 2 */ AM_RANGE(0xfc00, 0xfc00) AM_READ(input_port_0_r) // Player 1 inputs AM_RANGE(0xfc01, 0xfc01) AM_READ(input_port_1_r) // Player 2 inputs AM_RANGE(0xfc02, 0xfc02) AM_READ(input_port_2_r) // Player 3 inputs AM_RANGE(0xfc03, 0xfc03) AM_READ(input_port_3_r) // Player 4 inputs // AM_RANGE(0xfc06, 0xfc06) AM_READ(dummy_r) // Read During NMI AM_RANGE(0xfc07, 0xfc07) AM_READ(input_port_4_r) // System inputs AM_RANGE(0xfc08, 0xfc08) AM_READ(input_port_5_r) // DSW1 AM_RANGE(0xfc09, 0xfc09) AM_READ(input_port_6_r) // DSW2 AM_RANGE(0xfc0a, 0xfc0a) AM_READ(input_port_7_r) // DSW3 ADDRESS_MAP_END static ADDRESS_MAP_START( writemem_6206B, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x7fff) AM_WRITE(MWA8_ROM) AM_RANGE(0x8000, 0x9fff) AM_WRITE(MWA8_RAM) AM_RANGE(0xa000, 0xbfff) AM_WRITE(tbowl_bg2videoram_w) AM_BASE(&tbowl_bg2videoram) AM_RANGE(0xc000, 0xdfff) AM_WRITE(tbowl_bgvideoram_w) AM_BASE(&tbowl_bgvideoram) AM_RANGE(0xe000, 0xefff) AM_WRITE(tbowl_txvideoram_w) AM_BASE(&tbowl_txvideoram) // AM_RANGE(0xf000, 0xf000) AM_WRITE(unknown_write)* written during start-up, not again */ AM_RANGE(0xf000, 0xf7ff) AM_WRITE(MWA8_ROM) AM_RANGE(0xf800, 0xfbff) AM_WRITE(shared_w) AM_BASE(&shared_ram) /* check */ AM_RANGE(0xfc00, 0xfc00) AM_WRITE(tbowlb_bankswitch_w) // AM_RANGE(0xfc01, 0xfc01) AM_WRITE(unknown_write) /* written during start-up, not again */ // AM_RANGE(0xfc02, 0xfc02) AM_WRITE(unknown_write) /* written during start-up, not again */ AM_RANGE(0xfc03, 0xfc03) AM_WRITE(tbowl_coin_counter_w) AM_RANGE(0xfc0d, 0xfc0d) AM_WRITE(tbowl_sound_command_w) /* not sure, used quite a bit */ // AM_RANGE(0xfc05, 0xfc05) AM_WRITE(unknown_write) /* no idea */ // AM_RANGE(0xfc08, 0xfc08) AM_WRITE(unknown_write) /* hardly used .. */ // AM_RANGE(0xfc0a, 0xfc0a) AM_WRITE(unknown_write) /* hardly used .. */ AM_RANGE(0xfc10, 0xfc10) AM_WRITE(tbowl_bg2xscroll_lo) AM_RANGE(0xfc11, 0xfc11) AM_WRITE(tbowl_bg2xscroll_hi) AM_RANGE(0xfc12, 0xfc12) AM_WRITE(tbowl_bg2yscroll_lo) AM_RANGE(0xfc13, 0xfc13) AM_WRITE(tbowl_bg2yscroll_hi) AM_RANGE(0xfc14, 0xfc14) AM_WRITE(tbowl_bgxscroll_lo) AM_RANGE(0xfc15, 0xfc15) AM_WRITE(tbowl_bgxscroll_hi) AM_RANGE(0xfc16, 0xfc16) AM_WRITE(tbowl_bgyscroll_lo) AM_RANGE(0xfc17, 0xfc17) AM_WRITE(tbowl_bgyscroll_hi) ADDRESS_MAP_END /* Board C */ static WRITE8_HANDLER ( tbowl_trigger_nmi ) { /* trigger NMI on 6206B's Cpu? (guess but seems to work..) */ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE); } static ADDRESS_MAP_START( readmem_6206C, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0xbfff) AM_READ(MRA8_ROM) AM_RANGE(0xc000, 0xdfff) AM_READ(MRA8_RAM) AM_RANGE(0xe000, 0xefff) AM_READ(MRA8_RAM) /* not read? */ AM_RANGE(0xf000, 0xf7ff) AM_READ(MRA8_BANK2) /* Banked ROM */ AM_RANGE(0xf800, 0xfbff) AM_READ(shared_r) ADDRESS_MAP_END static ADDRESS_MAP_START( writemem_6206C, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0xbfff) AM_WRITE(MWA8_ROM) AM_RANGE(0xc000, 0xd7ff) AM_WRITE(MWA8_RAM) AM_RANGE(0xd800, 0xdfff) AM_WRITE(MWA8_RAM) AM_BASE(&tbowl_spriteram) AM_RANGE(0xe000, 0xefff) AM_WRITE(paletteram_xxxxBBBBRRRRGGGG_be_w) AM_BASE(&paletteram) // 2x palettes, one for each monitor? AM_RANGE(0xf000, 0xf7ff) AM_WRITE(MWA8_ROM) AM_RANGE(0xf800, 0xfbff) AM_WRITE(shared_w) AM_RANGE(0xfc00, 0xfc00) AM_WRITE(tbowlc_bankswitch_w) AM_RANGE(0xfc01, 0xfc01) AM_WRITE(MWA8_NOP) /* ? */ AM_RANGE(0xfc02, 0xfc02) AM_WRITE(tbowl_trigger_nmi) /* ? */ AM_RANGE(0xfc03, 0xfc03) AM_WRITE(MWA8_NOP) /* ? */ AM_RANGE(0xfc06, 0xfc06) AM_WRITE(MWA8_NOP) /* ? */ ADDRESS_MAP_END /* Board A */ static int adpcm_pos[2],adpcm_end[2]; static WRITE8_HANDLER( tbowl_adpcm_start_w ) { adpcm_pos[offset & 1] = data << 8; MSM5205_reset_w(offset & 1,0); } static WRITE8_HANDLER( tbowl_adpcm_end_w ) { adpcm_end[offset & 1] = (data + 1) << 8; } static WRITE8_HANDLER( tbowl_adpcm_vol_w ) { MSM5205_set_volume(offset & 1, (data & 0x7f) * 100 / 0x7f); } static void tbowl_adpcm_int(int num) { static int adpcm_data[2] = { -1, -1 }; if (adpcm_pos[num] >= adpcm_end[num] || adpcm_pos[num] >= memory_region_length(REGION_SOUND1)/2) MSM5205_reset_w(num,1); else if (adpcm_data[num] != -1) { MSM5205_data_w(num,adpcm_data[num] & 0x0f); adpcm_data[num] = -1; } else { UINT8 *ROM = memory_region(REGION_SOUND1) + 0x10000 * num; adpcm_data[num] = ROM[adpcm_pos[num]++]; MSM5205_data_w(num,adpcm_data[num] >> 4); } } static ADDRESS_MAP_START( readmem_6206A, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x7fff) AM_READ(MRA8_ROM) AM_RANGE(0xc000, 0xc7ff) AM_READ(MRA8_RAM) AM_RANGE(0xe010, 0xe010) AM_READ(soundlatch_r) ADDRESS_MAP_END static ADDRESS_MAP_START( writemem_6206A, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x7fff) AM_WRITE(MWA8_ROM) AM_RANGE(0xc000, 0xc7ff) AM_WRITE(MWA8_RAM) AM_RANGE(0xd000, 0xd000) AM_WRITE(YM3812_control_port_0_w) AM_RANGE(0xd001, 0xd001) AM_WRITE(YM3812_write_port_0_w) AM_RANGE(0xd800, 0xd800) AM_WRITE(YM3812_control_port_1_w) AM_RANGE(0xd801, 0xd801) AM_WRITE(YM3812_write_port_1_w) AM_RANGE(0xe000, 0xe001) AM_WRITE(tbowl_adpcm_end_w) AM_RANGE(0xe002, 0xe003) AM_WRITE(tbowl_adpcm_start_w) AM_RANGE(0xe004, 0xe005) AM_WRITE(tbowl_adpcm_vol_w) AM_RANGE(0xe006, 0xe006) AM_WRITE(MWA8_NOP) AM_RANGE(0xe007, 0xe007) AM_WRITE(MWA8_NOP) /* NMI acknowledge */ ADDRESS_MAP_END /*** Input Ports Haze's notes : There are controls for 4 players, each player has 4 directions and 2 buttons as well as coin and start. The service switch acts as inserting a coin for all 4 players, the dipswitches are listed in the manual Steph's notes (2002.02.12) : I haven't found any manual, so my notes only rely on the Z80 code ... -- Inputs -- According to the Z80 code, here is the list of controls for each player : - NO START button (you need to press BUTTON1n to start a game for player n) - 4 or 8 directions (I can't tell for the moment, so I've chosen 8 directions) - 2 buttons (I can't tell for the moment what they do) There are also 1 coin slot and a "Service" button for each player. 1 "credit" will mean <