diff --git a/history.txt b/history.txt index 177a6a8..7da115a 100644 --- a/history.txt +++ b/history.txt @@ -33,7 +33,7 @@ CURRENT: - fixed "Reset" button behavior, now acts more like Genesis Reset button ;-) - minor bugfixes and menu tweaks - + [NGC only] - added 480p support in menu diff --git a/source/cart_hw/cart_hw.c b/source/cart_hw/cart_hw.c index a43802b..3a59101 100644 --- a/source/cart_hw/cart_hw.c +++ b/source/cart_hw/cart_hw.c @@ -3,7 +3,7 @@ * Genesis Plus 1.2a * Cartridge Hardware support * - * code by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * Most cartridge protections documented by Haze * (http://haze.mameworld.info/) @@ -112,7 +112,7 @@ T_CART_ENTRY rom_database[CART_CNT] = /* previous inputs */ -static int old_system[2] = {-1,-1}; +int old_system[2] = {-1,-1}; /* temporary memory chunk */ uint8 mem_chunk[0x10000]; @@ -341,15 +341,12 @@ void cart_hw_init() ***********************************************/ memset(&cart_hw, 0, sizeof(cart_hw)); - /* default write handler for !TIME signal */ - cart_hw.time_w = default_time_w; - - /* search for game into database */ + /* search for game into database */ for (i=0; i < CART_CNT + 1; i++) { /* known cart found ! */ if ((rominfo.checksum == rom_database[i].chk_1) && - (realchecksum == rom_database[i].chk_2)) + (realchecksum == rom_database[i].chk_2)) { /* retrieve hardware information */ memcpy(&cart_hw, &(rom_database[i].cart_hw), sizeof(cart_hw)); @@ -405,11 +402,15 @@ void cart_hw_init() /* assume SSF2 mapper */ cart_hw.bankshift = 1; } + + /* default write handler for !TIME signal */ + if (!cart_hw.time_w) cart_hw.time_w = default_time_w; } /************************************************************ MAPPER handlers *************************************************************/ + /* "official" ROM/RAM switch */ @@ -492,8 +493,8 @@ void special_mapper_w(uint32 address, uint32 data) Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter) */ void realtec_mapper_w(uint32 address, uint32 data) - { - int i; +{ + int i; uint32 base; /* 32 x 128k banks */ @@ -537,27 +538,27 @@ void seganet_mapper_w(uint32 address, uint32 data) { if ((address & 0xff) == 0xf1) { - int i; - if (data & 1) - { + int i; + if (data & 1) + { /* ROM Write protected */ for (i=0; i<0x40; i++) { m68k_memory_map[i].write8 = m68k_unused_8_w; m68k_memory_map[i].write16 = m68k_unused_16_w; zbank_memory_map[i].write = zbank_unused_w; - } - } - else - { - /* ROM Write enabled */ - for (i=0; i<0x40; i++); + } + } + else + { + /* ROM Write enabled */ + for (i=0; i<0x40; i++) { m68k_memory_map[i].write8 = NULL; m68k_memory_map[i].write16 = NULL; zbank_memory_map[i].write = NULL; } - } + } } } @@ -571,7 +572,7 @@ uint32 radica_mapper_r(uint32 address) /* 64 x 64k banks */ for (i = 0; i < 64; i++) -{ + { m68k_memory_map[i].base = &cart_rom[((address++)& 0x3f)<< 16]; } return 0xff; diff --git a/source/cart_hw/cart_hw.h b/source/cart_hw/cart_hw.h index 05d0c5c..000a9b9 100644 --- a/source/cart_hw/cart_hw.h +++ b/source/cart_hw/cart_hw.h @@ -2,7 +2,7 @@ * Genesis Plus 1.2a * Cartridge Hardware support * - * code by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * Lots of protection mechanism have been discovered by Haze * (http://haze.mameworld.info/) diff --git a/source/cart_hw/eeprom.c b/source/cart_hw/eeprom.c index 349d24a..c3a3651 100644 --- a/source/cart_hw/eeprom.c +++ b/source/cart_hw/eeprom.c @@ -2,7 +2,7 @@ * Genesis Plus 1.2a * Serial EEPROM support * - * code by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source/cart_hw/eeprom.h b/source/cart_hw/eeprom.h index 1da1feb..4e0329f 100644 --- a/source/cart_hw/eeprom.h +++ b/source/cart_hw/eeprom.h @@ -2,7 +2,7 @@ * Genesis Plus 1.2a * Serial EEPROM support * - * code by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source/mem68k.c b/source/mem68k.c index e73e552..583aca5 100644 --- a/source/mem68k.c +++ b/source/mem68k.c @@ -27,23 +27,7 @@ uint32 m68k_read_bus_8(uint32 address) { #ifdef LOGERROR - error("Unused read8 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); - error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0)); - error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1)); - error("D2 = %x \n", m68k_get_reg (NULL, M68K_REG_D2)); - error("D3 = %x \n", m68k_get_reg (NULL, M68K_REG_D3)); - error("D4 = %x \n", m68k_get_reg (NULL, M68K_REG_D4)); - error("D5 = %x \n", m68k_get_reg (NULL, M68K_REG_D5)); - error("D6 = %x \n", m68k_get_reg (NULL, M68K_REG_D6)); - error("D7 = %x \n", m68k_get_reg (NULL, M68K_REG_D7)); - error("A0 = %x \n", m68k_get_reg (NULL, M68K_REG_A0)); - error("A1 = %x \n", m68k_get_reg (NULL, M68K_REG_A1)); - error("A2 = %x \n", m68k_get_reg (NULL, M68K_REG_A2)); - error("A3 = %x \n", m68k_get_reg (NULL, M68K_REG_A3)); - error("A4 = %x \n", m68k_get_reg (NULL, M68K_REG_A4)); - error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5)); - error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6)); - error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7)); + error("Unused read8 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); #endif return m68k_read_pcrelative_8(REG_PC | (address&1)); @@ -52,23 +36,7 @@ uint32 m68k_read_bus_8(uint32 address) uint32 m68k_read_bus_16(uint32 address) { #ifdef LOGERROR - error("Unused read16 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); - error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0)); - error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1)); - error("D2 = %x \n", m68k_get_reg (NULL, M68K_REG_D2)); - error("D3 = %x \n", m68k_get_reg (NULL, M68K_REG_D3)); - error("D4 = %x \n", m68k_get_reg (NULL, M68K_REG_D4)); - error("D5 = %x \n", m68k_get_reg (NULL, M68K_REG_D5)); - error("D6 = %x \n", m68k_get_reg (NULL, M68K_REG_D6)); - error("D7 = %x \n", m68k_get_reg (NULL, M68K_REG_D7)); - error("A0 = %x \n", m68k_get_reg (NULL, M68K_REG_A0)); - error("A1 = %x \n", m68k_get_reg (NULL, M68K_REG_A1)); - error("A2 = %x \n", m68k_get_reg (NULL, M68K_REG_A2)); - error("A3 = %x \n", m68k_get_reg (NULL, M68K_REG_A3)); - error("A4 = %x \n", m68k_get_reg (NULL, M68K_REG_A4)); - error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5)); - error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6)); - error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7)); + error("Unused read16 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); #endif return m68k_read_pcrelative_16(REG_PC); } @@ -77,14 +45,14 @@ uint32 m68k_read_bus_16(uint32 address) void m68k_unused_8_w (uint32 address, uint32 data) { #ifdef LOGERROR - error("Unused write8 %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); + error("Unused write8 %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif } void m68k_unused_16_w (uint32 address, uint32 data) { #ifdef LOGERROR - error("Unused write16 %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); + error("Unused write16 %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif } @@ -97,39 +65,39 @@ void m68k_unused_16_w (uint32 address, uint32 data) void m68k_lockup_w_8 (uint32 address, uint32 data) { #ifdef LOGERROR - error ("Lockup %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif - gen_running = config.force_dtack; - if (!gen_running) m68k_end_timeslice (); + gen_running = config.force_dtack; + if (!gen_running) m68k_end_timeslice (); } void m68k_lockup_w_16 (uint32 address, uint32 data) { #ifdef LOGERROR - error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif - gen_running = config.force_dtack; - if (!gen_running) m68k_end_timeslice (); + gen_running = config.force_dtack; + if (!gen_running) m68k_end_timeslice (); } uint32 m68k_lockup_r_8 (uint32 address) { #ifdef LOGERROR - error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); #endif - gen_running = config.force_dtack; - if (!gen_running) m68k_end_timeslice (); - return -1; + gen_running = config.force_dtack; + if (!gen_running) m68k_end_timeslice (); + return -1; } uint32 m68k_lockup_r_16 (uint32 address) { #ifdef LOGERROR - error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); #endif - gen_running = config.force_dtack; - if (!gen_running) m68k_end_timeslice (); - return -1; + gen_running = config.force_dtack; + if (!gen_running) m68k_end_timeslice (); + return -1; } /* PICO data */ @@ -143,135 +111,123 @@ static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F}; uint32 eeprom_read_byte(uint32 address) { - if (address == eeprom.type.sda_out_adr) - return eeprom_read(address, 0); - else - return READ_BYTE(cart_rom, address); + if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0); + else return READ_BYTE(cart_rom, address); } uint32 eeprom_read_word(uint32 address) { - if (address == (eeprom.type.sda_out_adr & 0xfffffe)) - return eeprom_read(address, 1); - else - return *(uint16 *)(cart_rom + address); + if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1); + else return *(uint16 *)(cart_rom + address); } void eeprom_write_byte(uint32 address, uint32 data) { - if ((address == eeprom.type.sda_in_adr) || - (address == eeprom.type.scl_adr)) + if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, data, 0); - else - m68k_unused_8_w(address, data); + else m68k_unused_8_w(address, data); } void eeprom_write_word(uint32 address, uint32 data) { - if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || - (address == (eeprom.type.scl_adr&0xfffffe))) + if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe))) eeprom_write(address, data, 1); - else - m68k_unused_16_w (address, data); + else m68k_unused_16_w (address, data); } /******* Z80 *************************************************/ uint32 z80_read_byte(uint32 address) - { - if (zbusack) return m68k_read_bus_8(address); - - switch ((address >> 13) & 3) - { - case 2: /* YM2612 */ - return fm_read(0, address & 3); +{ + if (zbusack) return m68k_read_bus_8(address); + + switch ((address >> 13) & 3) + { + case 2: /* YM2612 */ + return fm_read(0, address & 3); - case 3: /* MISC */ - if ((address & 0xff00) == 0x7f00) - return m68k_lockup_r_8(address); /* VDP */ - else - return (m68k_read_bus_8(address) | 0xff); + case 3: /* MISC */ + if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_8(address); /* VDP */ + else return (m68k_read_bus_8(address) | 0xff); - default: /* ZRAM */ - return zram[address & 0x1fff]; - } - } - + default: /* ZRAM */ + return zram[address & 0x1fff]; + } +} + uint32 z80_read_word(uint32 address) { if (zbusack) return m68k_read_bus_16(address); switch ((address >> 13) & 3) - { + { case 2: /* YM2612 */ - { + { int temp = fm_read(0, address & 3); return (temp << 8 | temp); } case 3: /* MISC */ - if ((address & 0xff00) == 0x7f00) - return m68k_lockup_r_16(address); /* VDP */ - else - return (m68k_read_bus_16(address) | 0xffff); + if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_16(address); /* VDP */ + else return (m68k_read_bus_16(address) | 0xffff); default: /* ZRAM */ { int temp = zram[address & 0x1fff]; return (temp << 8 | temp); } - } - } - + } +} + void z80_write_byte(uint32 address, uint32 data) { if (zbusack) - { + { m68k_unused_8_w(address, data); return; } - + switch ((address >> 13) & 3) { case 2: /* YM2612 */ fm_write(0, address & 3, data); return; - + case 3: switch ((address >> 8) & 0x7f) { - case 0x60: /* Bank register */ + case 0x60: /* Bank register */ gen_bank_w(data & 1); return; - case 0x7f: /* VDP */ + case 0x7f: /* VDP */ m68k_lockup_w_8(address, data); return; - + default: m68k_unused_8_w(address, data); return; } - + default: /* ZRAM */ zram[address & 0x1fff] = data; count_m68k++; /* Z80 bus latency (Pacman 2: New Adventures) */ return; } - } +} void z80_write_word(uint32 address, uint32 data) - { +{ /* Z80 still hold the bus ? */ if (zbusack) - { + { m68k_unused_16_w(address, data); return; } switch ((address >> 13) & 3) - { + { case 2: /* YM2612 */ fm_write (0, address & 3, data >> 8); return; @@ -279,255 +235,217 @@ void z80_write_word(uint32 address, uint32 data) case 3: switch ((address >> 8) & 0x7f) { - case 0x60: /* Bank register */ + case 0x60: /* Bank register */ gen_bank_w ((data >> 8) & 1); return; - case 0x7f: /* VDP */ + case 0x7f: /* VDP */ m68k_lockup_w_16(address, data); return; - default: + default: m68k_unused_16_w(address, data); return; - } + } - default: /* ZRAM */ - zram[address & 0x1fff] = data >> 8; - return; + default: /* ZRAM */ + zram[address & 0x1fff] = data >> 8; + return; } } - + /******* I/O & CTRL ******************************************/ - + uint32 ctrl_io_read_byte(uint32 address) - { - /* I/O & CONTROL REGISTERS */ - switch ((address >> 8) & 0xff) - { - case 0x00: /* I/O chip */ - if (address & 0xe0) - return m68k_read_bus_8(address); - else - return (io_read((address >> 1) & 0x0f)); +{ + switch ((address >> 8) & 0xff) + { + case 0x00: /* I/O chip */ + if (address & 0xe0) return m68k_read_bus_8(address); + else return (io_read((address >> 1) & 0x0f)); - case 0x11: /* BUSACK */ - if (address & 1) - return m68k_read_bus_8(address); - else - return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack); + case 0x11: /* BUSACK */ + if (address & 1) return m68k_read_bus_8(address); + else return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack); - case 0x30: /* TIME */ - if (cart_hw.time_r) - return cart_hw.time_r(address); - else - return m68k_read_bus_8(address); + case 0x30: /* TIME */ + if (cart_hw.time_r) return cart_hw.time_r(address); + else return m68k_read_bus_8(address); - case 0x10: /* MEMORY MODE */ - case 0x12: /* RESET */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x41: /* BOOTROM */ - case 0x44: /* RADICA */ - case 0x50: /* SVP REGISTERS */ - return m68k_read_bus_8(address); + case 0x10: /* MEMORY MODE */ + case 0x12: /* RESET */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x41: /* BOOTROM */ + case 0x44: /* RADICA */ + case 0x50: /* SVP REGISTERS */ + return m68k_read_bus_8(address); - default: /* Invalid address */ - return m68k_lockup_r_8(address); - } - } + default: /* Invalid address */ + return m68k_lockup_r_8(address); + } +} uint32 ctrl_io_read_word(uint32 address) - { - switch ((address >> 8) & 0xff) - { - case 0x00: /* I/O chip */ - { - if (address & 0xe0) - return m68k_read_bus_16(address); - int temp = io_read((address >> 1) & 0x0f); - return (temp << 8 | temp); - } +{ + switch ((address >> 8) & 0xff) + { + case 0x00: /* I/O chip */ + { + if (address & 0xe0) return m68k_read_bus_16(address); + int temp = io_read((address >> 1) & 0x0f); + return (temp << 8 | temp); + } - case 0x11: /* BUSACK */ - return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8)); + case 0x11: /* BUSACK */ + return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8)); - case 0x50: /* SVP */ - if (svp) - { - switch (address & 0xff) - { - case 0: - case 2: - return svp->ssp1601.gr[SSP_XST].h; + case 0x30: /* TIME */ + if (cart_hw.time_r) return cart_hw.time_r(address); + else return m68k_read_bus_16(address); - case 4: - { - uint32 temp = svp->ssp1601.gr[SSP_PM0].h; - svp->ssp1601.gr[SSP_PM0].h &= ~1; - return temp; - } + case 0x50: /* SVP */ + if (svp) + { + if ((address & 0xfd) == 0) return svp->ssp1601.gr[SSP_XST].h; + else if ((address & 0xff) == 4) + { + uint32 temp = svp->ssp1601.gr[SSP_PM0].h; + svp->ssp1601.gr[SSP_PM0].h &= ~1; + return temp; + } + } + return m68k_read_bus_16(address); - default: - return m68k_read_bus_16(address); - } - } - else - return m68k_read_bus_16(address); - - case 0x30: /* TIME */ - if (cart_hw.time_r) - return cart_hw.time_r(address); - else - return m68k_read_bus_16(address); - - case 0x10: /* MEMORY MODE */ - case 0x12: /* RESET */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x41: /* BOOTROM */ - case 0x44: /* RADICA */ - return m68k_read_bus_16(address); - - default: /* Invalid address */ + case 0x10: /* MEMORY MODE */ + case 0x12: /* RESET */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x41: /* BOOTROM */ + case 0x44: /* RADICA */ + return m68k_read_bus_16(address); + + default: /* Invalid address */ return m68k_lockup_r_16(address); - } - } + } +} void ctrl_io_write_byte(uint32 address, uint32 data) - { - switch ((address >> 8) & 0xff) - { - case 0x00: /* I/O chip */ - if ((address & 0xe1) == 0x01) - io_write((address >> 1) & 0x0f, data); /* get /LWR only */ - else - m68k_unused_8_w(address, data); - return; +{ + switch ((address >> 8) & 0xff) + { + case 0x00: /* I/O chip */ + if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */ + else m68k_unused_8_w(address, data); + return; - case 0x11: /* BUSREQ */ + case 0x11: /* BUSREQ */ + if (address & 1) m68k_unused_8_w(address, data); + else gen_busreq_w(data & 1); + return; + + case 0x12: /* RESET */ + if (address & 1) m68k_unused_8_w(address, data); + else gen_reset_w(data & 1); + return; + + case 0x30: /* TIME */ + cart_hw.time_w(address, data); + return; + + case 0x41: /* BOOTROM */ if (address & 1) - m68k_unused_8_w(address, data); - else - gen_busreq_w(data & 1); - return; - - case 0x12: /* RESET */ - if (address & 1) - m68k_unused_8_w(address, data); - else - gen_reset_w(data & 1); - return; - - case 0x30: /* TIME */ - if (cart_hw.time_w) - cart_hw.time_w(address, data); - else - m68k_unused_8_w(address, data); - return; - - case 0x41: /* BOOTROM */ - if (address & 1) - { + { m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; - /* autodetect BIOS ROM file */ - if (!(config.bios_enabled & 2)) - { - config.bios_enabled |= 2; - memcpy(bios_rom, cart_rom, 0x800); - memset(cart_rom, 0, genromsize); - } - } - else m68k_unused_8_w (address, data); - return; + /* autodetect BIOS ROM file */ + if (!(config.bios_enabled & 2)) + { + config.bios_enabled |= 2; + memcpy(bios_rom, cart_rom, 0x800); + memset(cart_rom, 0, genromsize); + } + } + else m68k_unused_8_w (address, data); + return; - case 0x10: /* MEMORY MODE */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x44: /* RADICA */ - case 0x50: /* SVP REGISTERS */ - m68k_unused_8_w(address, data); - return; + case 0x10: /* MEMORY MODE */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x44: /* RADICA */ + case 0x50: /* SVP REGISTERS */ + m68k_unused_8_w(address, data); + return; - default: /* Invalid address */ - m68k_lockup_w_8(address, data); - return; - } - } + default: /* Invalid address */ + m68k_lockup_w_8(address, data); + return; + } +} void ctrl_io_write_word(uint32 address, uint32 data) - { - switch ((address >> 8) & 0xff) - { - case 0x00: /* I/O chip */ - if (address & 0xe0) - m68k_unused_16_w (address, data); - else - io_write ((address >> 1) & 0x0f, data & 0xff); - return; - - case 0x11: /* BUSREQ */ - gen_busreq_w ((data >> 8) & 1); - return; - - case 0x12: /* RESET */ - gen_reset_w ((data >> 8) & 1); - return; - - case 0x50: /* SVP REGISTERS */ - if (svp) - { - if (address & 0xfd) - m68k_unused_16_w(address, data); - else - { - /* just guessing here (Notaz) */ - svp->ssp1601.gr[SSP_XST].h = data; - svp->ssp1601.gr[SSP_PM0].h |= 2; - svp->ssp1601.emu_status &= ~SSP_WAIT_PM0; - } - } - else - m68k_unused_16_w (address, data); - return; +{ + switch ((address >> 8) & 0xff) + { + case 0x00: /* I/O chip */ + if (address & 0xe0) m68k_unused_16_w (address, data); + else io_write ((address >> 1) & 0x0f, data & 0xff); + return; + + case 0x11: /* BUSREQ */ + gen_busreq_w ((data >> 8) & 1); + return; + + case 0x12: /* RESET */ + gen_reset_w ((data >> 8) & 1); + return; + + case 0x50: /* SVP REGISTERS */ + if (svp) + { + if (address & 0xfd) m68k_unused_16_w(address, data); + else + { + /* just guessing here (Notaz) */ + svp->ssp1601.gr[SSP_XST].h = data; + svp->ssp1601.gr[SSP_PM0].h |= 2; + svp->ssp1601.emu_status &= ~SSP_WAIT_PM0; + } + } + else m68k_unused_16_w (address, data); + return; - case 0x30: /* TIME */ - if (cart_hw.time_w) - { - cart_hw.time_w(address & 0xfe, data >> 8); - cart_hw.time_w(address, data & 0xff); - } - else - m68k_unused_16_w (address, data); - return; - - case 0x41: /* BOOTROM */ - + case 0x30: /* TIME */ + cart_hw.time_w(address & 0xfe, data >> 8); + cart_hw.time_w(address, data & 0xff); + return; + + case 0x41: /* BOOTROM */ + m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; - /* autodetect BIOS ROM file */ - if (!(config.bios_enabled & 2)) - { - config.bios_enabled |= 2; - memcpy(bios_rom, cart_rom, 0x800); - memset(cart_rom, 0, genromsize); - } - return; - - case 0x10: /* MEMORY MODE */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x44: /* RADICA */ - m68k_unused_16_w (address, data); - return; - - default: /* Unused */ - m68k_lockup_w_16 (address, data); - return; - } - } + /* autodetect BIOS ROM file */ + if (!(config.bios_enabled & 2)) + { + config.bios_enabled |= 2; + memcpy(bios_rom, cart_rom, 0x800); + memset(cart_rom, 0, genromsize); + } + return; + + case 0x10: /* MEMORY MODE */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x44: /* RADICA */ + m68k_unused_16_w (address, data); + return; + + default: /* Unused */ + m68k_lockup_w_16 (address, data); + return; + } +} /******* VDP *************************************************/ @@ -574,14 +492,14 @@ uint32 vdp_read_word(uint32 address) case 0x00: /* DATA */ return vdp_data_r(); - case 0x04: /* CTRL */ + case 0x04: /* CTRL */ return ((vdp_ctrl_r() & 0x3FF) | (m68k_read_pcrelative_16(REG_PC) & 0xFC00)); - case 0x08: /* HVC */ + case 0x08: /* HVC */ case 0x0c: return vdp_hvc_r(); - case 0x18: /* Unused */ + case 0x18: /* Unused */ case 0x1c: return m68k_read_bus_16(address); @@ -594,15 +512,15 @@ void vdp_write_byte(uint32 address, uint32 data) { switch (address & 0xfc) { - case 0x00: /* Data port */ + case 0x00: /* Data port */ vdp_data_w(data << 8 | data); return; - case 0x04: /* Control port */ + case 0x04: /* Control port */ vdp_ctrl_w(data << 8 | data); return; - case 0x10: /* PSG */ + case 0x10: /* PSG */ case 0x14: if (address & 1) psg_write(0, data); else m68k_unused_8_w(address, data); @@ -616,42 +534,42 @@ void vdp_write_byte(uint32 address, uint32 data) vdp_test_w(data << 8 | data); return; - default: /* Invalid address */ + default: /* Invalid address */ m68k_lockup_w_8(address, data); return; } } void vdp_write_word(uint32 address, uint32 data) - { - switch (address & 0xfc) - { - case 0x00: /* DATA */ - vdp_data_w(data); - return; - - case 0x04: /* CTRL */ - vdp_ctrl_w(data); - return; - - case 0x10: /* PSG */ - case 0x14: - psg_write(0, data & 0xff); - return; - - case 0x18: /* Unused */ - m68k_unused_16_w(address, data); - return; - - case 0x1c: /* Test register */ - vdp_test_w(data); - return; - - default: /* Invalid address */ - m68k_lockup_w_16 (address, data); +{ + switch (address & 0xfc) + { + case 0x00: /* DATA */ + vdp_data_w(data); return; - } - } + + case 0x04: /* CTRL */ + vdp_ctrl_w(data); + return; + + case 0x10: /* PSG */ + case 0x14: + psg_write(0, data & 0xff); + return; + + case 0x18: /* Unused */ + m68k_unused_16_w(address, data); + return; + + case 0x1c: /* Test register */ + vdp_test_w(data); + return; + + default: /* Invalid address */ + m68k_lockup_w_16 (address, data); + return; + } +} /******* PICO ************************************************/ @@ -701,7 +619,7 @@ uint32 pico_read_byte(uint32 address) default: return m68k_read_bus_8(address); - } + } } uint32 pico_read_word(uint32 address) diff --git a/source/membnk.c b/source/membnk.c index 604898d..74f9873 100644 --- a/source/membnk.c +++ b/source/membnk.c @@ -60,11 +60,10 @@ void zbank_lockup_w(uint32 address, uint32 data) } /* I/O & Control registers */ - uint32 zbank_read_ctrl_io(uint32 address) { switch ((address >> 8) & 0xff) - { + { case 0x00: /* I/O chip */ if (address & 0xe0) return zbank_unused_r(address); else return (io_read((address >> 1) & 0x0f)); @@ -89,99 +88,98 @@ uint32 zbank_read_ctrl_io(uint32 address) default: /* Invalid address */ return zbank_lockup_r(address); } - } +} void zbank_write_ctrl_io(uint32 address, uint32 data) - { - switch ((address >> 8) & 0xff) - { - case 0x00: /* I/O chip */ - if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */ +{ + switch ((address >> 8) & 0xff) + { + case 0x00: /* I/O chip */ + if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */ else zbank_unused_w(address, data); - return; + return; - case 0x11: /* BUSREQ */ + case 0x11: /* BUSREQ */ if (address & 1) zbank_unused_w(address, data); - else gen_busreq_w(data & 1); - return; + else gen_busreq_w(data & 1); + return; - case 0x12: /* RESET */ + case 0x12: /* RESET */ if (address & 1) zbank_unused_w(address, data); - else gen_reset_w(data & 1); - return; + else gen_reset_w(data & 1); + return; - case 0x30: /* TIME */ + case 0x30: /* TIME */ if (cart_hw.time_w) cart_hw.time_w(address, data); else zbank_unused_w(address, data); - return; + return; - case 0x41: /* BOOTROM */ - if (address & 1) - { + case 0x41: /* BOOTROM */ + if (address & 1) + { m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom; - /* autodetect BIOS ROM file */ - if (!(config.bios_enabled & 2)) - { - config.bios_enabled |= 2; - memcpy(bios_rom, cart_rom, 0x800); - memset(cart_rom, 0, genromsize); - } - } + /* autodetect BIOS ROM file */ + if (!(config.bios_enabled & 2)) + { + config.bios_enabled |= 2; + memcpy(bios_rom, cart_rom, 0x800); + memset(cart_rom, 0, genromsize); + } + } else zbank_unused_w (address, data); - return; + return; - case 0x10: /* MEMORY MODE */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x44: /* RADICA */ - case 0x50: /* SVP REGISTERS */ + case 0x10: /* MEMORY MODE */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x44: /* RADICA */ + case 0x50: /* SVP REGISTERS */ zbank_unused_w(address, data); - return; + return; - default: /* Invalid address */ + default: /* Invalid address */ zbank_lockup_w(address, data); - return; - } - } + return; + } +} - /* VDP */ - +/* VDP */ uint32 zbank_read_vdp(uint32 address) - { - switch (address & 0xfd) - { - case 0x00: /* DATA */ - return (vdp_data_r() >> 8); +{ + switch (address & 0xfd) + { + case 0x00: /* DATA */ + return (vdp_data_r() >> 8); - case 0x01: /* DATA */ - return (vdp_data_r() & 0xff); + case 0x01: /* DATA */ + return (vdp_data_r() & 0xff); - case 0x04: /* CTRL */ - return (0xfc | ((vdp_ctrl_r() >> 8) & 3)); + case 0x04: /* CTRL */ + return (0xfc | ((vdp_ctrl_r() >> 8) & 3)); - case 0x05: /* CTRL */ - return (vdp_ctrl_r() & 0xff); + case 0x05: /* CTRL */ + return (vdp_ctrl_r() & 0xff); - case 0x08: /* HVC */ - case 0x0c: - return (vdp_hvc_r() >> 8); + case 0x08: /* HVC */ + case 0x0c: + return (vdp_hvc_r() >> 8); - case 0x09: /* HVC */ - case 0x0d: - return (vdp_hvc_r() & 0xff); - - case 0x18: /* Unused */ - case 0x19: - case 0x1c: - case 0x1d: + case 0x09: /* HVC */ + case 0x0d: + return (vdp_hvc_r() & 0xff); + + case 0x18: /* Unused */ + case 0x19: + case 0x1c: + case 0x1d: return zbank_unused_r(address); - default: /* Invalid address */ + default: /* Invalid address */ return zbank_lockup_r(address); } - } +} void zbank_write_vdp(uint32 address, uint32 data) { diff --git a/source/state.c b/source/state.c index 5c90f15..fbbb731 100644 --- a/source/state.c +++ b/source/state.c @@ -2,7 +2,7 @@ * Genesis Plus 1.2a * FreezeState support * - * coded by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source/state.h b/source/state.h index b0c8482..841aeb0 100644 --- a/source/state.h +++ b/source/state.h @@ -2,7 +2,7 @@ * Genesis Plus 1.2a * FreezeState support * - * coded by Eke-Eke, GC/Wii port + * Copyright (C) Eke-Eke, GC/Wii port * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source/system.c b/source/system.c index 6c8de13..371f1a5 100644 --- a/source/system.c +++ b/source/system.c @@ -23,8 +23,6 @@ #include "shared.h" -#define CLOCK_NTSC 53693175 -#define CLOCK_PAL 53203424 #define SND_SIZE (snd.buffer_size * sizeof(int16)) /* Global variables */ @@ -32,7 +30,6 @@ t_bitmap bitmap; t_snd snd; uint8 vdp_rate; uint16 lines_per_frame; -double Master_Clock; uint32 aim_m68k; uint32 count_m68k; uint32 line_m68k; @@ -55,7 +52,6 @@ void system_init (void) /* PAL/NTSC timings */ vdp_rate = vdp_pal ? 50 : 60; lines_per_frame = vdp_pal ? 313 : 262; - Master_Clock = vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC; gen_init (); vdp_init (); @@ -139,27 +135,29 @@ int system_frame (int do_skip) } odd_frame ^= 1; - /* update VDP status */ - status &= 0xFFF5; // clear VBLANK and DMA flags - if (odd_frame && interlaced) status |= 0x0010; // even/odd field flag (interlaced modes only) + /* clear VBLANK and DMA flags */ + status &= 0xFFF5; + + /* even/odd field flag (interlaced modes only) */ + if (odd_frame && interlaced) status |= 0x0010; else status &= 0xFFEF; - /* Reload H Counter */ + /* reload HCounter */ int h_counter = reg[10]; /* parse sprites for line 0 (done on last line) */ parse_satb (0x80); - /* Line processing */ + /* process frame */ for (line = 0; line < lines_per_frame; line ++) { - /* Update VCounter */ + /* update VCounter */ v_counter = line; - /* 6-Buttons or Menacer update */ + /* update 6-Buttons or Menacer */ input_update(); - /* Update CPU cycle counters */ + /* update CPU cycle counters */ hint_m68k = count_m68k; line_m68k = aim_m68k; line_z80 = aim_z80; @@ -176,10 +174,11 @@ int system_frame (int do_skip) gen_reset(0); } - /* Horizontal Interrupt */ + /* active display */ if (line <= vdp_height) { - if(--h_counter < 0) + /* H Interrupt */ + if(--h_counter < 0) { h_counter = reg[10]; hint_pending = 1; @@ -196,44 +195,46 @@ int system_frame (int do_skip) if ((line < vdp_height) && (h_counter == 0)) aim_m68k -= 36; /* update DMA timings */ - if (dma_length) dma_update(); + if (dma_length) dma_update(); - /* Vertical Retrace */ + /* vertical retrace */ if (line == vdp_height) - { + { /* render overscan */ if ((line < end_line) && (!do_skip)) render_line(line, 1); - /* update inputs */ - update_input(); + /* update inputs (doing this here fix Warriors of Eternal Sun) */ + update_input(); - /* set VBLANK flag */ - status |= 0x08; + /* set VBLANK flag */ + status |= 0x08; - /* Z80 interrupt is 16ms period (one frame) and 64us length (one scanline) */ - zirq = 1; - z80_set_irq_line(0, ASSERT_LINE); + /* Z80 interrupt is 16ms period (one frame) and 64us length (one scanline) */ + zirq = 1; + z80_set_irq_line(0, ASSERT_LINE); - /* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */ - m68k_run(line_m68k + 84); + /* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */ + m68k_run(line_m68k + 84); if (zreset && !zbusreq) { current_z80 = line_z80 + 39 - count_z80; if (current_z80 > 0) count_z80 += z80_execute(current_z80); } - else count_z80 = line_z80 + 39; + else count_z80 = line_z80 + 39; - /* Vertical Interrupt */ - status |= 0x80; - vint_pending = 1; - if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416; // 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) + /* V Interrupt */ + status |= 0x80; + vint_pending = 1; + + /* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */ + if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416; } else if (!do_skip) { /* render scanline and parse sprites for line n+1 */ render_line(line, 0); if (line < (vdp_height-1)) parse_satb(0x81 + line); - } + } } else { @@ -241,20 +242,17 @@ int system_frame (int do_skip) if (dma_length) dma_update(); /* render overscan */ - if ((line < end_line) || (line >= start_line)) - { - if (!do_skip) render_line(line, 1); - } + if ((!do_skip) && ((line < end_line) || (line >= start_line))) render_line(line, 1); /* clear any pending Z80 interrupt */ if (zirq) { - zirq = 0; - z80_set_irq_line(0, CLEAR_LINE); - } + zirq = 0; + z80_set_irq_line(0, CLEAR_LINE); + } } - /* Process line */ + /* process line */ m68k_run(aim_m68k); if (zreset == 1 && zbusreq == 0) { diff --git a/source/vdp.c b/source/vdp.c index 3233caf..4ea3b8e 100644 --- a/source/vdp.c +++ b/source/vdp.c @@ -76,7 +76,6 @@ uint32 fifo_lastwrite; /* last VDP write cycle */ uint8 fifo_latency; /* VDP write cycles latency */ uint8 vdp_pal = 0; /* 1: PAL , 0: NTSC (default) */ -double vdp_timings[4][4]; /* Tables that define the playfield layout */ static const uint8 shift_table[] = { 6, 7, 0, 8 }; @@ -84,10 +83,11 @@ static const uint8 col_mask_table[] = { 0x0F, 0x1F, 0x0F, 0x3F }; static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF }; static const uint32 y_mask_table[] = { 0x1FC0, 0x1F80, 0x1FC0, 0x1F00 }; -static uint16 sat_base_mask; /* Base bits of SAT */ -static uint16 sat_addr_mask; /* Index bits of SAT */ -static uint32 dma_endCycles; /* 68k cycles to DMA end */ -static uint8 dma_type; /* Type of DMA */ +static uint16 sat_base_mask; /* Base bits of SAT */ +static uint16 sat_addr_mask; /* Index bits of SAT */ +static uint32 dma_endCycles; /* 68k cycles to DMA end */ +static uint8 dma_type; /* Type of DMA */ +static double vdp_timings[4][4]; /* DMA timings */ static inline void vdp_reg_w(unsigned int r, unsigned int d); @@ -119,10 +119,10 @@ static inline void vdp_reg_w(unsigned int r, unsigned int d); */ static const uint8 dma_rates[16] = { - 8, 9, 83 , 102, /* 68K to VRAM */ + 8, 9, 83 , 102, /* 68K to VRAM */ 16, 18, 167, 205, /* 68K to CRAM or VSRAM */ 15, 17, 166, 204, /* DMA fill */ - 8, 9, 83 , 102, /* DMA Copy */ + 8, 9, 83 , 102, /* DMA Copy */ }; /* Function prototypes */ @@ -159,6 +159,7 @@ void vdp_reset(void) pending = 0; status = 0x200; /* fifo empty */ + status |= vdp_pal; ntab = 0; ntbb = 0; @@ -324,7 +325,7 @@ void dma_update() */ static inline void dma_copy(void) { - int name; + int name; int length = (reg[20] << 8 | reg[19]) & 0xFFFF; int source = (reg[22] << 8 | reg[21]) & 0xFFFF; if (!length) length = 0x10000; @@ -365,48 +366,45 @@ static inline void dma_vbus (void) dma_length = length; dma_update(); - switch (source >> 21) + /* DMA source */ + if ((source >> 17) == 0x50) { - case 5: - do - { - /* Return $FFFF only when the Z80 isn't hogging the Z-bus. - (e.g. Z80 isn't reset and 68000 has the bus) */ - if (source <= 0xa0ffff) temp = (zbusack ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff); + /* Z80 & I/O area */ + do + { + /* Return $FFFF only when the Z80 isn't hogging the Z-bus. + (e.g. Z80 isn't reset and 68000 has the bus) */ + if (source <= 0xa0ffff) temp = (zbusack ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff); - /* The I/O chip and work RAM try to drive the data bus which results + /* The I/O chip and work RAM try to drive the data bus which results in both values being combined in random ways when read. We return the I/O chip values which seem to have precedence, */ - else if (source <= 0xa1001f) - { - temp = io_read((source >> 1) & 0x0f); + else if (source <= 0xa1001f) + { + temp = io_read((source >> 1) & 0x0f); temp = (temp << 8 | temp); - } - - /* All remaining locations access work RAM */ - else temp = *(uint16 *)(work_ram + (source & 0xffff)); - - source += 2; - source = ((base & 0xFE0000) | (source & 0x1FFFF)); - data_write (temp); } - while (--length); - break; - case 0: - case 1: - if (svp) source = source - 2; + /* All remaining locations access work RAM */ + else temp = *(uint16 *)(work_ram + (source & 0xffff)); - default: - do - { - temp = *(uint16 *)(m68k_memory_map[source>>16].base + (source & 0xffff)); - source += 2; - source = ((base & 0xFE0000) | (source & 0x1FFFF)); - data_write (temp); - } - while (--length); - break; + source += 2; + source = ((base & 0xFE0000) | (source & 0x1FFFF)); + data_write (temp); + } + while (--length); + } + else + { + /* ROM & RAM */ + do + { + temp = *(uint16 *)(m68k_memory_map[source>>16].base + (source & 0xffff)); + source += 2; + source = ((base & 0xFE0000) | (source & 0x1FFFF)); + data_write (temp); + } + while (--length); } /* update length & source address registers */ @@ -420,7 +418,7 @@ static inline void dma_vbus (void) /* VRAM FILL */ static inline void dma_fill(unsigned int data) { - int name; + int name; int length = (reg[20] << 8 | reg[19]) & 0xFFFF; if (!length) length = 0x10000; @@ -442,7 +440,6 @@ static inline void dma_fill(unsigned int data) { /* update internal SAT (fix Battletech) */ WRITE_BYTE(sat, (addr & sat_addr_mask)^1, data); - WRITE_BYTE(vram, addr^1, data); MARK_BG_DIRTY (addr); addr += reg[15]; @@ -618,39 +615,26 @@ static inline void vdp_reg_w(unsigned int r, unsigned int d) switch(r) { case 0x00: /* CTRL #1 */ - /* Check if HINT has been enabled or disabled */ if (hint_pending && ((d&0x10) != (reg[0]&0x10))) { + /* update IRQ status */ irq_status &= 0x20; irq_status |= 0x10; - if (vint_pending && (reg[1] & 0x20)) - { - irq_status |= 6; - } - else if (d & 0x10) - { - irq_status |= 4; - } + if (vint_pending && (reg[1] & 0x20)) irq_status |= 6; + else if (d & 0x10) irq_status |= 4; } break; case 0x01: /* CTRL #2 */ - /* Check if VINT has been enabled or disabled */ if (vint_pending && ((d&0x20) != (reg[1]&0x20))) { + /* update IRQ status */ irq_status &= 0x20; irq_status |= 0x110; - if (d & 0x20) - { - irq_status |= 6; - } - else if (hint_pending && (reg[0] & 0x10)) - { - irq_status |= 4; - } + if (d & 0x20) irq_status |= 6; + else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4; } - /* Check if the viewport height has actually been changed */ if((reg[1] & 8) != (d & 8)) { @@ -792,22 +776,24 @@ unsigned int vdp_ctrl_r(void) * 8 Write FIFO full * 9 Write FIFO empty * 10 - 15 Next word on bus - */ + */ - /* update FIFO flags */ - fifo_update(); - if (fifo_write_cnt < 4) - { - status &= 0xFEFF; - if (fifo_write_cnt == 0) status |= 0x200; - } + /* update FIFO flags */ + fifo_update(); + if (fifo_write_cnt < 4) + { + status &= 0xFEFF; + if (fifo_write_cnt == 0) status |= 0x200; + } else status ^= 0x200; /* update DMA Busy flag */ if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles)) + { status &= 0xFFFD; + } - unsigned int temp = status | vdp_pal; + unsigned int temp = status; /* display OFF: VBLANK flag is set */ if (!(reg[1] & 0x40)) temp |= 0x8; @@ -917,25 +903,21 @@ void vdp_test_w(unsigned int value) int vdp_int_ack_callback(int int_level) { + /* VINT triggered ? */ if (irq_status&0x20) { vint_pending = 0; - status &= ~0x80; /* clear VINT flag */ + status &= ~0x80; /* clear VINT flag */ } else { - hint_pending = 0; + hint_pending = 0; } + /* update IRQ status */ irq_status = 0x10; - if (vint_pending && (reg[1] & 0x20)) - { - irq_status |= 6; - } - else if (hint_pending && (reg[0] & 0x10)) - { - irq_status |= 4; - } + if (vint_pending && (reg[1] & 0x20)) irq_status |= 6; + else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4; return M68K_INT_ACK_AUTOVECTOR; } diff --git a/source/vdp.h b/source/vdp.h index 1af0a36..1c9e249 100644 --- a/source/vdp.h +++ b/source/vdp.h @@ -63,7 +63,6 @@ extern int32 fifo_write_cnt; extern uint32 fifo_lastwrite; extern uint8 fifo_latency; extern uint8 vdp_pal; -extern double vdp_timings[4][4]; extern uint8 *vctab; extern uint8 *hctab;