.added proper TMSS emulation

.memory bus handlers code cleanup & optimization
This commit is contained in:
ekeeke31 2010-06-14 08:05:45 +00:00
parent f8c7045b72
commit 79d5f55611
17 changed files with 666 additions and 372 deletions

View File

@ -50,11 +50,11 @@ typedef struct
typedef struct
{
uint8 *rom; /* ROM data */
uint8 *base; /* ROM base area (slot 0) */
uint8 *base; /* ROM base (slot 0) */
uint32 romsize; /* ROM size */
uint32 mask; /* mask ROM */
uint16 lock_on; /* 1: Lock-On enabled */
uint16 jcart; /* 1: J-CART port enabled */
uint32 mask; /* ROM mask */
uint8 lock_on; /* 1: Lock-On port */
uint8 jcart; /* 1: J-CART port */
T_CART_HW hw; /* Extra hardware */
} T_CART;

View File

@ -117,7 +117,7 @@ void io_init(void)
void io_reset(void)
{
/* Reset I/O registers */
io_reg[0x00] = region_code | 0x20 | (config.bios_enabled == 3);
io_reg[0x00] = region_code | 0x20 | (config.tmss & 1);
io_reg[0x01] = 0x7F;
io_reg[0x02] = 0x7F;
io_reg[0x03] = 0x7F;

View File

@ -23,11 +23,16 @@
#include "shared.h"
uint8 bios_rom[0x10000]; /* OS ROM */
uint8 tmss[4]; /* TMSS security register */
uint8 bios_rom[0x800]; /* OS ROM */
uint8 work_ram[0x10000]; /* 68K RAM */
uint8 zram[0x2000]; /* Z80 RAM */
uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
uint32 zbank; /* Z80 bank window address */
uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
/* PICO data */
uint8 pico_current;
uint8 pico_page[7];
/*--------------------------------------------------------------------------*/
/* Init, reset, shutdown functions */
@ -68,11 +73,7 @@ void gen_init(void)
zbank_memory_map[i].write = zbank_lockup_w;
}
/* Z80 bus */
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
/* Z80 bus (bank access) */
zbank_memory_map[0xa0].read = zbank_lockup_r;
zbank_memory_map[0xa0].write = zbank_lockup_w;
@ -84,26 +85,9 @@ void gen_init(void)
zbank_memory_map[0xa1].read = zbank_read_ctrl_io;
zbank_memory_map[0xa1].write = zbank_write_ctrl_io;
/* SEGA PICO */
if (system_hw == SYSTEM_PICO)
/* VDP (initially locked on models with TMSS) */
if (!(config.tmss & 1))
{
m68k_memory_map[0x80].read8 = pico_read_byte;
m68k_memory_map[0x80].read16 = pico_read_word;
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
/* there is no I/O area (Notaz) */
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
}
/* VDP */
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = vdp_read_byte;
@ -115,14 +99,41 @@ void gen_init(void)
}
}
/* SEGA PICO */
if (system_hw == SYSTEM_PICO)
{
m68k_memory_map[0x80].read8 = pico_read_byte;
m68k_memory_map[0x80].read16 = pico_read_word;
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
/* there is no I/O area (Notaz) */
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
/* page registers */
pico_current = 0x00;
pico_page[0] = 0x00;
pico_page[1] = 0x01;
pico_page[2] = 0x03;
pico_page[3] = 0x07;
pico_page[4] = 0x0F;
pico_page[5] = 0x1F;
pico_page[6] = 0x3F;
}
}
void gen_hardreset(void)
{
/* Clear RAM */
memset (work_ram, 0x00, sizeof (work_ram));
memset (zram, 0x00, sizeof (zram));
/* TMSS BIOS support */
if (config.bios_enabled == 3)
/* TMSS + OS ROM support */
memset(tmss, 0x00, sizeof(tmss));
if (config.tmss == 3)
m68k_memory_map[0].base = bios_rom;
/* Reset CPU cycles (check EA logo corruption, no glitches for Skitchin/Budokan on PAL 60hz MD2 with TMSS) */
@ -130,6 +141,10 @@ void gen_hardreset(void)
/* Z80 bus is released & Z80 reset is asserted */
zstate = 0;
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
/* Assume default bank is $000000-$007FFF */
zbank = 0;
@ -170,10 +185,76 @@ void gen_shutdown(void)
z80_exit();
}
/*-----------------------------------------------------------------------
Bus controller chip functions
OS ROM / TMSS register control functions
-----------------------------------------------------------------------*/
void gen_busreq_w(uint32 state, uint32 cycles)
void gen_tmss_w(unsigned int offset, unsigned int data)
{
/* write TMSS regisiter */
WRITE_WORD(tmss, offset, data);
/* VDP requires "SEGA" value to be written in TMSSS register */
int i;
if (strncmp((char *)tmss, "SEGA", 4) == 0)
{
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = vdp_read_byte;
m68k_memory_map[i].read16 = vdp_read_word;
m68k_memory_map[i].write8 = vdp_write_byte;
m68k_memory_map[i].write16 = vdp_write_word;
zbank_memory_map[i].read = zbank_read_vdp;
zbank_memory_map[i].write = zbank_write_vdp;
}
}
else
{
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = m68k_lockup_r_8;
m68k_memory_map[i].read16 = m68k_lockup_r_16;
m68k_memory_map[i].write8 = m68k_lockup_w_8;
m68k_memory_map[i].write16 = m68k_lockup_w_16;
zbank_memory_map[i].read = zbank_lockup_r;
zbank_memory_map[i].write = zbank_lockup_w;
}
}
}
void gen_bankswitch_w(unsigned int data)
{
/* BIOS has not been loaded yet */
if (!(config.tmss & 2))
{
config.tmss |= 2;
memcpy(bios_rom, cart.rom, 0x800);
memset(cart.rom, 0xff, cart.romsize);
}
if (data & 1)
{
/* enable CART */
m68k_memory_map[0].base = cart.base;
}
else
{
/* enable internal BIOS ROM */
m68k_memory_map[0].base = bios_rom;
}
}
unsigned int gen_bankswitch_r(void)
{
return (m68k_memory_map[0].base == cart.base);
}
/*-----------------------------------------------------------------------
Z80 Bus controller chip functions
-----------------------------------------------------------------------*/
void gen_zbusreq_w(unsigned int state, unsigned int cycles)
{
if (state) /* Z80 Bus Requested */
{
@ -183,6 +264,15 @@ void gen_busreq_w(uint32 state, uint32 cycles)
/* request Z80 bus */
zstate |= 2;
/* enable 68k access */
if (zstate & 1)
{
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
}
}
else /* Z80 Bus Released */
{
@ -192,10 +282,16 @@ void gen_busreq_w(uint32 state, uint32 cycles)
/* release Z80 bus */
zstate &= 1;
/* disable 68k access */
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
}
}
void gen_reset_w(uint32 state, uint32 cycles)
void gen_zreset_w(unsigned int state, unsigned int cycles)
{
/* detect !ZRESET transitions */
if (state == (zstate & 1))
@ -212,6 +308,15 @@ void gen_reset_w(uint32 state, uint32 cycles)
/* negate Z80 reset */
zstate |= 1;
/* enable 68k access */
if (zstate & 1)
{
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
}
}
else /* !ZRESET active */
{
@ -221,13 +326,19 @@ void gen_reset_w(uint32 state, uint32 cycles)
/* assert Z80 reset */
zstate &= 2;
/* disable 68k access */
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
}
/* reset YM2612 */
fm_reset(cycles);
}
void gen_bank_w (uint32 state)
void gen_zbank_w (unsigned int state)
{
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
}

