mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-09-10 16:53:15 +02:00
[Core/VDP]
--------------- * improved VBLANK flag accuracy, as observed on real hardware. * improved DMA operations accuracy, writes are now performed on a scanline basis: fixes Gaiares (flickering title screen). * improved DMA Fill timing accuracy. * fixed DMA with bad code values: fixes Williams Arcade Classics (corrupted gfx after soft reset). * fixed horizontal resolution changes during HBLANK: fixes Bugs Bunny in Double Trouble (2nd stage). * fixed Vertical Counter in interlace mode 1, as observed on real hardware. * fixed horizontal border width, as observed on real hardware. * various code improvments & optimizations. [Core/Extra] --------------- * improved savestate format: added DMA, SVP, cartridge mapping & internal registers state informations * improved unlicensed ROM mappers emulation * added Chinese Fighters III mapper support * added Top Fighter mapper support * fixed Barver Battle Saga mapper support * fixed cartridge hardware soft-reset (Game Genie, SVP, ...) * fixed Game Genie registers byte reads
This commit is contained in:
parent
edf479a257
commit
a4cfc2a77a
@ -151,23 +151,26 @@ void areplay_shutdown(void)
|
||||
action_replay.enabled = 0;
|
||||
}
|
||||
|
||||
void areplay_reset(int hard_reset)
|
||||
void areplay_reset(int hard)
|
||||
{
|
||||
if (action_replay.enabled)
|
||||
{
|
||||
/* reset internal registers */
|
||||
memset(action_replay.regs, 0, sizeof(action_replay.regs));
|
||||
memset(action_replay.old, 0, sizeof(action_replay.old));
|
||||
memset(action_replay.data, 0, sizeof(action_replay.data));
|
||||
memset(action_replay.addr, 0, sizeof(action_replay.addr));
|
||||
|
||||
/* by default, internal ROM is mapped at $000000-$00FFFF */
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
|
||||
/* internal RAM is cleared on power ON */
|
||||
if (hard_reset)
|
||||
if (hard || (action_replay.status == AR_SWITCH_TRAINER))
|
||||
{
|
||||
memset(action_replay.ram,0xff,0x10000);
|
||||
/* reset internal registers */
|
||||
memset(action_replay.regs, 0, sizeof(action_replay.regs));
|
||||
memset(action_replay.old, 0, sizeof(action_replay.old));
|
||||
memset(action_replay.data, 0, sizeof(action_replay.data));
|
||||
memset(action_replay.addr, 0, sizeof(action_replay.addr));
|
||||
|
||||
/* by default, internal ROM is mapped at $000000-$00FFFF */
|
||||
m68k_memory_map[0].base = action_replay.rom;
|
||||
|
||||
/* reset internal RAM on power-on */
|
||||
if (hard)
|
||||
{
|
||||
memset(action_replay.ram,0xff,0x10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
extern void areplay_init(void);
|
||||
extern void areplay_shutdown(void);
|
||||
extern void areplay_reset(int hard_reset);
|
||||
extern void areplay_reset(int hard);
|
||||
extern void areplay_set_status(int status);
|
||||
extern int areplay_get_status(void);
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Genesis Plus
|
||||
* Cartridge Hardware support
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Eke-Eke (GCN/Wii port)
|
||||
*
|
||||
* Most cartridge protections documented by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define CART_CNT 28
|
||||
#define CART_CNT 30
|
||||
|
||||
extern int emulate_address_error;
|
||||
|
||||
@ -45,15 +45,19 @@ typedef struct
|
||||
} T_CART_ENTRY;
|
||||
|
||||
/* Function prototypes */
|
||||
static void sega_mapper_w(uint32 address, uint32 data);
|
||||
static void special_mapper_w(uint32 address, uint32 data);
|
||||
static void realtec_mapper_w(uint32 address, uint32 data);
|
||||
static void seganet_mapper_w(uint32 address, uint32 data);
|
||||
static uint32 radica_mapper_r(uint32 address);
|
||||
static void mapper_sega_w(uint32 data);
|
||||
static void mapper_ssf2_w(uint32 address, uint32 data);
|
||||
static void mapper_realtec_w(uint32 address, uint32 data);
|
||||
static void mapper_seganet_w(uint32 address, uint32 data);
|
||||
static void mapper_32k_w(uint32 data);
|
||||
static void mapper_64k_w(uint32 data);
|
||||
static void mapper_64k_multi_w(uint32 address);
|
||||
static uint32 mapper_radica_r(uint32 address);
|
||||
static void default_time_w(uint32 address, uint32 data);
|
||||
static void default_regs_w(uint32 address, uint32 data);
|
||||
static uint32 default_regs_r(uint32 address);
|
||||
static void special_regs_w(uint32 address, uint32 data);
|
||||
static void custom_regs_w(uint32 address, uint32 data);
|
||||
static void custom_alt_regs_w(uint32 address, uint32 data);
|
||||
|
||||
/* Games that need extra hardware emulation:
|
||||
- copy protection device
|
||||
@ -62,31 +66,37 @@ static void special_regs_w(uint32 address, uint32 data);
|
||||
static const T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{
|
||||
/* Funny World & Balloon Boy */
|
||||
{0x0000,0x06ab,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,1,NULL,NULL,NULL,realtec_mapper_w}},
|
||||
{0x0000,0x06ab,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
|
||||
/* Whac-a-Critter */
|
||||
{0xffff,0xf863,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,1,NULL,NULL,NULL,realtec_mapper_w}},
|
||||
{0xffff,0xf863,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
|
||||
/* Earth Defense */
|
||||
{0xffff,0x44fb,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,1,NULL,NULL,NULL,realtec_mapper_w}},
|
||||
{0xffff,0x44fb,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},1,0,NULL,NULL,NULL,mapper_realtec_w}},
|
||||
/* RADICA (Volume 1) (not byteswapped) */
|
||||
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,radica_mapper_r,NULL,NULL,NULL}},
|
||||
{0x0000,0x2326,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* RADICA (Volume 2) */
|
||||
{0x4f10,0x0836,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,radica_mapper_r,NULL,NULL,NULL}},
|
||||
{0x4f10,0x0836,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* RADICA (Volume 1) */
|
||||
{0xf424,0x9f82,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,radica_mapper_r,NULL,NULL,NULL}},
|
||||
{0xf424,0x9f82,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,mapper_radica_r,NULL,NULL,NULL}},
|
||||
/* Chinese Fighters III */
|
||||
{0x9490,0x8180,0x40,0x6f,{{0x00,0x00,0x00,0x00},{0xf0000c,0xf0000c,0xf0000c,0xf0000c},{0x400000,0x400004,0x400008,0x40000c},0,1,NULL,NULL,default_regs_r,custom_alt_regs_w}},
|
||||
/* Top Fighter */
|
||||
{0x4eb9,0x5d8b,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Mulan */
|
||||
{0x0404,0x1b40,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,special_regs_w}},
|
||||
{0x0404,0x1b40,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Pocket Monsters II */
|
||||
{0x47f9,0x17e5,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,special_regs_w}},
|
||||
{0x47f9,0x17e5,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Lion King 3 */
|
||||
{0x0000,0x507c,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x507c,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Super King Kong 99 */
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0x00,0x00,0x00,0x00},{0xf00007,0xf00007,0xf00007,0xffffff},{0x600001,0x600003,0x600005,0x000000},0,1,NULL,NULL,default_regs_r,custom_regs_w}},
|
||||
/* Pokemon Stadium */
|
||||
{0x0000,0x843c,0x70,0x7f,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,NULL,NULL,NULL,special_regs_w}},
|
||||
{0x0000,0x843c,0x70,0x7f,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,1,NULL,NULL,NULL,custom_regs_w}},
|
||||
/* Lion King 2 */
|
||||
{0xffff,0x1d9b,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Squirell King */
|
||||
{0x0000,0x8ec8,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffffd,0xfffffd,0xffffff,0xffffff},{0x400000,0x400004,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0x00,0x00,0x00,0x00},{0xfffff4,0xffffff,0xffffff,0xffffff},{0x400004,0x000000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,default_regs_w}},
|
||||
/* Supper Bubble Bobble */
|
||||
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Mahjong Lover */
|
||||
@ -101,13 +111,9 @@ static const T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0x00,0x00,0x00,0x00},{0x000000,0x000000,0x000000,0x000000},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,NULL,default_regs_r,NULL}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x400004,0x000000,0x000000},0,0,default_regs_r,NULL,default_regs_r,NULL}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0xffff,0x0474,0x00,0x00,{{0x0a,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* Super Mario 2 1998 */
|
||||
/* Super Mario World */
|
||||
{0x2020,0xb4eb,0x00,0x00,{{0x1c,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x000000,0x000000,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* A Bug's Life */
|
||||
{0x7f7f,0x2aad,0x00,0x00,{{0x28,0x1f,0x01,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
@ -115,8 +121,10 @@ static const T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{0x0000,0x021e,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* Pocket Monster */
|
||||
{0xd6fc,0x1eb1,0x00,0x00,{{0x00,0x01,0x1f,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0xa13002,0xa1303e,0x000000},0,0,default_regs_r,NULL,NULL,NULL}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0xa13000,0x400004,0x000000,0x000000},0,0,default_regs_r,NULL,default_regs_r,NULL}},
|
||||
/* Game no Kanzume Otokuyou */
|
||||
{0x0000,0xf9d1,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,seganet_mapper_w,NULL,NULL}}
|
||||
{0x0000,0xf9d1,0x00,0x00,{{0x00,0x00,0x00,0x00},{0xffffff,0xffffff,0xffffff,0xffffff},{0x000000,0x000000,0x000000,0x000000},0,0,NULL,mapper_seganet_w,NULL,NULL}}
|
||||
};
|
||||
|
||||
|
||||
@ -311,12 +319,16 @@ void cart_hw_init()
|
||||
switch (config.lock_on)
|
||||
{
|
||||
case TYPE_GG:
|
||||
{
|
||||
ggenie_init();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_AR:
|
||||
{
|
||||
areplay_init();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_SK:
|
||||
{
|
||||
@ -359,14 +371,18 @@ void cart_hw_init()
|
||||
|
||||
/*$000000-$1fffff is mapped to S&K ROM */
|
||||
for (i=0x00; i<0x20; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = (cart.rom + 0x600000) + (i<<16);
|
||||
}
|
||||
|
||||
cart.lock_on = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
@ -408,6 +424,22 @@ void cart_hw_init()
|
||||
}
|
||||
}
|
||||
|
||||
/* Realtec mapper */
|
||||
if (cart.hw.realtec)
|
||||
{
|
||||
/* 8k BOOT ROM */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
memcpy(cart.rom + 0x900000 + i*0x2000, cart.rom + 0x7e000, 0x2000);
|
||||
}
|
||||
|
||||
/* BOOT ROM is mapped to $000000-$3FFFFF */
|
||||
for (i=0x00; i<0x40; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = cart.rom + 0x900000;
|
||||
}
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* default behavior */
|
||||
emulate_address_error = config.addr_error;
|
||||
@ -434,50 +466,42 @@ void cart_hw_init()
|
||||
{
|
||||
/* assume SSF2 mapper */
|
||||
cart.hw.bankshift = 1;
|
||||
cart.hw.time_w = sega_mapper_w;
|
||||
cart.hw.time_w = mapper_ssf2_w;
|
||||
}
|
||||
|
||||
/* default write handler for !TIME signal */
|
||||
/* default write handler for !TIME range ($A130xx)*/
|
||||
if (!cart.hw.time_w)
|
||||
{
|
||||
cart.hw.time_w = default_time_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* hardware that need to be reseted on power on */
|
||||
void cart_hw_reset()
|
||||
void cart_hw_reset(int hard)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* reset bankshifting */
|
||||
/* reset cartridge mapping */
|
||||
if (cart.hw.bankshift)
|
||||
{
|
||||
for (i=0x00; i<0x40; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Realtec mapper */
|
||||
if (cart.hw.realtec & 1)
|
||||
{
|
||||
/* enable BOOTROM */
|
||||
for (i=0; i<8; i++)
|
||||
memcpy(cart.rom + 0x900000 + i*0x2000, cart.rom + 0x7e000, 0x2000);
|
||||
for (i=0x00; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart.rom + 0x900000;
|
||||
cart.hw.realtec |= 2;
|
||||
}
|
||||
|
||||
|
||||
/* SVP chip */
|
||||
if (svp)
|
||||
svp_reset();
|
||||
if (svp) svp_reset();
|
||||
|
||||
/* Lock-ON */
|
||||
switch (config.lock_on)
|
||||
{
|
||||
case TYPE_GG:
|
||||
ggenie_reset();
|
||||
ggenie_reset(hard);
|
||||
break;
|
||||
|
||||
case TYPE_AR:
|
||||
areplay_reset(1);
|
||||
areplay_reset(hard);
|
||||
break;
|
||||
|
||||
case TYPE_SK:
|
||||
@ -497,118 +521,180 @@ void cart_hw_reset()
|
||||
cart.base = m68k_memory_map[0].base;
|
||||
}
|
||||
|
||||
int cart_hw_context_save(uint8 *state)
|
||||
{
|
||||
int i;
|
||||
int bufferptr = 0;
|
||||
uint8 *base;
|
||||
|
||||
/* cartridge mapping */
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
/* get base address */
|
||||
base = m68k_memory_map[i].base;
|
||||
|
||||
if (base == sram.sram)
|
||||
{
|
||||
/* SRAM */
|
||||
state[bufferptr++] = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM */
|
||||
state[bufferptr++] = ((base - cart.rom) >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* hardware registers */
|
||||
save_param(cart.hw.regs, sizeof(cart.hw.regs));
|
||||
|
||||
/* SVP */
|
||||
if (svp)
|
||||
{
|
||||
save_param(svp->iram_rom, 0x800);
|
||||
save_param(svp->dram,sizeof(svp->dram));
|
||||
save_param(&svp->ssp1601,sizeof(ssp1601_t));
|
||||
}
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
int cart_hw_context_load(uint8 *state, char *version)
|
||||
{
|
||||
int i;
|
||||
int bufferptr = 0;
|
||||
uint8 offset;
|
||||
|
||||
/* extended state */
|
||||
if (version[15] > 0x30)
|
||||
{
|
||||
/* cartridge mapping */
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
/* get offset */
|
||||
offset = state[bufferptr++];
|
||||
|
||||
if (offset == 0xff)
|
||||
{
|
||||
/* SRAM */
|
||||
m68k_memory_map[i].base = sram.sram;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM */
|
||||
m68k_memory_map[i].base = cart.rom + (offset << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* hardware registers */
|
||||
load_param(cart.hw.regs, sizeof(cart.hw.regs));
|
||||
|
||||
/* SVP */
|
||||
if (svp)
|
||||
{
|
||||
load_param(svp->iram_rom, 0x800);
|
||||
load_param(svp->dram,sizeof(svp->dram));
|
||||
load_param(&svp->ssp1601,sizeof(ssp1601_t));
|
||||
}
|
||||
}
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
MAPPER handlers
|
||||
*************************************************************/
|
||||
|
||||
/*
|
||||
"official" ROM/RAM switch
|
||||
ROM/SRAM Bankswitch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles)
|
||||
*/
|
||||
static void sega_mapper_w(uint32 address, uint32 data)
|
||||
static void mapper_sega_w(uint32 data)
|
||||
{
|
||||
uint32 i,slot = (address >> 1) & 7;
|
||||
uint8 *src;
|
||||
int i;
|
||||
|
||||
switch (slot)
|
||||
if (data & 1)
|
||||
{
|
||||
case 0:
|
||||
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
if (data & 1)
|
||||
/* Only if SRAM is detected */
|
||||
if (sram.on)
|
||||
{
|
||||
/* $200000-$3fffff is mapped to SRAM */
|
||||
for (i=0x20; i<0x40; i++)
|
||||
{
|
||||
/* $200000-$3fffff is mapped to SRAM (only if SRAM exists) */
|
||||
if (sram.on)
|
||||
{
|
||||
for (i=0x20; i<0x40; i++)
|
||||
m68k_memory_map[i].base = sram.sram;
|
||||
m68k_memory_map[i].base = sram.sram;
|
||||
}
|
||||
|
||||
if (data & 2)
|
||||
{
|
||||
/* SRAM write disabled */
|
||||
for (i=0x20; 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
|
||||
{
|
||||
/* SRAM write enabled */
|
||||
for (i=0x20; i<0x40; i++)
|
||||
{
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
m68k_memory_map[i].write16 = NULL;
|
||||
zbank_memory_map[i].write = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cart.lock_on)
|
||||
if (data & 2)
|
||||
{
|
||||
/* SRAM write disabled */
|
||||
for (i=0x20; i<0x40; i++)
|
||||
{
|
||||
/* enable UPMEM chip at $300000-$3fffff */
|
||||
for (i=0x30; i<0x40; i++)
|
||||
m68k_memory_map[i].base = (cart.rom + 0x800000) + ((i & 3)<<16);
|
||||
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 enabled */
|
||||
/* SRAM write enabled */
|
||||
for (i=0x20; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
|
||||
|
||||
if (cart.lock_on)
|
||||
{
|
||||
/* enable cartridge ROM at $300000-$3fffff */
|
||||
for (i=0x30; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
m68k_memory_map[i].write16 = NULL;
|
||||
zbank_memory_map[i].write = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* ROM Bankswitch (Super Street Fighter 2)
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
slot = slot << 3; /* 8 x 512k banks */
|
||||
src = cart.rom + (data << 19);
|
||||
for (i=0; i<8; i++)
|
||||
m68k_memory_map[slot++].base = src + (i<<16);
|
||||
break;
|
||||
/* S&K lock-on chip */
|
||||
if (cart.lock_on && (config.lock_on == TYPE_SK))
|
||||
{
|
||||
/* $300000-$3fffff is mapped to S2K upmem chip */
|
||||
for (i=0x30; i<0x40; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = (cart.rom + 0x800000) + ((i & 3)<<16);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $200000-$3fffff is mapped to ROM */
|
||||
for (i=0x20; i<0x40; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
||||
/*
|
||||
Super Street Fighter 2 ROM Bankswitch
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
static void multi_mapper_w(uint32 address, uint32 data)
|
||||
static void mapper_ssf2_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
/* 8 x 512k banks */
|
||||
uint32 dst = (address << 2) & 0x38;
|
||||
|
||||
/* bank 0 remains unchanged */
|
||||
if (dst)
|
||||
{
|
||||
uint32 i;
|
||||
uint8 *src = cart.rom + (data << 19);
|
||||
|
||||
cart.hw.bankshift = 1;
|
||||
|
||||
/* 64 x 64k banks */
|
||||
for (i=0; i<64; i++)
|
||||
m68k_memory_map[i].base = &cart.rom[((address++) & 0x3f) << 16];
|
||||
}
|
||||
|
||||
/*
|
||||
Special ROM Bankswitch used for copy protection
|
||||
Used by unlicensed cartridges (Lion King III, Super King Kong 99)
|
||||
*/
|
||||
static void special_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
/* 1 x 32k bank */
|
||||
memcpy(cart.rom + 0x900000, cart.rom + ((data & 0x7f) << 15), 0x8000);
|
||||
memcpy(cart.rom + 0x908000, cart.rom + 0x8000, 0x8000);
|
||||
m68k_memory_map[0].base = cart.rom + 0x900000;
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_memory_map[dst++].base = src + (i<<16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
||||
(Note: register usage is inverted in TascoDlx documentation)
|
||||
*/
|
||||
static void realtec_mapper_w(uint32 address, uint32 data)
|
||||
static void mapper_realtec_w(uint32 address, uint32 data)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
@ -648,7 +734,7 @@ static void realtec_mapper_w(uint32 address, uint32 data)
|
||||
}
|
||||
|
||||
/* Game no Kanzume Otokuyou ROM Mapper */
|
||||
static void seganet_mapper_w(uint32 address, uint32 data)
|
||||
static void mapper_seganet_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xff) == 0xf1)
|
||||
{
|
||||
@ -676,19 +762,92 @@ static void seganet_mapper_w(uint32 address, uint32 data)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RADICA ROM Bankswitch (use !TIME)
|
||||
/*
|
||||
Custom ROM Bankswitch used in Top Fighter, Mulan, Pocket Monsters II, Lion King 3, Super King Kong 99, Pokemon Stadium
|
||||
*/
|
||||
static uint32 radica_mapper_r(uint32 address)
|
||||
static void mapper_32k_w(uint32 data)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* 64 x 32k banks */
|
||||
if (data)
|
||||
{
|
||||
/* unverified (Top Fighter writes $2A instead $2E) */
|
||||
if (data >> 2) data |= 4;
|
||||
|
||||
/* bank is mapped at $000000-$0FFFFF */
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
memcpy(cart.rom + 0x900000 + (i<<16), cart.rom + ((data & 0x3f) << 15), 0x8000);
|
||||
memcpy(cart.rom + 0x908000 + (i<<16), cart.rom + ((data & 0x3f) << 15), 0x8000);
|
||||
m68k_memory_map[i].base = cart.rom + 0x900000 + (i<<16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset default $000000-$0FFFFF mapping */
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart.rom[i << 16];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Custom ROM Bankswitch used in Chinese Fighter III
|
||||
*/
|
||||
static void mapper_64k_w(uint32 data)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* 16 x 64k banks */
|
||||
if (data)
|
||||
{
|
||||
/* bank is mapped at $000000-$0FFFFF */
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart.rom[(data & 0xf) << 16];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* reset default $000000-$0FFFFF mapping */
|
||||
for (i=0; i<16; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart.rom[(i & 0xf) << 16];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Custom ROM Bankswitch used in pirate "Multi-in-1" cartridges, A Bug's Life, King of Fighter 99, Pocket Monster, Rockman X3
|
||||
*/
|
||||
static void mapper_64k_multi_w(uint32 address)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* 64 x 64k banks */
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart.rom[((address++) & 0x3f) << 16];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Custom ROM Bankswitch used in RADICA cartridges
|
||||
*/
|
||||
static uint32 mapper_radica_r(uint32 address)
|
||||
{
|
||||
int i = 0;
|
||||
address = (address >> 1);
|
||||
|
||||
/* 64 x 64k banks */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = &cart.rom[((address++)& 0x3f)<< 16];
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
@ -696,14 +855,17 @@ static uint32 radica_mapper_r(uint32 address)
|
||||
default !TIME signal handler
|
||||
*************************************************************/
|
||||
|
||||
/* default ROM bankswitch */
|
||||
static void default_time_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xf1) == 0xf1)
|
||||
sega_mapper_w(address, data);
|
||||
if (address < 0xa13040)
|
||||
{
|
||||
/* unlicensed cartridges mapper (default) */
|
||||
mapper_64k_multi_w(address);
|
||||
return;
|
||||
}
|
||||
|
||||
else if (address < 0xa13040)
|
||||
multi_mapper_w(address, data);
|
||||
/* official cartridges mapper (default) */
|
||||
mapper_sega_w(data);
|
||||
}
|
||||
|
||||
|
||||
@ -717,10 +879,10 @@ static uint32 default_regs_r(uint32 address)
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart.hw.mask[i]) == cart.hw.addr[i])
|
||||
{
|
||||
return cart.hw.regs[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* unused */
|
||||
return m68k_read_bus_8(address);
|
||||
}
|
||||
|
||||
@ -738,22 +900,22 @@ static void default_regs_w(uint32 address, uint32 data)
|
||||
m68k_unused_8_w(address, data);
|
||||
}
|
||||
|
||||
/* special register behaviour (Lion King III, Super Donkey Kong 99, Mulan, Pocket Monsters II) */
|
||||
static void special_regs_w(uint32 address, uint32 data)
|
||||
/* custom register hardware (Top Fighter, Lion King III, Super Donkey Kong 99, Mulan, Pocket Monsters II, Pokemon Stadium) */
|
||||
static void custom_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x6f)
|
||||
{
|
||||
special_mapper_w(address, data);
|
||||
mapper_32k_w(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write regs */
|
||||
/* write register */
|
||||
default_regs_w(address, data);
|
||||
|
||||
/* bitswapping (documented by Haze) */
|
||||
/* bitswapping */
|
||||
uint32 temp = cart.hw.regs[0];
|
||||
switch (cart.hw.regs[1])
|
||||
switch (cart.hw.regs[1] & 3)
|
||||
{
|
||||
case 0:
|
||||
cart.hw.regs[2] = (temp << 1);
|
||||
@ -775,3 +937,17 @@ static void special_regs_w(uint32 address, uint32 data)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* alternate custom register hardware (Chinese Fighters III) */
|
||||
static void custom_alt_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x5f)
|
||||
{
|
||||
mapper_64k_w(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write regs */
|
||||
default_regs_w(address, data);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Genesis Plus
|
||||
* Cartridge Hardware support
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Eke-Eke (GCN/Wii port)
|
||||
*
|
||||
* Lots of protection mechanism have been discovered by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
@ -38,8 +38,8 @@ typedef struct
|
||||
uint8 regs[4]; /* internal registers (R/W) */
|
||||
uint32 mask[4]; /* registers address mask */
|
||||
uint32 addr[4]; /* registers address */
|
||||
uint16 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
uint16 bankshift; /* cartridge with bankshift mecanism */
|
||||
uint16 realtec; /* realtec mapper */
|
||||
uint16 bankshift; /* cartridge with bankshift mecanism reseted on soft-reset */
|
||||
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
|
||||
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
|
||||
unsigned int (*regs_r)(unsigned int address); /* cart hardware registers read handler */
|
||||
@ -63,7 +63,9 @@ extern T_CART cart;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void cart_hw_init();
|
||||
extern void cart_hw_reset();
|
||||
extern void cart_hw_reset(int hard);
|
||||
extern int cart_hw_context_save(uint8 *state);
|
||||
extern int cart_hw_context_load(uint8 *state, char *version);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -34,10 +34,11 @@ static struct
|
||||
uint32 addr[6];
|
||||
} ggenie;
|
||||
|
||||
static void ggenie_write_byte(uint32 address, uint32 data);
|
||||
static void ggenie_write_word(uint32 address, uint32 data);
|
||||
static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type);
|
||||
static uint32 ggenie_read_regs(uint32 address);
|
||||
static unsigned int ggenie_read_byte(unsigned int address);
|
||||
static unsigned int ggenie_read_word(unsigned int address);
|
||||
static void ggenie_write_byte(unsigned int address, unsigned int data);
|
||||
static void ggenie_write_word(unsigned int address, unsigned int data);
|
||||
static void ggenie_write_regs(unsigned int offset, unsigned int data);
|
||||
|
||||
void ggenie_init(void)
|
||||
{
|
||||
@ -87,29 +88,32 @@ void ggenie_shutdown(void)
|
||||
}
|
||||
}
|
||||
|
||||
void ggenie_reset(void)
|
||||
void ggenie_reset(int hard)
|
||||
{
|
||||
if (!ggenie.enabled)
|
||||
return;
|
||||
|
||||
/* clear codes */
|
||||
ggenie_switch(0);
|
||||
if (ggenie.enabled)
|
||||
{
|
||||
if (hard)
|
||||
{
|
||||
/* clear codes */
|
||||
ggenie_switch(0);
|
||||
|
||||
/* reset internal state */
|
||||
memset(ggenie.regs,0,sizeof(ggenie.regs));
|
||||
memset(ggenie.old,0,sizeof(ggenie.old));
|
||||
memset(ggenie.data,0,sizeof(ggenie.data));
|
||||
memset(ggenie.addr,0,sizeof(ggenie.addr));
|
||||
/* reset internal state */
|
||||
memset(ggenie.regs,0,sizeof(ggenie.regs));
|
||||
memset(ggenie.old,0,sizeof(ggenie.old));
|
||||
memset(ggenie.data,0,sizeof(ggenie.data));
|
||||
memset(ggenie.addr,0,sizeof(ggenie.addr));
|
||||
}
|
||||
|
||||
/* Game Genie ROM is mapped at $000000-$007fff */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
/* Game Genie ROM is mapped at $000000-$007fff */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
|
||||
/* Internal registers are mapped at $000000-$00001f */
|
||||
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||
/* Internal registers are mapped at $000000-$00001f */
|
||||
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||
|
||||
/* Disable registers reads */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
/* Disable registers reads */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ggenie_switch(int enable)
|
||||
@ -156,71 +160,75 @@ void ggenie_switch(int enable)
|
||||
}
|
||||
}
|
||||
|
||||
/* Byte write handler */
|
||||
/* Note: 2nd revision of the Game Genie software use byte writes to set register values on exit */
|
||||
static void ggenie_write_byte(uint32 address, uint32 data)
|
||||
static unsigned int ggenie_read_byte(unsigned int address)
|
||||
{
|
||||
unsigned int data = ggenie.regs[(address >> 1) & 0x1f];
|
||||
return ((address & 1) ? (data & 0xff) : ((data >> 8) & 0xff));
|
||||
}
|
||||
|
||||
static unsigned int ggenie_read_word(unsigned int address)
|
||||
{
|
||||
return ggenie.regs[(address >> 1) & 0x1f];
|
||||
}
|
||||
|
||||
static void ggenie_write_byte(unsigned int address, unsigned int data)
|
||||
{
|
||||
/* Register offset */
|
||||
uint8 offset = (address >> 1) & 0x1f;
|
||||
|
||||
/* Write internal register (lower or upper BYTE) */
|
||||
ggenie_write_regs(offset,data,address & 1);
|
||||
/* /LWR and /UWR are used to decode writes */
|
||||
if (address & 1)
|
||||
{
|
||||
data = (ggenie.regs[offset] & 0xff00) | (data & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = (ggenie.regs[offset] & 0x00ff) | ((data & 0xff) << 8);
|
||||
}
|
||||
|
||||
/* Update internal register */
|
||||
ggenie_write_regs(offset,data);
|
||||
}
|
||||
|
||||
/* Word write handler */
|
||||
static void ggenie_write_word(uint32 address, uint32 data)
|
||||
static void ggenie_write_word(unsigned int address, unsigned int data)
|
||||
{
|
||||
/* Register offset */
|
||||
uint8 offset = (address >> 1) & 0x1f;
|
||||
|
||||
/* Write internal register (full WORD) */
|
||||
ggenie_write_regs(offset,data,2);
|
||||
ggenie_write_regs(offset,data);
|
||||
}
|
||||
|
||||
static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
static void ggenie_write_regs(unsigned int offset, unsigned int data)
|
||||
{
|
||||
/* access type */
|
||||
switch (type)
|
||||
{
|
||||
case 0: /* upper byte write */
|
||||
data = (ggenie.regs[offset] & 0x00ff) | ((data & 0xff) << 8);
|
||||
break;
|
||||
|
||||
case 1: /* lower byte write */
|
||||
data = (ggenie.regs[offset] & 0xff00) | (data & 0xff);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* update internal register */
|
||||
ggenie.regs[offset] = data;
|
||||
|
||||
/* Mode Register */
|
||||
if (offset == 0)
|
||||
{
|
||||
/* by default, registers are write only */
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
|
||||
/* MODE bits */
|
||||
/* MODE bit */
|
||||
if (data & 0x400)
|
||||
{
|
||||
/* $0000-$7ffff reads mapped to Cartridge ROM */
|
||||
m68k_memory_map[0].base = cart.rom;
|
||||
m68k_memory_map[0].read8 = NULL;
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* $0000-$7ffff reads mapped to Game Genie ROM */
|
||||
m68k_memory_map[0].base = ggenie.rom;
|
||||
m68k_memory_map[0].read8 = NULL;
|
||||
m68k_memory_map[0].read16 = NULL;
|
||||
|
||||
/* READ_ENABLE bit */
|
||||
if (data & 0x200)
|
||||
{
|
||||
/* $0000-$7ffff reads mapped to Game Genie Registers */
|
||||
/* code doing this should execute in RAM so we don't need to modify base address */
|
||||
m68k_memory_map[0].read16 = ggenie_read_regs;
|
||||
m68k_memory_map[0].read8 = ggenie_read_byte;
|
||||
m68k_memory_map[0].read16 = ggenie_read_word;
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,6 +261,11 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
/* on real HW, address decoding would be done on each reads */
|
||||
ggenie_switch(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||
}
|
||||
}
|
||||
|
||||
/* RESET register */
|
||||
@ -261,9 +274,3 @@ static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type)
|
||||
ggenie.regs[1] |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 ggenie_read_regs(uint32 address)
|
||||
{
|
||||
return ggenie.regs[(address >> 1) & 0x1f];
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
/* Function prototypes */
|
||||
extern void ggenie_init(void);
|
||||
extern void ggenie_shutdown(void);
|
||||
extern void ggenie_reset(void);
|
||||
extern void ggenie_reset(int hard);
|
||||
extern void ggenie_switch(int enable);
|
||||
|
||||
#endif
|
||||
|
@ -99,7 +99,9 @@ static void lightgun_update(int num)
|
||||
{
|
||||
/* External Interrupt ? */
|
||||
if (reg[11] & 0x08)
|
||||
irq_status = (irq_status & ~0x40) | 0x12;
|
||||
{
|
||||
irq_status = (irq_status & 4) | 0x12;
|
||||
}
|
||||
|
||||
/* HV Counter Latch:
|
||||
1) some games does not enable HVC latch but instead use bigger X offset
|
||||
@ -107,11 +109,15 @@ static void lightgun_update(int num)
|
||||
2) for games using H40 mode, the gun routine scales up the Hcounter value
|
||||
--> H-Counter range is approx. 290 dot clocks
|
||||
*/
|
||||
hvc_latch = 0x10000 | (vctab[v_counter] << 8);
|
||||
hvc_latch = 0x10000 | (v_counter << 8);
|
||||
if (reg[12] & 1)
|
||||
{
|
||||
hvc_latch |= hc_320[((input.analog[num][0] * 290) / (2 * 320) + x_offset) % 210];
|
||||
}
|
||||
else
|
||||
hvc_latch |= hc_256[(input.analog[num][0] / 2 + x_offset)%171];
|
||||
{
|
||||
hvc_latch |= hc_256[(input.analog[num][0] / 2 + x_offset) % 171];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,9 +351,9 @@ static inline unsigned int gamepad_read(int i)
|
||||
|
||||
/* 6buttons specific (taken from gen-hw.txt) */
|
||||
/* A 6-button gamepad allows the extra buttons to be read based on how */
|
||||
/* many times TH is switched from 1 to 0 (and not 0 to 1). Observe the */
|
||||
/* following sequence */
|
||||
/*
|
||||
/* many times TH is switched from 1 to 0 (and not 0 to 1). Observe the */
|
||||
/* following sequence */
|
||||
/*
|
||||
TH = 1 : ?1CBRLDU 3-button pad return value
|
||||
TH = 0 : ?0SA00DU 3-button pad return value
|
||||
TH = 1 : ?1CBRLDU 3-button pad return value
|
||||
|
@ -142,37 +142,44 @@ void gen_hardreset(void)
|
||||
mcycles_68k = mcycles_z80 = (uint32)((MCYCLES_PER_LINE * lines_per_frame) * ((double)rand() / (double)RAND_MAX));
|
||||
|
||||
/* Z80 bus is released & Z80 is stopped */
|
||||
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;
|
||||
zstate = 0;
|
||||
|
||||
/* Assume default bank is $000000-$007FFF */
|
||||
zbank = 0;
|
||||
|
||||
/* Reset 68k, Z80 & YM2612 */
|
||||
/* Reset 68k & Z80 */
|
||||
m68k_pulse_reset();
|
||||
z80_reset();
|
||||
YM2612ResetChip();
|
||||
}
|
||||
|
||||
void gen_softreset(int state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
/* Halt 68k, Z80 & YM2612 */
|
||||
/* Halt 68k */
|
||||
m68k_pulse_halt();
|
||||
|
||||
/* Z80 bus is released & Z80 is reseted */
|
||||
zstate = 0;
|
||||
YM2612ResetChip();
|
||||
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;
|
||||
|
||||
/* Reset YM2612 */
|
||||
fm_reset(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset PRO Action Replay (if switch is in TRAINER position) */
|
||||
if (areplay_get_status() == AR_SWITCH_TRAINER)
|
||||
{
|
||||
areplay_reset(0);
|
||||
}
|
||||
/* Reset Cartridge Hardware */
|
||||
cart_hw_reset(0);
|
||||
|
||||
/* 68k & Z80 could restart anywhere in VDP frame (Bonkers, Eternal Champions, X-Men 2) */
|
||||
mcycles_68k = mcycles_z80 = (uint32)((MCYCLES_PER_LINE * lines_per_frame) * ((double)rand() / (double)RAND_MAX));
|
||||
@ -180,7 +187,7 @@ void gen_softreset(int state)
|
||||
/* Reset 68k, Z80 & YM2612 */
|
||||
m68k_pulse_reset();
|
||||
z80_reset();
|
||||
YM2612ResetChip();
|
||||
fm_reset(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,9 +458,14 @@ static void gxSetAspectRatio(int *xscale, int *yscale)
|
||||
{
|
||||
/* vertical borders */
|
||||
if (config.overscan & 1)
|
||||
{
|
||||
/* Genesis outputs 288(PAL) or 243(NTSC) lines */
|
||||
/* Wii & Game Cube output 286/574(PAL50) or 240/480 (PAL60 & NTSC) lines */
|
||||
*yscale = vdp_pal + ((gc_pal && !config.render) ? 143 : 120);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* overscan is simulated (black) */
|
||||
*yscale = bitmap.viewport.h / 2;
|
||||
if (vdp_pal && (!gc_pal || config.render))
|
||||
*yscale = *yscale * 240 / 288;
|
||||
@ -470,29 +475,45 @@ static void gxSetAspectRatio(int *xscale, int *yscale)
|
||||
|
||||
/* horizontal borders */
|
||||
if (config.overscan & 2)
|
||||
*xscale = 358 + ((reg[12] & 1)*2) - gc_pal;
|
||||
{
|
||||
/* max visible range is ~712 pixels, not 720 */
|
||||
*xscale = 356;
|
||||
}
|
||||
else
|
||||
*xscale = 325 + ((reg[12] & 1)*2) - gc_pal;
|
||||
{
|
||||
/* overscan is simulated (black) */
|
||||
*xscale = 327;
|
||||
}
|
||||
|
||||
/* 16/9 correction */
|
||||
if (config.aspect & 2)
|
||||
{
|
||||
*xscale = (*xscale * 3) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* manual aspect ratio (default is fullscreen) */
|
||||
/* manual aspect ratio (default is unscaled raw) */
|
||||
else
|
||||
{
|
||||
/* vertical borders */
|
||||
if (config.overscan & 1)
|
||||
{
|
||||
*yscale = (gc_pal && !config.render) ? (vdp_pal ? (268*144 / bitmap.viewport.h):143) : (vdp_pal ? (224*144 / bitmap.viewport.h):120);
|
||||
}
|
||||
else
|
||||
{
|
||||
*yscale = (gc_pal && !config.render) ? 134 : 112;
|
||||
}
|
||||
|
||||
/* horizontal borders */
|
||||
if (config.overscan & 2)
|
||||
*xscale = 352;
|
||||
{
|
||||
*xscale = 348;
|
||||
}
|
||||
else
|
||||
{
|
||||
*xscale = 320;
|
||||
}
|
||||
|
||||
/* add user scaling */
|
||||
*xscale += config.xscale;
|
||||
@ -565,9 +586,11 @@ static void gxResetScaler(u32 width)
|
||||
int xshift = (config.xshift * rmode->fbWidth) / rmode->viWidth;
|
||||
int yshift = (config.yshift * rmode->efbHeight) / rmode->viHeight;
|
||||
|
||||
/* Configure GX vertical scaling (480i/576i/480p) */
|
||||
/* Double Resolution modes (480i/576i/480p) */
|
||||
if (config.render)
|
||||
{
|
||||
yscale = yscale * 2;
|
||||
}
|
||||
|
||||
/* Set GX scaler (Vertex Position matrix) */
|
||||
square[6] = square[3] = xshift + xscale;
|
||||
@ -834,7 +857,7 @@ void gxCopyScreenshot(gx_texture *texture)
|
||||
GX_InvalidateTexAll();
|
||||
|
||||
/* scale texture to EFB width */
|
||||
s32 w = bitmap.viewport.x ? 704 : 640;
|
||||
s32 w = bitmap.viewport.x ? 696 : 640;
|
||||
s32 h = (bitmap.viewport.h + 2*bitmap.viewport.y) * 2;
|
||||
s32 x = -w/2;
|
||||
s32 y = -(240+ 2*bitmap.viewport.y);
|
||||
|
149
source/hvc.h
149
source/hvc.h
@ -123,144 +123,6 @@
|
||||
#ifndef _HVC_H_
|
||||
#define _HVC_H_
|
||||
|
||||
/* V counter values for NTSC 192-line display */
|
||||
const uint8 vc_ntsc_192[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
|
||||
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 224-line display */
|
||||
const uint8 vc_ntsc_224[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
|
||||
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for NTSC 240-line display (invalid mode) */
|
||||
const uint8 vc_ntsc_240[262] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
|
||||
};
|
||||
|
||||
/* V counter values for PAL 192-line display */
|
||||
const uint8 vc_pal_192[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2,
|
||||
0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6,
|
||||
0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 224-line display */
|
||||
const uint8 vc_pal_224[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* V counter values for PAL 240-line display */
|
||||
const uint8 vc_pal_240[313] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
|
||||
0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
|
||||
0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6,
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* H-counter timings in H40 & H32 modes (starts from HINT) */
|
||||
@ -276,9 +138,9 @@ const uint8 vc_pal_240[313] = {
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
const uint8 cycle2hc40[3420] =
|
||||
static const uint8 cycle2hc40[3420] =
|
||||
{
|
||||
/* end of active display (16 pixels -> 128 Mcycles) , HINT triggered , Vcounter jump */
|
||||
/* end of active display (16 pixels -> 128 Mcycles) , HINT triggered , Vcounter increment */
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
@ -513,9 +375,9 @@ const uint8 cycle2hc40[3420] =
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
};
|
||||
|
||||
const uint8 cycle2hc32[3420] =
|
||||
static const uint8 cycle2hc32[3420] =
|
||||
{
|
||||
/* end of active display (16 pixels -> 160 Mcycles) , HINT triggered ? , Vcounter jump */
|
||||
/* end of active display (16 pixels -> 160 Mcycles) , HINT triggered ? , Vcounter increment */
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
@ -752,8 +614,7 @@ const uint8 cycle2hc32[3420] =
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
};
|
||||
|
||||
const uint8 *vctab;
|
||||
const uint8 *hctab;
|
||||
static const uint8 *hctab;
|
||||
|
||||
#endif /* _HVC_H_ */
|
||||
|
||||
|
@ -862,7 +862,7 @@ void m68k_run (unsigned int cycles)
|
||||
CPU_INT_LEVEL = (irq_status & 6) << 8;
|
||||
|
||||
/* IRQ was triggered during previous instruction */
|
||||
if (irq_status & 0x40)
|
||||
if (irq_status & 0x20)
|
||||
{
|
||||
/* one instruction latency */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
|
@ -476,8 +476,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
|
||||
|
||||
case 0x30: /* TIME */
|
||||
{
|
||||
cart.hw.time_w(address & 0xfe, data >> 8);
|
||||
cart.hw.time_w(address, data & 0xff);
|
||||
cart.hw.time_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1754,12 +1754,7 @@ void render_line(int line)
|
||||
int width = bitmap.viewport.w;
|
||||
int x_offset = bitmap.viewport.x;
|
||||
|
||||
/* background color (blanked display or vertical borders) */
|
||||
if (!(reg[1] & 0x40) || (status & 8))
|
||||
{
|
||||
memset(&lb[0x20 - x_offset], 0x40, width + 2*x_offset);
|
||||
}
|
||||
else
|
||||
if ((reg[1] & 0x40) && (line < bitmap.viewport.h))
|
||||
{
|
||||
/* update pattern generator */
|
||||
if (bg_list_index)
|
||||
@ -1826,6 +1821,11 @@ void render_line(int line)
|
||||
memset(&lb[0x20 + width], 0x40, x_offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* background color (blanked display or vertical borders) */
|
||||
memset(&lb[0x20 - x_offset], 0x40, width + 2*x_offset);
|
||||
}
|
||||
|
||||
/* pixel color remapping */
|
||||
remap_buffer(line);
|
||||
@ -1833,15 +1833,12 @@ void render_line(int line)
|
||||
|
||||
void remap_buffer(int line)
|
||||
{
|
||||
/* display disabled */
|
||||
if (reg[0] & 0x01) return;
|
||||
|
||||
int width = bitmap.viewport.w + 2*bitmap.viewport.x;
|
||||
|
||||
/* get line offset from framebuffer */
|
||||
line = (line + bitmap.viewport.y) % lines_per_frame;
|
||||
|
||||
/* double resolution mode */
|
||||
/* interlaced modes */
|
||||
if (config.render && interlaced)
|
||||
line = (line << 1) + odd_frame;
|
||||
|
||||
|
@ -157,6 +157,35 @@ void sound_reset(void)
|
||||
psg_cycles_count = 0;
|
||||
}
|
||||
|
||||
int sound_context_save(uint8 *state)
|
||||
{
|
||||
int bufferptr = 0;
|
||||
|
||||
save_param(YM2612GetContextPtr(),YM2612GetContextSize());
|
||||
save_param(SN76489_GetContextPtr(),SN76489_GetContextSize());
|
||||
save_param(&fm_cycles_count,sizeof(fm_cycles_count));
|
||||
save_param(&psg_cycles_count,sizeof(psg_cycles_count));
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
int sound_context_load(uint8 *state, char *version)
|
||||
{
|
||||
int bufferptr = 0;
|
||||
|
||||
YM2612Restore(&state[bufferptr]);
|
||||
bufferptr += YM2612GetContextSize();
|
||||
load_param(SN76489_GetContextPtr(),SN76489_GetContextSize());
|
||||
|
||||
if (version[15] > 0x30)
|
||||
{
|
||||
load_param(&fm_cycles_count,sizeof(fm_cycles_count));
|
||||
load_param(&psg_cycles_count,sizeof(psg_cycles_count));
|
||||
}
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
/* End of frame update, return the number of samples run so far. */
|
||||
int sound_update(unsigned int cycles)
|
||||
{
|
||||
|
@ -27,6 +27,8 @@
|
||||
/* Function prototypes */
|
||||
extern void sound_init(void);
|
||||
extern void sound_reset(void);
|
||||
extern int sound_context_save(uint8 *state);
|
||||
extern int sound_context_load(uint8 *state, char *version);
|
||||
extern int sound_update(unsigned int cycles);
|
||||
extern void fm_reset(unsigned int cycles);
|
||||
extern void fm_write(unsigned int cycles, unsigned int address, unsigned int data);
|
||||
|
@ -22,16 +22,6 @@
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
#define STATE_VERSION "GENPLUS-GX 1.4.0"
|
||||
|
||||
#define load_param(param, size) \
|
||||
memcpy(param, &state[bufferptr], size); \
|
||||
bufferptr+= size;
|
||||
|
||||
#define save_param(param, size) \
|
||||
memcpy(&state[bufferptr], param, size); \
|
||||
bufferptr+= size;
|
||||
|
||||
int state_load(unsigned char *buffer)
|
||||
{
|
||||
/* buffer size */
|
||||
@ -48,9 +38,10 @@ int state_load(unsigned char *buffer)
|
||||
uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes);
|
||||
|
||||
/* version check */
|
||||
char version[16];
|
||||
char version[17];
|
||||
load_param(version,16);
|
||||
if (strncmp(version,STATE_VERSION,16))
|
||||
version[16] = 0;
|
||||
if (strncmp(version,STATE_VERSION,15))
|
||||
{
|
||||
free(state);
|
||||
return -1;
|
||||
@ -58,41 +49,42 @@ int state_load(unsigned char *buffer)
|
||||
|
||||
/* reset system */
|
||||
system_reset();
|
||||
m68k_memory_map[0].base = cart.base;
|
||||
|
||||
// GENESIS
|
||||
load_param(work_ram, sizeof(work_ram));
|
||||
load_param(zram, sizeof(zram));
|
||||
load_param(&zstate, sizeof(zstate));
|
||||
load_param(&zbank, sizeof(zbank));
|
||||
if (zstate == 3)
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (version[15] > 0x30)
|
||||
{
|
||||
/* extended state */
|
||||
load_param(&mcycles_68k, sizeof(mcycles_68k));
|
||||
load_param(&mcycles_z80, sizeof(mcycles_z80));
|
||||
}
|
||||
|
||||
// IO
|
||||
load_param(io_reg, sizeof(io_reg));
|
||||
|
||||
// VDP
|
||||
uint8 temp_reg[0x20];
|
||||
load_param(sat, sizeof(sat));
|
||||
load_param(vram, sizeof(vram));
|
||||
load_param(cram, sizeof(cram));
|
||||
load_param(vsram, sizeof(vsram));
|
||||
load_param(temp_reg, sizeof(temp_reg));
|
||||
load_param(&addr, sizeof(addr));
|
||||
load_param(&addr_latch, sizeof(addr_latch));
|
||||
load_param(&code, sizeof(code));
|
||||
load_param(&pending, sizeof(pending));
|
||||
load_param(&status, sizeof(status));
|
||||
load_param(&dmafill, sizeof(dmafill));
|
||||
load_param(&hint_pending, sizeof(hint_pending));
|
||||
load_param(&vint_pending, sizeof(vint_pending));
|
||||
load_param(&irq_status, sizeof(irq_status));
|
||||
vdp_restore(temp_reg);
|
||||
bufferptr += vdp_context_load(&state[bufferptr], version);
|
||||
|
||||
// FM
|
||||
YM2612Restore(&state[bufferptr]);
|
||||
bufferptr+= YM2612GetContextSize();
|
||||
|
||||
// PSG
|
||||
load_param(SN76489_GetContextPtr(),SN76489_GetContextSize());
|
||||
// SOUND
|
||||
bufferptr += sound_context_load(&state[bufferptr], version);
|
||||
|
||||
// 68000
|
||||
uint16 tmp16;
|
||||
@ -120,6 +112,9 @@ int state_load(unsigned char *buffer)
|
||||
// Z80
|
||||
load_param(&Z80, sizeof(Z80_Regs));
|
||||
|
||||
// Cartridge HW
|
||||
bufferptr += cart_hw_context_load(&state[bufferptr], version);
|
||||
|
||||
free(state);
|
||||
return 1;
|
||||
}
|
||||
@ -143,31 +138,17 @@ int state_save(unsigned char *buffer)
|
||||
save_param(zram, sizeof(zram));
|
||||
save_param(&zstate, sizeof(zstate));
|
||||
save_param(&zbank, sizeof(zbank));
|
||||
save_param(&mcycles_68k, sizeof(mcycles_68k));
|
||||
save_param(&mcycles_z80, sizeof(mcycles_z80));
|
||||
|
||||
// IO
|
||||
save_param(io_reg, sizeof(io_reg));
|
||||
|
||||
// VDP
|
||||
save_param(sat, sizeof(sat));
|
||||
save_param(vram, sizeof(vram));
|
||||
save_param(cram, sizeof(cram));
|
||||
save_param(vsram, sizeof(vsram));
|
||||
save_param(reg, sizeof(reg));
|
||||
save_param(&addr, sizeof(addr));
|
||||
save_param(&addr_latch, sizeof(addr_latch));
|
||||
save_param(&code, sizeof(code));
|
||||
save_param(&pending, sizeof(pending));
|
||||
save_param(&status, sizeof(status));
|
||||
save_param(&dmafill, sizeof(dmafill));
|
||||
save_param(&hint_pending, sizeof(hint_pending));
|
||||
save_param(&vint_pending, sizeof(vint_pending));
|
||||
save_param(&irq_status, sizeof(irq_status));
|
||||
bufferptr += vdp_context_save(&state[bufferptr]);
|
||||
|
||||
// FM
|
||||
save_param(YM2612GetContextPtr(),YM2612GetContextSize());
|
||||
|
||||
// PSG
|
||||
save_param(SN76489_GetContextPtr(),SN76489_GetContextSize());
|
||||
// SOUND
|
||||
bufferptr += sound_context_save(&state[bufferptr]);
|
||||
|
||||
// 68000
|
||||
uint16 tmp16;
|
||||
@ -195,6 +176,9 @@ int state_save(unsigned char *buffer)
|
||||
// Z80
|
||||
save_param(&Z80, sizeof(Z80_Regs));
|
||||
|
||||
// Cartridge HW
|
||||
bufferptr += cart_hw_context_save(&state[bufferptr]);
|
||||
|
||||
/* compress state file */
|
||||
unsigned long inbytes = bufferptr;
|
||||
unsigned long outbytes = STATE_SIZE;
|
||||
|
@ -23,7 +23,16 @@
|
||||
#ifndef _STATE_H_
|
||||
#define _STATE_H_
|
||||
|
||||
#define STATE_SIZE 0x28000
|
||||
#define STATE_SIZE 0x48100
|
||||
#define STATE_VERSION "GENPLUS-GX 1.4.1"
|
||||
|
||||
#define load_param(param, size) \
|
||||
memcpy(param, &state[bufferptr], size); \
|
||||
bufferptr+= size;
|
||||
|
||||
#define save_param(param, size) \
|
||||
memcpy(&state[bufferptr], param, size); \
|
||||
bufferptr+= size;
|
||||
|
||||
/* Function prototypes */
|
||||
extern int state_load(unsigned char *buffer);
|
||||
|
415
source/system.c
415
source/system.c
@ -288,7 +288,7 @@ void system_init (void)
|
||||
void system_reset (void)
|
||||
{
|
||||
/* Cartridge Hardware */
|
||||
cart_hw_reset();
|
||||
cart_hw_reset(1);
|
||||
|
||||
/* Genesis hardware */
|
||||
gen_hardreset();
|
||||
@ -317,11 +317,30 @@ void system_shutdown (void)
|
||||
/****************************************************************
|
||||
* Virtual Genesis Frame emulation
|
||||
****************************************************************/
|
||||
|
||||
void system_frame (int do_skip)
|
||||
{
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
int line = 0;
|
||||
/* line counter */
|
||||
int line = 0;
|
||||
|
||||
/* Z80 interrupt flag */
|
||||
int zirq = 0;
|
||||
|
||||
/* reload H Counter */
|
||||
int h_counter = reg[10];
|
||||
|
||||
/* reload V Counter */
|
||||
v_counter = lines_per_frame - 1;
|
||||
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
|
||||
/* reset line cycle count */
|
||||
mcycles_vdp = 0;
|
||||
|
||||
/* update 6-Buttons & Lightguns */
|
||||
input_refresh();
|
||||
|
||||
/* display changed during VBLANK */
|
||||
if (bitmap.viewport.changed & 2)
|
||||
@ -339,33 +358,27 @@ void system_frame (int do_skip)
|
||||
}
|
||||
|
||||
/* active screen height */
|
||||
if (reg[1] & 8)
|
||||
{
|
||||
bitmap.viewport.h = 240;
|
||||
bitmap.viewport.y = (config.overscan & 1) ? (vdp_pal ? 24 : 0) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.viewport.h = 224;
|
||||
bitmap.viewport.y = (config.overscan & 1) ? (vdp_pal ? 32 : 8) : 0;
|
||||
}
|
||||
bitmap.viewport.h = 224 + ((reg[1] & 8) << 1);
|
||||
bitmap.viewport.y = (config.overscan & 1) * (8 - (reg[1] & 8) + vdp_pal*24);
|
||||
|
||||
/* active screen width */
|
||||
if (reg[12] & 1)
|
||||
{
|
||||
bitmap.viewport.w = 320;
|
||||
bitmap.viewport.x = (config.overscan & 2) ? 16 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.viewport.w = 256;
|
||||
bitmap.viewport.x = (config.overscan & 2) ? 12 : 0;
|
||||
}
|
||||
bitmap.viewport.w = 256 + ((reg[12] & 1) << 6);
|
||||
bitmap.viewport.x = (config.overscan & 2) * 7;
|
||||
}
|
||||
|
||||
/* render last line of overscan */
|
||||
if (!do_skip && bitmap.viewport.y)
|
||||
{
|
||||
render_line(v_counter);
|
||||
}
|
||||
|
||||
/* parse first line of sprites */
|
||||
object_which = 1;
|
||||
if (reg[1] & 0x40)
|
||||
{
|
||||
parse_satb(0x80);
|
||||
}
|
||||
|
||||
/* Z80 interrupt flag */
|
||||
int zirq = 0;
|
||||
|
||||
/* clear VBLANK, DMA, FIFO FULL & field flags */
|
||||
status &= 0xFEE5;
|
||||
|
||||
@ -374,142 +387,256 @@ void system_frame (int do_skip)
|
||||
|
||||
/* even/odd field flag (interlaced modes only) */
|
||||
odd_frame ^= 1;
|
||||
if (interlaced) status |= (odd_frame << 4);
|
||||
|
||||
/* reload HCounter */
|
||||
int h_counter = reg[10];
|
||||
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
|
||||
/* reset line cycle count */
|
||||
mcycles_vdp = 0;
|
||||
|
||||
/* parse sprites on line zero */
|
||||
object_which = 1;
|
||||
if (reg[1] & 0x40) parse_satb(0x80);
|
||||
|
||||
/* process scanlines */
|
||||
for (line = 0; line < lines_per_frame; line ++)
|
||||
if (interlaced)
|
||||
{
|
||||
/* update VCounter */
|
||||
status |= (odd_frame << 4);
|
||||
}
|
||||
|
||||
/* update VDP DMA */
|
||||
if (dma_length)
|
||||
{
|
||||
vdp_update_dma(0);
|
||||
}
|
||||
|
||||
/* run 68k & Z80 */
|
||||
m68k_run(MCYCLES_PER_LINE);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcycles_z80 = MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
{
|
||||
ssp1601_run(SVP_cycles);
|
||||
}
|
||||
|
||||
/* update line cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
|
||||
/* Active Display */
|
||||
do
|
||||
{
|
||||
/* update V Counter */
|
||||
v_counter = line;
|
||||
|
||||
/* update 6-Buttons & Lightguns */
|
||||
input_refresh();
|
||||
|
||||
/* update VDP DMA */
|
||||
if (dma_length) vdp_update_dma();
|
||||
|
||||
/* vertical blanking */
|
||||
if (status & 8)
|
||||
/* H Interrupt */
|
||||
if(--h_counter < 0)
|
||||
{
|
||||
/* render overscan */
|
||||
if (!do_skip && ((line < end) || (line >= start)))
|
||||
render_line(line);
|
||||
|
||||
if (zirq)
|
||||
/* reload H Counter */
|
||||
h_counter = reg[10];
|
||||
|
||||
/* interrupt level 4 */
|
||||
hint_pending = 0x10;
|
||||
if (reg[0] & 0x10)
|
||||
{
|
||||
/* Z80 interrupt is asserted during one exact line */
|
||||
m68k_run(mcycles_vdp + 788);
|
||||
if (zstate == 1) z80_run(mcycles_vdp + 788);
|
||||
else mcycles_z80 = mcycles_vdp + 788;
|
||||
|
||||
/* clear Z80 interrupt */
|
||||
z80_set_irq_line(0, CLEAR_LINE);
|
||||
zirq = 0;
|
||||
irq_status = (irq_status & 2) | 0x14;
|
||||
}
|
||||
}
|
||||
|
||||
/* active display */
|
||||
/* update VDP DMA */
|
||||
if (dma_length)
|
||||
{
|
||||
vdp_update_dma(mcycles_vdp);
|
||||
}
|
||||
|
||||
/* swap sprite line buffers */
|
||||
object_which ^= 1;
|
||||
|
||||
/* render scanline */
|
||||
if (!do_skip)
|
||||
{
|
||||
render_line(line);
|
||||
}
|
||||
|
||||
/* parse next line of sprites */
|
||||
if ((reg[1] & 0x40) && (line < (bitmap.viewport.h - 1)))
|
||||
{
|
||||
parse_satb(0x81 + line);
|
||||
}
|
||||
|
||||
/* run 68k & Z80 */
|
||||
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* H Interrupt */
|
||||
if(--h_counter < 0)
|
||||
{
|
||||
h_counter = reg[10];
|
||||
hint_pending = 0x10;
|
||||
if (reg[0] & 0x10)
|
||||
irq_status = (irq_status & ~0x40) | 0x14;
|
||||
}
|
||||
|
||||
/* end of active display */
|
||||
if (line == bitmap.viewport.h)
|
||||
{
|
||||
/* set border area */
|
||||
start = lines_per_frame - bitmap.viewport.y;
|
||||
end = bitmap.viewport.h + bitmap.viewport.y;
|
||||
|
||||
/* check viewport changes */
|
||||
if (bitmap.viewport.h != bitmap.viewport.oh)
|
||||
{
|
||||
bitmap.viewport.oh = bitmap.viewport.h;
|
||||
bitmap.viewport.changed |= 1;
|
||||
}
|
||||
|
||||
if (bitmap.viewport.w != bitmap.viewport.ow)
|
||||
{
|
||||
bitmap.viewport.ow = bitmap.viewport.w;
|
||||
bitmap.viewport.changed |= 1;
|
||||
}
|
||||
|
||||
/* set VBLANK flag */
|
||||
status |= 0x08;
|
||||
|
||||
/* render overscan */
|
||||
if (!do_skip && (line < end))
|
||||
render_line(line);
|
||||
|
||||
/* update inputs (doing this here fix Warriors of Eternal Sun) */
|
||||
osd_input_Update();
|
||||
|
||||
/* delay between VINT flag & V Interrupt (Ex-Mutants, Tyrant) */
|
||||
m68k_run(mcycles_vdp + 588);
|
||||
status |= 0x80;
|
||||
|
||||
/* delay between VBLANK flag & V Interrupt (Dracula, OutRunners, VR Troopers) */
|
||||
m68k_run(mcycles_vdp + 788);
|
||||
if (zstate == 1) z80_run(mcycles_vdp + 788);
|
||||
else mcycles_z80 = mcycles_vdp + 788;
|
||||
|
||||
/* V Interrupt */
|
||||
vint_pending = 0x20;
|
||||
if (reg[1] & 0x20)
|
||||
irq_status = (irq_status & ~0x40) | 0x36;
|
||||
|
||||
/* Z80 interrupt */
|
||||
z80_set_irq_line(0, ASSERT_LINE);
|
||||
zirq = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* swap sprite line buffers */
|
||||
object_which ^= 1;
|
||||
|
||||
/* render scanline */
|
||||
if (!do_skip)
|
||||
{
|
||||
render_line(line);
|
||||
|
||||
/* parse sprites on next line */
|
||||
if ((reg[1] & 0x40) && (line < (bitmap.viewport.h - 1)))
|
||||
parse_satb(0x81 + line);
|
||||
}
|
||||
}
|
||||
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* process line */
|
||||
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
if (zstate == 1) z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
else mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
|
||||
/* SVP chip */
|
||||
if (svp) ssp1601_run(SVP_cycles);
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
{
|
||||
ssp1601_run(SVP_cycles);
|
||||
}
|
||||
|
||||
/* update line cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
}
|
||||
while (++line < bitmap.viewport.h);
|
||||
|
||||
/* end of active display */
|
||||
v_counter = line;
|
||||
|
||||
/* update 6-Buttons & Lightguns */
|
||||
input_refresh();
|
||||
|
||||
/* H Interrupt */
|
||||
if(--h_counter < 0)
|
||||
{
|
||||
/* reload H Counter */
|
||||
h_counter = reg[10];
|
||||
|
||||
/* interrupt level 4 */
|
||||
hint_pending = 0x10;
|
||||
if (reg[0] & 0x10)
|
||||
{
|
||||
irq_status = (irq_status & 2) | 0x14;
|
||||
}
|
||||
}
|
||||
|
||||
/* overscan area */
|
||||
int start = lines_per_frame - bitmap.viewport.y;
|
||||
int end = bitmap.viewport.h + bitmap.viewport.y;
|
||||
|
||||
/* check viewport changes */
|
||||
if ((bitmap.viewport.w != bitmap.viewport.ow) || (bitmap.viewport.h != bitmap.viewport.oh))
|
||||
{
|
||||
bitmap.viewport.ow = bitmap.viewport.w;
|
||||
bitmap.viewport.oh = bitmap.viewport.h;
|
||||
bitmap.viewport.changed |= 1;
|
||||
}
|
||||
|
||||
/* set VBLANK flag */
|
||||
status |= 0x08;
|
||||
|
||||
/* update VDP DMA */
|
||||
if (dma_length)
|
||||
{
|
||||
vdp_update_dma(mcycles_vdp);
|
||||
}
|
||||
|
||||
/* render overscan */
|
||||
if (!do_skip && (line < end))
|
||||
{
|
||||
render_line(line);
|
||||
}
|
||||
|
||||
/* update inputs before VINT (Warriors of Eternal Sun) */
|
||||
osd_input_Update();
|
||||
|
||||
/* delay between VINT flag & V Interrupt (Ex-Mutants, Tyrant) */
|
||||
m68k_run(mcycles_vdp + 588);
|
||||
status |= 0x80;
|
||||
|
||||
/* delay between VBLANK flag & V Interrupt (Dracula, OutRunners, VR Troopers) */
|
||||
m68k_run(mcycles_vdp + 788);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(mcycles_vdp + 788);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcycles_z80 = mcycles_vdp + 788;
|
||||
}
|
||||
|
||||
/* V Interrupt */
|
||||
vint_pending = 0x20;
|
||||
if (reg[1] & 0x20)
|
||||
{
|
||||
irq_status = 0x16;
|
||||
}
|
||||
|
||||
/* Z80 interrupt */
|
||||
z80_set_irq_line(0, ASSERT_LINE);
|
||||
zirq = 1;
|
||||
|
||||
/* run 68k & Z80 */
|
||||
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
{
|
||||
ssp1601_run(SVP_cycles);
|
||||
}
|
||||
|
||||
/* update line cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
|
||||
/* increment line count */
|
||||
line++;
|
||||
|
||||
/* Vertical Blanking */
|
||||
do
|
||||
{
|
||||
/* update V Counter */
|
||||
v_counter = line;
|
||||
|
||||
/* update 6-Buttons & Lightguns */
|
||||
input_refresh();
|
||||
|
||||
/* render overscan */
|
||||
if (!do_skip && ((line < end) || (line >= start)))
|
||||
{
|
||||
render_line(line);
|
||||
}
|
||||
|
||||
/* Z80 interrupt is asserted for one line */
|
||||
if (zirq)
|
||||
{
|
||||
m68k_run(mcycles_vdp + 788);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(mcycles_vdp + 788);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcycles_z80 = mcycles_vdp + 788;
|
||||
}
|
||||
|
||||
/* clear Z80 interrupt */
|
||||
z80_set_irq_line(0, CLEAR_LINE);
|
||||
zirq = 0;
|
||||
}
|
||||
|
||||
/* run 68k & Z80 */
|
||||
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
if (zstate == 1)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
{
|
||||
ssp1601_run(SVP_cycles);
|
||||
}
|
||||
|
||||
/* update line cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
}
|
||||
while (++line < (lines_per_frame - 1));
|
||||
|
||||
/* adjust cpu cycle count for next frame */
|
||||
mcycles_68k -= mcycles_vdp;
|
||||
|
492
source/vdp.c
492
source/vdp.c
@ -42,16 +42,12 @@ uint8 vram[0x10000]; /* Video RAM (64Kx8) */
|
||||
uint8 cram[0x80]; /* On-chip color RAM (64x9) */
|
||||
uint8 vsram[0x80]; /* On-chip vertical scroll RAM (40x11) */
|
||||
uint8 reg[0x20]; /* Internal VDP registers (23x8) */
|
||||
uint16 addr; /* Address register */
|
||||
uint16 addr_latch; /* Latched A15, A14 of address */
|
||||
uint8 code; /* Code register */
|
||||
uint8 pending; /* Pending write flag */
|
||||
uint16 status; /* VDP status flags */
|
||||
uint8 dmafill; /* next VDP Write is DMA Fill */
|
||||
uint8 hint_pending; /* 0= Line interrupt is pending */
|
||||
uint8 vint_pending; /* 1= Frame interrupt is pending */
|
||||
uint8 irq_status; /* 68K IRQ status */
|
||||
|
||||
uint16 status; /* VDP status flags */
|
||||
uint32 dma_length; /* DMA remaining length */
|
||||
|
||||
/* Global variables */
|
||||
uint16 ntab; /* Name table A base address */
|
||||
uint16 ntbb; /* Name table B base address */
|
||||
@ -66,16 +62,16 @@ uint8 bg_pattern_cache[0x80000]; /* Cached and flipped patterns */
|
||||
uint8 playfield_shift; /* Width of planes A, B (in bits) */
|
||||
uint8 playfield_col_mask; /* Vertical scroll mask */
|
||||
uint16 playfield_row_mask; /* Horizontal scroll mask */
|
||||
uint16 v_counter; /* VDP scanline counter */
|
||||
uint32 hvc_latch; /* latched HVCounter (INT2) */
|
||||
uint32 dma_length; /* Current DMA remaining bytes */
|
||||
int32 fifo_write_cnt; /* VDP writes fifo count */
|
||||
uint32 fifo_lastwrite; /* last VDP write cycle */
|
||||
uint8 odd_frame; /* 1: odd field, 0: even field */
|
||||
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
|
||||
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
|
||||
uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
|
||||
uint16 v_counter; /* VDP scanline counter */
|
||||
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
|
||||
int32 fifo_write_cnt; /* VDP writes fifo count */
|
||||
uint32 fifo_lastwrite; /* last VDP write cycle */
|
||||
uint32 hvc_latch; /* latched HVCounter (INT2) */
|
||||
uint32 vc_max; /* Vertical Counter max value */
|
||||
|
||||
|
||||
/* Tables that define the playfield layout */
|
||||
@ -84,11 +80,18 @@ static const uint8 col_mask_table[] = { 0x0F, 0x1F, 0x0F, 0x3F };
|
||||
static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF };
|
||||
|
||||
static uint8 border; /* Border color index */
|
||||
static uint8 dma_type; /* DMA mode */
|
||||
static uint8 dmafill; /* next VDP Write is DMA Fill */
|
||||
static uint8 pending; /* Pending write flag */
|
||||
static uint8 code; /* Code register */
|
||||
static uint16 addr; /* Address register */
|
||||
static uint16 addr_latch; /* Latched A15, A14 of address */
|
||||
static uint16 fill_data; /* VRAM Fill data */
|
||||
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 uint32 dma_type; /* DMA mode */
|
||||
static uint32 fifo_latency; /* CPU access latency */
|
||||
static int cached_write; /* 2nd part of 32-bit CTRL port write */
|
||||
|
||||
/* DMA Timings
|
||||
|
||||
@ -120,7 +123,7 @@ static uint32 fifo_latency; /* CPU access latency */
|
||||
static const uint8 dma_rates[16] = {
|
||||
8, 83, 9, 102, /* 68K to VRAM (1 word = 2 bytes) */
|
||||
16, 167, 18, 205, /* 68K to CRAM or VSRAM */
|
||||
15, 166, 17, 204, /* DMA fill */
|
||||
16, 167, 18, 205, /* DMA fill (same as above, dma length is adjusted to take first write in account)*/
|
||||
8, 83, 9, 102, /* DMA Copy */
|
||||
};
|
||||
|
||||
@ -130,9 +133,9 @@ static const uint8 dma_rates[16] = {
|
||||
static void fifo_update(unsigned int cycles);
|
||||
static void data_w(unsigned int data);
|
||||
static void reg_w(unsigned int r, unsigned int d);
|
||||
static void dma_copy(void);
|
||||
static void dma_vbus (void);
|
||||
static void dma_fill(unsigned int data);
|
||||
static void dma_copy(int length);
|
||||
static void dma_vbus (int length);
|
||||
static void dma_fill(int length, unsigned int data);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown functions */
|
||||
@ -141,6 +144,7 @@ void vdp_init(void)
|
||||
{
|
||||
/* PAL/NTSC timings */
|
||||
lines_per_frame = vdp_pal ? 313: 262;
|
||||
status = (status & ~1) | vdp_pal;
|
||||
}
|
||||
|
||||
void vdp_reset(void)
|
||||
@ -161,6 +165,7 @@ void vdp_reset(void)
|
||||
hvc_latch = 0;
|
||||
v_counter = 0;
|
||||
dmafill = 0;
|
||||
fill_data = 0;
|
||||
dma_length = 0;
|
||||
dma_endCycles = 0;
|
||||
dma_type = 0;
|
||||
@ -170,8 +175,11 @@ void vdp_reset(void)
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
fifo_latency = 190;
|
||||
cached_write = -1;
|
||||
|
||||
status = vdp_pal | 0x0200; /* FIFO empty */
|
||||
vc_max = 0xEA + 24*vdp_pal;
|
||||
|
||||
status = vdp_pal | 0x200; /* FIFO empty flag */
|
||||
|
||||
ntab = 0;
|
||||
ntbb = 0;
|
||||
@ -190,27 +198,18 @@ void vdp_reset(void)
|
||||
memset ((char *) bg_name_list, 0, sizeof (bg_name_list));
|
||||
memset ((char *) bg_pattern_cache, 0, sizeof (bg_pattern_cache));
|
||||
|
||||
playfield_shift = 6;
|
||||
playfield_col_mask = 0x0F;
|
||||
playfield_row_mask = 0x0FF;
|
||||
|
||||
/* reset HVC tables */
|
||||
vctab = vdp_pal ? vc_pal_224 : vc_ntsc_224;
|
||||
/* default HVC tables */
|
||||
hctab = cycle2hc32;
|
||||
|
||||
/* reset display area */
|
||||
/* default display area */
|
||||
bitmap.viewport.w = 256;
|
||||
bitmap.viewport.h = 224;
|
||||
bitmap.viewport.ow = 256;
|
||||
bitmap.viewport.oh = 224;
|
||||
|
||||
/* reset overscan area */
|
||||
bitmap.viewport.x = 0;
|
||||
bitmap.viewport.y = 0;
|
||||
if (config.overscan & 1)
|
||||
bitmap.viewport.y = vdp_pal ? 32 : 8;
|
||||
if (config.overscan & 2)
|
||||
bitmap.viewport.x = 12;
|
||||
/* default overscan area */
|
||||
bitmap.viewport.x = (config.overscan & 2) * 7;
|
||||
bitmap.viewport.y = (config.overscan & 1) * (8 + 24*vdp_pal);
|
||||
|
||||
/* initialize registers if OS ROM is not used */
|
||||
if (config.tmss == 1)
|
||||
@ -226,18 +225,76 @@ void vdp_reset(void)
|
||||
void vdp_shutdown(void)
|
||||
{}
|
||||
|
||||
void vdp_restore(uint8 *vdp_regs)
|
||||
int vdp_context_save(uint8 *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
int bufferptr = 0;
|
||||
|
||||
save_param(sat, sizeof(sat));
|
||||
save_param(vram, sizeof(vram));
|
||||
save_param(cram, sizeof(cram));
|
||||
save_param(vsram, sizeof(vsram));
|
||||
save_param(reg, sizeof(reg));
|
||||
save_param(&addr, sizeof(addr));
|
||||
save_param(&addr_latch, sizeof(addr_latch));
|
||||
save_param(&code, sizeof(code));
|
||||
save_param(&pending, sizeof(pending));
|
||||
save_param(&status, sizeof(status));
|
||||
save_param(&dmafill, sizeof(dmafill));
|
||||
save_param(&hint_pending, sizeof(hint_pending));
|
||||
save_param(&vint_pending, sizeof(vint_pending));
|
||||
save_param(&irq_status, sizeof(irq_status));
|
||||
|
||||
/* extended state */
|
||||
save_param(&dma_length, sizeof(dma_length));
|
||||
save_param(&dma_type, sizeof(dma_type));
|
||||
save_param(&fill_data, sizeof(fill_data));
|
||||
save_param(&cached_write, sizeof(cached_write));
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
int vdp_context_load(uint8 *state, char *version)
|
||||
{
|
||||
int i, bufferptr = 0;
|
||||
uint8 temp_reg[0x20];
|
||||
|
||||
load_param(sat, sizeof(sat));
|
||||
load_param(vram, sizeof(vram));
|
||||
load_param(cram, sizeof(cram));
|
||||
load_param(vsram, sizeof(vsram));
|
||||
load_param(temp_reg, sizeof(temp_reg));
|
||||
load_param(&addr, sizeof(addr));
|
||||
load_param(&addr_latch, sizeof(addr_latch));
|
||||
load_param(&code, sizeof(code));
|
||||
load_param(&pending, sizeof(pending));
|
||||
load_param(&status, sizeof(status));
|
||||
load_param(&dmafill, sizeof(dmafill));
|
||||
load_param(&hint_pending, sizeof(hint_pending));
|
||||
load_param(&vint_pending, sizeof(vint_pending));
|
||||
load_param(&irq_status, sizeof(irq_status));
|
||||
|
||||
/* extended state */
|
||||
if (version[15] > 0x30)
|
||||
{
|
||||
load_param(&dma_length, sizeof(dma_length));
|
||||
load_param(&dma_type, sizeof(dma_type));
|
||||
load_param(&fill_data, sizeof(fill_data));
|
||||
load_param(&cached_write, sizeof(cached_write));
|
||||
}
|
||||
|
||||
/* restore VDP registers */
|
||||
for (i=0;i<0x20;i++)
|
||||
{
|
||||
reg_w(i, vdp_regs[i]);
|
||||
reg_w(i, temp_reg[i]);
|
||||
}
|
||||
|
||||
/* reinitialize HVC tables */
|
||||
vctab = (vdp_pal) ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||
vc_max = 0xEA + 24*vdp_pal;
|
||||
if (reg[1] & 8)
|
||||
{
|
||||
vc_max += (28 - 20*vdp_pal);
|
||||
}
|
||||
|
||||
/* restore FIFO timings */
|
||||
fifo_latency = (reg[12] & 1) ? 190 : 214;
|
||||
@ -256,6 +313,8 @@ void vdp_restore(uint8 *vdp_regs)
|
||||
color_update(0x00, *(uint16 *)&cram[border << 1]);
|
||||
for(i = 1; i < 0x40; i += 1)
|
||||
color_update(i, *(uint16 *)&cram[i << 1]);
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
|
||||
@ -263,66 +322,125 @@ void vdp_restore(uint8 *vdp_regs)
|
||||
/* DMA update */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void vdp_update_dma()
|
||||
void vdp_update_dma(unsigned int cycles)
|
||||
{
|
||||
int dma_cycles = 0;
|
||||
|
||||
/* update DMA timings */
|
||||
unsigned int index = dma_type;
|
||||
if ((status & 8) || !(reg[1] & 0x40)) index++;
|
||||
if (reg[12] & 1) index += 2;
|
||||
int dma_cycles;
|
||||
|
||||
/* DMA transfer rate (bytes per line) */
|
||||
unsigned int rate = dma_rates[index];
|
||||
unsigned int rate = dma_type;
|
||||
if ((status & 8) || !(reg[1] & 0x40)) rate++;
|
||||
if (reg[12] & 1) rate += 2;
|
||||
rate = dma_rates[rate];
|
||||
|
||||
/* 68k cycles left */
|
||||
int left_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - mcycles_68k;
|
||||
if (left_cycles < 0) left_cycles = 0;
|
||||
/* Remaining DMA cycles */
|
||||
if (status & 8)
|
||||
{
|
||||
/* Process DMA until the end of VBLANK */
|
||||
dma_cycles = (lines_per_frame * MCYCLES_PER_LINE) - cycles;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process DMA until the end of current line */
|
||||
dma_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - cycles;
|
||||
}
|
||||
|
||||
/* DMA bytes left */
|
||||
unsigned int dma_bytes = (left_cycles * rate) / MCYCLES_PER_LINE;
|
||||
/* Remaining DMA bytes */
|
||||
int dma_bytes = (dma_cycles * rate) / MCYCLES_PER_LINE;
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)-> %d access (%d remaining) (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,dma_type/4, rate, dma_length, dma_bytes, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)(%d cycles left)-> %d access (%d remaining) (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,dma_type/4, rate, dma_cycles, dma_bytes, dma_length, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* determinate DMA length in CPU cycles */
|
||||
/* Check if DMA will be finished during current line */
|
||||
if (dma_length < dma_bytes)
|
||||
{
|
||||
/* DMA will be finished during this line */
|
||||
dma_cycles = (dma_length * MCYCLES_PER_LINE) / rate;
|
||||
dma_length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DMA can not be finished until next scanline */
|
||||
dma_cycles = left_cycles;
|
||||
dma_length -= dma_bytes;
|
||||
/* Adjust remaining DMA */
|
||||
dma_bytes = dma_length;
|
||||
dma_cycles = (dma_bytes * MCYCLES_PER_LINE) / rate;
|
||||
}
|
||||
|
||||
/* update 68k cycles counter */
|
||||
/* Update DMA timings */
|
||||
if (dma_type < 8)
|
||||
{
|
||||
/* 68K to VRAM, CRAM, VSRAM */
|
||||
/* 68K is frozen during DMA operation */
|
||||
mcycles_68k += dma_cycles;
|
||||
|
||||
#ifdef LOGVDP
|
||||
mcycles_68k = cycles + dma_cycles;
|
||||
#ifdef LOGVDP
|
||||
error("-->CPU frozen for %d cycles\n", dma_cycles);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* VRAM Fill or VRAM Copy */
|
||||
/* set DMA end cyles count */
|
||||
dma_endCycles = mcycles_68k + dma_cycles;
|
||||
/* Set DMA Busy flag */
|
||||
status |= 0x0002;
|
||||
|
||||
/* 68K is still running, set DMA end cycle */
|
||||
dma_endCycles = cycles + dma_cycles;
|
||||
#ifdef LOGVDP
|
||||
error("-->DMA ends in %d cycles\n", dma_cycles);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set DMA Busy flag */
|
||||
status |= 0x0002;
|
||||
/* Process DMA */
|
||||
if (dma_bytes > 0)
|
||||
{
|
||||
/* Update DMA length */
|
||||
dma_length -= dma_bytes;
|
||||
|
||||
/* Select DMA operation */
|
||||
switch (dma_type >> 2)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
/* 68K to VRAM, CRAM or VSRAM */
|
||||
dma_vbus(dma_bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
/* VRAM Fill */
|
||||
if (dmafill)
|
||||
{
|
||||
/* process intial write */
|
||||
dmafill = 0;
|
||||
data_w(fill_data);
|
||||
|
||||
/* adjust remaining DMA length */
|
||||
dma_bytes--;
|
||||
|
||||
/* fill MSB */
|
||||
fill_data = (fill_data >> 8) & 0xff;
|
||||
|
||||
/* check remaining DMA length */
|
||||
if (!dma_bytes) break;
|
||||
}
|
||||
|
||||
dma_fill(dma_bytes, fill_data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
/* VRAM Copy */
|
||||
dma_copy(dma_bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if DMA is finished */
|
||||
if (!dma_length)
|
||||
{
|
||||
/* Reset DMA length registers */
|
||||
reg[19] = reg[20] = 0;
|
||||
|
||||
/* Perform cached write, if any */
|
||||
if (cached_write >= 0)
|
||||
{
|
||||
vdp_ctrl_w(cached_write);
|
||||
cached_write = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,6 +451,14 @@ void vdp_ctrl_w(unsigned int data)
|
||||
{
|
||||
if (pending == 0)
|
||||
{
|
||||
/* check that DMA operation was not first triggered with the same instruction */
|
||||
if (dma_length)
|
||||
{
|
||||
/* 2nd part of 32-bit write should be done after DMA completion (Formula One, Kawasaki Superbike Challenge) */
|
||||
cached_write = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((data & 0xC000) == 0x8000)
|
||||
{
|
||||
/* VDP register write */
|
||||
@ -364,17 +490,47 @@ void vdp_ctrl_w(unsigned int data)
|
||||
{
|
||||
switch (reg[23] >> 6)
|
||||
{
|
||||
case 2: /* VRAM fill */
|
||||
dmafill = 1;
|
||||
case 2:
|
||||
{
|
||||
/* VRAM write operation only (Williams Greatest Hits after soft reset) */
|
||||
if ((code & 0x0F) == 1)
|
||||
{
|
||||
/* VRAM fill is triggered next time DATA port is written */
|
||||
dmafill = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: /* VRAM copy */
|
||||
dma_copy();
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
/* VRAM read/write operation only */
|
||||
if ((code & 0x1F) == 0x10)
|
||||
{
|
||||
/* retrieve DMA length */
|
||||
dma_length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
if (!dma_length) dma_length = 0x10000;
|
||||
|
||||
default: /* V bus to VDP DMA */
|
||||
dma_vbus();
|
||||
/* VRAM copy */
|
||||
dma_type = 12;
|
||||
vdp_update_dma(mcycles_68k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
/* retrieve DMA length */
|
||||
dma_length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
if (!dma_length) dma_length = 0x10000;
|
||||
|
||||
/* SVP transfer latency */
|
||||
if (svp && !(reg[23] & 0x60)) reg[21]--;
|
||||
|
||||
/* 68k to VDP DMA */
|
||||
dma_type = (code & 0x06) ? 4 : 0;
|
||||
vdp_update_dma(mcycles_68k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,8 +587,7 @@ unsigned int vdp_ctrl_r(unsigned int cycles)
|
||||
temp |= 0x08;
|
||||
|
||||
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican, V.R Troopers, Gouketsuji Ichizoku, ...) */
|
||||
if ((cycles % MCYCLES_PER_LINE) < 588)
|
||||
temp |= 0x04;
|
||||
if ((cycles % MCYCLES_PER_LINE) < 588) temp |= 0x04;
|
||||
|
||||
/* clear pending flag */
|
||||
pending = 0;
|
||||
@ -455,16 +610,25 @@ unsigned int vdp_hvc_r(unsigned int cycles)
|
||||
uint8 hc = hctab[cycles%MCYCLES_PER_LINE];
|
||||
|
||||
/* Vertical Counter */
|
||||
uint8 vc = vctab[v_counter];
|
||||
int16 vc = v_counter;
|
||||
|
||||
/* interlace mode 2 (Sonic the Hedgehog 2, Combat Cars) */
|
||||
if (im2_flag)
|
||||
vc = (vc << 1) | ((vc >> 7) & 1);
|
||||
/* Check counter overflow */
|
||||
if (vc > vc_max) vc -= lines_per_frame;
|
||||
|
||||
/* Interlaced Modes */
|
||||
if (interlaced)
|
||||
{
|
||||
/* interlace mode 2 (Sonic the Hedgehog 2, Combat Cars) */
|
||||
if (im2_flag) vc = vc << 1;
|
||||
|
||||
/* replace bit 0 with bit 8 */
|
||||
vc = (vc & ~1) | ((vc >> 8) & 1);
|
||||
}
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VDP HVC Read -> 0x%04x (%x)\n", v_counter, cycles/MCYCLES_PER_LINE, cycles, cycles%MCYCLES_PER_LINE,(vc << 8) | hc, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
return ((vc << 8) | hc);
|
||||
return (((vc & 0xff) << 8) | hc);
|
||||
}
|
||||
|
||||
void vdp_test_w(unsigned int data)
|
||||
@ -479,9 +643,22 @@ void vdp_data_w(unsigned int data)
|
||||
/* Clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
/* DMA Fill */
|
||||
if (dmafill)
|
||||
{
|
||||
dma_fill(data);
|
||||
/* save fill data */
|
||||
fill_data = data;
|
||||
|
||||
/* retrieve DMA length */
|
||||
dma_length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
if (!dma_length) dma_length = 0x10000;
|
||||
|
||||
/* adjust DMA length (first write counts for timings) */
|
||||
dma_length++;
|
||||
|
||||
/* perform DMA */
|
||||
dma_type = 8;
|
||||
vdp_update_dma(mcycles_68k);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -523,14 +700,14 @@ unsigned int vdp_data_r(void)
|
||||
switch (code & 0x0F)
|
||||
{
|
||||
case 0x00: /* VRAM */
|
||||
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
||||
temp = *(uint16 *) &vram[(addr & 0xFFFE)];
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x08: /* CRAM */
|
||||
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
||||
temp = *(uint16 *) &cram[(addr & 0x7E)];
|
||||
temp = UNPACK_CRAM (temp);
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] CRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
@ -538,7 +715,7 @@ unsigned int vdp_data_r(void)
|
||||
break;
|
||||
|
||||
case 0x04: /* VSRAM */
|
||||
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
||||
temp = *(uint16 *) &vsram[(addr & 0x7E)];
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
@ -569,7 +746,7 @@ int vdp_int_ack_callback(int int_level)
|
||||
#endif
|
||||
|
||||
/* VINT triggered ? */
|
||||
if (irq_status&0x20)
|
||||
if ((irq_status & 6) == 6)
|
||||
{
|
||||
vint_pending = 0;
|
||||
status &= ~0x80; /* clear VINT flag */
|
||||
@ -696,7 +873,7 @@ static void data_w(unsigned int data)
|
||||
color_update (0x00, data);
|
||||
|
||||
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, etc) */
|
||||
if (!(status & 8) && (reg[1]& 0x40) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
if ((v_counter < bitmap.viewport.h) && (reg[1]& 0x40) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
{
|
||||
/* remap current line */
|
||||
remap_buffer(v_counter);
|
||||
@ -754,9 +931,9 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
if ((r & 0x10) && hint_pending)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status = 0x50;
|
||||
irq_status = 0x30;
|
||||
if (vint_pending & reg[1])
|
||||
irq_status |= 0x26;
|
||||
irq_status |= 6;
|
||||
else if (d & 0x10)
|
||||
irq_status |= 4;
|
||||
}
|
||||
@ -775,7 +952,7 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
if (r & 0x02)
|
||||
{
|
||||
if (reg[0] & 2) /* latch current HVC */
|
||||
hvc_latch = 0x10000 | (vctab[v_counter] << 8) | hctab[mcycles_68k%MCYCLES_PER_LINE];
|
||||
hvc_latch = 0x10000 | vdp_hvc_r(mcycles_68k);
|
||||
else /* free-running HVC */
|
||||
hvc_latch = 0;
|
||||
}
|
||||
@ -792,9 +969,9 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
if ((r & 0x20) && vint_pending)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status = 0x50;
|
||||
irq_status = 0x30;
|
||||
if (d & 0x20)
|
||||
irq_status |= 0x26;
|
||||
irq_status |= 6;
|
||||
else if (hint_pending & reg[0])
|
||||
irq_status |= 4;
|
||||
}
|
||||
@ -802,35 +979,29 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
/* See if the viewport height has actually been changed */
|
||||
if (r & 0x08)
|
||||
{
|
||||
/* Update V Counter table */
|
||||
if (vdp_pal)
|
||||
vctab = (d & 8) ? vc_pal_240 : vc_pal_224;
|
||||
|
||||
/* Update viewport */
|
||||
if (status & 8)
|
||||
if (v_counter < bitmap.viewport.h)
|
||||
{
|
||||
/* Update active display */
|
||||
bitmap.viewport.h = 224 + ((d & 8) << 1);
|
||||
bitmap.viewport.y = (config.overscan & 1) * ( 8 - (d & 8) + vdp_pal*24);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* changes should be applied on next frame */
|
||||
bitmap.viewport.changed |= 2;
|
||||
}
|
||||
else
|
||||
|
||||
/* update vertical counter max value (see hvc.h) */
|
||||
vc_max = 0xEA + 24*vdp_pal;
|
||||
if (d & 8)
|
||||
{
|
||||
/* Update active display */
|
||||
if (d & 8)
|
||||
{
|
||||
bitmap.viewport.h = 240;
|
||||
bitmap.viewport.y = (config.overscan & 1) ? (vdp_pal ? 24 : 0) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap.viewport.h = 224;
|
||||
bitmap.viewport.y = (config.overscan & 1) ? (vdp_pal ? 32 : 8) : 0;
|
||||
}
|
||||
vc_max += (28 - 20*vdp_pal);
|
||||
}
|
||||
}
|
||||
|
||||
/* Display status modified during active display (Legend of Galahad, Lemmings 2, */
|
||||
/* Formula One Championship, Nigel Mansell's World Championship Racing, ...) */
|
||||
if ((r & 0x40) && !(status & 8))
|
||||
if ((r & 0x40) && (v_counter < bitmap.viewport.h))
|
||||
{
|
||||
int offset = mcycles_68k - mcycles_vdp - 860;
|
||||
if (offset <= 0)
|
||||
@ -914,7 +1085,7 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
color_update(0x00, *(uint16 *)&cram[(d << 1)]);
|
||||
|
||||
/* background color modified during Horizontal Blanking (Road Rash 1,2,3)*/
|
||||
if (!(status & 8) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
if ((v_counter < bitmap.viewport.h) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
{
|
||||
/* remap entire line */
|
||||
remap_buffer(v_counter);
|
||||
@ -962,28 +1133,33 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
/* Update HC table */
|
||||
hctab = cycle2hc32;
|
||||
|
||||
/* Update fifo timings */
|
||||
/* Update FIFO timings */
|
||||
fifo_latency = 214;
|
||||
}
|
||||
|
||||
/* Adjust VRAM timings */
|
||||
if ((code & 0x0F) == 0x01)
|
||||
{
|
||||
fifo_latency = fifo_latency * 2;
|
||||
}
|
||||
|
||||
/* Update clipping */
|
||||
window_clip();
|
||||
|
||||
/* display width changed during HBLANK (Bugs Bunny Double Trouble) */
|
||||
if (!(status & 8))
|
||||
/* Display width switched during HBLANK (Bugs Bunny Double Trouble) */
|
||||
if ((v_counter < bitmap.viewport.h) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
{
|
||||
if (mcycles_68k <= (mcycles_vdp + 860))
|
||||
{
|
||||
/* redraw entire line */
|
||||
render_line(v_counter);
|
||||
}
|
||||
}
|
||||
/* Update active display */
|
||||
bitmap.viewport.w = 256 + ((d & 1) << 6);
|
||||
|
||||
/* changes should be applied on next frame */
|
||||
bitmap.viewport.changed |= 2;
|
||||
/* Redraw entire line */
|
||||
render_line(v_counter);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Changes should only be applied on next frame (Golden Axe III intro) */
|
||||
bitmap.viewport.changed |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Interlaced modes */
|
||||
@ -1038,20 +1214,11 @@ static void reg_w(unsigned int r, unsigned int d)
|
||||
- see how source addr is affected
|
||||
(can it make high source byte inc?)
|
||||
*/
|
||||
static void dma_copy(void)
|
||||
static void dma_copy(int length)
|
||||
{
|
||||
int name;
|
||||
unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
unsigned int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
|
||||
|
||||
if (!length)
|
||||
length = 0x10000;
|
||||
|
||||
dma_type = 12;
|
||||
dma_length = length;
|
||||
vdp_update_dma();
|
||||
|
||||
/* proceed DMA */
|
||||
do
|
||||
{
|
||||
vram[addr] = vram[source];
|
||||
@ -1060,29 +1227,18 @@ static void dma_copy(void)
|
||||
addr += reg[15];
|
||||
} while (--length);
|
||||
|
||||
/* update length & source address registers */
|
||||
reg[19] = length & 0xFF;
|
||||
reg[20] = (length >> 8) & 0xFF;
|
||||
/* update source address registers */
|
||||
reg[21] = source & 0xFF; /* not sure */
|
||||
reg[22] = (source >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
/* 68K Copy to VRAM, VSRAM or CRAM */
|
||||
static void dma_vbus (void)
|
||||
static void dma_vbus (int length)
|
||||
{
|
||||
unsigned int source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE;
|
||||
unsigned int base = source;
|
||||
unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
uint16 temp;
|
||||
|
||||
if (!length)
|
||||
length = 0x10000;
|
||||
|
||||
/* DMA timings */
|
||||
dma_type = (code & 0x06) ? 4 : 0;
|
||||
dma_length = length;
|
||||
vdp_update_dma();
|
||||
|
||||
/* DMA source */
|
||||
if ((source >> 17) == 0x50)
|
||||
{
|
||||
@ -1105,7 +1261,9 @@ static void dma_vbus (void)
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
else
|
||||
{
|
||||
temp = *(uint16 *)(work_ram + (source & 0xffff));
|
||||
}
|
||||
|
||||
source += 2;
|
||||
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
||||
@ -1115,12 +1273,6 @@ static void dma_vbus (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SVP latency */
|
||||
if (svp && (source < 0x400000))
|
||||
{
|
||||
source = (source - 2);
|
||||
}
|
||||
|
||||
/* ROM & RAM */
|
||||
do
|
||||
{
|
||||
@ -1132,33 +1284,16 @@ static void dma_vbus (void)
|
||||
while (--length);
|
||||
}
|
||||
|
||||
/* update length & source address registers */
|
||||
reg[19] = length & 0xFF;
|
||||
reg[20] = (length >> 8) & 0xFF;
|
||||
/* update source address registers */
|
||||
reg[21] = (source >> 1) & 0xFF;
|
||||
reg[22] = (source >> 9) & 0xFF;
|
||||
reg[23] = (reg[23] & 0x80) | ((source >> 17) & 0x7F);
|
||||
}
|
||||
|
||||
/* VRAM FILL */
|
||||
static void dma_fill(unsigned int data)
|
||||
static void dma_fill(int length, unsigned int data)
|
||||
{
|
||||
int name;
|
||||
unsigned int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
|
||||
if (!length)
|
||||
length = 0x10000;
|
||||
|
||||
/* DMA timings */
|
||||
dma_type = 8;
|
||||
dma_length = length;
|
||||
vdp_update_dma();
|
||||
|
||||
/* proceed DMA */
|
||||
data_w(data);
|
||||
|
||||
/* write MSB */
|
||||
data = (data >> 8) & 0xff;
|
||||
|
||||
/* intercept SAT writes */
|
||||
if ((addr & sat_base_mask) == satb)
|
||||
@ -1183,9 +1318,4 @@ static void dma_fill(unsigned int data)
|
||||
}
|
||||
while (--length);
|
||||
}
|
||||
|
||||
/* update length register */
|
||||
reg[19] = length & 0xFF;
|
||||
reg[20] = (length >> 8) & 0xFF;
|
||||
dmafill = 0;
|
||||
}
|
||||
|
25
source/vdp.h
25
source/vdp.h
@ -30,15 +30,11 @@ extern uint8 vram[0x10000];
|
||||
extern uint8 cram[0x80];
|
||||
extern uint8 vsram[0x80];
|
||||
extern uint8 reg[0x20];
|
||||
extern uint16 addr;
|
||||
extern uint16 addr_latch;
|
||||
extern uint8 code;
|
||||
extern uint8 pending;
|
||||
extern uint16 status;
|
||||
extern uint8 dmafill;
|
||||
extern uint8 hint_pending;
|
||||
extern uint8 vint_pending;
|
||||
extern uint8 irq_status;
|
||||
extern uint16 status;
|
||||
extern uint32 dma_length;
|
||||
|
||||
/* Global variables */
|
||||
extern uint16 ntab;
|
||||
@ -55,8 +51,6 @@ extern uint8 playfield_shift;
|
||||
extern uint8 playfield_col_mask;
|
||||
extern uint16 playfield_row_mask;
|
||||
extern uint16 v_counter;
|
||||
extern uint32 hvc_latch;
|
||||
extern uint32 dma_length;
|
||||
extern int32 fifo_write_cnt;
|
||||
extern uint32 fifo_lastwrite;
|
||||
extern uint8 im2_flag;
|
||||
@ -64,21 +58,16 @@ extern uint8 interlaced;
|
||||
extern uint8 odd_frame;
|
||||
extern uint8 vdp_pal;
|
||||
extern uint16 lines_per_frame;
|
||||
|
||||
extern const uint8 vc_ntsc_224[262];
|
||||
extern const uint8 vc_pal_224[313];
|
||||
extern const uint8 vc_pal_240[313];
|
||||
extern const uint8 cycle2hc32[3420];
|
||||
extern const uint8 cycle2hc40[3420];
|
||||
extern const uint8 *vctab;
|
||||
extern const uint8 *hctab;
|
||||
extern uint32 hvc_latch;
|
||||
extern uint32 vc_max;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void vdp_init(void);
|
||||
extern void vdp_reset(void);
|
||||
extern void vdp_shutdown(void);
|
||||
extern void vdp_restore(uint8 *vdp_regs);
|
||||
extern void vdp_update_dma();
|
||||
extern int vdp_context_save(uint8 *state);
|
||||
extern int vdp_context_load(uint8 *state, char *version);
|
||||
extern void vdp_update_dma(unsigned int cycles);
|
||||
extern void vdp_ctrl_w(unsigned int data);
|
||||
extern unsigned int vdp_ctrl_r(unsigned int cycles);
|
||||
extern void vdp_data_w(unsigned int data);
|
||||
|
Loading…
Reference in New Issue
Block a user