diff --git a/.gitattributes b/.gitattributes index 51d68e369f6..65c64a86e1c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7763,6 +7763,8 @@ src/mess/machine/sns_sdd1.c svneol=native#text/plain src/mess/machine/sns_sdd1.h svneol=native#text/plain src/mess/machine/sns_sfx.c svneol=native#text/plain src/mess/machine/sns_sfx.h svneol=native#text/plain +src/mess/machine/sns_sgb.c svneol=native#text/plain +src/mess/machine/sns_sgb.h svneol=native#text/plain src/mess/machine/sns_slot.c svneol=native#text/plain src/mess/machine/sns_slot.h svneol=native#text/plain src/mess/machine/sns_spc7110.c svneol=native#text/plain diff --git a/src/mess/drivers/snes.c b/src/mess/drivers/snes.c index 95e795b0375..29d0fce0ad9 100644 --- a/src/mess/drivers/snes.c +++ b/src/mess/drivers/snes.c @@ -40,6 +40,7 @@ #include "machine/sns_sa1.h" #include "machine/sns_sdd1.h" #include "machine/sns_sfx.h" +#include "machine/sns_sgb.h" #include "machine/sns_spc7110.h" #include "machine/sns_sufami.h" #include "machine/sns_upd.h" @@ -87,6 +88,10 @@ public: DECLARE_WRITE8_MEMBER( snesbsx_hi_w ); DECLARE_READ8_MEMBER( snesbsx_lo_r ); DECLARE_WRITE8_MEMBER( snesbsx_lo_w ); + DECLARE_READ8_MEMBER( snessgb_hi_r ); + DECLARE_READ8_MEMBER( snessgb_lo_r ); + DECLARE_WRITE8_MEMBER( snessgb_hi_w ); + DECLARE_WRITE8_MEMBER( snessgb_lo_w ); DECLARE_READ8_MEMBER( pfest94_hi_r ); DECLARE_WRITE8_MEMBER( pfest94_hi_w ); DECLARE_READ8_MEMBER( pfest94_lo_r ); @@ -874,6 +879,55 @@ WRITE8_MEMBER( snes_console_state::snesbsx_lo_w ) } +//--------------------------------------------------------------------------------- +// LoROM + SuperGB +//--------------------------------------------------------------------------------- + +READ8_MEMBER( snes_console_state::snessgb_hi_r ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000) + { + if (address < 0x2000) + return space.read_byte(0x7e0000 + address); + else if (address < 0x6000) + return snes_r_io(space, address); + else if (address < 0x8000) + return m_cartslot->chip_read(space, offset); + else + return m_cartslot->read_h(space, offset); + } + else if (address >= 0x8000) + return m_cartslot->read_h(space, offset); + + return snes_open_bus_r(space, 0); +} + +READ8_MEMBER( snes_console_state::snessgb_lo_r ) +{ + return snessgb_hi_r(space, offset, 0xff); +} + +WRITE8_MEMBER( snes_console_state::snessgb_hi_w ) +{ + UINT16 address = offset & 0xffff; + if (offset < 0x400000) + { + if (address < 0x2000) + space.write_byte(0x7e0000 + address, data); + else if (address < 0x6000) + snes_w_io(space, address, data); + else if (address < 0x8000) + m_cartslot->chip_write(space, offset, data); + } +} + +WRITE8_MEMBER( snes_console_state::snessgb_lo_w ) +{ + snessgb_hi_w(space, offset, data, 0xff); +} + //--------------------------------------------------------------------------------- // Powerfest '94 event cart //--------------------------------------------------------------------------------- @@ -1579,7 +1633,7 @@ static SLOT_INTERFACE_START(snes_cart) SLOT_INTERFACE_INTERNAL("lorom_sa1", SNS_LOROM_SA1) // Cart + SA1 - unsupported SLOT_INTERFACE_INTERNAL("lorom_sdd1", SNS_LOROM_SDD1) SLOT_INTERFACE_INTERNAL("lorom_sfx", SNS_LOROM_SUPERFX) - SLOT_INTERFACE_INTERNAL("lorom_sgb", SNS_LOROM) // SuperGB base cart - unsupported + SLOT_INTERFACE_INTERNAL("lorom_sgb", SNS_LOROM_SUPERGB) // SuperGB base cart - unsupported SLOT_INTERFACE_INTERNAL("lorom_st010", SNS_LOROM_SETA10) SLOT_INTERFACE_INTERNAL("lorom_st011", SNS_LOROM_SETA11) SLOT_INTERFACE_INTERNAL("lorom_st018", SNS_LOROM) // Cart + ST018 - unsupported @@ -1628,7 +1682,11 @@ void snes_console_state::machine_start() case SNES_ST010: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w case SNES_ST011: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w case SNES_ST018: // still unemulated - case SNES_Z80GB: // still unemulated + break; + case SNES_Z80GB: // skeleton support + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessgb_lo_r),this), write8_delegate(FUNC(snes_console_state::snessgb_lo_w),this)); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snessgb_hi_r),this), write8_delegate(FUNC(snes_console_state::snessgb_hi_w),this)); + set_5a22_map(m_maincpu); break; case SNES_SA1: // skeleton support m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessa1_lo_r),this), write8_delegate(FUNC(snes_console_state::snessa1_lo_w),this)); diff --git a/src/mess/machine/sns_sgb.c b/src/mess/machine/sns_sgb.c new file mode 100644 index 00000000000..eba0b14b57e --- /dev/null +++ b/src/mess/machine/sns_sgb.c @@ -0,0 +1,247 @@ +/*********************************************************************************************************** + + Super Game Boy emulation (for SNES/SFC) + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + + TODO: almost everything + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "machine/sns_sgb.h" + +#include "cpu/lr35902/lr35902.h" + +//------------------------------------------------- +// sns_rom_sgb_device - constructor +//------------------------------------------------- + +const device_type SNS_LOROM_SUPERGB = &device_creator; + + +sns_rom_sgb_device::sns_rom_sgb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : sns_rom_device(mconfig, SNS_LOROM_SUPERGB, "SNES Super Game Boy Cart", tag, owner, clock, "sns_rom_sgb", __FILE__), + m_gb_cpu(*this, "supergb"), + m_cartslot(*this, "gb_slot") +{ +} + + +void sns_rom_sgb_device::device_start() +{ +} + +void sns_rom_sgb_device::device_reset() +{ +} + + + +// SuperGB emulation + +//------------------------------------------------- +// ADDRESS_MAP( supergb_map ) +//------------------------------------------------- + +READ8_MEMBER(sns_rom_sgb_device::gb_cart_r) +{ + return m_cartslot->read_rom(space, offset); +} + +WRITE8_MEMBER(sns_rom_sgb_device::gb_bank_w) +{ + m_cartslot->write_bank(space, offset, data); +} + +READ8_MEMBER(sns_rom_sgb_device::gb_ram_r) +{ + return m_cartslot->read_ram(space, offset); +} + +WRITE8_MEMBER(sns_rom_sgb_device::gb_ram_w) +{ + m_cartslot->write_ram(space, offset, data); +} + + +static ADDRESS_MAP_START(supergb_map, AS_PROGRAM, 8, sns_rom_sgb_device ) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x0000, 0x7fff) AM_READWRITE(gb_cart_r, gb_bank_w) + AM_RANGE(0xa000, 0xbfff) AM_READWRITE(gb_ram_r, gb_ram_w ) /* 8k switched RAM bank (cartridge) */ + AM_RANGE(0xc000, 0xfdff) AM_RAM /* 8k low RAM, echo RAM */ + AM_RANGE(0xff27, 0xff2f) AM_NOP /* unused */ + AM_RANGE(0xff80, 0xfffe) AM_RAM /* High RAM */ +ADDRESS_MAP_END + + + +WRITE8_MEMBER( sns_rom_sgb_device::gb_timer_callback ) +{ +} + + +static SLOT_INTERFACE_START(supergb_cart) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_FRAGMENT( supergb ) + MCFG_CPU_ADD("supergb", LR35902, 4295454) /* 4.295454 MHz */ + MCFG_CPU_PROGRAM_MAP(supergb_map) + MCFG_LR35902_TIMER_CB(WRITE8(sns_rom_sgb_device, gb_timer_callback)) + MCFG_LR35902_HALT_BUG + + MCFG_GB_CARTRIDGE_ADD("gb_slot", supergb_cart, NULL) +MACHINE_CONFIG_END + + +machine_config_constructor sns_rom_sgb_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( supergb ); +} + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + + +READ8_MEMBER(sns_rom_sgb_device::read_l) +{ + return read_h(space, offset); +} + +READ8_MEMBER(sns_rom_sgb_device::read_h) +{ + int bank = offset / 0x10000; + return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; +} + +READ8_MEMBER( sns_rom_sgb_device::chip_read ) +{ + UINT16 address = offset & 0xffff; + + //LY counter + if (address == 0x6000) + { + m_sgb_ly = 0;// GameBoy PPU LY here + m_sgb_row = m_lcd_row; + return m_sgb_ly; + } + + //command ready port + if (address == 0x6002) + { + bool data = (m_packetsize > 0); + if (data) + { + for (int i = 0; i < 16; i++) + m_joy_pckt[i] = m_packet_data[0][i]; + m_packetsize--; + + //hack because we still don't emulate input packets! + if (!m_packetsize) m_packetsize = 64; + + // shift packet + for (int i = 0; i < m_packetsize; i++) + for (int j = 0; j < 16; j++) + m_packet_data[i][j] = m_packet_data[i + 1][j]; + } + return data; + } + + //ICD2 revision + if (address == 0x600f) + return 0x21; + + //command port + if ((address & 0xfff0) == 0x7000) + return m_joy_pckt[address & 0x0f]; + + //VRAM port + if (address == 0x7800) + { + UINT8 data = m_lcd_output[m_vram_offs]; + m_vram_offs = (m_vram_offs + 1) % 320; + return data; + } + + return 0x00; // this should never happen? +} + +void sns_rom_sgb_device::lcd_render(UINT32 *source) +{ + memset(m_lcd_output, 0x00, 320 * sizeof(UINT16)); + + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 160; x++) + { + UINT32 pixel = *source++; + UINT16 addr = y * 2 + (x / 8 * 16); + m_lcd_output[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7)); + m_lcd_output[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7)); + } + } +} + +WRITE8_MEMBER( sns_rom_sgb_device::chip_write ) +{ + UINT16 address = offset & 0xffff; + + //VRAM port + if (address == 0x6001) + { + m_vram = data; + m_vram_offs = 0; + + UINT8 offset = (m_sgb_row - (4 - (m_vram - (m_sgb_ly & 3)))) & 3; + lcd_render(m_lcd_buffer + offset * 160 * 8); + + return; + } + + //control port + if (address == 0x6003) + { + if ((m_port & 0x80) == 0x00 && (data & 0x80) == 0x80) + { + //reset + } + + switch (data & 3) + { + //change CPU frequency + } + m_port = data; + return; + } + + if (address == 0x6004) + { + //joypad 1 + m_joy1 = data; + return; + } + if (address == 0x6005) + { + //joypad 2 + m_joy2 = data; + return; + } + if (address == 0x6006) + { + //joypad 3 + m_joy3 = data; + return; + } + if (address == 0x6007) + { + //joypad 4 + m_joy4 = data; + return; + } + +} + diff --git a/src/mess/machine/sns_sgb.h b/src/mess/machine/sns_sgb.h new file mode 100644 index 00000000000..4c6ebf15af5 --- /dev/null +++ b/src/mess/machine/sns_sgb.h @@ -0,0 +1,63 @@ +#ifndef __SNS_SGB_H +#define __SNS_SGB_H + +#include "machine/sns_slot.h" +#include "machine/sns_rom.h" + +#include "machine/gb_slot.h" + + +// ======================> sns_rom_sgb_device + +class sns_rom_sgb_device : public sns_rom_device +{ +public: + // construction/destruction + sns_rom_sgb_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_l); + virtual DECLARE_READ8_MEMBER(read_h); + virtual DECLARE_READ8_MEMBER(chip_read); + virtual DECLARE_WRITE8_MEMBER(chip_write); + + virtual DECLARE_READ8_MEMBER(gb_cart_r); + virtual DECLARE_WRITE8_MEMBER(gb_bank_w); + virtual DECLARE_READ8_MEMBER(gb_ram_r); + virtual DECLARE_WRITE8_MEMBER(gb_ram_w); + virtual DECLARE_WRITE8_MEMBER(gb_timer_callback); + + required_device m_gb_cpu; + required_device m_cartslot; + + void lcd_render(UINT32 *source); + + // ICD2 regs + UINT8 m_sgb_ly; + UINT8 m_sgb_row; + UINT8 m_vram; + UINT8 m_port; + UINT8 m_joy1, m_joy2, m_joy3, m_joy4; + UINT8 m_joy_pckt[16]; + UINT16 m_vram_offs; + UINT8 m_mlt_req; + + UINT32 m_lcd_buffer[4 * 160 * 8]; + UINT16 m_lcd_output[320]; + UINT16 m_lcd_row; + + // input bits + int m_packetsize; + UINT8 m_packet_data[64][16]; +}; + + +// device type definition +extern const device_type SNS_LOROM_SUPERGB; + +#endif diff --git a/src/mess/mess.mak b/src/mess/mess.mak index 312f2c9e84d..afb9a438c32 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -1678,6 +1678,7 @@ $(MESSOBJ)/nintendo.a: \ $(MESS_MACHINE)/sns_sa1.o \ $(MESS_MACHINE)/sns_sdd1.o \ $(MESS_MACHINE)/sns_sfx.o \ + $(MESS_MACHINE)/sns_sgb.o \ $(MESS_MACHINE)/sns_spc7110.o \ $(MESS_MACHINE)/sns_sufami.o\ $(MESS_MACHINE)/sns_upd.o \