diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2019-10-19 22:35:04 -0400 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2019-10-19 22:40:04 -0400 |
commit | 270a2736b0770e5be2d9967b399e178500dbe7a5 (patch) | |
tree | 4bfe26c9e3f453e73f1c6d27641133c3862323f7 | |
parent | c08c7d6e53a484570b7f0645f45bb2d529547e48 (diff) |
segaic16.cpp: Code cleanup, reorganization and decoupling (nw)
- Move open_bus_r down into the 315-5195 mapper device (not 100% ideal, but the next best place)
- Split out 315-5195 mapper device into separate source file and modernize logging
- Move remaining portion of sega_16bit_common_base (all to do with palettes) into video/segaic16.cpp
segahang.cpp: Split I/O handlers; eliminate probably unnecessary open bus read semantics to decouple from sega_16bit_common_base (nw)
-rw-r--r-- | src/mame/drivers/segahang.cpp | 121 | ||||
-rw-r--r-- | src/mame/drivers/segaorun.cpp | 6 | ||||
-rw-r--r-- | src/mame/drivers/segas16a.cpp | 1 | ||||
-rw-r--r-- | src/mame/drivers/segas16b.cpp | 4 | ||||
-rw-r--r-- | src/mame/drivers/segas18.cpp | 10 | ||||
-rw-r--r-- | src/mame/drivers/segaxbd.cpp | 1 | ||||
-rw-r--r-- | src/mame/drivers/segaybd.cpp | 1 | ||||
-rw-r--r-- | src/mame/includes/segahang.h | 11 | ||||
-rw-r--r-- | src/mame/includes/segaorun.h | 5 | ||||
-rw-r--r-- | src/mame/includes/segas16a.h | 6 | ||||
-rw-r--r-- | src/mame/includes/segas16b.h | 8 | ||||
-rw-r--r-- | src/mame/includes/segas18.h | 9 | ||||
-rw-r--r-- | src/mame/includes/segaxbd.h | 2 | ||||
-rw-r--r-- | src/mame/includes/segaybd.h | 4 | ||||
-rw-r--r-- | src/mame/includes/system16.h | 7 | ||||
-rw-r--r-- | src/mame/machine/315_5195.cpp | 610 | ||||
-rw-r--r-- | src/mame/machine/315_5195.h | 147 | ||||
-rw-r--r-- | src/mame/machine/segaic16.cpp | 752 | ||||
-rw-r--r-- | src/mame/machine/segaic16.h | 156 | ||||
-rw-r--r-- | src/mame/video/segaic16.cpp | 155 | ||||
-rw-r--r-- | src/mame/video/segaic16.h | 37 |
21 files changed, 1017 insertions, 1036 deletions
diff --git a/src/mame/drivers/segahang.cpp b/src/mame/drivers/segahang.cpp index d6a030d7154..665da5653f1 100644 --- a/src/mame/drivers/segahang.cpp +++ b/src/mame/drivers/segahang.cpp @@ -159,119 +159,38 @@ READ8_MEMBER( segahang_state::adc_status_r ) //************************************************************************** //------------------------------------------------- -// hangon_io_r - I/O handler for Hang-On boards +// hangon_inputs_r - input port selector for +// Hang-On boards //------------------------------------------------- -READ16_MEMBER( segahang_state::hangon_io_r ) +uint8_t segahang_state::hangon_inputs_r(offs_t offset) { - switch (offset & 0x3020/2) - { - case 0x0000/2: // PPI @ 4B - return m_i8255_1->read(offset & 3); - - case 0x1000/2: // Input ports and DIP switches - { - static const char *const sysports[] = { "SERVICE", "COINAGE", "DSW", "UNKNOWN" }; - return ioport(sysports[offset & 3])->read(); - } - - case 0x3000/2: // PPI @ 4C - return m_i8255_2->read(offset & 3); - - case 0x3020/2: // ADC0804 data output - return m_adc->read(); - } - - //logerror("%06X:hangon_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + static const char *const sysports[] = { "SERVICE", "COINAGE", "DSW", "UNKNOWN" }; + return ioport(sysports[offset & 3])->read(); } //------------------------------------------------- -// hangon_io_w - I/O handler for Hang-On boards +// sharrier_inputs_r - input port selector for +// Space Harrier boards //------------------------------------------------- -WRITE16_MEMBER( segahang_state::hangon_io_w ) +uint8_t segahang_state::sharrier_inputs_r(offs_t offset) { - if (ACCESSING_BITS_0_7) - switch (offset & 0x3020/2) - { - case 0x0000/2: // PPI @ 4B - // the port C handshaking signals control the Z80 NMI, - // so we have to sync whenever we access this PPI - synchronize(TID_PPI_WRITE, ((offset & 3) << 8) | (data & 0xff)); - return; - - case 0x3000/2: // PPI @ 4C - m_i8255_2->write(offset & 3, data & 0xff); - return; - - case 0x3020/2: // ADC0804 - m_adc->write(); - return; - } - - //logerror("%06X:hangon_io_w - unknown write access to address %04X = %04X & %04X\n", m_maincpu->pc(), offset * 2, data, mem_mask); -} - - -//------------------------------------------------- -// sharrier_io_r - I/O handler for Space Harrier -// boards -//------------------------------------------------- - -READ16_MEMBER( segahang_state::sharrier_io_r ) -{ - switch (offset & 0x0030/2) - { - case 0x0000/2: - return m_i8255_1->read(offset & 3); - - case 0x0010/2: // Input ports and DIP switches - { - static const char *const sysports[] = { "SERVICE", "UNKNOWN", "COINAGE", "DSW" }; - return ioport(sysports[offset & 3])->read(); - } - - case 0x0020/2: // PPI @ 4C - if (offset == 2) return 0; - return m_i8255_2->read(offset & 3); - - case 0x0030/2: // ADC0804 data output - return m_adc->read(); - } - - //logerror("%06X:sharrier_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + static const char *const sysports[] = { "SERVICE", "UNKNOWN", "COINAGE", "DSW" }; + return ioport(sysports[offset & 3])->read(); } //------------------------------------------------- -// sharrier_io_w - I/O handler for Space Harrier -// boards +// sync_ppi_w - helper for writes to the PPI @ 4B //------------------------------------------------- -WRITE16_MEMBER( segahang_state::sharrier_io_w ) +void segahang_state::sync_ppi_w(offs_t offset, uint8_t data) { - if (ACCESSING_BITS_0_7) - switch (offset & 0x0030/2) - { - case 0x0000/2: - // the port C handshaking signals control the Z80 NMI, - // so we have to sync whenever we access this PPI - synchronize(TID_PPI_WRITE, ((offset & 3) << 8) | (data & 0xff)); - return; - - case 0x0020/2: // PPI @ 4C - m_i8255_2->write(offset & 3, data & 0xff); - return; - - case 0x0030/2: // ADC0804 - m_adc->write(); - return; - } - - //logerror("%06X:sharrier_io_w - unknown write access to address %04X = %04X & %04X\n", m_maincpu->pc(), offset * 2, data, mem_mask); + // the port C handshaking signals control the Z80 NMI, + // so we have to sync whenever we access this PPI + synchronize(TID_PPI_WRITE, ((offset & 3) << 8) | data); } @@ -420,7 +339,10 @@ void segahang_state::hangon_map(address_map &map) map(0xc00000, 0xc3ffff).rom().region("subcpu", 0); map(0xc68000, 0xc68fff).ram().share("segaic16road:roadram"); map(0xc7c000, 0xc7ffff).ram().share("subram"); - map(0xe00000, 0xffffff).rw(FUNC(segahang_state::hangon_io_r), FUNC(segahang_state::hangon_io_w)); + map(0xe00000, 0xe00007).mirror(0x1fcfd8).r(m_i8255_1, FUNC(i8255_device::read)).w(FUNC(segahang_state::sync_ppi_w)).umask16(0x00ff); + map(0xe01000, 0xe01007).mirror(0x1fcfd8).r(FUNC(segahang_state::hangon_inputs_r)).umask16(0x00ff); + map(0xe03000, 0xe03007).mirror(0x1fcfd8).rw(m_i8255_2, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff); + map(0xe03021, 0xe03021).mirror(0x1fcfde).rw(m_adc, FUNC(adc0804_device::read), FUNC(adc0804_device::write)); } void segahang_state::decrypted_opcodes_map(address_map &map) @@ -439,7 +361,10 @@ void segahang_state::sharrier_map(address_map &map) map(0x110000, 0x110fff).ram().w(FUNC(segahang_state::paletteram_w)).share("paletteram"); map(0x124000, 0x127fff).ram().share("subram"); map(0x130000, 0x130fff).ram().share("sprites"); - map(0x140000, 0x14ffff).rw(FUNC(segahang_state::sharrier_io_r), FUNC(segahang_state::sharrier_io_w)); + map(0x140000, 0x140007).mirror(0xffc8).r(m_i8255_1, FUNC(i8255_device::read)).w(FUNC(segahang_state::sync_ppi_w)).umask16(0x00ff); + map(0x140010, 0x140017).mirror(0xffc8).r(FUNC(segahang_state::sharrier_inputs_r)).umask16(0x00ff); + map(0x140020, 0x140027).mirror(0xffc8).rw(m_i8255_2, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff); + map(0x140031, 0x140031).mirror(0xffce).rw(m_adc, FUNC(adc0804_device::read), FUNC(adc0804_device::write)); map(0xc68000, 0xc68fff).ram().share("segaic16road:roadram"); } diff --git a/src/mame/drivers/segaorun.cpp b/src/mame/drivers/segaorun.cpp index 2ce4221a57f..890012781fa 100644 --- a/src/mame/drivers/segaorun.cpp +++ b/src/mame/drivers/segaorun.cpp @@ -491,7 +491,7 @@ READ16_MEMBER( segaorun_state::misc_io_r ) return m_custom_io_r(space, offset, mem_mask); logerror("%06X:misc_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + return m_mapper->open_bus_r(); } @@ -664,7 +664,7 @@ READ16_MEMBER( segaorun_state::outrun_custom_io_r ) } logerror("%06X:outrun_custom_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + return m_mapper->open_bus_r(); } @@ -745,7 +745,7 @@ READ16_MEMBER( segaorun_state::shangon_custom_io_r ) } logerror("%06X:misc_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + return m_mapper->open_bus_r(); } diff --git a/src/mame/drivers/segas16a.cpp b/src/mame/drivers/segas16a.cpp index 8eae81d1c55..80c31947558 100644 --- a/src/mame/drivers/segas16a.cpp +++ b/src/mame/drivers/segas16a.cpp @@ -151,6 +151,7 @@ Tetris - - - - EPR12169 EPR12170 - #include "includes/segaipt.h" #include "machine/fd1089.h" +#include "machine/fd1094.h" #include "machine/nvram.h" #include "machine/segacrp2_device.h" #include "sound/dac.h" diff --git a/src/mame/drivers/segas16b.cpp b/src/mame/drivers/segas16b.cpp index 5531f9282fa..85ac0f7aa95 100644 --- a/src/mame/drivers/segas16b.cpp +++ b/src/mame/drivers/segas16b.cpp @@ -1005,7 +1005,7 @@ READ16_MEMBER( segas16b_state::rom_5797_bank_math_r ) // compare registers return m_cmptimer_1->read(offset); } - return open_bus_r(space); + return m_mapper->open_bus_r(); } @@ -1080,7 +1080,7 @@ READ16_MEMBER( segas16b_state::standard_io_r ) return ioport((offset & 1) ? "DSW1" : "DSW2")->read(); } logerror("%06X:standard_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + return m_mapper.found() ? m_mapper->open_bus_r() : 0xffff; } diff --git a/src/mame/drivers/segas18.cpp b/src/mame/drivers/segas18.cpp index fdd6fd95773..edc09a610e1 100644 --- a/src/mame/drivers/segas18.cpp +++ b/src/mame/drivers/segas18.cpp @@ -211,7 +211,7 @@ READ16_MEMBER( segas18_state::misc_io_r ) // I/O chip case 0x0000/2: case 0x1000/2: - return m_io->read(space, offset) | (open_bus_r(space) & 0xff00); + return m_io->read(space, offset) | (m_mapper->open_bus_r() & 0xff00); // video control latch case 0x2000/2: @@ -224,7 +224,7 @@ READ16_MEMBER( segas18_state::misc_io_r ) if (!m_custom_io_r.isnull()) return m_custom_io_r(space, offset, mem_mask); logerror("%06X:misc_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2); - return open_bus_r(space); + return m_mapper->open_bus_r(); } WRITE16_MEMBER( segas18_state::misc_io_w ) @@ -356,7 +356,7 @@ READ16_MEMBER( segas18_state::ddcrew_custom_io_r ) case 0x3024/2: return ioport("EXSERVICE")->read(); } - return open_bus_r(space); + return m_mapper->open_bus_r(); } @@ -380,7 +380,7 @@ READ16_MEMBER( segas18_state::lghost_custom_io_r ) m_lghost_value <<= 1; return result; } - return open_bus_r(space); + return m_mapper->open_bus_r(); } WRITE16_MEMBER( segas18_state::lghost_custom_io_w ) @@ -584,7 +584,7 @@ READ16_MEMBER( segas18_state::wwally_custom_io_r ) if (offset >= 0x3000/2 && offset < 0x3018/2) return m_upd4701[(offset & 0x0018/2) >> 2]->read_xy(space, offset & 0x0006/2); - return open_bus_r(space); + return m_mapper->open_bus_r(); } diff --git a/src/mame/drivers/segaxbd.cpp b/src/mame/drivers/segaxbd.cpp index e03ebf82bc9..79e19f3e166 100644 --- a/src/mame/drivers/segaxbd.cpp +++ b/src/mame/drivers/segaxbd.cpp @@ -270,6 +270,7 @@ ROMs: #include "includes/segaipt.h" #include "machine/adc0804.h" +#include "machine/fd1094.h" #include "machine/nvram.h" #include "sound/ym2151.h" #include "sound/segapcm.h" diff --git a/src/mame/drivers/segaybd.cpp b/src/mame/drivers/segaybd.cpp index f97425e6f00..567d367dca6 100644 --- a/src/mame/drivers/segaybd.cpp +++ b/src/mame/drivers/segaybd.cpp @@ -64,6 +64,7 @@ MB89372 - Uses 3 serial data transfer protocols: ASYNC, COP & BOP. Has a built #include "machine/mb8421.h" #include "machine/msm6253.h" #include "machine/nvram.h" +#include "machine/segaic16.h" #include "machine/315_5296.h" #include "sound/segapcm.h" #include "sound/ym2151.h" diff --git a/src/mame/includes/segahang.h b/src/mame/includes/segahang.h index 134e8dbec89..41b5947eccd 100644 --- a/src/mame/includes/segahang.h +++ b/src/mame/includes/segahang.h @@ -12,10 +12,10 @@ #include "machine/adc0804.h" #include "machine/i8255.h" #include "machine/gen_latch.h" -#include "machine/segaic16.h" #include "video/segaic16.h" #include "video/segaic16_road.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segahang_state @@ -33,6 +33,7 @@ public: , m_i8255_1(*this, "i8255_1") , m_i8255_2(*this, "i8255_2") , m_adc(*this, "adc") + , m_screen(*this, "screen") , m_sprites(*this, "sprites") , m_segaic16vid(*this, "segaic16vid") , m_segaic16road(*this, "segaic16road") @@ -79,10 +80,9 @@ private: DECLARE_READ8_MEMBER( adc_status_r ); // main CPU read/write handlers - DECLARE_READ16_MEMBER( hangon_io_r ); - DECLARE_WRITE16_MEMBER( hangon_io_w ); - DECLARE_READ16_MEMBER( sharrier_io_r ); - DECLARE_WRITE16_MEMBER( sharrier_io_w ); + uint8_t hangon_inputs_r(offs_t offset); + uint8_t sharrier_inputs_r(offs_t offset); + void sync_ppi_w(offs_t offset, uint8_t data); // ADC0804 read handler uint8_t analog_r(); @@ -135,6 +135,7 @@ private: required_device<i8255_device> m_i8255_1; required_device<i8255_device> m_i8255_2; required_device<adc0804_device> m_adc; + required_device<screen_device> m_screen; required_device<sega_16bit_sprite_device> m_sprites; required_device<segaic16_video_device> m_segaic16vid; required_device<segaic16_road_device> m_segaic16road; diff --git a/src/mame/includes/segaorun.h b/src/mame/includes/segaorun.h index d2cc1c9146e..c56d785273d 100644 --- a/src/mame/includes/segaorun.h +++ b/src/mame/includes/segaorun.h @@ -8,15 +8,16 @@ #include "cpu/m68000/m68000.h" #include "cpu/z80/z80.h" +#include "machine/315_5195.h" #include "machine/adc0804.h" #include "machine/i8255.h" #include "machine/nvram.h" -#include "machine/segaic16.h" #include "machine/timer.h" #include "machine/watchdog.h" #include "video/segaic16.h" #include "video/segaic16_road.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segaorun_state @@ -35,6 +36,7 @@ public: m_adc(*this, "adc"), m_nvram(*this, "nvram"), m_watchdog(*this, "watchdog"), + m_screen(*this, "screen"), m_sprites(*this, "sprites"), m_segaic16vid(*this, "segaic16vid"), m_segaic16road(*this, "segaic16road"), @@ -137,6 +139,7 @@ protected: required_device<adc0804_device> m_adc; optional_device<nvram_device> m_nvram; required_device<watchdog_timer_device> m_watchdog; + required_device<screen_device> m_screen; required_device<sega_16bit_sprite_device> m_sprites; required_device<segaic16_video_device> m_segaic16vid; required_device<segaic16_road_device> m_segaic16road; diff --git a/src/mame/includes/segas16a.h b/src/mame/includes/segas16a.h index 638d119d035..9486ee0e0f8 100644 --- a/src/mame/includes/segas16a.h +++ b/src/mame/includes/segas16a.h @@ -15,11 +15,11 @@ #include "machine/i8255.h" #include "machine/i8243.h" #include "machine/nvram.h" -#include "machine/segaic16.h" #include "machine/watchdog.h" #include "sound/ym2151.h" #include "video/segaic16.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segas16a_state @@ -41,6 +41,7 @@ public: , m_watchdog(*this, "watchdog") , m_segaic16vid(*this, "segaic16vid") , m_soundlatch(*this, "soundlatch") + , m_screen(*this, "screen") , m_sprites(*this, "sprites") , m_cxdio(*this, "cxdio") , m_workram(*this, "nvram") @@ -53,7 +54,7 @@ public: , m_last_buttons2(0) , m_read_port(0) , m_mj_input_num(0) - , m_mj_inputs(*this, {"MJ0", "MJ1", "MJ2", "MJ3", "MJ4", "MJ5"}) + , m_mj_inputs(*this, "MJ%u", 0U) , m_lamps(*this, "lamp%u", 0U) { } @@ -161,6 +162,7 @@ private: required_device<watchdog_timer_device> m_watchdog; required_device<segaic16_video_device> m_segaic16vid; required_device<generic_latch_8_device> m_soundlatch; + required_device<screen_device> m_screen; required_device<sega_sys16a_sprite_device> m_sprites; optional_device<cxd1095_device> m_cxdio; diff --git a/src/mame/includes/segas16b.h b/src/mame/includes/segas16b.h index 16fe92e61ca..49d7077d2bf 100644 --- a/src/mame/includes/segas16b.h +++ b/src/mame/includes/segas16b.h @@ -13,6 +13,7 @@ #include "cpu/m68000/m68000.h" #include "cpu/mcs51/mcs51.h" #include "cpu/z80/z80.h" +#include "machine/315_5195.h" #include "machine/cxd1095.h" #include "machine/gen_latch.h" #include "machine/nvram.h" @@ -25,6 +26,7 @@ #include "sound/volt_reg.h" #include "video/segaic16.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segas16b_state @@ -47,11 +49,12 @@ public: , m_cmptimer_1(*this, "cmptimer_1") , m_cmptimer_2(*this, "cmptimer_2") , m_nvram(*this, "nvram") + , m_screen(*this, "screen") , m_sprites(*this, "sprites") , m_segaic16vid(*this, "segaic16vid") , m_soundlatch(*this, "soundlatch") , m_cxdio(*this, "cxdio") - , m_upd4701a(*this, {"upd4701a1", "upd4701a2"}) + , m_upd4701a(*this, "upd4701a%u", 1U) , m_workram(*this, "workram") , m_romboard(ROM_BOARD_INVALID) , m_tilemap_type(segaic16_video_device::TILEMAP_16B) @@ -65,7 +68,7 @@ public: , m_hwc_right(*this, "RIGHT") , m_mj_input_num(0) , m_mj_last_val(0) - , m_mj_inputs(*this, {"MJ0", "MJ1", "MJ2", "MJ3", "MJ4", "MJ5"}) + , m_mj_inputs(*this, "MJ%u", 0U) , m_spritepalbase(0x400) , m_gfxdecode(*this, "gfxdecode") , m_sound_decrypted_opcodes(*this, "sound_decrypted_opcodes") @@ -252,6 +255,7 @@ protected: optional_device<sega_315_5250_compare_timer_device> m_cmptimer_1; optional_device<sega_315_5250_compare_timer_device> m_cmptimer_2; required_device<nvram_device> m_nvram; + required_device<screen_device> m_screen; optional_device<sega_sys16b_sprite_device> m_sprites; required_device<segaic16_video_device> m_segaic16vid; optional_device<generic_latch_8_device> m_soundlatch; // not for atomicp diff --git a/src/mame/includes/segas18.h b/src/mame/includes/segas18.h index 89309dd3fa7..af0a09b1ed1 100644 --- a/src/mame/includes/segas18.h +++ b/src/mame/includes/segas18.h @@ -13,13 +13,14 @@ #include "cpu/m68000/m68000.h" #include "cpu/mcs51/mcs51.h" #include "cpu/z80/z80.h" +#include "machine/315_5195.h" +#include "machine/315_5296.h" #include "machine/nvram.h" -#include "machine/segaic16.h" #include "machine/upd4701.h" -#include "machine/315_5296.h" #include "video/315_5313.h" #include "video/segaic16.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segas18_state @@ -38,10 +39,11 @@ public: , m_vdp(*this, "gen_vdp") , m_io(*this, "io") , m_nvram(*this, "nvram") + , m_screen(*this, "screen") , m_sprites(*this, "sprites") , m_segaic16vid(*this, "segaic16vid") , m_gfxdecode(*this, "gfxdecode") - , m_upd4701(*this, {"upd1", "upd2", "upd3"}) + , m_upd4701(*this, "upd%u", 1U) , m_workram(*this, "workram") , m_sprites_region(*this, "sprites") , m_soundbank(*this, "soundbank") @@ -152,6 +154,7 @@ private: required_device<sega315_5313_device> m_vdp; required_device<sega_315_5296_device> m_io; required_device<nvram_device> m_nvram; + required_device<screen_device> m_screen; required_device<sega_sys16b_sprite_device> m_sprites; required_device<segaic16_video_device> m_segaic16vid; required_device<gfxdecode_device> m_gfxdecode; diff --git a/src/mame/includes/segaxbd.h b/src/mame/includes/segaxbd.h index b93f9be1a57..34d82b1187f 100644 --- a/src/mame/includes/segaxbd.h +++ b/src/mame/includes/segaxbd.h @@ -10,7 +10,6 @@ #pragma once -#include "machine/segaic16.h" #include "video/segaic16.h" #include "video/segaic16_road.h" #include "video/sega16sp.h" @@ -22,6 +21,7 @@ #include "machine/i8251.h" #include "machine/mb3773.h" #include "machine/mb8421.h" +#include "machine/segaic16.h" #include "video/resnet.h" #include "emupal.h" #include "screen.h" diff --git a/src/mame/includes/segaybd.h b/src/mame/includes/segaybd.h index d344e610c10..9bb11c4ddab 100644 --- a/src/mame/includes/segaybd.h +++ b/src/mame/includes/segaybd.h @@ -13,9 +13,9 @@ #include "cpu/m68000/m68000.h" #include "cpu/z80/z80.h" #include "machine/mb3773.h" -#include "machine/segaic16.h" #include "video/segaic16.h" #include "video/sega16sp.h" +#include "screen.h" // ======================> segaybd_state @@ -32,6 +32,7 @@ public: , m_soundcpu(*this, "soundcpu") , m_linkcpu(*this, "linkcpu") , m_watchdog(*this, "watchdog") + , m_screen(*this, "screen") , m_bsprites(*this, "bsprites") , m_ysprites(*this, "ysprites") , m_segaic16vid(*this, "segaic16vid") @@ -121,6 +122,7 @@ private: required_device<z80_device> m_soundcpu; optional_device<z80_device> m_linkcpu; required_device<mb3773_device> m_watchdog; + required_device<screen_device> m_screen; required_device<sega_sys16b_sprite_device> m_bsprites; required_device<sega_yboard_sprite_device> m_ysprites; required_device<segaic16_video_device> m_segaic16vid; diff --git a/src/mame/includes/system16.h b/src/mame/includes/system16.h index 6d58f568b65..665cfeee563 100644 --- a/src/mame/includes/system16.h +++ b/src/mame/includes/system16.h @@ -5,12 +5,13 @@ #pragma once -#include "video/sega16sp.h" #include "machine/74157.h" #include "machine/gen_latch.h" -#include "machine/segaic16.h" #include "sound/msm5205.h" #include "sound/upd7759.h" +#include "video/sega16sp.h" +#include "video/segaic16.h" +#include "screen.h" #include "tilemap.h" class segas1x_bootleg_state : public sega_16bit_common_base @@ -28,6 +29,7 @@ public: , m_soundcpu_region(*this, "soundcpu") , m_soundbank(*this, "soundbank") , m_okibank(*this, "okibank") + , m_screen(*this, "screen") , m_sprites(*this, "sprites") , m_maincpu(*this, "maincpu") , m_soundcpu(*this, "soundcpu") @@ -225,6 +227,7 @@ private: optional_memory_bank m_soundbank; optional_memory_bank m_okibank; + required_device<screen_device> m_screen; optional_device<sega_16bit_sprite_device> m_sprites; uint16_t m_coinctrl; diff --git a/src/mame/machine/315_5195.cpp b/src/mame/machine/315_5195.cpp new file mode 100644 index 00000000000..0ba261a9854 --- /dev/null +++ b/src/mame/machine/315_5195.cpp @@ -0,0 +1,610 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + Sega 315-5195 memory mapper + +***************************************************************************/ + +#include "emu.h" +#include "315_5195.h" + +#include <algorithm> + +//************************************************************************** +// DEBUGGING +//************************************************************************** + +#define VERBOSE (0) + +#include "logmacro.h" + + + +//************************************************************************** +// CONSTANTS +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device, "sega_315_5195", "Sega 315-5195 Memory Mapper") + + + +//************************************************************************** +// 315-5195 MEMORY MAPPER +//************************************************************************** + +//------------------------------------------------- +// sega_315_5195_mapper_device - constructor +//------------------------------------------------- + +sega_315_5195_mapper_device::sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, SEGA_315_5195_MEM_MAPPER, tag, owner, clock) + , m_cpu(*this, finder_base::DUMMY_TAG) + , m_cpuregion(*this, finder_base::DUMMY_TAG) + , m_pbf_callback(*this) + , m_mcu_int_callback(*this) + , m_space(nullptr) + , m_decrypted_space(nullptr) + , m_curregion(0) + , m_to_sound(0) + , m_from_sound(0) + , m_open_bus_recurse(false) +{ +} + + +//------------------------------------------------- +// open_bus_r - return value from reading an +// unmapped address +//------------------------------------------------- + +u16 sega_315_5195_mapper_device::open_bus_r() +{ + // Unmapped memory returns the last word on the data bus, which is almost always the opcode + // of the next instruction due to prefetch; however, since we may be encrypted, we actually + // need to return the encrypted opcode, not the last decrypted data. + + // Believe it or not, this is actually important for Cotton, which has the following evil + // code: btst #0,$7038f7, which tests the low bit of an unmapped address, which thus should + // return the prefetched value. + + // prevent recursion + if (!machine().side_effects_disabled()) + { + if (m_open_bus_recurse) + return 0xffff; + + // read original encrypted memory at that address + m_open_bus_recurse = true; + const u16 result = m_space->read_word(m_cpu->pc()); + m_open_bus_recurse = false; + return result; + } + return 0xffff; +} + + +//------------------------------------------------- +// write - handle a write to the memory mapper +//------------------------------------------------- + +WRITE8_MEMBER( sega_315_5195_mapper_device::write ) +{ + // wraps every 32 bytes + offset &= 0x1f; + + LOG("(Write %02X = %02X)\n", offset, data); + + // remember the previous value and swap in the new one + const u8 oldval = m_regs[offset]; + m_regs[offset] = data; + + // switch off the offset + switch (offset) + { + case 0x02: + // misc commands + // 00 - resume execution after 03 + // 03 - maybe controls halt and reset lines together? + if ((oldval ^ m_regs[offset]) & 3) + { + // fd1094_machine_init calls device_reset on the CPU, so we must do this afterwards + m_cpu->set_input_line(INPUT_LINE_RESET, (m_regs[offset] & 3) == 3 ? ASSERT_LINE : CLEAR_LINE); + } + break; + + case 0x03: + // write through to the sound chip + machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_to_sound), this), data); + break; + + case 0x04: + // controls IRQ lines to 68000, negative logic -- write $B to signal IRQ4 + if ((m_regs[offset] & 7) != 7) + for (int irqnum = 0; irqnum < 8; irqnum++) + m_cpu->set_input_line(irqnum, (irqnum == (~m_regs[offset] & 7)) ? HOLD_LINE : CLEAR_LINE); + break; + + case 0x05: + // read/write control + // 01 - write data latched in 00,01 to 2 * (address in 0A,0B,0C) + // 02 - read data into latches 00,01 from 2 * (address in 07,08,09) + if (data == 0x01) + { + const offs_t addr = (m_regs[0x0a] << 17) | (m_regs[0x0b] << 9) | (m_regs[0x0c] << 1); + m_space->write_word(addr, (m_regs[0x00] << 8) | m_regs[0x01]); + } + else if (data == 0x02) + { + const offs_t addr = (m_regs[0x07] << 17) | (m_regs[0x08] << 9) | (m_regs[0x09] << 1); + const u16 result = m_space->read_word(addr); + m_regs[0x00] = result >> 8; + m_regs[0x01] = result; + } + break; + + case 0x07: case 0x08: case 0x09: + // writes here latch a 68000 address for writing + break; + + case 0x0a: case 0x0b: case 0x0c: + // writes here latch a 68000 address for reading + break; + + case 0x10: case 0x11: + case 0x12: case 0x13: + case 0x14: case 0x15: + case 0x16: case 0x17: + case 0x18: case 0x19: + case 0x1a: case 0x1b: + case 0x1c: case 0x1d: + case 0x1e: case 0x1f: + if (oldval != data) + update_mapping(); + break; + + default: + logerror("Unknown memory_mapper_w to address %02X = %02X\n", offset, data); + break; + } +} + + +//------------------------------------------------- +// read - handle a read from the memory mapper +//------------------------------------------------- + +READ8_MEMBER( sega_315_5195_mapper_device::read ) +{ + // wraps every 32 bytes + offset &= 0x1f; + + // switch off the offset + switch (offset) + { + case 0x00: + case 0x01: + // data latches - return the values latched + return m_regs[offset]; + + case 0x02: + // various input bits from the 68000 + // 01 - ???? + // 02 - ???? + // 04 - ???? + // 08 - ???? + // 40 - set if busy processing a read/write request + // Together, 01+02 == 00 if the 68000 is halted + // Together, 01+02+04+08 == 0F if the 68000 is executing + return (m_regs[0x02] & 3) == 3 ? 0x00 : 0x0f; + + case 0x03: + // this returns data that the sound CPU writes + if (!m_mcu_int_callback.isnull() && !machine().side_effects_disabled()) + m_mcu_int_callback(CLEAR_LINE); + return m_from_sound; + + default: + logerror("Unknown memory_mapper_r from address %02X\n", offset); + break; + } + return (space.data_width() == 8) ? 0xff : open_bus_r(); +} + + +//------------------------------------------------- +// map_as_rom - map a region as ROM data +//------------------------------------------------- + +void sega_315_5195_mapper_device::map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler) +{ + // determine parameters + region_info info; + compute_region(info, m_curregion, length, mirror, offset); + LOG("Map %06X-%06X (%06X) as ROM+%06X(%s) with handler=%s\n", info.start, info.end, info.mirror, rgnoffset, bank_name, + whandler.isnull() ? "none" : whandler.name()); + + // don't map if the start is past the end of the ROM region + const offs_t romsize = m_cpuregion->bytes(); + if (rgnoffset < romsize) + { + // clamp the end to the ROM size + offs_t romend = info.end; + if (rgnoffset + romend + 1 - info.start >= romsize) + romend = romsize - 1 - rgnoffset + info.start; + + // map now + m_space->install_read_bank(info.start, romend, info.mirror, bank_name); + if (m_decrypted_space) + m_decrypted_space->install_read_bank(info.start, romend, info.mirror, decrypted_bank_name); + + // configure the bank + memory_bank *bank = owner()->membank(bank_name); + memory_bank *decrypted_bank = owner()->membank(decrypted_bank_name); + u8 *memptr = m_cpuregion->base() + rgnoffset; + bank->set_base(memptr); + + // remember this bank, and decrypt if necessary + m_banks[m_curregion].set(bank, decrypted_bank, info.start, romend, rgnoffset, memptr); + } + + // either install a write handler if provided or unmap the region + // + // shdancer relies on this behaviour to prevent a write to ROM from + // falling through to the memory-mapping registers and crashing the + // game during stage 2-4 (see PC:$18a98). Protection maybe? + if (!whandler.isnull()) + m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); + else + m_space->unmap_write(info.start, info.end | info.mirror); +} + + +//------------------------------------------------- +// map_as_ram - map a region as RAM, with an +// optional write handler +//------------------------------------------------- + +void sega_315_5195_mapper_device::map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler) +{ + // determine parameters + region_info info; + compute_region(info, m_curregion, length, mirror, offset); + LOG("Map %06X-%06X (%06X) as RAM(%s) with handler=%s\n", info.start, info.end, info.mirror, bank_share_name, + whandler.isnull() ? "none" : whandler.name()); + + // map now + m_space->install_read_bank(info.start, info.end, info.mirror, bank_share_name); + + // either install a write handler or a write bank, as appropriate + if (!whandler.isnull()) + m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); + else + m_space->install_write_bank(info.start, info.end, info.mirror, bank_share_name); + + // configure the bank + memory_bank *bank = owner()->membank(bank_share_name); + bank->set_base(owner()->memshare(bank_share_name)->ptr()); + + // clear this rom bank reference + m_banks[m_curregion].clear(); +} + + +//------------------------------------------------- +// map_as_handler - map a region as a pair of +// read write handlers +//------------------------------------------------- + +void sega_315_5195_mapper_device::map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler) +{ + // determine parameters + region_info info; + compute_region(info, m_curregion, length, mirror, offset); + LOG("Map %06X-%06X (%06X) as handler read=%s write=%s\n", info.start, info.end, info.mirror, + rhandler.isnull() ? "none" : rhandler.name(), + whandler.isnull() ? "none" : whandler.name()); + + // install read/write handlers + if (!rhandler.isnull()) + m_space->install_read_handler(info.start, info.end, 0, info.mirror, 0, rhandler); + if (!whandler.isnull()) + m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); + + // clear this rom bank reference + m_banks[m_curregion].clear(); +} + + +//------------------------------------------------- +// configure_explicit - explicitly configure the +// memory map +//------------------------------------------------- + +void sega_315_5195_mapper_device::configure_explicit(const u8 *map_data) +{ + memcpy(&m_regs[0x10], map_data, 0x10); + update_mapping(); +} + + +//------------------------------------------------- +// fd1094_state_change - handle notifications +// of state changes +//------------------------------------------------- + +void sega_315_5195_mapper_device::fd1094_state_change(u8 state) +{ + // iterate over regions and set the decrypted address of any ROM banks + for (auto & elem : m_banks) + elem.update(); +} + + +//------------------------------------------------- +// write_to_sound - write data for the sound CPU +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_to_sound) +{ + m_to_sound = param; + if (!m_pbf_callback.isnull()) + m_pbf_callback(ASSERT_LINE); +} + + +//------------------------------------------------- +// write_from_sound - handle writes from the +// sound CPU +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_from_sound) +{ + m_from_sound = param; + if (!m_mcu_int_callback.isnull()) + m_mcu_int_callback(ASSERT_LINE); +} + + +//------------------------------------------------- +// pread - sound CPU read handler +//------------------------------------------------- + +READ8_MEMBER(sega_315_5195_mapper_device::pread) +{ + if (!m_pbf_callback.isnull() && !machine().side_effects_disabled()) + m_pbf_callback(CLEAR_LINE); + return m_to_sound; +} + + +//------------------------------------------------- +// pwrite - sound CPU write handler +//------------------------------------------------- + +WRITE8_MEMBER(sega_315_5195_mapper_device::pwrite) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_from_sound), this), data); +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sega_315_5195_mapper_device::device_start() +{ + // bind our handlers + m_mapper.bind_relative_to(*owner()); + m_pbf_callback.resolve(); + m_mcu_int_callback.resolve(); + + // if we are mapping an FD1089, tell all the banks + fd1089_base_device *fd1089 = dynamic_cast<fd1089_base_device *>(m_cpu.target()); + if (fd1089 != nullptr) + for (auto & elem : m_banks) + elem.set_decrypt(fd1089); + + // if we are mapping an FD1094, register for state change notifications and tell all the banks + fd1094_device *fd1094 = dynamic_cast<fd1094_device *>(m_cpu.target()); + if (fd1094 != nullptr) + { + fd1094->notify_state_change(fd1094_device::state_change_delegate(&sega_315_5195_mapper_device::fd1094_state_change, this)); + for (auto & elem : m_banks) + elem.set_decrypt(fd1094); + } + + // find the address space that is to be mapped + m_space = &m_cpu->space(AS_PROGRAM); + if (m_space == nullptr) + throw emu_fatalerror("Unable to find program address space on device '%s'", m_cpu.finder_tag()); + + m_decrypted_space = m_cpu->has_space(AS_OPCODES) ? &m_cpu->space(AS_OPCODES) : nullptr; + + // register for saves + save_item(NAME(m_regs)); + save_item(NAME(m_to_sound)); + save_item(NAME(m_from_sound)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sega_315_5195_mapper_device::device_reset() +{ + // hold the CPU in reset + m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + + // clear registers and recompute the memory mapping + std::fill(std::begin(m_regs), std::end(m_regs), 0); + update_mapping(); + + // release the CPU + m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + + m_to_sound = 0; + m_from_sound = 0; + if (!m_pbf_callback.isnull()) + m_pbf_callback(CLEAR_LINE); + if (!m_mcu_int_callback.isnull()) + m_mcu_int_callback(CLEAR_LINE); +} + + +//------------------------------------------------- +// compute_region - determine region parameters +// based on current configuration registers and +// actual underlying bus connections +//------------------------------------------------- + +void sega_315_5195_mapper_device::compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset) +{ + static const offs_t region_size_map[4] = { 0x00ffff, 0x01ffff, 0x07ffff, 0x1fffff }; + info.size_mask = region_size_map[m_regs[0x10 + 2 * index] & 3]; + info.base = (m_regs[0x11 + 2 * index] << 16) & ~info.size_mask; + info.mirror = mirror & info.size_mask; + info.start = info.base + (offset & info.size_mask); + info.end = info.start + std::min(length - 1, info.size_mask); +} + + +//------------------------------------------------- +// update_mapping - remap the entire CPU address +// space based on updated mappings +//------------------------------------------------- + +void sega_315_5195_mapper_device::update_mapping() +{ + LOG("---- Remapping:\n"); + + // first reset everything back to the beginning + m_space->unmap_readwrite(0x000000, 0xffffff); + m_space->install_readwrite_handler(0x000000, 0xffffff, read8_delegate(FUNC(sega_315_5195_mapper_device::read), this), write8_delegate(FUNC(sega_315_5195_mapper_device::write), this), 0x00ff); + + // loop over the regions + for (int index = 7; index >= 0; index--) + { + // note the current region and call the mapper to find out what to do + m_curregion = index; + m_mapper(*this, index); + } +} + + +//************************************************************************** +// DECRYPT BANK HELPER CLASS +//************************************************************************** + +//------------------------------------------------- +// decrypt_bank - constructor +//------------------------------------------------- + +sega_315_5195_mapper_device::decrypt_bank::decrypt_bank() + : m_bank(nullptr) + , m_decrypted_bank(nullptr) + , m_start(0) + , m_end(0) + , m_rgnoffs(~0) + , m_srcptr(nullptr) + , m_fd1089(nullptr) +{ + // invalidate all states + reset(); +} + + +//------------------------------------------------- +// ~decrypt_bank - destructor +//------------------------------------------------- + +sega_315_5195_mapper_device::decrypt_bank::~decrypt_bank() +{ +} + + +//------------------------------------------------- +// set_decrypt - configure the decryption target +// CPU +//------------------------------------------------- + +void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1089_base_device *fd1089) +{ + // set the fd1089 pointer + m_fd1089 = fd1089; + + // clear out all fd1094 stuff + m_fd1094_cache.reset(); +} + +void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1094_device *fd1094) +{ + // set the fd1094 pointer and allocate a decryption cache + m_fd1094_cache = std::make_unique<fd1094_decryption_cache>(*fd1094); + + // clear out all fd1089 stuff + m_fd1089 = nullptr; + m_fd1089_decrypted.clear(); +} + + +//------------------------------------------------- +// set - set the parameters of this bank after +// a change +//------------------------------------------------- + +void sega_315_5195_mapper_device::decrypt_bank::set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src) +{ + // ignore if not encrypted + if (m_fd1089 == nullptr && m_fd1094_cache == nullptr) + return; + + // ignore if nothing is changing + if (bank == m_bank && start == m_start && end == m_end && rgnoffs == m_rgnoffs && src == m_srcptr) + return; + + // if the start, end, or src change, throw away any cached data + reset(); + + // update to the current state + m_bank = bank; + m_decrypted_bank = decrypted_bank; + m_start = start; + m_end = end; + m_rgnoffs = rgnoffs; + m_srcptr = src; + + // configure the fd1094 cache + if (m_fd1094_cache != nullptr) + m_fd1094_cache->configure(m_start, m_end + 1 - m_start, m_rgnoffs); + + // force an update of what we have + update(); +} + + +//------------------------------------------------- +// update - update the decrypted memory base +// if this rom bank has been assigned +//------------------------------------------------- + +void sega_315_5195_mapper_device::decrypt_bank::update() +{ + // if this isn't a valid state, don't try to do anything + if (m_bank == nullptr || m_srcptr == nullptr) + return; + + // fd1089 case + if (m_fd1089 != nullptr) + { + m_fd1089_decrypted.resize((m_end + 1 - m_start) / 2); + m_fd1089->decrypt(m_start, m_end + 1 - m_start, m_rgnoffs, &m_fd1089_decrypted[0], reinterpret_cast<u16 *>(m_srcptr)); + m_decrypted_bank->set_base(&m_fd1089_decrypted[0]); + } + + // fd1094 case + if (m_fd1094_cache != nullptr) + m_decrypted_bank->set_base(m_fd1094_cache->decrypted_opcodes(m_fd1094_cache->fd1094().state())); +} diff --git a/src/mame/machine/315_5195.h b/src/mame/machine/315_5195.h new file mode 100644 index 00000000000..479abf824f9 --- /dev/null +++ b/src/mame/machine/315_5195.h @@ -0,0 +1,147 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles +/*************************************************************************** + + Sega 315-5195 memory mapper + +***************************************************************************/ + +#ifndef MAME_MACHINE_315_5195_H +#define MAME_MACHINE_315_5195_H + +#pragma once + +#include "cpu/m68000/m68000.h" +#include "machine/fd1089.h" +#include "machine/fd1094.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> sega_315_5195_mapper_device + +class sega_315_5195_mapper_device : public device_t +{ +public: + typedef device_delegate<void (sega_315_5195_mapper_device &, u8)> mapper_delegate; + + // construction/destruction + template <typename T> + sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&cpu_tag) + : sega_315_5195_mapper_device(mconfig, tag, owner, clock) + { + m_cpu.set_tag(std::forward<T>(cpu_tag)); + m_cpuregion.set_tag(std::forward<T>(cpu_tag)); + } + + sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // configuration helpers + template <typename... T> void set_mapper(T &&... args) { m_mapper = mapper_delegate(std::forward<T>(args)...); } + + auto pbf() { return m_pbf_callback.bind(); } + auto mcu_int() { return m_mcu_int_callback.bind(); } + + // public interface + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( pread ); + DECLARE_WRITE8_MEMBER( pwrite ); + + // mapping helpers + void map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler); + void map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler); + void map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler); + + // perform an explicit configuration (for bootlegs with hard-coded mappings) + void configure_explicit(const u8 *map_data); + + // open bus read helpers + u16 open_bus_r(); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + +private: + TIMER_CALLBACK_MEMBER(write_to_sound); + TIMER_CALLBACK_MEMBER(write_from_sound); + + // internal region struct + struct region_info + { + offs_t size_mask; + offs_t base; + offs_t mirror; + offs_t start; + offs_t end; + }; + + // helper class for tracking banks mapped to ROM regions + class decrypt_bank + { + public: + // construction/destruction + decrypt_bank(); + ~decrypt_bank(); + + // configuration + void set_decrypt(fd1089_base_device *fd1089); + void set_decrypt(fd1094_device *fd1094); + void clear() { set(nullptr, nullptr, 0, 0, ~0, nullptr); } + void set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src); + + // updating + void update(); + void reset() { m_fd1089_decrypted.clear(); if (m_fd1094_cache != nullptr) m_fd1094_cache->reset(); } + + private: + // internal state + memory_bank * m_bank; + memory_bank * m_decrypted_bank; + offs_t m_start; + offs_t m_end; + offs_t m_rgnoffs; + u8 * m_srcptr; + fd1089_base_device *m_fd1089; + std::vector<u16> m_fd1089_decrypted; + std::unique_ptr<fd1094_decryption_cache> m_fd1094_cache; + }; + + // internal helpers + void compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset = 0); + void update_mapping(); + void fd1094_state_change(u8 state); + + // configuration + required_device<m68000_device> m_cpu; + required_memory_region m_cpuregion; + mapper_delegate m_mapper; + devcb_write_line m_pbf_callback; + devcb_write_line m_mcu_int_callback; + + // internal state + address_space * m_space; + address_space * m_decrypted_space; + u8 m_regs[0x20]; + u8 m_curregion; + decrypt_bank m_banks[8]; + + // communication registers + u8 m_to_sound; + u8 m_from_sound; + + // flag to track recursion through open_bus_r + bool m_open_bus_recurse; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device) + + +#endif // MAME_MACHINE_315_5195_H diff --git a/src/mame/machine/segaic16.cpp b/src/mame/machine/segaic16.cpp index 42ba9e2e0c9..11f47ce911e 100644 --- a/src/mame/machine/segaic16.cpp +++ b/src/mame/machine/segaic16.cpp @@ -8,7 +8,6 @@ #include "emu.h" #include "segaic16.h" -#include "video/resnet.h" #include <algorithm> @@ -16,7 +15,6 @@ // DEBUGGING //************************************************************************** -#define LOG_MEMORY_MAP (0) #define LOG_MULTIPLY (0) #define LOG_DIVIDE (0) #define LOG_COMPARE (0) @@ -28,7 +26,6 @@ //************************************************************************** // device type definition -DEFINE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device, "sega_315_5195", "Sega 315-5195 Memory Mapper") DEFINE_DEVICE_TYPE(SEGA_315_5248_MULTIPLIER, sega_315_5248_multiplier_device, "sega_315_5248", "Sega 315-5248 Multiplier") DEFINE_DEVICE_TYPE(SEGA_315_5249_DIVIDER, sega_315_5249_divider_device, "sega_315_5249", "Sega 315-5249 Divider") DEFINE_DEVICE_TYPE(SEGA_315_5250_COMPARE_TIMER, sega_315_5250_compare_timer_device, "sega_315_5250", "Sega 315-5250 Compare/Timer") @@ -36,755 +33,6 @@ DEFINE_DEVICE_TYPE(SEGA_315_5250_COMPARE_TIMER, sega_315_5250_compare_timer_devi //************************************************************************** -// MISC HELPERS -//************************************************************************** - -//------------------------------------------------- -// sega_16bit_common_base - constructor -//------------------------------------------------- - -sega_16bit_common_base::sega_16bit_common_base(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_paletteram(*this, "paletteram") - , m_open_bus_recurse(false) - , m_palette_entries(0) - , m_screen(*this, "screen") - , m_palette(*this, "palette") -{ - palette_init(); -} - - -//------------------------------------------------- -// open_bus_r - return value from reading an -// unmapped address -//------------------------------------------------- - -u16 sega_16bit_common_base::open_bus_r(address_space &space) -{ - // Unmapped memory returns the last word on the data bus, which is almost always the opcode - // of the next instruction due to prefetch; however, since we may be encrypted, we actually - // need to return the encrypted opcode, not the last decrypted data. - - // Believe it or not, this is actually important for Cotton, which has the following evil - // code: btst #0,$7038f7, which tests the low bit of an unmapped address, which thus should - // return the prefetched value. - - // prevent recursion - if (!machine().side_effects_disabled()) - { - if (m_open_bus_recurse) - return 0xffff; - - // read original encrypted memory at that address - m_open_bus_recurse = true; - const u16 result = space.read_word(space.device().state().pc()); - m_open_bus_recurse = false; - return result; - } - return 0xffff; -} - - -//------------------------------------------------- -// palette_init - precompute weighted RGB values -// for each input value 0-31 -//------------------------------------------------- - -void sega_16bit_common_base::palette_init() -{ - // - // Color generation details - // - // Each color is made up of 5 bits, connected through one or more resistors like so: - // - // Bit 0 = 1 x 3.9K ohm - // Bit 1 = 1 x 2.0K ohm - // Bit 2 = 1 x 1.0K ohm - // Bit 3 = 2 x 1.0K ohm - // Bit 4 = 4 x 1.0K ohm - // - // Another data bit is connected by a tristate buffer to the color output through a - // 470 ohm resistor. The buffer allows the resistor to have no effect (tristate), - // halve brightness (pull-down) or double brightness (pull-up). The data bit source - // is bit 15 of each color RAM entry. - // - - // compute weight table for regular palette entries - static const int resistances_normal[6] = { 3900, 2000, 1000, 1000/2, 1000/4, 0 }; - double weights_normal[6]; - compute_resistor_weights(0, 255, -1.0, - 6, resistances_normal, weights_normal, 0, 0, - 0, nullptr, nullptr, 0, 0, - 0, nullptr, nullptr, 0, 0); - - // compute weight table for shadow/hilight palette entries - static const int resistances_sh[6] = { 3900, 2000, 1000, 1000/2, 1000/4, 470 }; - double weights_sh[6]; - compute_resistor_weights(0, 255, -1.0, - 6, resistances_sh, weights_sh, 0, 0, - 0, nullptr, nullptr, 0, 0, - 0, nullptr, nullptr, 0, 0); - - // compute R, G, B for each weight - for (int value = 0; value < 32; value++) - { - const u8 i4 = (value >> 4) & 1; - const u8 i3 = (value >> 3) & 1; - const u8 i2 = (value >> 2) & 1; - const u8 i1 = (value >> 1) & 1; - const u8 i0 = (value >> 0) & 1; - m_palette_normal[value] = combine_weights(weights_normal, i0, i1, i2, i3, i4, 0); - m_palette_shadow[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 0); - m_palette_hilight[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 1); - } -} - - -//------------------------------------------------- -// paletteram_w - handle writes to palette RAM -//------------------------------------------------- - -WRITE16_MEMBER( sega_16bit_common_base::paletteram_w ) -{ - // compute the number of entries - if (m_palette_entries == 0) - m_palette_entries = memshare("paletteram")->bytes() / 2; - - // get the new value - u16 newval = m_paletteram[offset]; - COMBINE_DATA(&newval); - m_paletteram[offset] = newval; - - // byte 0 byte 1 - // sBGR BBBB GGGG RRRR - // x000 4321 4321 4321 - const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e); - const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e); - const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e); - - // shadow / hilight toggle bit in palette RAM - rgb_t effects = (newval & 0x8000) ? - rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) : - rgb_t(m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); - m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); - m_palette->set_pen_color(offset + 1 * m_palette_entries, effects); -} - -WRITE16_MEMBER( sega_16bit_common_base::hangon_paletteram_w ) -{ - // compute the number of entries - if (m_palette_entries == 0) - m_palette_entries = memshare("paletteram")->bytes() / 2; - - // get the new value - u16 newval = m_paletteram[offset]; - COMBINE_DATA(&newval); - m_paletteram[offset] = newval; - - // byte 0 byte 1 - // xBGR BBBB GGGG RRRR - // x000 4321 4321 4321 - const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e); - const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e); - const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e); - - // hangon has external shadow / hilight toggle bit - m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); - m_palette->set_pen_color(offset + 1 * m_palette_entries, m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); - m_palette->set_pen_color(offset + 2 * m_palette_entries, m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]); -} - -WRITE16_MEMBER( sega_16bit_common_base::philko_paletteram_w ) -{ - // compute the number of entries - if (m_palette_entries == 0) - m_palette_entries = memshare("paletteram")->bytes() / 2; - - // get the new value - u16 newval = m_paletteram[offset]; - COMBINE_DATA(&newval); - m_paletteram[offset] = newval; - - // byte 0 byte 1 - // sRRR RRGG GGGB BBBB - // x432 1043 2104 3210 - const u8 b = (newval >> 0) & 0x1f; - const u8 g = (newval >> 5) & 0x1f; - const u8 r = (newval >> 10) & 0x1f; - - // shadow / hilight toggle bit in palette RAM - rgb_t effects = (newval & 0x8000) ? - rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) : - rgb_t(m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); - m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); - m_palette->set_pen_color(offset + 1 * m_palette_entries, effects); -} - - - -//************************************************************************** -// 315-5195 MEMORY MAPPER -//************************************************************************** - -//------------------------------------------------- -// sega_315_5195_mapper_device - constructor -//------------------------------------------------- - -sega_315_5195_mapper_device::sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, SEGA_315_5195_MEM_MAPPER, tag, owner, clock) - , m_cpu(*this, finder_base::DUMMY_TAG) - , m_cpuregion(*this, finder_base::DUMMY_TAG) - , m_pbf_callback(*this) - , m_mcu_int_callback(*this) - , m_space(nullptr) - , m_decrypted_space(nullptr) - , m_curregion(0) - , m_to_sound(0) - , m_from_sound(0) -{ -} - - -//------------------------------------------------- -// write - handle a write to the memory mapper -//------------------------------------------------- - -WRITE8_MEMBER( sega_315_5195_mapper_device::write ) -{ - // wraps every 32 bytes - offset &= 0x1f; - -if (LOG_MEMORY_MAP) osd_printf_debug("(Write %02X = %02X)\n", offset, data); - - // remember the previous value and swap in the new one - const u8 oldval = m_regs[offset]; - m_regs[offset] = data; - - // switch off the offset - switch (offset) - { - case 0x02: - // misc commands - // 00 - resume execution after 03 - // 03 - maybe controls halt and reset lines together? - if ((oldval ^ m_regs[offset]) & 3) - { - // fd1094_machine_init calls device_reset on the CPU, so we must do this afterwards - m_cpu->set_input_line(INPUT_LINE_RESET, (m_regs[offset] & 3) == 3 ? ASSERT_LINE : CLEAR_LINE); - } - break; - - case 0x03: - // write through to the sound chip - machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_to_sound), this), data); - break; - - case 0x04: - // controls IRQ lines to 68000, negative logic -- write $B to signal IRQ4 - if ((m_regs[offset] & 7) != 7) - for (int irqnum = 0; irqnum < 8; irqnum++) - m_cpu->set_input_line(irqnum, (irqnum == (~m_regs[offset] & 7)) ? HOLD_LINE : CLEAR_LINE); - break; - - case 0x05: - // read/write control - // 01 - write data latched in 00,01 to 2 * (address in 0A,0B,0C) - // 02 - read data into latches 00,01 from 2 * (address in 07,08,09) - if (data == 0x01) - { - const offs_t addr = (m_regs[0x0a] << 17) | (m_regs[0x0b] << 9) | (m_regs[0x0c] << 1); - m_space->write_word(addr, (m_regs[0x00] << 8) | m_regs[0x01]); - } - else if (data == 0x02) - { - const offs_t addr = (m_regs[0x07] << 17) | (m_regs[0x08] << 9) | (m_regs[0x09] << 1); - const u16 result = m_space->read_word(addr); - m_regs[0x00] = result >> 8; - m_regs[0x01] = result; - } - break; - - case 0x07: case 0x08: case 0x09: - // writes here latch a 68000 address for writing - break; - - case 0x0a: case 0x0b: case 0x0c: - // writes here latch a 68000 address for reading - break; - - case 0x10: case 0x11: - case 0x12: case 0x13: - case 0x14: case 0x15: - case 0x16: case 0x17: - case 0x18: case 0x19: - case 0x1a: case 0x1b: - case 0x1c: case 0x1d: - case 0x1e: case 0x1f: - if (oldval != data) - update_mapping(); - break; - - default: - logerror("Unknown memory_mapper_w to address %02X = %02X\n", offset, data); - break; - } -} - - -//------------------------------------------------- -// read - handle a read from the memory mapper -//------------------------------------------------- - -READ8_MEMBER( sega_315_5195_mapper_device::read ) -{ - // wraps every 32 bytes - offset &= 0x1f; - - // switch off the offset - switch (offset) - { - case 0x00: - case 0x01: - // data latches - return the values latched - return m_regs[offset]; - - case 0x02: - // various input bits from the 68000 - // 01 - ???? - // 02 - ???? - // 04 - ???? - // 08 - ???? - // 40 - set if busy processing a read/write request - // Together, 01+02 == 00 if the 68000 is halted - // Together, 01+02+04+08 == 0F if the 68000 is executing - return (m_regs[0x02] & 3) == 3 ? 0x00 : 0x0f; - - case 0x03: - // this returns data that the sound CPU writes - if (!m_mcu_int_callback.isnull() && !machine().side_effects_disabled()) - m_mcu_int_callback(CLEAR_LINE); - return m_from_sound; - - default: - logerror("Unknown memory_mapper_r from address %02X\n", offset); - break; - } - return (space.data_width() == 8) ? 0xff : machine().driver_data<sega_16bit_common_base>()->open_bus_r(space); -} - - -//------------------------------------------------- -// map_as_rom - map a region as ROM data -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - if (LOG_MEMORY_MAP) - { - osd_printf_debug("Map %06X-%06X (%06X) as ROM+%06X(%s)", info.start, info.end, info.mirror, rgnoffset, bank_name); - if (!whandler.isnull()) osd_printf_debug(" with handler=%s", whandler.name()); - osd_printf_debug("\n"); - } - - // don't map if the start is past the end of the ROM region - const offs_t romsize = m_cpuregion->bytes(); - if (rgnoffset < romsize) - { - // clamp the end to the ROM size - offs_t romend = info.end; - if (rgnoffset + romend + 1 - info.start >= romsize) - romend = romsize - 1 - rgnoffset + info.start; - - // map now - m_space->install_read_bank(info.start, romend, info.mirror, bank_name); - if (m_decrypted_space) - m_decrypted_space->install_read_bank(info.start, romend, info.mirror, decrypted_bank_name); - - // configure the bank - memory_bank *bank = owner()->membank(bank_name); - memory_bank *decrypted_bank = owner()->membank(decrypted_bank_name); - u8 *memptr = m_cpuregion->base() + rgnoffset; - bank->set_base(memptr); - - // remember this bank, and decrypt if necessary - m_banks[m_curregion].set(bank, decrypted_bank, info.start, romend, rgnoffset, memptr); - } - - // either install a write handler if provided or unmap the region - // - // shdancer relies on this behaviour to prevent a write to ROM from - // falling through to the memory-mapping registers and crashing the - // game during stage 2-4 (see PC:$18a98). Protection maybe? - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - else - m_space->unmap_write(info.start, info.end | info.mirror); -} - - -//------------------------------------------------- -// map_as_ram - map a region as RAM, with an -// optional write handler -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - if (LOG_MEMORY_MAP) - { - osd_printf_debug("Map %06X-%06X (%06X) as RAM(%s)", info.start, info.end, info.mirror, bank_share_name); - if (!whandler.isnull()) osd_printf_debug(" with handler=%s", whandler.name()); - osd_printf_debug("\n"); - } - - // map now - m_space->install_read_bank(info.start, info.end, info.mirror, bank_share_name); - - // either install a write handler or a write bank, as appropriate - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - else - m_space->install_write_bank(info.start, info.end, info.mirror, bank_share_name); - - // configure the bank - memory_bank *bank = owner()->membank(bank_share_name); - bank->set_base(owner()->memshare(bank_share_name)->ptr()); - - // clear this rom bank reference - m_banks[m_curregion].clear(); -} - - -//------------------------------------------------- -// map_as_handler - map a region as a pair of -// read write handlers -//------------------------------------------------- - -void sega_315_5195_mapper_device::map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler) -{ - // determine parameters - region_info info; - compute_region(info, m_curregion, length, mirror, offset); - if (LOG_MEMORY_MAP) - { - osd_printf_debug("Map %06X-%06X (%06X) as handler", info.start, info.end, info.mirror); - if (!rhandler.isnull()) osd_printf_debug(" read=%s", rhandler.name()); - if (!whandler.isnull()) osd_printf_debug(" write=%s", whandler.name()); - osd_printf_debug("\n"); - } - - // install read/write handlers - if (!rhandler.isnull()) - m_space->install_read_handler(info.start, info.end, 0, info.mirror, 0, rhandler); - if (!whandler.isnull()) - m_space->install_write_handler(info.start, info.end, 0, info.mirror, 0, whandler); - - // clear this rom bank reference - m_banks[m_curregion].clear(); -} - - -//------------------------------------------------- -// configure_explicit - explicitly configure the -// memory map -//------------------------------------------------- - -void sega_315_5195_mapper_device::configure_explicit(const u8 *map_data) -{ - memcpy(&m_regs[0x10], map_data, 0x10); - update_mapping(); -} - - -//------------------------------------------------- -// fd1094_state_change - handle notifications -// of state changes -//------------------------------------------------- - -void sega_315_5195_mapper_device::fd1094_state_change(u8 state) -{ - // iterate over regions and set the decrypted address of any ROM banks - for (auto & elem : m_banks) - elem.update(); -} - - -//------------------------------------------------- -// write_to_sound - write data for the sound CPU -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_to_sound) -{ - m_to_sound = param; - if (!m_pbf_callback.isnull()) - m_pbf_callback(ASSERT_LINE); -} - - -//------------------------------------------------- -// write_from_sound - handle writes from the -// sound CPU -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(sega_315_5195_mapper_device::write_from_sound) -{ - m_from_sound = param; - if (!m_mcu_int_callback.isnull()) - m_mcu_int_callback(ASSERT_LINE); -} - - -//------------------------------------------------- -// pread - sound CPU read handler -//------------------------------------------------- - -READ8_MEMBER(sega_315_5195_mapper_device::pread) -{ - if (!m_pbf_callback.isnull() && !machine().side_effects_disabled()) - m_pbf_callback(CLEAR_LINE); - return m_to_sound; -} - - -//------------------------------------------------- -// pwrite - sound CPU write handler -//------------------------------------------------- - -WRITE8_MEMBER(sega_315_5195_mapper_device::pwrite) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(sega_315_5195_mapper_device::write_from_sound), this), data); -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sega_315_5195_mapper_device::device_start() -{ - // bind our handlers - m_mapper.bind_relative_to(*owner()); - m_pbf_callback.resolve(); - m_mcu_int_callback.resolve(); - - // if we are mapping an FD1089, tell all the banks - fd1089_base_device *fd1089 = dynamic_cast<fd1089_base_device *>(m_cpu.target()); - if (fd1089 != nullptr) - for (auto & elem : m_banks) - elem.set_decrypt(fd1089); - - // if we are mapping an FD1094, register for state change notifications and tell all the banks - fd1094_device *fd1094 = dynamic_cast<fd1094_device *>(m_cpu.target()); - if (fd1094 != nullptr) - { - fd1094->notify_state_change(fd1094_device::state_change_delegate(&sega_315_5195_mapper_device::fd1094_state_change, this)); - for (auto & elem : m_banks) - elem.set_decrypt(fd1094); - } - - // find the address space that is to be mapped - m_space = &m_cpu->space(AS_PROGRAM); - if (m_space == nullptr) - throw emu_fatalerror("Unable to find program address space on device '%s'", m_cpu.finder_tag()); - - m_decrypted_space = m_cpu->has_space(AS_OPCODES) ? &m_cpu->space(AS_OPCODES) : nullptr; - - // register for saves - save_item(NAME(m_regs)); - save_item(NAME(m_to_sound)); - save_item(NAME(m_from_sound)); -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sega_315_5195_mapper_device::device_reset() -{ - // hold the CPU in reset - m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - - // clear registers and recompute the memory mapping - std::fill(std::begin(m_regs), std::end(m_regs), 0); - update_mapping(); - - // release the CPU - m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - - m_to_sound = 0; - m_from_sound = 0; - if (!m_pbf_callback.isnull()) - m_pbf_callback(CLEAR_LINE); - if (!m_mcu_int_callback.isnull()) - m_mcu_int_callback(CLEAR_LINE); -} - - -//------------------------------------------------- -// compute_region - determine region parameters -// based on current configuration registers and -// actual underlying bus connections -//------------------------------------------------- - -void sega_315_5195_mapper_device::compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset) -{ - static const offs_t region_size_map[4] = { 0x00ffff, 0x01ffff, 0x07ffff, 0x1fffff }; - info.size_mask = region_size_map[m_regs[0x10 + 2 * index] & 3]; - info.base = (m_regs[0x11 + 2 * index] << 16) & ~info.size_mask; - info.mirror = mirror & info.size_mask; - info.start = info.base + (offset & info.size_mask); - info.end = info.start + std::min(length - 1, info.size_mask); -} - - -//------------------------------------------------- -// update_mapping - remap the entire CPU address -// space based on updated mappings -//------------------------------------------------- - -void sega_315_5195_mapper_device::update_mapping() -{ - if (LOG_MEMORY_MAP) osd_printf_debug("----\nRemapping:\n"); - - // first reset everything back to the beginning - m_space->unmap_readwrite(0x000000, 0xffffff); - m_space->install_readwrite_handler(0x000000, 0xffffff, read8_delegate(FUNC(sega_315_5195_mapper_device::read), this), write8_delegate(FUNC(sega_315_5195_mapper_device::write), this), 0x00ff); - - // loop over the regions - for (int index = 7; index >= 0; index--) - { - // note the current region and call the mapper to find out what to do - m_curregion = index; - m_mapper(*this, index); - } -} - - -//************************************************************************** -// DECRYPT BANK HELPER CLASS -//************************************************************************** - -//------------------------------------------------- -// decrypt_bank - constructor -//------------------------------------------------- - -sega_315_5195_mapper_device::decrypt_bank::decrypt_bank() - : m_bank(nullptr) - , m_decrypted_bank(nullptr) - , m_start(0) - , m_end(0) - , m_rgnoffs(~0) - , m_srcptr(nullptr) - , m_fd1089(nullptr) -{ - // invalidate all states - reset(); -} - - -//------------------------------------------------- -// ~decrypt_bank - destructor -//------------------------------------------------- - -sega_315_5195_mapper_device::decrypt_bank::~decrypt_bank() -{ -} - - -//------------------------------------------------- -// set_decrypt - configure the decryption target -// CPU -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1089_base_device *fd1089) -{ - // set the fd1089 pointer - m_fd1089 = fd1089; - - // clear out all fd1094 stuff - m_fd1094_cache.reset(); -} - -void sega_315_5195_mapper_device::decrypt_bank::set_decrypt(fd1094_device *fd1094) -{ - // set the fd1094 pointer and allocate a decryption cache - m_fd1094_cache = std::make_unique<fd1094_decryption_cache>(*fd1094); - - // clear out all fd1089 stuff - m_fd1089 = nullptr; - m_fd1089_decrypted.clear(); -} - - -//------------------------------------------------- -// set - set the parameters of this bank after -// a change -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src) -{ - // ignore if not encrypted - if (m_fd1089 == nullptr && m_fd1094_cache == nullptr) - return; - - // ignore if nothing is changing - if (bank == m_bank && start == m_start && end == m_end && rgnoffs == m_rgnoffs && src == m_srcptr) - return; - - // if the start, end, or src change, throw away any cached data - reset(); - - // update to the current state - m_bank = bank; - m_decrypted_bank = decrypted_bank; - m_start = start; - m_end = end; - m_rgnoffs = rgnoffs; - m_srcptr = src; - - // configure the fd1094 cache - if (m_fd1094_cache != nullptr) - m_fd1094_cache->configure(m_start, m_end + 1 - m_start, m_rgnoffs); - - // force an update of what we have - update(); -} - - -//------------------------------------------------- -// update - update the decrypted memory base -// if this rom bank has been assigned -//------------------------------------------------- - -void sega_315_5195_mapper_device::decrypt_bank::update() -{ - // if this isn't a valid state, don't try to do anything - if (m_bank == nullptr || m_srcptr == nullptr) - return; - - // fd1089 case - if (m_fd1089 != nullptr) - { - m_fd1089_decrypted.resize((m_end + 1 - m_start) / 2); - m_fd1089->decrypt(m_start, m_end + 1 - m_start, m_rgnoffs, &m_fd1089_decrypted[0], reinterpret_cast<u16 *>(m_srcptr)); - m_decrypted_bank->set_base(&m_fd1089_decrypted[0]); - } - - // fd1094 case - if (m_fd1094_cache != nullptr) - m_decrypted_bank->set_base(m_fd1094_cache->decrypted_opcodes(m_fd1094_cache->fd1094().state())); -} - - - -//************************************************************************** // 315-5248 MULTIPLIER //************************************************************************** diff --git a/src/mame/machine/segaic16.h b/src/mame/machine/segaic16.h index f1e7b9b5e45..06483b4e727 100644 --- a/src/mame/machine/segaic16.h +++ b/src/mame/machine/segaic16.h @@ -11,167 +11,12 @@ #pragma once -#include "cpu/m68000/m68000.h" -#include "machine/fd1089.h" -#include "machine/fd1094.h" -#include "emupal.h" -#include "screen.h" - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -// ======================> sega_16bit_common_base - -class sega_16bit_common_base : public driver_device -{ -public: - // open bus read helpers - u16 open_bus_r(address_space &space); - - // palette helpers - DECLARE_WRITE16_MEMBER( paletteram_w ); - DECLARE_WRITE16_MEMBER( hangon_paletteram_w ); - DECLARE_WRITE16_MEMBER( philko_paletteram_w ); - -protected: - // construction/destruction - sega_16bit_common_base(const machine_config &mconfig, device_type type, const char *tag); - - // internal helpers - void palette_init(); - -public: // -- stupid system16.cpp - // memory pointers - required_shared_ptr<u16> m_paletteram; -protected: - - // internal state - bool m_open_bus_recurse; // flag to track recursion through open_bus_r - u32 m_palette_entries; // number of palette entries - u8 m_palette_normal[32]; // RGB translations for normal pixels - u8 m_palette_shadow[32]; // RGB translations for shadowed pixels - u8 m_palette_hilight[32]; // RGB translations for hilighted pixels - required_device<screen_device> m_screen; - required_device<palette_device> m_palette; -}; - - -// ======================> sega_315_5195_mapper_device - -class sega_315_5195_mapper_device : public device_t -{ -public: - typedef device_delegate<void (sega_315_5195_mapper_device &, u8)> mapper_delegate; - - // construction/destruction - template <typename T> - sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&cpu_tag) - : sega_315_5195_mapper_device(mconfig, tag, owner, clock) - { - m_cpu.set_tag(std::forward<T>(cpu_tag)); - m_cpuregion.set_tag(std::forward<T>(cpu_tag)); - } - - sega_315_5195_mapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - // configuration helpers - template <typename... T> void set_mapper(T &&... args) { m_mapper = mapper_delegate(std::forward<T>(args)...); } - - auto pbf() { return m_pbf_callback.bind(); } - auto mcu_int() { return m_mcu_int_callback.bind(); } - - // public interface - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); - DECLARE_READ8_MEMBER( pread ); - DECLARE_WRITE8_MEMBER( pwrite ); - - // mapping helpers - void map_as_rom(u32 offset, u32 length, offs_t mirror, const char *bank_name, const char *decrypted_bank_name, offs_t rgnoffset, write16_delegate whandler); - void map_as_ram(u32 offset, u32 length, offs_t mirror, const char *bank_share_name, write16_delegate whandler); - void map_as_handler(u32 offset, u32 length, offs_t mirror, read16_delegate rhandler, write16_delegate whandler); - - // perform an explicit configuration (for bootlegs with hard-coded mappings) - void configure_explicit(const u8 *map_data); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - -private: - TIMER_CALLBACK_MEMBER(write_to_sound); - TIMER_CALLBACK_MEMBER(write_from_sound); - - // internal region struct - struct region_info - { - offs_t size_mask; - offs_t base; - offs_t mirror; - offs_t start; - offs_t end; - }; - - // helper class for tracking banks mapped to ROM regions - class decrypt_bank - { - public: - // construction/destruction - decrypt_bank(); - ~decrypt_bank(); - - // configuration - void set_decrypt(fd1089_base_device *fd1089); - void set_decrypt(fd1094_device *fd1094); - void clear() { set(nullptr, nullptr, 0, 0, ~0, nullptr); } - void set(memory_bank *bank, memory_bank *decrypted_bank, offs_t start, offs_t end, offs_t rgnoffs, u8 *src); - - // updating - void update(); - void reset() { m_fd1089_decrypted.clear(); if (m_fd1094_cache != nullptr) m_fd1094_cache->reset(); } - - private: - // internal state - memory_bank * m_bank; - memory_bank * m_decrypted_bank; - offs_t m_start; - offs_t m_end; - offs_t m_rgnoffs; - u8 * m_srcptr; - fd1089_base_device *m_fd1089; - std::vector<u16> m_fd1089_decrypted; - std::unique_ptr<fd1094_decryption_cache> m_fd1094_cache; - }; - - // internal helpers - void compute_region(region_info &info, u8 index, u32 length, u32 mirror, u32 offset = 0); - void update_mapping(); - void fd1094_state_change(u8 state); - - // configuration - required_device<m68000_device> m_cpu; - required_memory_region m_cpuregion; - mapper_delegate m_mapper; - devcb_write_line m_pbf_callback; - devcb_write_line m_mcu_int_callback; - - // internal state - address_space * m_space; - address_space * m_decrypted_space; - u8 m_regs[0x20]; - u8 m_curregion; - decrypt_bank m_banks[8]; - - // communication registers - u8 m_to_sound; - u8 m_from_sound; -}; - - // ======================> sega_315_5248_multiplier_device class sega_315_5248_multiplier_device : public device_t @@ -263,7 +108,6 @@ private: // device type definition -DECLARE_DEVICE_TYPE(SEGA_315_5195_MEM_MAPPER, sega_315_5195_mapper_device) DECLARE_DEVICE_TYPE(SEGA_315_5248_MULTIPLIER, sega_315_5248_multiplier_device) DECLARE_DEVICE_TYPE(SEGA_315_5249_DIVIDER, sega_315_5249_divider_device) DECLARE_DEVICE_TYPE(SEGA_315_5250_COMPARE_TIMER, sega_315_5250_compare_timer_device) diff --git a/src/mame/video/segaic16.cpp b/src/mame/video/segaic16.cpp index 622ef9f95a2..eb2a7535c30 100644 --- a/src/mame/video/segaic16.cpp +++ b/src/mame/video/segaic16.cpp @@ -373,6 +373,161 @@ Quick review of the system16 hardware: +//************************************************************************** +// PALETTE HELPERS +//************************************************************************** + +//------------------------------------------------- +// sega_16bit_common_base - constructor +//------------------------------------------------- + +sega_16bit_common_base::sega_16bit_common_base(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_paletteram(*this, "paletteram") + , m_palette_entries(0) + , m_palette(*this, "palette") +{ + palette_init(); +} + + +//------------------------------------------------- +// palette_init - precompute weighted RGB values +// for each input value 0-31 +//------------------------------------------------- + +void sega_16bit_common_base::palette_init() +{ + // + // Color generation details + // + // Each color is made up of 5 bits, connected through one or more resistors like so: + // + // Bit 0 = 1 x 3.9K ohm + // Bit 1 = 1 x 2.0K ohm + // Bit 2 = 1 x 1.0K ohm + // Bit 3 = 2 x 1.0K ohm + // Bit 4 = 4 x 1.0K ohm + // + // Another data bit is connected by a tristate buffer to the color output through a + // 470 ohm resistor. The buffer allows the resistor to have no effect (tristate), + // halve brightness (pull-down) or double brightness (pull-up). The data bit source + // is bit 15 of each color RAM entry. + // + + // compute weight table for regular palette entries + static const int resistances_normal[6] = { 3900, 2000, 1000, 1000/2, 1000/4, 0 }; + double weights_normal[6]; + compute_resistor_weights(0, 255, -1.0, + 6, resistances_normal, weights_normal, 0, 0, + 0, nullptr, nullptr, 0, 0, + 0, nullptr, nullptr, 0, 0); + + // compute weight table for shadow/hilight palette entries + static const int resistances_sh[6] = { 3900, 2000, 1000, 1000/2, 1000/4, 470 }; + double weights_sh[6]; + compute_resistor_weights(0, 255, -1.0, + 6, resistances_sh, weights_sh, 0, 0, + 0, nullptr, nullptr, 0, 0, + 0, nullptr, nullptr, 0, 0); + + // compute R, G, B for each weight + for (int value = 0; value < 32; value++) + { + const u8 i4 = (value >> 4) & 1; + const u8 i3 = (value >> 3) & 1; + const u8 i2 = (value >> 2) & 1; + const u8 i1 = (value >> 1) & 1; + const u8 i0 = (value >> 0) & 1; + m_palette_normal[value] = combine_weights(weights_normal, i0, i1, i2, i3, i4, 0); + m_palette_shadow[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 0); + m_palette_hilight[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 1); + } +} + + +//------------------------------------------------- +// paletteram_w - handle writes to palette RAM +//------------------------------------------------- + +WRITE16_MEMBER( sega_16bit_common_base::paletteram_w ) +{ + // compute the number of entries + if (m_palette_entries == 0) + m_palette_entries = memshare("paletteram")->bytes() / 2; + + // get the new value + u16 newval = m_paletteram[offset]; + COMBINE_DATA(&newval); + m_paletteram[offset] = newval; + + // byte 0 byte 1 + // sBGR BBBB GGGG RRRR + // x000 4321 4321 4321 + const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e); + const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e); + const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e); + + // shadow / hilight toggle bit in palette RAM + rgb_t effects = (newval & 0x8000) ? + rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) : + rgb_t(m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); + m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); + m_palette->set_pen_color(offset + 1 * m_palette_entries, effects); +} + +WRITE16_MEMBER( sega_16bit_common_base::hangon_paletteram_w ) +{ + // compute the number of entries + if (m_palette_entries == 0) + m_palette_entries = memshare("paletteram")->bytes() / 2; + + // get the new value + u16 newval = m_paletteram[offset]; + COMBINE_DATA(&newval); + m_paletteram[offset] = newval; + + // byte 0 byte 1 + // xBGR BBBB GGGG RRRR + // x000 4321 4321 4321 + const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e); + const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e); + const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e); + + // hangon has external shadow / hilight toggle bit + m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); + m_palette->set_pen_color(offset + 1 * m_palette_entries, m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); + m_palette->set_pen_color(offset + 2 * m_palette_entries, m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]); +} + +WRITE16_MEMBER( sega_16bit_common_base::philko_paletteram_w ) +{ + // compute the number of entries + if (m_palette_entries == 0) + m_palette_entries = memshare("paletteram")->bytes() / 2; + + // get the new value + u16 newval = m_paletteram[offset]; + COMBINE_DATA(&newval); + m_paletteram[offset] = newval; + + // byte 0 byte 1 + // sRRR RRGG GGGB BBBB + // x432 1043 2104 3210 + const u8 b = (newval >> 0) & 0x1f; + const u8 g = (newval >> 5) & 0x1f; + const u8 r = (newval >> 10) & 0x1f; + + // shadow / hilight toggle bit in palette RAM + rgb_t effects = (newval & 0x8000) ? + rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) : + rgb_t(m_palette_shadow[r], m_palette_shadow[g], m_palette_shadow[b]); + m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r], m_palette_normal[g], m_palette_normal[b]); + m_palette->set_pen_color(offset + 1 * m_palette_entries, effects); +} + + + DEFINE_DEVICE_TYPE(SEGAIC16VID, segaic16_video_device, "segaic16_video", "Sega 16-bit Video") segaic16_video_device::segaic16_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) diff --git a/src/mame/video/segaic16.h b/src/mame/video/segaic16.h index 13fe52179c6..42ffb1539eb 100644 --- a/src/mame/video/segaic16.h +++ b/src/mame/video/segaic16.h @@ -10,15 +10,46 @@ #pragma once +#include "emupal.h" #include "tilemap.h" typedef device_delegate<void (int, uint16_t*, uint16_t*, uint16_t*, uint16_t*)> segaic16_video_pagelatch_delegate; -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> sega_16bit_common_base + +class sega_16bit_common_base : public driver_device +{ +public: + // palette helpers + DECLARE_WRITE16_MEMBER( paletteram_w ); + DECLARE_WRITE16_MEMBER( hangon_paletteram_w ); + DECLARE_WRITE16_MEMBER( philko_paletteram_w ); +protected: + // construction/destruction + sega_16bit_common_base(const machine_config &mconfig, device_type type, const char *tag); + + // internal helpers + void palette_init(); + +public: // -- stupid system16.cpp + // memory pointers + required_shared_ptr<u16> m_paletteram; +protected: + + // internal state + u32 m_palette_entries; // number of palette entries + u8 m_palette_normal[32]; // RGB translations for normal pixels + u8 m_palette_shadow[32]; // RGB translations for shadowed pixels + u8 m_palette_hilight[32]; // RGB translations for hilighted pixels + required_device<palette_device> m_palette; +}; class segaic16_video_device : public device_t, |