View File

@ -25,20 +25,26 @@
#define _GENESIS_H_
/* Global variables */
extern uint8 bios_rom[0x10000];
extern uint8 tmss[4];
extern uint8 bios_rom[0x800];
extern uint8 work_ram[0x10000];
extern uint8 zram[0x2000];
extern uint8 zstate;
extern uint32 zbank;
extern uint8 zstate;
extern uint8 pico_current;
extern uint8 pico_page[7];
/* Function prototypes */
extern void gen_init(void);
extern void gen_hardreset(void);
extern void gen_softreset(int state);
extern void gen_shutdown(void);
extern void gen_busreq_w(uint32 state, uint32 cycles);
extern void gen_reset_w(uint32 state, uint32 cycles);
extern void gen_bank_w(uint32 state);
extern void gen_tmss_w(unsigned int offset, unsigned int data);
extern void gen_bankswitch_w(unsigned int data);
extern unsigned int gen_bankswitch_r(void);
extern void gen_zbusreq_w(unsigned int state, unsigned int cycles);
extern void gen_zreset_w(unsigned int state, unsigned int cycles);
extern void gen_zbank_w(unsigned int state);
extern int z80_irq_callback(int param);
#endif /* _GEN_H_ */

View File

@ -85,7 +85,7 @@ void config_default(void)
config.region_detect = 0;
config.force_dtack = 0;
config.addr_error = 1;
config.bios_enabled = 0;
config.tmss = 0;
config.lock_on = 0;
config.romtype = 0;
config.hot_swap = 0;

View File

@ -47,7 +47,7 @@ typedef struct
uint8 region_detect;
uint8 force_dtack;
uint8 addr_error;
uint8 bios_enabled;
uint8 tmss;
uint8 lock_on;
uint8 hot_swap;
uint8 romtype;

View File

