mirror of
https://github.com/holub/mame
synced 2025-06-03 11:26:56 +03:00
gameboy: more updates to the cart emulation [Tauwasser]
- fixed some MBC1, MBC2 details - added MMM01 notes on registers - fixed Sachen MMC1 implementation so that Sachen logo is properly displayed - started work on the emulation of Sachen MMC2 mapper
This commit is contained in:
parent
5ba57c6cde
commit
05ac233c0a
@ -23524,6 +23524,18 @@ These were produced between 2000 and 2001 by Rocket Games, run by Datel Design
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="4in1_01c">
|
||||
<description>4 in 1 (4B-001)</description>
|
||||
<year>20??</year>
|
||||
<publisher>Sachen</publisher>
|
||||
<part name="cart" interface="gameboy_cart">
|
||||
<feature name="slot" value="rom_sachen1" />
|
||||
<dataarea name="rom" size="524288">
|
||||
<rom name="4b-001.gbc" size="524288" crc="42a2fdf8" sha1="79a4faddfd1aca397e56d7895e45b1bc12900dab" offset="000000" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="mc_8in1">
|
||||
<description>8 in 1 (Tw)</description>
|
||||
<year>19??</year>
|
||||
|
@ -26,8 +26,8 @@ const device_type GB_ROM_MBC6 = &device_creator<gb_rom_mbc6_device>;
|
||||
const device_type GB_ROM_MBC7 = &device_creator<gb_rom_mbc7_device>;
|
||||
const device_type GB_ROM_M161_M12 = &device_creator<gb_rom_m161_device>;
|
||||
const device_type GB_ROM_MMM01 = &device_creator<gb_rom_mmm01_device>;
|
||||
const device_type GB_ROM_SACHEN1 = &device_creator<gb_rom_sachen1_device>;
|
||||
const device_type GB_ROM_SACHEN2 = &device_creator<gb_rom_sachen1_device>; // Just a placeholder for the moment...
|
||||
const device_type GB_ROM_SACHEN1 = &device_creator<gb_rom_sachen_mmc1_device>;
|
||||
const device_type GB_ROM_SACHEN2 = &device_creator<gb_rom_sachen_mmc2_device>;
|
||||
const device_type GB_ROM_188IN1 = &device_creator<gb_rom_188in1_device>;
|
||||
const device_type GB_ROM_SINTAX = &device_creator<gb_rom_sintax_device>;
|
||||
const device_type GB_ROM_CHONGWU = &device_creator<gb_rom_chongwu_device>;
|
||||
@ -97,8 +97,18 @@ gb_rom_mmm01_device::gb_rom_mmm01_device(const machine_config &mconfig, const ch
|
||||
{
|
||||
}
|
||||
|
||||
gb_rom_sachen1_device::gb_rom_sachen1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: gb_rom_mbc1_device(mconfig, GB_ROM_SACHEN1, "GB Sachen MMC1 Carts", tag, owner, clock, "gb_rom_sachen1", __FILE__)
|
||||
gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: gb_rom_mbc_device(mconfig, GB_ROM_SACHEN1, "GB Sachen MMC1 Carts", tag, owner, clock, "gb_rom_sachen1", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: gb_rom_mbc_device(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
{
|
||||
}
|
||||
|
||||
gb_rom_sachen_mmc2_device::gb_rom_sachen_mmc2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: gb_rom_sachen_mmc1_device(mconfig, GB_ROM_SACHEN2, "GB Sachen MMC2 Carts", tag, owner, clock, "gb_rom_sachen2", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
@ -233,18 +243,40 @@ void gb_rom_mmm01_device::device_reset()
|
||||
m_reg = 0;
|
||||
}
|
||||
|
||||
void gb_rom_sachen1_device::device_start()
|
||||
void gb_rom_sachen_mmc1_device::device_start()
|
||||
{
|
||||
shared_start();
|
||||
save_item(NAME(m_base_bank));
|
||||
save_item(NAME(m_mask));
|
||||
save_item(NAME(m_mode));
|
||||
save_item(NAME(m_unlock_cnt));
|
||||
}
|
||||
|
||||
void gb_rom_sachen1_device::device_reset()
|
||||
void gb_rom_sachen_mmc1_device::device_reset()
|
||||
{
|
||||
shared_reset();
|
||||
m_base_bank = 0;
|
||||
m_mask = 0;
|
||||
m_base_bank = 0x00;
|
||||
m_mask = 0x00;
|
||||
m_mode = MODE_LOCKED;
|
||||
m_unlock_cnt = 0x00;
|
||||
}
|
||||
|
||||
void gb_rom_sachen_mmc2_device::device_start()
|
||||
{
|
||||
shared_start();
|
||||
save_item(NAME(m_base_bank));
|
||||
save_item(NAME(m_mask));
|
||||
save_item(NAME(m_mode));
|
||||
save_item(NAME(m_unlock_cnt));
|
||||
}
|
||||
|
||||
void gb_rom_sachen_mmc2_device::device_reset()
|
||||
{
|
||||
shared_reset();
|
||||
m_base_bank = 0x00;
|
||||
m_mask = 0x00;
|
||||
m_mode = MODE_LOCKED_DMG;
|
||||
m_unlock_cnt = 0x00;
|
||||
}
|
||||
|
||||
void gb_rom_sintax_device::device_start()
|
||||
@ -310,18 +342,18 @@ WRITE8_MEMBER(gb_rom_mbc_device::write_ram)
|
||||
|
||||
READ8_MEMBER(gb_rom_mbc1_device::read_rom)
|
||||
{
|
||||
if (offset < 0x4000)
|
||||
{
|
||||
if (offset & 0x4000) /* RB1 */
|
||||
return m_rom[rom_bank_map[(m_ram_bank << (5 + m_shift)) | m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
|
||||
else
|
||||
{ /* RB0 */
|
||||
int bank = (m_mode == MODE_4M_256k) ? (m_ram_bank << (5 + m_shift)) : 0;
|
||||
return m_rom[rom_bank_map[bank] * 0x4000 + (offset & 0x3fff)];
|
||||
}
|
||||
else
|
||||
return m_rom[rom_bank_map[(m_ram_bank << (5 + m_shift)) | m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_rom_mbc1_device::write_bank)
|
||||
{
|
||||
// the mapper only uses inputs A13-A15
|
||||
// the mapper only uses inputs A15..A13
|
||||
switch (offset & 0xe000)
|
||||
{
|
||||
case 0x0000: // RAM Enable Register
|
||||
@ -395,7 +427,7 @@ WRITE8_MEMBER(gb_rom_mbc2_device::write_bank)
|
||||
READ8_MEMBER(gb_rom_mbc2_device::read_ram)
|
||||
{
|
||||
if (!m_ram.empty() && m_ram_enable)
|
||||
return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
|
||||
return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] | 0xF0;
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
@ -403,7 +435,7 @@ READ8_MEMBER(gb_rom_mbc2_device::read_ram)
|
||||
WRITE8_MEMBER(gb_rom_mbc2_device::write_ram)
|
||||
{
|
||||
if (!m_ram.empty() && m_ram_enable)
|
||||
m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
|
||||
m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] = data & 0x0F;
|
||||
}
|
||||
|
||||
|
||||
@ -661,6 +693,14 @@ WRITE8_MEMBER(gb_rom_m161_device::write_bank)
|
||||
|
||||
// MMM01
|
||||
// This mmm01 implementation is mostly guess work, no clue how correct it all is
|
||||
/* TODO: This implementation is wrong. Tauwasser
|
||||
*
|
||||
* Register 0: Map Latch, AA Mask, RAM Enable
|
||||
* Register 1: EA1..EA0, RA18..RA14
|
||||
* Register 2: ??, AA18..AA15, AA14..AA13
|
||||
* Register 3: AA Multiplex, RA Mask, ???, MBC1 Mode
|
||||
*
|
||||
*/
|
||||
|
||||
READ8_MEMBER(gb_rom_mmm01_device::read_rom)
|
||||
{
|
||||
@ -704,37 +744,140 @@ WRITE8_MEMBER(gb_rom_mmm01_device::write_bank)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sachen MMC1
|
||||
|
||||
READ8_MEMBER(gb_rom_sachen1_device::read_rom)
|
||||
READ8_MEMBER(gb_rom_sachen_mmc1_device::read_rom)
|
||||
{
|
||||
if (offset < 0x4000)
|
||||
return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (offset & 0x3fff)];
|
||||
|
||||
UINT16 off_edit = offset;
|
||||
|
||||
/* Wait for 0x31 transitions of A15 (hi -> lo), i.e. ROM accesses; A15 = HI while in bootstrap */
|
||||
/* This is 0x31 transitions, because we increment counter _after_ checking it */
|
||||
if (m_unlock_cnt == 0x30)
|
||||
m_mode = MODE_UNLOCKED;
|
||||
else
|
||||
m_unlock_cnt++;
|
||||
|
||||
/* Logo Switch */
|
||||
if (m_mode == MODE_LOCKED)
|
||||
off_edit |= 0x80;
|
||||
|
||||
/* Header Un-Scramble */
|
||||
if ((off_edit & 0xFF00) == 0x0100) {
|
||||
off_edit &= 0xFFAC;
|
||||
off_edit |= ((offset >> 6) & 0x01) << 0;
|
||||
off_edit |= ((offset >> 4) & 0x01) << 1;
|
||||
off_edit |= ((offset >> 1) & 0x01) << 4;
|
||||
off_edit |= ((offset >> 0) & 0x01) << 6;
|
||||
}
|
||||
//logerror("read from %04X (%04X)\n", offset, off_edit);
|
||||
|
||||
if (offset & 0x4000) /* RB1 */
|
||||
return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)];
|
||||
else /* RB0 */
|
||||
return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)];
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_rom_sachen1_device::write_bank)
|
||||
WRITE8_MEMBER(gb_rom_sachen_mmc1_device::write_bank)
|
||||
{
|
||||
if (offset < 0x2000) // Base ROM Bank register
|
||||
|
||||
/* Only A15..A6, A4, A1..A0 are connected */
|
||||
/* We only decode upper three bits */
|
||||
switch ((offset & 0xFFD3) & 0xE000)
|
||||
{
|
||||
if ((m_latch_bank2 & 0x30) == 0x30 && data)
|
||||
m_base_bank = data & 0x0f;
|
||||
//logerror("write to base bank %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
case 0x0000: /* Base ROM Bank Register */
|
||||
|
||||
if ((m_latch_bank2 & 0x30) == 0x30)
|
||||
m_base_bank = data;
|
||||
//logerror("write to base bank %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
break;
|
||||
|
||||
case 0x2000: /* ROM Bank Register */
|
||||
|
||||
m_latch_bank2 = data ? data : 0x01;
|
||||
//logerror("write to latch %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
break;
|
||||
|
||||
case 0x4000: /* ROM Bank Mask Register */
|
||||
|
||||
if ((m_latch_bank2 & 0x30) == 0x30)
|
||||
m_mask = data;
|
||||
//logerror("write to mask %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
break;
|
||||
|
||||
case 0x6000:
|
||||
|
||||
/* nothing happens when writing to 0x6000-0x7fff, as verified by Tauwasser */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
//logerror("write to unknown/unmapped area %04X <= %02X\n", offset, data);
|
||||
/* did not extensively test other unlikely ranges */
|
||||
break;
|
||||
}
|
||||
else if (offset < 0x4000) // ROM Bank Register
|
||||
{
|
||||
m_latch_bank2 = data ? data : 1;
|
||||
//logerror("write to latch %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
}
|
||||
|
||||
// Sachen MMC2
|
||||
|
||||
READ8_MEMBER(gb_rom_sachen_mmc2_device::read_rom)
|
||||
{
|
||||
|
||||
UINT16 off_edit = offset;
|
||||
|
||||
/* Wait for 0x30 transitions of A15 (lo -> hi), i.e. ROM accesses; A15 = HI while in bootstrap */
|
||||
/* This is 0x30 transitions, because we increment counter _after_ checking it, but A15 lo -> hi*/
|
||||
/* transition means first read (hi -> lo transition) must not count */
|
||||
|
||||
if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_DMG) {
|
||||
m_mode = MODE_LOCKED_CGB;
|
||||
m_unlock_cnt = 0x00;
|
||||
} else if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_CGB) {
|
||||
m_mode = MODE_UNLOCKED;
|
||||
}
|
||||
else if (offset < 0x6000) // ROM bank mask register
|
||||
{
|
||||
if ((m_latch_bank2 & 0x30) == 0x30)
|
||||
m_mask = data;
|
||||
//logerror("write to mask %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
|
||||
|
||||
if (m_unlock_cnt != 0x30)
|
||||
m_unlock_cnt++;
|
||||
|
||||
/* Logo Switch */
|
||||
if (m_mode == MODE_LOCKED_CGB)
|
||||
off_edit |= 0x80;
|
||||
|
||||
/* Header Un-Scramble */
|
||||
if ((off_edit & 0xFF00) == 0x0100) {
|
||||
off_edit &= 0xFFAC;
|
||||
off_edit |= ((offset >> 6) & 0x01) << 0;
|
||||
off_edit |= ((offset >> 4) & 0x01) << 1;
|
||||
off_edit |= ((offset >> 1) & 0x01) << 4;
|
||||
off_edit |= ((offset >> 0) & 0x01) << 6;
|
||||
}
|
||||
// nothing happens when writing to 0x6000-0x7fff, as verified by Tauwasser
|
||||
//logerror("read from %04X (%04X) cnt: %02X\n", offset, off_edit, m_unlock_cnt);
|
||||
|
||||
if (offset & 0x4000) /* RB1 */
|
||||
return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)];
|
||||
else /* RB0 */
|
||||
return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)];
|
||||
}
|
||||
|
||||
READ8_MEMBER(gb_rom_sachen_mmc2_device::read_ram)
|
||||
{
|
||||
|
||||
if (m_mode == MODE_LOCKED_DMG) {
|
||||
m_unlock_cnt = 0x00;
|
||||
m_mode = MODE_LOCKED_CGB;
|
||||
}
|
||||
return 0xFF;
|
||||
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(gb_rom_sachen_mmc2_device::write_ram)
|
||||
{
|
||||
|
||||
if (m_mode == MODE_LOCKED_DMG) {
|
||||
m_unlock_cnt = 0x00;
|
||||
m_mode = MODE_LOCKED_CGB;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,14 +191,20 @@ public:
|
||||
UINT8 m_bank_mask, m_bank, m_reg;
|
||||
};
|
||||
|
||||
// ======================> gb_rom_sachen1_device
|
||||
// ======================> gb_rom_sachen_mmc1_device
|
||||
|
||||
class gb_rom_sachen1_device : public gb_rom_mbc1_device
|
||||
class gb_rom_sachen_mmc1_device : public gb_rom_mbc_device
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
MODE_LOCKED,
|
||||
MODE_UNLOCKED
|
||||
};
|
||||
|
||||
// construction/destruction
|
||||
gb_rom_sachen1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
gb_rom_sachen_mmc1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
gb_rom_sachen_mmc1_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
@ -209,7 +215,32 @@ public:
|
||||
virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; }
|
||||
virtual DECLARE_WRITE8_MEMBER(write_ram) { }
|
||||
|
||||
UINT8 m_base_bank, m_mask;
|
||||
UINT8 m_base_bank, m_mask, m_mode, m_unlock_cnt;
|
||||
};
|
||||
|
||||
// ======================> gb_rom_sachen_mmc2_device
|
||||
|
||||
class gb_rom_sachen_mmc2_device : public gb_rom_sachen_mmc1_device
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
MODE_LOCKED_DMG,
|
||||
MODE_LOCKED_CGB,
|
||||
MODE_UNLOCKED
|
||||
};
|
||||
|
||||
// construction/destruction
|
||||
gb_rom_sachen_mmc2_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 DECLARE_READ8_MEMBER(read_rom);
|
||||
virtual DECLARE_READ8_MEMBER(read_ram);
|
||||
virtual DECLARE_WRITE8_MEMBER(write_ram);
|
||||
|
||||
};
|
||||
|
||||
// ======================> gb_rom_188in1_device
|
||||
|
Loading…
Reference in New Issue
Block a user