From 238d365b0c44051b3d5d8c5140812da085f00d25 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Wed, 22 May 2013 13:49:41 +0000 Subject: [PATCH] (MESS) sms/gamegear: fixed a few regressions in the new code (mostly due to missing bits in the softlist), improved handling of proto dumps with weird sizes, added cart internal header logging. nw. --- hash/gamegear.xml | 15 +++- hash/sms.xml | 4 + src/mess/machine/sega8_rom.c | 60 ++++++------- src/mess/machine/sega8_slot.c | 160 ++++++++++++++++++++++++++++++++-- src/mess/machine/sega8_slot.h | 2 +- 5 files changed, 202 insertions(+), 39 deletions(-) diff --git a/hash/gamegear.xml b/hash/gamegear.xml index 3cae9322b29..7c5036e08e8 100644 --- a/hash/gamegear.xml +++ b/hash/gamegear.xml @@ -1705,6 +1705,7 @@ A few games have been listed as rumored, but they might very well be fake (pleas 1991 Codemasters + @@ -1819,12 +1820,13 @@ A few games have been listed as rumored, but they might very well be fake (pleas - + Cosmic Spacehead (Euro) 1993 Codemasters + @@ -2207,6 +2209,8 @@ A few games have been listed as rumored, but they might very well be fake (pleas + + @@ -4400,6 +4404,7 @@ A few games have been listed as rumored, but they might very well be fake (pleas 1993 Codemasters + @@ -4412,6 +4417,7 @@ A few games have been listed as rumored, but they might very well be fake (pleas Codemasters + @@ -5798,6 +5804,7 @@ A few games have been listed as rumored, but they might very well be fake (pleas 1994 Codemasters + @@ -6522,9 +6529,11 @@ A few games have been listed as rumored, but they might very well be fake (pleas S.S. Lucifer - Man Overboard! (Euro) - 199? - <unknown> + 1994 + Codemasters + + diff --git a/hash/sms.xml b/hash/sms.xml index 27ef5522e1e..e814a523096 100644 --- a/hash/sms.xml +++ b/hash/sms.xml @@ -1558,6 +1558,7 @@ 1991 Zemina + @@ -4209,6 +4210,7 @@ Zemina + @@ -6147,6 +6149,7 @@ Zemina + @@ -6170,6 +6173,7 @@ 1991 Zemina + diff --git a/src/mess/machine/sega8_rom.c b/src/mess/machine/sega8_rom.c index 86d2c920410..82f829fe656 100644 --- a/src/mess/machine/sega8_rom.c +++ b/src/mess/machine/sega8_rom.c @@ -195,43 +195,43 @@ void sega8_janggun_device::device_start() void sega8_rom_device::late_bank_setup() { m_rom_bank_base[0] = 0; - m_rom_bank_base[1] = 1 & (m_rom_page_count - 1); - m_rom_bank_base[2] = 2 & (m_rom_page_count - 1); + m_rom_bank_base[1] = 1 % m_rom_page_count; + m_rom_bank_base[2] = 2 % m_rom_page_count; } void sega8_eeprom_device::late_bank_setup() { m_rom_bank_base[0] = 0; - m_rom_bank_base[1] = 1 & (m_rom_page_count - 1); - m_rom_bank_base[2] = 2 & (m_rom_page_count - 1); + m_rom_bank_base[1] = 1 % m_rom_page_count; + m_rom_bank_base[2] = 2 % m_rom_page_count; } void sega8_codemasters_device::late_bank_setup() { m_rom_bank_base[0] = 0; - m_rom_bank_base[1] = 1 & (m_rom_page_count - 1); + m_rom_bank_base[1] = 1 % m_rom_page_count; m_rom_bank_base[2] = 0; } void sega8_zemina_device::late_bank_setup() { m_rom_bank_base[0] = 0; - m_rom_bank_base[1] = 1 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[2] = 2 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[3] = 3 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[4] = 4 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[5] = 5 & (m_rom_page_count * 2 - 1); + m_rom_bank_base[1] = 1 % (m_rom_page_count * 2); + m_rom_bank_base[2] = 2 % (m_rom_page_count * 2); + m_rom_bank_base[3] = 3 % (m_rom_page_count * 2); + m_rom_bank_base[4] = 4 % (m_rom_page_count * 2); + m_rom_bank_base[5] = 5 % (m_rom_page_count * 2); } void sega8_nemesis_device::late_bank_setup() { // Nemesis starts with last 8kb bank in page 0 (m_rom_page_count is for 16kb pages) m_rom_bank_base[0] = m_rom_page_count * 2 - 1; - m_rom_bank_base[1] = 1 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[2] = 2 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[3] = 3 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[4] = 4 & (m_rom_page_count * 2 - 1); - m_rom_bank_base[5] = 5 & (m_rom_page_count * 2 - 1); + m_rom_bank_base[1] = 1 % (m_rom_page_count * 2); + m_rom_bank_base[2] = 2 % (m_rom_page_count * 2); + m_rom_bank_base[3] = 3 % (m_rom_page_count * 2); + m_rom_bank_base[4] = 4 % (m_rom_page_count * 2); + m_rom_bank_base[5] = 5 % (m_rom_page_count * 2); } void sega8_janggun_device::late_bank_setup() @@ -303,7 +303,7 @@ WRITE8_MEMBER(sega8_rom_device::write_mapper) case 1: // Select 16k ROM bank for 0000-3fff case 2: // Select 16k ROM bank for 4000-7fff case 3: // Select 16k ROM bank for 8000-bfff - m_rom_bank_base[offset - 1] = data & (m_rom_page_count - 1); + m_rom_bank_base[offset - 1] = data % m_rom_page_count; break; } } @@ -362,7 +362,7 @@ WRITE8_MEMBER(sega8_eeprom_device::write_mapper) case 1: // Select 16k ROM bank for 0000-3fff case 2: // Select 16k ROM bank for 4000-7fff case 3: // Select 16k ROM bank for 8000-bfff - m_rom_bank_base[offset - 1] = data & (m_rom_page_count - 1); + m_rom_bank_base[offset - 1] = data % m_rom_page_count; break; } } @@ -458,7 +458,7 @@ WRITE8_MEMBER(sega8_codemasters_device::write_cart) switch (offset) { case 0x0000: - m_rom_bank_base[0] = data & (m_rom_page_count - 1); + m_rom_bank_base[0] = data % m_rom_page_count; break; case 0x4000: if (data & 0x80) @@ -469,11 +469,11 @@ WRITE8_MEMBER(sega8_codemasters_device::write_cart) else { m_ram_enabled = 0; - m_rom_bank_base[1] = data & (m_rom_page_count - 1); + m_rom_bank_base[1] = data % m_rom_page_count; } break; case 0x8000: - m_rom_bank_base[2] = data & (m_rom_page_count - 1); + m_rom_bank_base[2] = data % m_rom_page_count; break; } @@ -494,16 +494,16 @@ WRITE8_MEMBER(sega8_4pak_device::write_cart) { case 0x3ffe: m_reg[0] = data; - m_rom_bank_base[0] = data & (m_rom_page_count - 1); - m_rom_bank_base[2] = ((m_reg[0] & 0x30) + m_reg[2]) & (m_rom_page_count - 1); + m_rom_bank_base[0] = data % m_rom_page_count; + m_rom_bank_base[2] = ((m_reg[0] & 0x30) + m_reg[2]) % m_rom_page_count; break; case 0x7fff: m_reg[1] = data; - m_rom_bank_base[1] = data & (m_rom_page_count - 1); + m_rom_bank_base[1] = data % m_rom_page_count; break; case 0xbfff: m_reg[2] = data; - m_rom_bank_base[2] = ((m_reg[0] & 0x30) + m_reg[2]) & (m_rom_page_count - 1); + m_rom_bank_base[2] = ((m_reg[0] & 0x30) + m_reg[2]) % m_rom_page_count; break; } } @@ -537,16 +537,16 @@ WRITE8_MEMBER(sega8_zemina_device::write_cart) switch (offset & 3) { case 0: - m_rom_bank_base[4] = data & (m_rom_page_count * 2 - 1); + m_rom_bank_base[4] = data % (m_rom_page_count * 2); break; case 1: - m_rom_bank_base[5] = data & (m_rom_page_count * 2 - 1); + m_rom_bank_base[5] = data % (m_rom_page_count * 2); break; case 2: - m_rom_bank_base[2] = data & (m_rom_page_count * 2 - 1); + m_rom_bank_base[2] = data % (m_rom_page_count * 2); break; case 3: - m_rom_bank_base[3] = data & (m_rom_page_count * 2 - 1); + m_rom_bank_base[3] = data % (m_rom_page_count * 2); break; } } @@ -611,8 +611,8 @@ WRITE8_MEMBER(sega8_janggun_device::write_mapper) case 1: // Select 16k ROM bank for 0000-3fff case 2: // Select 16k ROM bank for 4000-7fff case 3: // Select 16k ROM bank for 8000-bfff - m_rom_bank_base[(offset - 1) * 2] = (data & (m_rom_page_count - 1)) * 2; - m_rom_bank_base[(offset - 1) * 2 + 1] = (data & (m_rom_page_count - 1)) * 2 + 1; + m_rom_bank_base[(offset - 1) * 2] = (data % m_rom_page_count) * 2; + m_rom_bank_base[(offset - 1) * 2 + 1] = (data % m_rom_page_count) * 2 + 1; break; } } diff --git a/src/mess/machine/sega8_slot.c b/src/mess/machine/sega8_slot.c index a966e5bd693..618ee3f85f8 100644 --- a/src/mess/machine/sega8_slot.c +++ b/src/mess/machine/sega8_slot.c @@ -1,7 +1,24 @@ /*********************************************************************************************************** + + + Sega 8-bit cart emulation + (through slot devices) + Master System (Mark III) and Game Gear memory map can access 3 x 16K banks of ROM in + 0x0000-0xbfff memory range. These banks can however point to different ROM or RAM area + of the cart (or to BIOS banks, but these are handled directly in SMS emulation). + + Hence, carts can interface with the main system through the following handlers + * read_cart : to read from ROM/RAM in memory range [0000-bfff] + * write_cart : to write to ROM/RAM in memory range [0000-bfff] + * write_mapper : to write to range [fffc-ffff] (called by the handler accessing those + same addresses in sms.c) - + TODO: + - investigate SG-1000 carts so to reduce duplicated code and to add full .sg support to sg1000m3 + - add support for sms card slot (using the same code, since the access are basically the same as + the cart ones) + ***********************************************************************************************************/ @@ -60,6 +77,8 @@ void device_sega8_cart_interface::rom_alloc(running_machine &machine, UINT32 siz m_rom = auto_alloc_array_clear(machine, UINT8, size); m_rom_size = size; m_rom_page_count = size / 0x4000; + if (!m_rom_page_count) + m_rom_page_count = 1; // we compute rom pages through (XXX % m_rom_page_count)! late_bank_setup(); } } @@ -255,7 +274,7 @@ bool sega8_cart_slot_device::call_load() offset = 512; len -= 512; } - + // make sure that we only get complete (0x4000) rom banks if (len & 0x3fff) len = ((len >> 14) + 1) << 14; @@ -290,7 +309,7 @@ bool sega8_cart_slot_device::call_load() { // for now m_cart->ram_alloc(machine(), 0x08000); - m_cart->set_has_battery(TRUE); + //m_cart->set_has_battery(TRUE); } set_lphaser_xoffset(ROM, len); @@ -310,7 +329,7 @@ bool sega8_cart_slot_device::call_load() //printf("Type: %s\n", sega8_get_slot(type)); - internal_header_logging(ROM + offset, len); + internal_header_logging(ROM + offset, len, m_cart->get_ram_size()); return IMAGE_INIT_PASS; } @@ -524,6 +543,137 @@ WRITE8_MEMBER(sega8_cart_slot_device::write_cart) Internal header logging -------------------------------------------------*/ -void sega8_cart_slot_device::internal_header_logging(UINT8 *ROM, UINT32 len) +void sega8_cart_slot_device::internal_header_logging(UINT8 *ROM, UINT32 len, UINT32 nvram_len) { + static const char *const system_region[] = + { + "", + "", + "", + "Master System Japan", + "Master System Export", + "Game Gear Japan", + "Game Gear Export", + "Game Gear International", + "", + "", + "", + "", + "", + "", + "", + "" + }; + + static int csum_length[] = + { + 0x40000, + 0x80000, + 0x100000, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x1ff0, + 0x3ff0, + 0x7ff0, + 0xcff0, + 0x10000, + 0x20000, + }; + + char reserved[10]; + UINT8 version, csum_size, region, serial[3]; + UINT16 checksum, csum = 0; + UINT32 csum_end = 0; + + // LOG FILE DETAILS + logerror("FILE DETAILS\n" ); + logerror("============\n" ); + logerror("Name: %s\n", basename()); + logerror("File Size: 0x%" I64FMT "x\n", (software_entry() == NULL) ? length() : get_software_region_length("rom")); + logerror("Detected type: %s\n", sega8_get_slot(m_type)); + logerror("ROM (Allocated) Size: 0x%X\n", len); + logerror("RAM: %s\n", nvram_len ? "Yes" : "No"); + if (nvram_len) + logerror("RAM (Allocated) Size: 0x%X - Battery: %s\n", nvram_len, m_cart->get_has_battery() ? "Yes" : "No"); + logerror("\n" ); + + + // LOG HEADER DETAILS + if (len < 0x8000) + return; + + for (int i = 0; i < 10; i++) + reserved[i] = ROM[0x7ff0 + i]; + + checksum = ROM[0x7ffa] | (ROM[0x7ffb] << 8); + + for (int i = 0; i < 3; i++) + serial[i] = ROM[0x7ffc + i]; + serial[2] &= 0x0f; + + version = (ROM[0x7ffe] & 0xf0) >> 4; + + csum_size = ROM[0x7fff] & 0x0f; + csum_end = csum_length[csum_size]; + if (!csum_end || csum_end > len) + csum_end = len; + + region = (ROM[0x7fff] & 0xf0) >> 4; + + // compute cart checksum to compare with expected one + for (int i = 0; i < csum_end; i++) + { + if (i < 0x7ff0 || i >= 0x8000) + { + csum += ROM[i]; + csum &= 0xffff; + } + } + + logerror("INTERNAL HEADER\n" ); + logerror("===============\n" ); + logerror("Reserved String: %.10s\n", reserved); + logerror("Region: %s\n", system_region[region]); + logerror("Checksum: (Expected) 0x%x - (Computed) 0x%x\n", checksum, csum); + logerror(" [checksum over 0x%X bytes]\n", csum_length[csum_size]); + logerror("Serial String: %X\n", serial[0] | (serial[1] << 8) | (serial[2] << 16)); + logerror("Software Revision: %x\n", version); + logerror("\n" ); + + + if (m_type == SEGA8_CODEMASTERS) + { + UINT8 day, month, year, hour, minute; + csum = 0; + + day = ROM[0x7fe1]; + month = ROM[0x7fe2]; + year = ROM[0x7fe3]; + hour = ROM[0x7fe4]; + minute = ROM[0x7fe5]; + checksum = ROM[0x7fe6] | (ROM[0x7fe7] << 8); + csum_size = ROM[0x7fe0]; + + // compute cart checksum to compare with expected one + for (int i = 0; i < len; i += 2) + { + if (i < 0x7ff0 || i >= 0x8000) + { + csum += (ROM[i] | (ROM[i + 1] << 8)); + csum &= 0xffff; + } + } + + logerror("CODEMASTERS HEADER\n" ); + logerror("==================\n" ); + logerror("Build date & time: %x/%x/%x %.2x:%.2x\n", day, month, year, hour, minute); + logerror("Checksum: (Expected) 0x%x - (Computed) 0x%x\n", checksum, csum); + logerror(" [checksum over 0x%X bytes]\n", csum_size * 0x4000); + logerror("\n" ); + } } diff --git a/src/mess/machine/sega8_slot.h b/src/mess/machine/sega8_slot.h index 4b4c75030c2..882a236dcf4 100644 --- a/src/mess/machine/sega8_slot.h +++ b/src/mess/machine/sega8_slot.h @@ -94,7 +94,7 @@ public: int get_type() { return m_type; } int get_cart_type(UINT8 *ROM, UINT32 len); - void internal_header_logging(UINT8 *ROM, UINT32 len); + void internal_header_logging(UINT8 *ROM, UINT32 len, UINT32 nvram_len); int verify_cart(UINT8 *magic, int size); void set_lphaser_xoffset(UINT8 *rom, int size);