@ -1009,7 +1009,7 @@ static void systemmenu ()
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON");
sprintf (items[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
sprintf (items[3].text, "System TMSS: %s", (config.tmss & 1) ? "ON":"OFF");
if (config.lock_on == TYPE_GG)
sprintf (items[4].text, "Lock-On: GAME GENIE");
@ -1106,8 +1106,8 @@ static void systemmenu ()
case 3: /*** BIOS support ***/
config.bios_enabled ^= 1;
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
config.tmss ^= 1;
sprintf (items[3].text, "System TMSS: %s", (config.tmss & 1) ? "ON":"OFF");
if (cart.romsize)
{
system_init();

View File

@ -104,8 +104,8 @@ static bool FindIOS(u32 ios)
***************************************************************************/
static void load_bios(void)
{
/* reset BIOS found flag */
config.bios_enabled &= ~2;
/* reset BIOS flag */
config.tmss &= ~2;
/* open BIOS file */
FILE *fp = fopen(OS_ROM, "rb");
@ -116,7 +116,7 @@ static void load_bios(void)
fclose(fp);
/* update BIOS flags */
config.bios_enabled |= 2;
config.tmss |= 2;
}
static void init_machine(void)

View File

@ -10,7 +10,7 @@
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[(ADDR)+1]<<24) | \
((BASE)[(ADDR)]<<16) | \
((BASE)[(ADDR)+3]<<8) | \
(BASE)[(ADDR)+1])
(BASE)[(ADDR)+2])
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL)&0xff
@ -25,8 +25,8 @@
#else
#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
#define READ_WORD(BASE, ADDR) *(uint16 *)((BASE) + (ADDR));
#define READ_WORD_LONG(BASE, ADDR) *(uint32 *)((BASE) + (ADDR));
#define READ_WORD(BASE, ADDR) *(uint16 *)((BASE) + (ADDR))
#define READ_WORD_LONG(BASE, ADDR) *(uint32 *)((BASE) + (ADDR))
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = VAL & 0xff
#define WRITE_WORD(BASE, ADDR, VAL) *(uint16 *)((BASE) + (ADDR)) = VAL & 0xffff
#define WRITE_WORD_LONG(BASE, ADDR, VAL) *(uint32 *)((BASE) + (ADDR)) = VAL & 0xffffffff

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* 68k bus arbitration
* 68k bus address decoding
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
@ -24,13 +24,16 @@
#include "m68kcpu.h"
#include "shared.h"
/*--------------------------------------------------------------------------*/
/* Unused area (return open bus data, i.e prefetched instruction word) */
/*--------------------------------------------------------------------------*/
uint32 m68k_read_bus_8(uint32 address)
{
#ifdef LOGERROR
error("Unused read8 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
#endif
return m68k_read_pcrelative_8(REG_PC | (address & 1));
}
uint32 m68k_read_bus_16(uint32 address)
@ -56,20 +59,20 @@ void m68k_unused_16_w (uint32 address, uint32 data)
#endif
}
/*
Functions to handle memory accesses which cause the Genesis to halt
either temporarily (press RESET button to restart) or unrecoverably
(cycle power to restart).
*/
/*--------------------------------------------------------------------------*/
/* Illegal area (cause system to lock-up since !DTACK is not returned) */
/*--------------------------------------------------------------------------*/
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));
#endif
if (!config.force_dtack)
{
m68k_pulse_halt();
}
}
void m68k_lockup_w_16 (uint32 address, uint32 data)
{
@ -77,8 +80,10 @@ void m68k_lockup_w_16 (uint32 address, uint32 data)
error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC));
#endif
if (!config.force_dtack)
{
m68k_pulse_halt();
}
}
uint32 m68k_lockup_r_8 (uint32 address)
{
@ -86,8 +91,10 @@ uint32 m68k_lockup_r_8 (uint32 address)
error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
#endif
if (!config.force_dtack)
{
m68k_pulse_halt();
return -1;
}
return m68k_read_pcrelative_8(REG_PC | (address & 1));
}
uint32 m68k_lockup_r_16 (uint32 address)
@ -96,120 +103,128 @@ uint32 m68k_lockup_r_16 (uint32 address)
error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
#endif
if (!config.force_dtack)
{
m68k_pulse_halt();
return -1;
}
return m68k_read_pcrelative_16(REG_PC);
}
/* PICO data */
static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F};
/*--------------------------------------------------------------------------*/
/* 68000 memory handlers */
/* cartridge EEPROM */
/*--------------------------------------------------------------------------*/
/******* EEPROM **********************************************/
uint32 eeprom_read_byte(uint32 address)
{
if (address == eeprom.type.sda_out_adr)
return eeprom_read(address, 0);
if (address != eeprom.type.sda_out_adr)
{
return READ_BYTE(cart.rom, address);
}
return eeprom_read(address, 0);
}
uint32 eeprom_read_word(uint32 address)
{
if (address == (eeprom.type.sda_out_adr & 0xfffffe))
return eeprom_read(address, 1);
if (address != (eeprom.type.sda_out_adr & 0xfffffe))
{
return *(uint16 *)(cart.rom + address);
}
return eeprom_read(address, 1);
}
void eeprom_write_byte(uint32 address, uint32 data)
{
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr))
eeprom_write(address, data, 0);
else
if ((address != eeprom.type.sda_in_adr) && (address != eeprom.type.scl_adr))
{
m68k_unused_8_w(address, data);
return;
}
eeprom_write(address, data, 0);
}
void eeprom_write_word(uint32 address, uint32 data)
{
if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe)))
eeprom_write(address, data, 1);
else
if ((address != (eeprom.type.sda_in_adr & 0xfffffe)) && (address != (eeprom.type.scl_adr & 0xfffffe)))
{
m68k_unused_16_w (address, data);
return;
}
eeprom_write(address, data, 1);
}
/******* Z80 *************************************************/
/*--------------------------------------------------------------------------*/
/* Z80 bus (accessed through I/O chip) */
/*--------------------------------------------------------------------------*/
uint32 z80_read_byte(uint32 address)
{
/* Z80 bus is available ? */
if (zstate ^ 3)
return m68k_read_bus_8(address);
switch ((address >> 13) & 3)
{
case 2: /* YM2612 */
{
return fm_read(mcycles_68k, address & 3);
}
case 3: /* MISC */
case 3: /* Misc */
{
if ((address & 0xff00) == 0x7f00)
return m68k_lockup_r_8(address); /* VDP */
{
/* VDP (through 68k bus) */
return m68k_lockup_r_8(address);
}
return (m68k_read_bus_8(address) | 0xff);
}
default: /* ZRAM */
{
return zram[address & 0x1fff];
}
}
}
uint32 z80_read_word(uint32 address)
{
/* Z80 bus is available ? */
if (zstate ^ 3)
return m68k_read_bus_16(address);
switch ((address >> 13) & 3)
{
case 2: /* YM2612 */
{
int temp = fm_read(mcycles_68k, address & 3);
return (temp << 8 | temp);
unsigned int data = fm_read(mcycles_68k, address & 3);
return (data << 8 | data);
}
case 3: /* MISC */
case 3: /* Misc */
{
if ((address & 0xff00) == 0x7f00)
return m68k_lockup_r_16(address); /* VDP */
{
/* VDP (through 68k bus) */
return m68k_lockup_r_16(address);
}
return (m68k_read_bus_16(address) | 0xffff);
}
default: /* ZRAM */
{
int temp = zram[address & 0x1fff];
return (temp << 8 | temp);
unsigned int data = zram[address & 0x1fff];
return (data << 8 | data);
}
}
}
void z80_write_byte(uint32 address, uint32 data)
{
/* Z80 bus is available ? */
if (zstate ^ 3)
{
m68k_unused_8_w(address, data);
return;
}
switch ((address >> 13) & 3)
{
case 2: /* YM2612 */
{
fm_write(mcycles_68k, address & 3, data);
return;
}
case 3:
{
switch ((address >> 8) & 0x7f)
{
case 0x60: /* Bank register */
gen_bank_w(data & 1);
gen_zbank_w(data & 1);
return;
case 0x7f: /* VDP */
@ -220,88 +235,130 @@ void z80_write_byte(uint32 address, uint32 data)
m68k_unused_8_w(address, data);
return;
}
}
default: /* ZRAM */
{
zram[address & 0x1fff] = data;
mcycles_68k+=8; /* Z80 bus latency (Pacman 2: New Adventures) */
mcycles_68k += 8; /* Z80 bus latency (fixes Pacman 2: New Adventures) */
return;
}
}
}
void z80_write_word(uint32 address, uint32 data)
{
/* Z80 bus is available ? */
if (zstate ^ 3)
{
m68k_unused_16_w(address, data);
return;
}
switch ((address >> 13) & 3)
{
case 2: /* YM2612 */
fm_write (mcycles_68k, address & 3, data >> 8);
return;
case 3:
switch ((address >> 8) & 0x7f)
{
case 0x60: /* Bank register */
gen_bank_w ((data >> 8) & 1);
return;
case 0x7f: /* VDP */
m68k_lockup_w_16(address, data);
return;
default:
m68k_unused_16_w(address, data);
fm_write(mcycles_68k, address & 3, data >> 8);
return;
}
case 3:
{
switch ((address >> 8) & 0x7f)
{
case 0x60: /* Bank register */
{
gen_zbank_w((data >> 8) & 1);
return;
}
case 0x7f: /* VDP */
{
m68k_lockup_w_16(address, data);
return;
}
default:
{
m68k_unused_16_w(address, data);
return;
}
}
}
default: /* ZRAM */
{
zram[address & 0x1fff] = data >> 8;
return;
}
}
}
/******* I/O & CTRL ******************************************/
/*--------------------------------------------------------------------------*/
/* I/O Control */
/*--------------------------------------------------------------------------*/
uint32 ctrl_io_read_byte(uint32 address)
{
switch ((address >> 8) & 0xff)
{
case 0x00: /* I/O chip */
{
if (address & 0xe0)
{
return m68k_read_bus_8(address);
return (io_read((address >> 1) & 0x0f));
}
return io_read((address >> 1) & 0x0f);
}
case 0x11: /* BUSACK */
{
if (address & 1)
{
return m68k_read_bus_8(address);
}
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xfe;
if (zstate ^ 3)
return (m68k_read_pcrelative_8(REG_PC) | 0x01);
return (m68k_read_pcrelative_8(REG_PC) & 0xfe);
{
return (data | 0x01);
}
return data;
}
case 0x30: /* TIME */
if (cart.hw.time_r)
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
{
if (!cart.hw.time_r)
{
return m68k_read_bus_8(address);
}
unsigned int data = cart.hw.time_r(address);
if (address & 1)
{
return (data & 0xff);
}
return (data >> 8);
}
case 0x41: /* OS ROM */
{
if (!(address & 1))
{
return m68k_read_bus_8(address);
}
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xfe;
return (gen_bankswitch_r() | data);
}
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);
}
}
}
uint32 ctrl_io_read_word(uint32 address)
{
@ -310,306 +367,394 @@ uint32 ctrl_io_read_word(uint32 address)
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);
}
unsigned int data = io_read((address >> 1) & 0x0f);
return (data << 8 | data);
}
case 0x11: /* BUSACK */
{
unsigned int data = m68k_read_pcrelative_16(REG_PC) & 0xfeff;
if (zstate ^ 3)
return (m68k_read_pcrelative_16(REG_PC) | 0x100);
return (m68k_read_pcrelative_16(REG_PC) & 0xfeff);
{
return data | 0x0100;
}
return data;
}
case 0x30: /* TIME */
if (cart.hw.time_r)
return cart.hw.time_r(address);
{
if (!cart.hw.time_r)
{
return m68k_read_bus_16(address);
}
return cart.hw.time_r(address);
}
case 0x50: /* SVP */
if (svp)
{
if ((address & 0xfd) == 0)
switch (address & 0xfe)
{
case 0:
case 2:
{
return svp->ssp1601.gr[SSP_XST].h;
if ((address & 0xff) == 4)
}
case 4:
{
uint32 temp = svp->ssp1601.gr[SSP_PM0].h;
svp->ssp1601.gr[SSP_PM0].h &= ~1;
return temp;
}
}
default:
{
return m68k_read_bus_16(address);
}
}
}
case 0x10: /* MEMORY MODE */
case 0x12: /* RESET */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x41: /* BOOTROM */
case 0x41: /* OS ROM */
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
{
if ((address & 0xe1) != 0x01)
{
/* get /LWR only */
m68k_unused_8_w(address, data);
return;
}
io_write((address >> 1) & 0x0f, data);
return;
}
case 0x11: /* BUSREQ */
{
if (address & 1)
{
m68k_unused_8_w(address, data);
else
gen_busreq_w(data & 1, mcycles_68k);
return;
}
gen_zbusreq_w(data & 1, mcycles_68k);
return;
}
case 0x12: /* RESET */
{
if (address & 1)
{
m68k_unused_8_w(address, data);
else
gen_reset_w(data & 1, mcycles_68k);
return;
}
gen_zreset_w(data & 1, mcycles_68k);
return;
}
case 0x30: /* TIME */
{
cart.hw.time_w(address, data);
return;
case 0x41: /* BOOTROM */
if (address & 1)
{
m68k_memory_map[0].base = (data & 1) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2))
{
config.bios_enabled |= 2;
memcpy(bios_rom, cart.rom, 0x800);
memset(cart.rom, 0xff, cart.romsize);
}
}
else
case 0x41: /* OS ROM */
{
if (!(address & 1))
{
m68k_unused_8_w(address, data);
}
return;
}
gen_bankswitch_w(data & 1);
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;
}
}
}
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
return;
}
io_write((address >> 1) & 0x0f, data & 0xff);
return;
}
case 0x11: /* BUSREQ */
gen_busreq_w ((data >> 8) & 1, mcycles_68k);
{
gen_zbusreq_w((data >> 8) & 1, mcycles_68k);
return;
}
case 0x12: /* RESET */
gen_reset_w ((data >> 8) & 1, mcycles_68k);
{
gen_zreset_w((data >> 8) & 1, mcycles_68k);
return;
}
case 0x30: /* TIME */
{
cart.hw.time_w(address & 0xfe, data >> 8);
cart.hw.time_w(address, data & 0xff);
return;
}
case 0x40: /* TMSS */
{
gen_tmss_w(address & 3, data);
break;
}
case 0x50: /* SVP REGISTERS */
if (svp)
{
if (address & 0xfd)
{
m68k_unused_16_w(address, data);
return;
}
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 */
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) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2))
{
config.bios_enabled |= 2;
memcpy(bios_rom, cart.rom, 0x800);
memset(cart.rom, 0xff, cart.romsize);
}
return;
case 0x10: /* MEMORY MODE */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x41: /* OS ROM */
case 0x44: /* RADICA */
{
m68k_unused_16_w (address, data);
return;
}
default: /* Unused */
default: /* Invalid address */
{
m68k_lockup_w_16 (address, data);
return;
}
}
}
/******* VDP *************************************************/
/*--------------------------------------------------------------------------*/
/* VDP */
/*--------------------------------------------------------------------------*/
uint32 vdp_read_byte(uint32 address)
{
switch (address & 0xfd)
{
case 0x00: /* DATA */
{
return (vdp_data_r() >> 8);
}
case 0x01: /* DATA */
{
return (vdp_data_r() & 0xff);
}
case 0x04: /* CTRL */
return ((m68k_read_pcrelative_8(REG_PC) & 0xfc) | ((vdp_ctrl_r(mcycles_68k) >> 8) & 3));
{
return (((vdp_ctrl_r(mcycles_68k) >> 8) & 3) | (m68k_read_pcrelative_8(REG_PC) & 0xfc));
}
case 0x05: /* CTRL */
{
return (vdp_ctrl_r(mcycles_68k) & 0xff);
}
case 0x08: /* HVC */
case 0x0c:
{
return (vdp_hvc_r(mcycles_68k) >> 8);
}
case 0x09: /* HVC */
case 0x0d:
{
return (vdp_hvc_r(mcycles_68k) & 0xff);
}
case 0x18: /* Unused */
case 0x19:
case 0x1c:
case 0x1d:
{
return m68k_read_bus_8(address);
}
default: /* Invalid address */
{
return m68k_lockup_r_8(address);
}
}
}
uint32 vdp_read_word(uint32 address)
{
switch (address & 0xfc)
{
case 0x00: /* DATA */
{
return vdp_data_r();
}
case 0x04: /* CTRL */
{
return ((vdp_ctrl_r(mcycles_68k) & 0x3FF) | (m68k_read_pcrelative_16(REG_PC) & 0xFC00));
}
case 0x08: /* HVC */
case 0x0c:
{
return vdp_hvc_r(mcycles_68k);
}
case 0x18: /* Unused */
case 0x1c:
{
return m68k_read_bus_16(address);
}
default: /* Invalid address */
{
return m68k_lockup_r_16(address);
}
}
}
void vdp_write_byte(uint32 address, uint32 data)
{
switch (address & 0xfc)
{
case 0x00: /* Data port */
{
vdp_data_w(data << 8 | data);
return;
}
case 0x04: /* Control port */
{
vdp_ctrl_w(data << 8 | data);
return;
}
case 0x10: /* PSG */
case 0x14:
if (address & 1)
psg_write(mcycles_68k, data);
else
{
if (!(address & 1))
{
m68k_unused_8_w(address, data);
return;
}
psg_write(mcycles_68k, data);
return;
}
case 0x18: /* Unused */
{
m68k_unused_8_w(address, data);
return;
}
case 0x1c: /* TEST register */
{
vdp_test_w(data << 8 | data);
return;
}
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(mcycles_68k, 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 ************************************************/
@ -620,7 +765,9 @@ uint32 pico_read_byte(uint32 address)
switch (address & 0xff)
{
case 0x01: /* VERSION register */
return (0x40);
{
return 0x40;
}
case 0x03: /* IO register */
{
@ -637,32 +784,43 @@ uint32 pico_read_byte(uint32 address)
}
case 0x05: /* MSB PEN X coordinate */
{
return (input.analog[0][0] >> 8);
}
case 0x07: /* LSB PEN X coordinate */
{
return (input.analog[0][0] & 0xff);
}
case 0x09: /* MSB PEN Y coordinate */
{
return (input.analog[0][1] >> 8);
}
case 0x0b: /* LSB PEN Y coordinate */
{
return (input.analog[0][1] & 0xff);
}
case 0x0d: /* PAGE register */
return pico_page[pico_current]; /* TODO */
case 0x0d: /* PAGE register (TODO) */
{
return pico_page[pico_current];
}
case 0x10: /* PCM registers */
case 0x11:
case 0x12:
case 0x13:
return 0x80; /* TODO */
case 0x10: /* PCM registers (TODO) */
{
return 0x80;
}
default:
{
return m68k_read_bus_8(address);
}
}
}
uint32 pico_read_word(uint32 address)
{
return ((m68k_read_bus_8(address) << 8) | pico_read_byte(address | 1));
return (pico_read_byte(address | 1) | (m68k_read_bus_8(address) << 8));
}

View File

@ -64,6 +64,4 @@ extern void vdp_write_word(uint32 address, uint32 data);
extern uint32 pico_read_byte(uint32 address);
extern uint32 pico_read_word(uint32 address);
uint32 pico_current;
#endif /* _MEM68K_H_ */

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* 68k bus banked access from Z80
* Z80 bank access to 68k bus
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
@ -32,7 +32,7 @@ uint32 zbank_unused_r(uint32 address)
#ifdef LOGERROR
error("Z80 bank unused read %06X\n", address);
#endif
return (address & 1) ? 0x00 : 0xFF;
return (address & 1) ? 0x00 : 0xff;
}
void zbank_unused_w(uint32 address, uint32 data)
@ -52,7 +52,7 @@ uint32 zbank_lockup_r(uint32 address)
mcycles_z80 = 0xffffffff;
zstate = 0;
}
return 0xFF;
return 0xff;
}
void zbank_lockup_w(uint32 address, uint32 data)
@ -73,95 +73,135 @@ uint32 zbank_read_ctrl_io(uint32 address)
switch ((address >> 8) & 0xff)
{
case 0x00: /* I/O chip */
{
if (address & 0xe0)
{
return zbank_unused_r(address);
}
return (io_read((address >> 1) & 0x0f));
}
case 0x11: /* BUSACK */
{
if (address & 1)
{
return zbank_unused_r(address);
}
return 0xff;
}
case 0x30: /* TIME */
if (cart.hw.time_r)
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
{
if (!cart.hw.time_r)
{
return zbank_unused_r(address);
}
unsigned int data = cart.hw.time_r(address);
if (address & 1)
{
return (data & 0xff);
}
return (data >> 8);
}
case 0x41: /* OS ROM */
{
if (!(address & 1))
{
return zbank_unused_r(address);
}
return (gen_bankswitch_r() | 0xfe);
}
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 zbank_unused_r(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 */
else
{
/* get /LWR only */
if ((address & 0xe1) != 0x01)
{
zbank_unused_w(address, data);
return;
}
io_write((address >> 1) & 0x0f, data);
return;
}
case 0x11: /* BUSREQ */
{
if (address & 1)
{
zbank_unused_w(address, data);
else
gen_busreq_w(data & 1, mcycles_z80);
return;
}
gen_zbusreq_w(data & 1, mcycles_z80);
return;
}
case 0x12: /* RESET */
{
if (address & 1)
{
zbank_unused_w(address, data);
else
gen_reset_w(data & 1, mcycles_z80);
return;
}
gen_zreset_w(data & 1, mcycles_z80);
return;
}
case 0x30: /* TIME */
{
cart.hw.time_w(address, data);
return;
case 0x41: /* BOOTROM */
if (address & 1)
{
m68k_memory_map[0].base = (data & 1) ? cart.base : bios_rom;
/* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2))
{
config.bios_enabled |= 2;
memcpy(bios_rom, cart.rom, 0x800);
memset(cart.rom, 0xff, cart.romsize);
}
}
else
case 0x41: /* OS ROM */
{
if (!(address & 1))
{
zbank_unused_w(address, data);
}
return;
}
gen_bankswitch_w(data & 1);
return;
}
case 0x10: /* MEMORY MODE */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */
{
zbank_unused_w(address, data);
return;
}
default: /* Invalid address */
{
zbank_lockup_w(address, data);
return;
}
}
}
/* VDP */
@ -170,66 +210,96 @@ uint32 zbank_read_vdp(uint32 address)
switch (address & 0xfd)
{
case 0x00: /* DATA */
{
return (vdp_data_r() >> 8);
}
case 0x01: /* DATA */
{
return (vdp_data_r() & 0xff);
}
case 0x04: /* CTRL */
return (0xfc | ((vdp_ctrl_r(mcycles_z80) >> 8) & 3));
{
return (((vdp_ctrl_r(mcycles_z80) >> 8) & 3) | 0xfc);
}
case 0x05: /* CTRL */
{
return (vdp_ctrl_r(mcycles_z80) & 0xff);
}
case 0x08: /* HVC */
case 0x0c:
{
return (vdp_hvc_r(mcycles_z80) >> 8);
}
case 0x09: /* HVC */
case 0x0d:
{
return (vdp_hvc_r(mcycles_z80) & 0xff);
}
case 0x18: /* Unused */
case 0x19:
case 0x1c:
case 0x1d:
{
return zbank_unused_r(address);
}
default: /* Invalid address */
{
return zbank_lockup_r(address);
}
}
}
void zbank_write_vdp(uint32 address, uint32 data)
{
switch (address & 0xfc)
{
case 0x00: /* Data port */
{
vdp_data_w(data << 8 | data);
return;
}
case 0x04: /* Control port */
{
vdp_ctrl_w(data << 8 | data);
return;
}
case 0x10: /* PSG */
case 0x14:
if (address & 1)
psg_write(mcycles_z80, data);
else
{
if (!(address & 1))
{
zbank_unused_w(address, data);
return;
}
psg_write(mcycles_z80, data);
return;
}
case 0x18: /* Unused */
{
zbank_unused_w(address, data);
return;
}
case 0x1c: /* TEST register */
{
vdp_test_w(data << 8 | data);
return;
}
default: /* Invalid address */
{
zbank_lockup_w(address, data);
return;
}
}
}

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* Z80 bus arbitration (Genesis mode)
* Z80 bus address decoding (Genesis mode)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
@ -65,78 +65,6 @@ static inline unsigned int z80_lockup_r(unsigned int address)
}
return 0xff;
}
/*
VDP access
*/
static inline unsigned int z80_vdp_r(unsigned int address)
{
switch (address & 0xfd)
{
case 0x00: /* DATA */
return (vdp_data_r() >> 8);
case 0x01: /* DATA */
return (vdp_data_r() & 0xff);
case 0x04: /* CTRL */
return (0xfc | (vdp_ctrl_r(mcycles_z80) >> 8));
case 0x05: /* CTRL */
return (vdp_ctrl_r(mcycles_z80) & 0xff);
case 0x08: /* HVC */
case 0x0c:
return (vdp_hvc_r(mcycles_z80) >> 8);
case 0x09: /* HVC */
case 0x0d:
return (vdp_hvc_r(mcycles_z80) & 0xff);
case 0x18: /* Unused */
case 0x19:
case 0x1c:
case 0x1d:
return z80_unused_r(address);
default: /* Invalid address */
return z80_lockup_r(address);
}
}
static inline void z80_vdp_w(unsigned int address, unsigned int data)
{
switch (address & 0xfc)
{
case 0x00: /* Data port */
vdp_data_w(data << 8 | data);
return;
case 0x04: /* Control port */
vdp_ctrl_w(data << 8 | data);
return;
case 0x10: /* PSG */
case 0x14:
if (address & 1)
psg_write(mcycles_z80, data);
else
z80_unused_w(address, data);
return;
case 0x18: /* Unused */
z80_unused_w(address, data);
return;
case 0x1c: /* Test register */
vdp_test_w(data << 8 | data);
return;
default: /* Invalid address */
z80_lockup_w(address, data);
return;
}
}
/*
Z80 memory handlers
*/
@ -146,22 +74,32 @@ unsigned int cpu_readmem16(unsigned int address)
{
case 0: /* Work RAM */
case 1:
{
return zram[address & 0x1fff];
}
case 2: /* YM2612 */
{
return fm_read(mcycles_68k, address & 3);
}
case 3: /* VDP */
if ((address >> 8) == 0x7f)
return z80_vdp_r (address);
{
if ((address >> 8) != 0x7f)
{
return z80_unused_r(address);
}
return (*zbank_memory_map[0xc0].read)(address);
}
default: /* V-bus bank */
{
address = zbank | (address & 0x7fff);
int slot = address >> 16;
unsigned int slot = address >> 16;
if (zbank_memory_map[slot].read)
{
return (*zbank_memory_map[slot].read)(address);
}
return READ_BYTE(m68k_memory_map[slot].base, address & 0xffff);
}
}
@ -174,37 +112,50 @@ void cpu_writemem16(unsigned int address, unsigned int data)
{
case 0: /* Work RAM */
case 1:
{
zram[address & 0x1fff] = data;
return;
}
case 2: /* YM2612 */
{
fm_write(mcycles_z80, address & 3, data);
return;
}
case 3: /* Bank register and VDP */
{
switch(address >> 8)
{
case 0x60:
gen_bank_w(data & 1);
{
gen_zbank_w(data & 1);
return;
}
case 0x7f:
z80_vdp_w(address, data);
{
(*zbank_memory_map[0xc0].write)(address, data);
return;
}
default:
{
z80_unused_w(address, data);
return;
}
return;
}
}
default: /* V-bus bank */
{
address = zbank | (address & 0x7fff);
int slot = address >> 16;
unsigned int slot = address >> 16;
if (zbank_memory_map[slot].write)
{
(*zbank_memory_map[slot].write)(address, data);
else
return;
}
WRITE_BYTE(m68k_memory_map[slot].base, address & 0xffff, data);
return;
}
@ -223,7 +174,7 @@ unsigned int cpu_readport16(unsigned int port)
#if LOGERROR
error("Z80 read port %04X\n", port);
#endif
return 0xFF;
return 0xff;
}
void cpu_writeport16(unsigned int port, unsigned int data)

