mirror of
https://github.com/holub/mame
synced 2025-07-04 17:38:08 +03:00
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)
This commit is contained in:
parent
c08c7d6e53
commit
270a2736b0
@ -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 )
|
||||
{
|
||||
switch (offset & 0x3020/2)
|
||||
{
|
||||
case 0x0000/2: // PPI @ 4B
|
||||
return m_i8255_1->read(offset & 3);
|
||||
|
||||
case 0x1000/2: // Input ports and DIP switches
|
||||
uint8_t segahang_state::hangon_inputs_r(offs_t offset)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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 )
|
||||
{
|
||||
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
|
||||
uint8_t segahang_state::sharrier_inputs_r(offs_t offset)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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);
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -13,13 +13,14 @@
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "cpu/mcs51/mcs51.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/segaic16.h"
|
||||
#include "machine/upd4701.h"
|
||||
#include "machine/315_5195.h"
|
||||
#include "machine/315_5296.h"
|
||||
#include "machine/nvram.h"
|
||||
#include "machine/upd4701.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;
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
610
src/mame/machine/315_5195.cpp
Normal file
610
src/mame/machine/315_5195.cpp
Normal file
@ -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()));
|
||||
}
|
147
src/mame/machine/315_5195.h
Normal file
147
src/mame/machine/315_5195.h
Normal file
@ -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
|
@ -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,762 +26,12 @@
|
||||
//**************************************************************************
|
||||
|
||||
// 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")
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// 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
|
||||
//**************************************************************************
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -10,16 +10,47 @@
|
||||
|
||||
#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,
|
||||
public device_video_interface
|
||||
|
Loading…
Reference in New Issue
Block a user