View File

@ -926,7 +926,6 @@ static inline uint32 get_hscroll(int line)
/*--------------------------------------------------------------------------*/
/* Layers render functions */
/*--------------------------------------------------------------------------*/
static void render_bg(int line, int width)
{
uint32 column, atex, atbuf, *src, *dst;
@ -1723,9 +1722,8 @@ void render_shutdown(void)
void render_line(int line)
{
/* display OFF */
if (reg[0] & 0x01)
return;
/* display disabled */
if (reg[0] & 0x01) return;
uint8 *lb = tmp_buf;
int width = bitmap.viewport.w;

View File

@ -27,7 +27,7 @@ void set_config_defaults(void)
config.region_detect = 0;
config.force_dtack = 0;
config.addr_error = 1;
config.bios_enabled = 0;
config.tmss = 0;
config.lock_on = 0;
config.romtype = 0;
@ -42,6 +42,7 @@ void set_config_defaults(void)
config.gun_cursor[1] = 1;
config.invert_mouse = 0;
for (i=0;i<MAX_INPUTS;i++)
{
config.input[i].padtype = DEVICE_3BUTTON;
}
}

View File

@ -9,35 +9,36 @@
typedef struct
{
uint8 padtype;
} t_input_c;
} t_input_config;
typedef struct
{
uint8 hq_fm;
uint8 psgBoostNoise;
int32 psg_preamp;
int32 fm_preamp;
uint8 filter;
uint16 low_freq;
uint16 high_freq;
uint8 lp_range;
float lg;
float mg;
float hg;
float rolloff;
uint8 psgBoostNoise;
uint8 dac_bits;
int16 psg_preamp;
int16 fm_preamp;
int16 lp_range;
int16 low_freq;
int16 high_freq;
int16 lg;
int16 mg;
int16 hg;
float rolloff;
uint8 region_detect;
uint8 force_dtack;
uint8 addr_error;
uint8 bios_enabled;
uint8 tmss;
uint8 lock_on;
uint8 hot_swap;
uint8 romtype;
uint8 overscan;
uint8 render;
uint8 ntsc;
t_input_c input[MAX_INPUTS];
uint8 gun_cursor[2];
uint8 invert_mouse;
uint8 gun_cursor[2];
uint8 overscan;
uint8 ntsc;
uint8 render;
t_input_config input[MAX_INPUTS];
} t_config;
/* Global variables */

View File

@ -215,8 +215,8 @@ void vdp_reset(void)
if (config.overscan & 2)
bitmap.viewport.x = 12;
/* reset some registers normally set by BIOS */
if (config.bios_enabled == 1)
/* initialize registers if OS ROM is not used */
if (config.tmss == 1)
{
reg_w(0 , 0x04); /* Palette bit set */
reg_w(1 , 0x04); /* Mode 5 enabled */