mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-09-10 16:53:15 +02:00
huge update
This commit is contained in:
parent
1a730e7183
commit
0165ac387f
11
history.txt
11
history.txt
@ -12,7 +12,7 @@ CURRENT:
|
||||
.modified SSG-EG Decay End Level: fix some sound effects (ChainSaw, Zap...) in "Beavis & Butthead"
|
||||
.improved Detune overflow accuracy: fix very high frequency sounds in many games
|
||||
.fixed registers 0x20-0x26 Reset state: fix intro music in "B.O.B"
|
||||
.reverted incorrect fix with KEY ON: fix "Flamethrower" sound effect in "Alien 3" and many other games
|
||||
.reverted incorrect fix with KEY ON: fix "Flamethrower" sound effect in "Alien 3" and many others
|
||||
|
||||
- adjusted HCounter values: fixes line flickering in "Sonic 3D" bonus stage
|
||||
- adjusted VINT timing: fixes hang-up in "V.R Troopers"
|
||||
@ -20,6 +20,7 @@ CURRENT:
|
||||
- fixed broken Z80 access to WRAM: fixes hang-up in "Mamono Hunter Youko"
|
||||
- modified JCART emulation: fixes corrupted tracks logo in "Micro Machines 2"
|
||||
- added Blargg's NTSC Filters support (NTSC video artifacts emulation)
|
||||
- improved emulation speed: highly optimized VDP rendering engine, 68k memory handlers, cpu execution & interrupts
|
||||
|
||||
|
||||
[NGC/Wii]
|
||||
@ -27,10 +28,9 @@ CURRENT:
|
||||
- remove slowest libsamplerate settings under "HQ YM2612" option, only keeps SRC_LINEAR (faster) and SRC_SINC_FAST (better)
|
||||
- implemented fast scrolling in menu using Wiimote D-PAD
|
||||
- added an option to enable/disable bilinear filtering
|
||||
- rewrote video renderer: improved horizontal scaling (VI+GX), faster rendering (direct texture mapping)...
|
||||
- rewrote video engine: improved horizontal scaling (VI+GX), improved rendering speed (direct texture mapping)
|
||||
- removed embedded font, (re)enabled IPL font support: now should works for Qoob users too (thanks to emukiddid)
|
||||
- fixed "Reset" button behavior, now acts more like Genesis Reset button ;-)
|
||||
- added SDCARD read-ahead cache support (svpe's libogc patches)
|
||||
- minor bugfixes and menu tweaks
|
||||
|
||||
|
||||
@ -40,8 +40,9 @@ CURRENT:
|
||||
|
||||
|
||||
[Wii only]
|
||||
- added "Power" button support, including shutdown from the wiimote (libogc CVS)
|
||||
- added SDHC support (libogc CVS)
|
||||
- added "Power" button support
|
||||
- improved SDCARD access speed (svpe's "read-ahead" patch)
|
||||
- compiled with libogc CVS: SDHC support, Wiimote shutdown button support
|
||||
|
||||
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
|
||||
/****************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* Cartridge Hardware support
|
||||
*
|
||||
* code by Eke-Eke, GC/Wii port
|
||||
*
|
||||
* Lots of protection mechanism have been discovered by Haze
|
||||
* Most cartridge protections documented by Haze
|
||||
* (http://haze.mameworld.info/)
|
||||
*
|
||||
* Realtec mapper has been figured out by TascoDeluxe
|
||||
* Realtec mapper documented by TascoDeluxe
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -30,14 +31,14 @@
|
||||
#define CART_CNT 26
|
||||
|
||||
/* Function prototypes */
|
||||
void default_time_w(unsigned int address, unsigned int value);
|
||||
void special_mapper_w(unsigned int address, unsigned int value);
|
||||
void realtec_mapper_w(unsigned int address, unsigned int value);
|
||||
void seganet_mapper_w(unsigned int address, unsigned int value);
|
||||
unsigned int radica_mapper_r(unsigned int address);
|
||||
void default_regs_w(unsigned int address, unsigned int value);
|
||||
unsigned int default_regs_r(unsigned int address);
|
||||
void special_regs_w(unsigned int address, unsigned int value);
|
||||
void default_time_w(uint32 address, uint32 data);
|
||||
void special_mapper_w(uint32 address, uint32 data);
|
||||
void realtec_mapper_w(uint32 address, uint32 data);
|
||||
void seganet_mapper_w(uint32 address, uint32 data);
|
||||
uint32 radica_mapper_r(uint32 address);
|
||||
void default_regs_w(uint32 address, uint32 data);
|
||||
uint32 default_regs_r(uint32 address);
|
||||
void special_regs_w(uint32 address, uint32 data);
|
||||
|
||||
/* Cart database entry */
|
||||
typedef struct
|
||||
@ -56,64 +57,65 @@ typedef struct
|
||||
T_CART_ENTRY rom_database[CART_CNT] =
|
||||
{
|
||||
/* Game no Kanzume Otokuyou */
|
||||
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,seganet_mapper_w,0,0}},
|
||||
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,seganet_mapper_w,0,0}},
|
||||
/* RADICA (Volume 1) (not byteswapped) */
|
||||
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 2) */
|
||||
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* RADICA (Volume 1) */
|
||||
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}},
|
||||
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
|
||||
/* Funny World & Balloon Boy */
|
||||
{0x0000,0x06ab,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
{0x0000,0x06ab,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Whac-a-Critter */
|
||||
{0xffff,0xf863,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
{0xffff,0xf863,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Earth Defense */
|
||||
{0xffff,0x44fb,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}},
|
||||
{0xffff,0x44fb,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
||||
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Super Mario 2 1998 */
|
||||
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}},
|
||||
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Supper Bubble Bobble */
|
||||
{0x0000,0x16cd,8,8,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,0,default_regs_r,0}},
|
||||
/* Mahjong Lover */
|
||||
{0x0000,0x7037,8,8,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,0,default_regs_r,0}},
|
||||
/* Lion King 2 */
|
||||
{0xffff,0x1d9b,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
||||
{0xffff,0x1d9b,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Squirell King */
|
||||
{0x0000,0x8ec8,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}},
|
||||
{0x0000,0x8ec8,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
|
||||
/* Rockman X3 */
|
||||
{0x0000,0x9d0e,8,8,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,default_regs_r,0,default_regs_r,0}},
|
||||
{0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,0,default_regs_r,0,default_regs_r,0}},
|
||||
/* A Bug's Life */
|
||||
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* King of Fighter 99 */
|
||||
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Pocket Monster */
|
||||
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}},
|
||||
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
|
||||
/* Lion King 3 */
|
||||
{0x0000,0x507c,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x507c,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
/* Super King Kong 99 */
|
||||
{0x0000,0x7d6e,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}},
|
||||
{0x0000,0x7d6e,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
|
||||
/* Pokemon Stadium */
|
||||
{0x0000,0x843c,14,15,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,special_regs_w}},
|
||||
{0x0000,0x843c,0x70,0x7f,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,0,0,0,special_regs_w}},
|
||||
/* Elf Wor */
|
||||
{0x0080,0x3dba,8,8,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
{0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Huan Le Tao Qi Shu - Smart Mouse */
|
||||
{0x0000,0x1a28,8,8,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Ya-Se Chuanshuo */
|
||||
{0xffff,0xd472,8,8,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
{0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* Soul Blade */
|
||||
{0x0000,0x0c5b,8,8,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}},
|
||||
{0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
|
||||
/* King of Fighter 98 */
|
||||
{0x0000,0xd0a0,9,9,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,default_regs_r,0}},
|
||||
{0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,0,default_regs_r,0}},
|
||||
/* Lian Huan Pao - Barver Battle Saga */
|
||||
{0x30b9,0x1c2a,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,default_regs_r,0}}
|
||||
{0x30b9,0x1c2a,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,default_regs_r,0}}
|
||||
};
|
||||
|
||||
|
||||
/* current cart hardware */
|
||||
T_CART_HW cart_hw;
|
||||
uint8 j_cart;
|
||||
int old_system[2] = {-1,-1};
|
||||
/* previous inputs */
|
||||
static int old_system[2] = {-1,-1};
|
||||
|
||||
/* temporary memory chunk */
|
||||
uint8 mem_chunk[0x10000];
|
||||
|
||||
/************************************************************
|
||||
Cart Hardware initialization
|
||||
@ -122,16 +124,27 @@ int old_system[2] = {-1,-1};
|
||||
/* hardware that need to be reseted on power on */
|
||||
void cart_hw_reset()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* reset bankshifting */
|
||||
if (cart_hw.bankshift)
|
||||
{
|
||||
for (i=0x00; i<0x40; i++)
|
||||
m68k_memory_map[i].base = cart_rom + (i<<16);
|
||||
}
|
||||
|
||||
/* Realtec mapper */
|
||||
if (cart_hw.realtec & 1)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* enable BOOTROM */
|
||||
for (i=0; i<8; i++) m68k_readmap_16[i] = REALTEC_ROM;
|
||||
for (i=0; i<0x40; i++) m68k_memory_map[i].base = mem_chunk;
|
||||
for (i=0; i<8; i++) memcpy(mem_chunk + i*0x2000, cart_rom + 0x7e000, 0x2000);
|
||||
cart_hw.realtec |= 2;
|
||||
}
|
||||
|
||||
/* save default cartridge slot mapping */
|
||||
default_rom = m68k_memory_map[0].base;
|
||||
|
||||
/* SVP chip */
|
||||
if (svp) svp_reset();
|
||||
}
|
||||
@ -142,22 +155,29 @@ void cart_hw_init()
|
||||
int i;
|
||||
|
||||
/**********************************************
|
||||
DEFAULT CART MAPPING
|
||||
DEFAULT CARTRIDGE MAPPING
|
||||
***********************************************/
|
||||
for (i=0; i<8; i++)
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
/* cartridge ROM */
|
||||
m68k_memory_map[i].base = cart_rom + (i<<16);
|
||||
m68k_memory_map[i].read8 = NULL;
|
||||
m68k_memory_map[i].read16 = NULL;
|
||||
m68k_memory_map[i].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].read = NULL;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
|
||||
for (i=8; i<16; i++)
|
||||
for (i=0x40; i<0x80; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UNUSED;
|
||||
m68k_readmap_16[i] = UNUSED;
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
/* unused area */
|
||||
m68k_memory_map[i].read8 = m68k_read_bus_8;
|
||||
m68k_memory_map[i].read16 = m68k_read_bus_16;
|
||||
m68k_memory_map[i].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].read = zbank_unused_r;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
|
||||
/* restore previous setting */
|
||||
@ -174,25 +194,29 @@ void cart_hw_init()
|
||||
if (sram.custom)
|
||||
{
|
||||
/* serial EEPROM */
|
||||
m68k_readmap_8[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
||||
m68k_readmap_16[eeprom.type.sda_out_adr >> 19] = EEPROM;
|
||||
m68k_writemap_8[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
||||
m68k_writemap_16[eeprom.type.sda_in_adr >> 19] = EEPROM;
|
||||
m68k_writemap_8[eeprom.type.scl_adr >> 19] = EEPROM;
|
||||
m68k_writemap_16[eeprom.type.scl_adr >> 19] = EEPROM;
|
||||
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read8 = eeprom_read_byte;
|
||||
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read16 = eeprom_read_word;
|
||||
m68k_memory_map[eeprom.type.sda_in_adr >> 16].read8 = eeprom_read_byte;
|
||||
m68k_memory_map[eeprom.type.sda_in_adr >> 16].read16 = eeprom_read_word;
|
||||
m68k_memory_map[eeprom.type.scl_adr >> 16].write8 = eeprom_write_byte;
|
||||
m68k_memory_map[eeprom.type.scl_adr >> 16].write16 = eeprom_write_word;
|
||||
zbank_memory_map[eeprom.type.sda_out_adr >> 16].read = eeprom_read_byte;
|
||||
zbank_memory_map[eeprom.type.sda_in_adr >> 16].read = eeprom_read_byte;
|
||||
zbank_memory_map[eeprom.type.scl_adr >> 16].write = eeprom_write_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 64KB SRAM */
|
||||
m68k_readmap_8[sram.start >> 19] = SRAM;
|
||||
m68k_readmap_16[sram.start >> 19] = SRAM;
|
||||
if (sram.write)
|
||||
{
|
||||
m68k_writemap_8[sram.start >> 19] = SRAM;
|
||||
m68k_writemap_16[sram.start >> 19] = SRAM;
|
||||
}
|
||||
/* Static RAM (64k max.) */
|
||||
m68k_memory_map[sram.start >> 16].base = sram.sram;
|
||||
m68k_memory_map[sram.start >> 16].read8 = NULL;
|
||||
m68k_memory_map[sram.start >> 16].read16 = NULL;
|
||||
m68k_memory_map[sram.start >> 16].write8 = NULL;
|
||||
m68k_memory_map[sram.start >> 16].write16 = NULL;
|
||||
zbank_memory_map[sram.start >> 16].read = NULL;
|
||||
zbank_memory_map[sram.start >> 16].write = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
SVP CHIP
|
||||
***********************************************/
|
||||
@ -200,12 +224,20 @@ void cart_hw_init()
|
||||
if (strstr(rominfo.international,"Virtua Racing") != NULL)
|
||||
{
|
||||
svp_init();
|
||||
m68k_readmap_16[6] = SVP_DRAM;
|
||||
m68k_writemap_16[6] = SVP_DRAM;
|
||||
m68k_readmap_16[7] = SVP_CELL;
|
||||
m68k_writemap_16[7] = SVP_CELL;
|
||||
|
||||
m68k_memory_map[0x30].base = svp->dram;
|
||||
m68k_memory_map[0x30].read16 = NULL;
|
||||
m68k_memory_map[0x30].write16 = svp_write_dram;
|
||||
|
||||
m68k_memory_map[0x31].base = svp->dram + 0x10000;
|
||||
m68k_memory_map[0x31].read16 = NULL;
|
||||
m68k_memory_map[0x31].write16 = svp_write_dram;
|
||||
|
||||
m68k_memory_map[0x39].read16 = svp_read_cell_1;
|
||||
m68k_memory_map[0x3a].read16 = svp_read_cell_2;
|
||||
}
|
||||
|
||||
|
||||
/* default GUN settings */
|
||||
input.x_offset = 0x00;
|
||||
input.y_offset = 0x00;
|
||||
@ -289,8 +321,10 @@ void cart_hw_init()
|
||||
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
|
||||
{
|
||||
j_cart = 1;
|
||||
m68k_readmap_16[7] = J_CART;
|
||||
m68k_writemap_16[7] = J_CART;
|
||||
m68k_memory_map[0x38].read16 = jcart_read;
|
||||
m68k_memory_map[0x38].write16 = jcart_write;
|
||||
m68k_memory_map[0x3f].read16 = jcart_read;
|
||||
m68k_memory_map[0x3f].write16 = jcart_write;
|
||||
|
||||
/* save current setting */
|
||||
if (old_system[0] == -1) old_system[0] = input.system[0];
|
||||
@ -302,27 +336,6 @@ void cart_hw_init()
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
ULTIMATE MK3 HACK
|
||||
***********************************************/
|
||||
if (genromsize > 0x600000)
|
||||
{
|
||||
for (i=8; i<20; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UMK3_HACK;
|
||||
m68k_readmap_16[i] = UMK3_HACK;
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* this game does not work properly on real hardware */
|
||||
emulate_address_error = 0;
|
||||
#endif
|
||||
}
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* default behavior */
|
||||
else emulate_address_error = 1;
|
||||
#endif
|
||||
|
||||
/**********************************************
|
||||
Mappers & HW registers
|
||||
***********************************************/
|
||||
@ -345,13 +358,53 @@ void cart_hw_init()
|
||||
int j = rom_database[i].bank_start;
|
||||
while (j <= rom_database[i].bank_end)
|
||||
{
|
||||
if (cart_hw.regs_r) m68k_readmap_8[j] = CART_HW;
|
||||
if (cart_hw.regs_w) m68k_writemap_8[j] = CART_HW;
|
||||
if (cart_hw.regs_r)
|
||||
{
|
||||
m68k_memory_map[j].read8 = cart_hw.regs_r;
|
||||
m68k_memory_map[j].read16 = cart_hw.regs_r;
|
||||
zbank_memory_map[j].read = cart_hw.regs_r;
|
||||
}
|
||||
if (cart_hw.regs_w)
|
||||
{
|
||||
m68k_memory_map[j].write8 = cart_hw.regs_w;
|
||||
m68k_memory_map[j].write16 = cart_hw.regs_w;
|
||||
zbank_memory_map[j].write = cart_hw.regs_w;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
/* leave loop */
|
||||
i = CART_CNT + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* default behavior */
|
||||
emulate_address_error = 1;
|
||||
#endif
|
||||
|
||||
/* detect ROM files larger than 4MB */
|
||||
if (genromsize > 0x800000)
|
||||
{
|
||||
/* Ultimate MK3 (hack) */
|
||||
for (i=0x40; i<0xA0; i++)
|
||||
{
|
||||
m68k_memory_map[i].base = cart_rom + (i<<16);
|
||||
m68k_memory_map[i].read8 = NULL;
|
||||
m68k_memory_map[i].read16 = NULL;
|
||||
zbank_memory_map[i].read = NULL;
|
||||
}
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
/* this game does not work properly on real hardware */
|
||||
emulate_address_error = 0;
|
||||
#endif
|
||||
}
|
||||
else if (genromsize > 0x400000)
|
||||
{
|
||||
/* assume SSF2 mapper */
|
||||
cart_hw.bankshift = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
@ -360,190 +413,167 @@ void cart_hw_init()
|
||||
/*
|
||||
"official" ROM/RAM switch
|
||||
*/
|
||||
static inline void sega_mapper_w(unsigned int address, unsigned int value)
|
||||
static inline void sega_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
uint8 bank = (address >> 1) & 7;
|
||||
uint32 i,slot = (address >> 1) & 7;
|
||||
uint8 *src;
|
||||
|
||||
switch (bank)
|
||||
switch (slot)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
/* ROM/RAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
if (value & 1)
|
||||
{
|
||||
/* SRAM is mapped above 200000h */
|
||||
m68k_readmap_8[4] = SRAM;
|
||||
m68k_readmap_16[4] = SRAM;
|
||||
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
|
||||
if (data & 1)
|
||||
{
|
||||
/* SRAM enabled */
|
||||
m68k_memory_map[0x20].base = sram.sram;
|
||||
|
||||
if (value & 2)
|
||||
{
|
||||
/* SRAM write protected */
|
||||
m68k_writemap_8[4] = UNUSED;
|
||||
m68k_writemap_16[4] = UNUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SRAM write enabled */
|
||||
m68k_writemap_8[4] = SRAM;
|
||||
m68k_writemap_16[4] = SRAM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM is mapped above 200000h */
|
||||
m68k_readmap_8[4] = ROM;
|
||||
m68k_readmap_16[4] = ROM;
|
||||
m68k_writemap_8[4] = UNUSED;
|
||||
m68k_writemap_16[4] = UNUSED;
|
||||
}
|
||||
if (data & 2)
|
||||
{
|
||||
/* SRAM write disabled */
|
||||
m68k_memory_map[0x20].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[0x20].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[0x20].write = zbank_unused_w;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SRAM write enabled */
|
||||
m68k_memory_map[0x20].write8 = NULL;
|
||||
m68k_memory_map[0x20].write16 = NULL;
|
||||
zbank_memory_map[0x20].write = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM enabled */
|
||||
m68k_memory_map[0x20].base = cart_rom + 0x200000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* ROM Bankswitch (Super Street Fighter 2)
|
||||
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
|
||||
*/
|
||||
rom_readmap[bank] = &cart_rom[value << 19];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
custom ROM Bankswitch used by pirate "Multi-in-1" carts
|
||||
(documented by Haze)
|
||||
*/
|
||||
static inline void multi_mapper_w(unsigned int address, unsigned int value)
|
||||
static inline void multi_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
uint32 bank_addr = (address & 0x3F) << 16;
|
||||
|
||||
/* those games are generally not bigger than 1MB but it's safer to update all 512K banks */
|
||||
for (i=0; i<8; i++)
|
||||
cart_hw.bankshift = 1;
|
||||
|
||||
/* 64 x 64k banks */
|
||||
for (i=0; i<64; i++)
|
||||
{
|
||||
if (bank_addr >= genromsize) return;
|
||||
rom_readmap[i] = &cart_rom[bank_addr];
|
||||
bank_addr += 0x80000;
|
||||
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)
|
||||
(documented by Haze)
|
||||
*/
|
||||
void special_mapper_w(unsigned int address, unsigned int value)
|
||||
void special_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[value << 15];
|
||||
/* 1 x 32k bank */
|
||||
m68k_memory_map[0].base = mem_chunk;
|
||||
memcpy(mem_chunk,&cart_rom[(data & 0x7f) << 15],0x8000);
|
||||
memcpy(mem_chunk+0x8000,cart_rom + 0x8000,0x8000);
|
||||
}
|
||||
|
||||
/*
|
||||
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
|
||||
(documented by TascoDeluxe)
|
||||
*/
|
||||
void realtec_mapper_w(unsigned int address, unsigned int value)
|
||||
{
|
||||
uint32 base_addr;
|
||||
|
||||
if (cart_hw.realtec & 2)
|
||||
void realtec_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
int i;
|
||||
cart_hw.realtec &= ~2;
|
||||
|
||||
/* disable Realtec BOOTROM */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
}
|
||||
}
|
||||
uint32 base;
|
||||
|
||||
/* 32 x 128k banks */
|
||||
switch (address)
|
||||
{
|
||||
case 0x404000: /* three lower bits of ROM base address */
|
||||
cart_hw.regs[0] = value;
|
||||
base_addr = (value | ((cart_hw.regs[1] & 6) << 2)) << 17;
|
||||
rom_readmap[0] = &cart_rom[base_addr];
|
||||
cart_hw.regs[0] = data & 7;
|
||||
base = ((data & 7) | (cart_hw.regs[1] << 2));
|
||||
for (i=0; i<=cart_hw.regs[2]; i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x400000: /* two higher bits of ROM base address */
|
||||
cart_hw.regs[1] = value;
|
||||
base_addr = ((cart_hw.regs[0] & 7) | ((value & 6) << 2)) << 17;
|
||||
rom_readmap[0] = &cart_rom[base_addr];
|
||||
cart_hw.regs[1] = data & 6;
|
||||
base = cart_hw.regs[0] | ((data & 6) << 2);
|
||||
for (i=0; i<=cart_hw.regs[2]; i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x402000: /* size of ROM range to map */
|
||||
cart_hw.regs[2] = value;
|
||||
case 0x402000: /* number of 128k blocks to map */
|
||||
cart_hw.regs[2] = data & 0x1f;
|
||||
base = cart_hw.regs[0] | (cart_hw.regs[1] << 2);
|
||||
for (i=0; i<=(data & 0x1f); i++)
|
||||
{
|
||||
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
|
||||
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Game no Kanzume Otokuyou ROM Mapper */
|
||||
void seganet_mapper_w(unsigned int address, unsigned int value)
|
||||
void seganet_mapper_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xff) == 0xf1)
|
||||
{
|
||||
int i;
|
||||
switch (address & 0xff)
|
||||
{
|
||||
case 0x01:
|
||||
if (value & 1)
|
||||
if (data & 1)
|
||||
{
|
||||
/* ROM disabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = UNUSED;
|
||||
m68k_readmap_16[i] = UNUSED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* ROM Write protected */
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
/* ROM enabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ROM;
|
||||
m68k_readmap_16[i] = ROM;
|
||||
}
|
||||
}
|
||||
break;;
|
||||
|
||||
case 0xf1:
|
||||
if (value & 1)
|
||||
{
|
||||
/* ROM Write protected*/
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_writemap_8[i] = UNUSED;
|
||||
m68k_writemap_16[i] = UNUSED;
|
||||
m68k_memory_map[i].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[i].write16 = m68k_unused_16_w;
|
||||
zbank_memory_map[i].write = zbank_unused_w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ROM Write enabled */
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
m68k_writemap_8[i] = ROM;
|
||||
m68k_writemap_16[i] = ROM;
|
||||
}
|
||||
for (i=0; i<0x40; i++);
|
||||
{
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
m68k_memory_map[i].write16 = NULL;
|
||||
zbank_memory_map[i].write = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
RADICA ROM Bankswitch
|
||||
(documented by Haze)
|
||||
RADICA ROM Bankswitch (use !TIME)
|
||||
*/
|
||||
unsigned int radica_mapper_r(unsigned int address)
|
||||
uint32 radica_mapper_r(uint32 address)
|
||||
{
|
||||
/* 64KB ROM banks */
|
||||
uint8 bank = (address >> 1) & 0x3F;
|
||||
rom_readmap[0] = &cart_rom[bank * 0x10000];
|
||||
rom_readmap[1] = &cart_rom[bank * 0x10000 + 0x80000]; /* ROM is max. 1MB */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -553,19 +583,20 @@ unsigned int radica_mapper_r(unsigned int address)
|
||||
*************************************************************/
|
||||
|
||||
/* default ROM bankswitch */
|
||||
void default_time_w(unsigned int address, unsigned int value)
|
||||
void default_time_w(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, value);
|
||||
else if (address < 0xa13040) multi_mapper_w(address, value);
|
||||
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data);
|
||||
else if (address < 0xa13040) multi_mapper_w(address, data);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
Internal register handlers
|
||||
*************************************************************/
|
||||
|
||||
unsigned int default_regs_r(unsigned int address)
|
||||
uint32 default_regs_r(uint32 address)
|
||||
{
|
||||
uint8 i;
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
@ -573,36 +604,36 @@ unsigned int default_regs_r(unsigned int address)
|
||||
}
|
||||
|
||||
/* unused */
|
||||
return -1;
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void default_regs_w(unsigned int address, unsigned int value)
|
||||
void default_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
uint8 i;
|
||||
int i;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
|
||||
{
|
||||
cart_hw.regs[i] = value;
|
||||
cart_hw.regs[i] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* special register behaviour (Lion King III, Super Donkey Kong 99) */
|
||||
void special_regs_w(unsigned int address, unsigned int value)
|
||||
void special_regs_w(uint32 address, uint32 data)
|
||||
{
|
||||
/* ROM bankswitch */
|
||||
if ((address >> 16) > 0x6f)
|
||||
{
|
||||
special_mapper_w(address, value);
|
||||
special_mapper_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* write regs */
|
||||
default_regs_w(address, value);
|
||||
default_regs_w(address, data);
|
||||
|
||||
/* bitswapping (documented by Haze) */
|
||||
uint8 temp = cart_hw.regs[0];
|
||||
uint32 temp = cart_hw.regs[0];
|
||||
switch (cart_hw.regs[1])
|
||||
{
|
||||
case 1:
|
||||
|
@ -33,7 +33,8 @@ typedef struct
|
||||
uint8 regs[4]; /* internal registers (R/W) */
|
||||
uint32 mask[4]; /* registers address mask */
|
||||
uint32 addr[4]; /* registers address */
|
||||
uint8 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
|
||||
uint32 bankshift; /* cartridge with bankshift mecanism */
|
||||
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 region ($400000-$7fffff) read handler */
|
||||
@ -41,8 +42,9 @@ typedef struct
|
||||
} T_CART_HW;
|
||||
|
||||
/* global variables */
|
||||
extern T_CART_HW cart_hw;
|
||||
extern uint8 j_cart;
|
||||
T_CART_HW cart_hw;
|
||||
uint8 j_cart;
|
||||
uint8 *default_rom;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void cart_hw_reset();
|
||||
|
@ -24,3 +24,25 @@ void svp_reset(void)
|
||||
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800);
|
||||
ssp1601_reset(&svp->ssp1601);
|
||||
}
|
||||
|
||||
void svp_write_dram(uint32 address, uint32 data)
|
||||
{
|
||||
*(uint16 *)(svp->dram + (address & 0x1fffe)) = data;
|
||||
if ((address == 0x30fe06) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
|
||||
if ((address == 0x30fe08) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
|
||||
}
|
||||
|
||||
uint32 svp_read_cell_1(uint32 address)
|
||||
{
|
||||
address >>= 1;
|
||||
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
|
||||
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||
}
|
||||
|
||||
uint32 svp_read_cell_2(uint32 address)
|
||||
{
|
||||
address >>= 1;
|
||||
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
|
||||
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||
}
|
||||
|
||||
|
@ -26,5 +26,8 @@ extern uint16 SVP_cycles;
|
||||
|
||||
extern void svp_init(void);
|
||||
extern void svp_reset(void);
|
||||
extern void svp_write_dram(uint32 address, uint32 data);
|
||||
extern uint32 svp_read_cell_1(uint32 address);
|
||||
extern uint32 svp_read_cell_2(uint32 address);
|
||||
|
||||
#endif
|
||||
|
@ -77,23 +77,25 @@ static inline void lightgun_update(int num)
|
||||
if (io_reg[5] & 0x80)
|
||||
{
|
||||
/* External Interrupt ? */
|
||||
if (reg[11] & 0x08) m68k_set_irq(2);
|
||||
if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
|
||||
|
||||
/* HVC Latch:
|
||||
1) some games does not set HVC latch but instead use bigger X offset
|
||||
2) for games using H40 mode, the gun routine scales up the Hcounter value,
|
||||
H-Counter range is approx. 292 pixel clocks
|
||||
*/
|
||||
hc_latch = 0x100;
|
||||
if (reg[12] & 1)
|
||||
hc_latch = hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
|
||||
hc_latch |= hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
|
||||
else
|
||||
hc_latch = hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
|
||||
hc_latch |= hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sega Menacer specific */
|
||||
unsigned int menacer_read()
|
||||
uint32 menacer_read()
|
||||
{
|
||||
/* pins should return 0 by default (fix Body Count when mouse is enabled) */
|
||||
int retval = 0x00;
|
||||
@ -106,7 +108,7 @@ unsigned int menacer_read()
|
||||
}
|
||||
|
||||
/* Konami Justifier specific */
|
||||
unsigned int justifier_read()
|
||||
uint32 justifier_read()
|
||||
{
|
||||
/* TL & TR pins should always return 1 (write only) */
|
||||
/* LEFT & RIGHT pins should always return 0 (needed during gun detection) */
|
||||
@ -152,7 +154,7 @@ static inline void mouse_reset()
|
||||
mouse.Port = (input.system[0] == SYSTEM_MOUSE) ? 0 : 4;
|
||||
}
|
||||
|
||||
void mouse_write(unsigned int data)
|
||||
void mouse_write(uint32 data)
|
||||
{
|
||||
if (mouse.Counter == 0)
|
||||
{
|
||||
@ -182,7 +184,7 @@ void mouse_write(unsigned int data)
|
||||
mouse.State = data;
|
||||
}
|
||||
|
||||
unsigned int mouse_read()
|
||||
uint32 mouse_read()
|
||||
{
|
||||
int temp = 0x00;
|
||||
|
||||
@ -263,24 +265,24 @@ struct pad
|
||||
uint8 Delay;
|
||||
} gamepad[MAX_DEVICES];
|
||||
|
||||
static inline void gamepad_raz(unsigned int i)
|
||||
static inline void gamepad_raz(uint32 i)
|
||||
{
|
||||
gamepad[i].Counter = 0;
|
||||
gamepad[i].Delay = 0;
|
||||
}
|
||||
|
||||
static inline void gamepad_reset(unsigned int i)
|
||||
static inline void gamepad_reset(uint32 i)
|
||||
{
|
||||
gamepad[i].State = 0x40;
|
||||
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
|
||||
}
|
||||
|
||||
static inline void gamepad_update(unsigned int i)
|
||||
static inline void gamepad_update(uint32 i)
|
||||
{
|
||||
if (gamepad[i].Delay++ > 25) gamepad_raz(i);
|
||||
}
|
||||
|
||||
static inline unsigned int gamepad_read(unsigned int i)
|
||||
static inline uint32 gamepad_read(uint32 i)
|
||||
{
|
||||
int control;
|
||||
int retval = 0x7F;
|
||||
@ -365,7 +367,7 @@ static inline unsigned int gamepad_read(unsigned int i)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void gamepad_write(unsigned int i, unsigned int data)
|
||||
static inline void gamepad_write(uint32 i, uint32 data)
|
||||
{
|
||||
if (input.dev[i] == DEVICE_6BUTTON)
|
||||
{
|
||||
@ -392,7 +394,7 @@ struct teamplayer
|
||||
uint8 Table[12];
|
||||
} teamplayer[2];
|
||||
|
||||
static inline void teamplayer_reset(unsigned int port)
|
||||
static inline void teamplayer_reset(uint32 port)
|
||||
{
|
||||
int i;
|
||||
int index = 0;
|
||||
@ -433,7 +435,7 @@ static inline void teamplayer_reset(unsigned int port)
|
||||
2/ START,A,C,B buttons
|
||||
3/ MODE, X,Y,Z buttons (6Button only !)
|
||||
*/
|
||||
static inline unsigned int teamplayer_read_device(unsigned int port, unsigned int index)
|
||||
static inline uint32 teamplayer_read_device(uint32 port, uint32 index)
|
||||
{
|
||||
int retval = 0x7F;
|
||||
int pad_input = teamplayer[port].Table[index] & 0x03;
|
||||
@ -469,7 +471,7 @@ static inline unsigned int teamplayer_read_device(unsigned int port, unsigned in
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline unsigned int teamplayer_read(unsigned int port)
|
||||
static inline uint32 teamplayer_read(uint32 port)
|
||||
{
|
||||
int retval = 0x7F;
|
||||
int padnum;
|
||||
@ -509,7 +511,7 @@ static inline unsigned int teamplayer_read(unsigned int port)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void teamplayer_write(unsigned int port, unsigned int data)
|
||||
static inline void teamplayer_write(uint32 port, uint32 data)
|
||||
{
|
||||
int old_state = teamplayer[port].State;
|
||||
teamplayer[port].State = (data & io_reg[port+4]) | (teamplayer[port].State & ~io_reg[port+4]);
|
||||
@ -521,13 +523,13 @@ static inline void teamplayer_write(unsigned int port, unsigned int data)
|
||||
* 4WAYPLAY adapter
|
||||
*
|
||||
*****************************************************************************/
|
||||
static inline void wayplay_write(unsigned int port, unsigned int data)
|
||||
static inline void wayplay_write(uint32 port, uint32 data)
|
||||
{
|
||||
if (port == 0) gamepad_write(input.current, data);
|
||||
else input.current = (data >> 4) & 0x07;
|
||||
}
|
||||
|
||||
static inline unsigned int wayplay_read(unsigned int port)
|
||||
static inline uint32 wayplay_read(uint32 port)
|
||||
{
|
||||
if (port == 1) return 0x7F;
|
||||
if (input.current >= 4) return 0x70; /* multitap detection (TH2 = 1) */
|
||||
@ -539,72 +541,72 @@ static inline unsigned int wayplay_read(unsigned int port)
|
||||
* I/O wrappers
|
||||
*
|
||||
*****************************************************************************/
|
||||
unsigned int gamepad_1_read (void)
|
||||
uint32 gamepad_1_read (void)
|
||||
{
|
||||
return gamepad_read(0);
|
||||
}
|
||||
|
||||
unsigned int gamepad_2_read (void)
|
||||
uint32 gamepad_2_read (void)
|
||||
{
|
||||
return gamepad_read(4);
|
||||
}
|
||||
|
||||
void gamepad_1_write (unsigned int data)
|
||||
void gamepad_1_write (uint32 data)
|
||||
{
|
||||
gamepad_write(0, data);
|
||||
}
|
||||
|
||||
void gamepad_2_write (unsigned int data)
|
||||
void gamepad_2_write (uint32 data)
|
||||
{
|
||||
gamepad_write(4, data);
|
||||
}
|
||||
|
||||
unsigned int wayplay_1_read (void)
|
||||
uint32 wayplay_1_read (void)
|
||||
{
|
||||
return wayplay_read(0);
|
||||
}
|
||||
|
||||
unsigned int wayplay_2_read (void)
|
||||
uint32 wayplay_2_read (void)
|
||||
{
|
||||
return wayplay_read(1);
|
||||
}
|
||||
|
||||
void wayplay_1_write (unsigned int data)
|
||||
void wayplay_1_write (uint32 data)
|
||||
{
|
||||
wayplay_write(0, data);
|
||||
}
|
||||
|
||||
void wayplay_2_write (unsigned int data)
|
||||
void wayplay_2_write (uint32 data)
|
||||
{
|
||||
wayplay_write(1, data);
|
||||
}
|
||||
|
||||
unsigned int teamplayer_1_read (void)
|
||||
uint32 teamplayer_1_read (void)
|
||||
{
|
||||
return teamplayer_read(0);
|
||||
}
|
||||
|
||||
unsigned int teamplayer_2_read (void)
|
||||
uint32 teamplayer_2_read (void)
|
||||
{
|
||||
return teamplayer_read(1);
|
||||
}
|
||||
|
||||
void teamplayer_1_write (unsigned int data)
|
||||
void teamplayer_1_write (uint32 data)
|
||||
{
|
||||
teamplayer_write(0, data);
|
||||
}
|
||||
|
||||
void teamplayer_2_write (unsigned int data)
|
||||
void teamplayer_2_write (uint32 data)
|
||||
{
|
||||
teamplayer_write(1, data);
|
||||
}
|
||||
|
||||
unsigned int jcart_read(void)
|
||||
uint32 jcart_read(uint32 address)
|
||||
{
|
||||
return (gamepad_read(5) | ((gamepad_read(6)&0x3f) << 8)); /* fixes Micro Machines 2 (is it correct ?) */
|
||||
}
|
||||
|
||||
void jcart_write(unsigned int data)
|
||||
void jcart_write(uint32 address, uint32 data)
|
||||
{
|
||||
gamepad_write(5, (data&1) << 6);
|
||||
gamepad_write(6, (data&1) << 6);
|
||||
|
@ -90,23 +90,23 @@ extern void input_update(void);
|
||||
extern void input_raz(void);
|
||||
|
||||
/* Peripherals specific */
|
||||
extern void mouse_write(unsigned int data);
|
||||
extern unsigned int mouse_read(void);
|
||||
extern unsigned int menacer_read (void);
|
||||
extern unsigned int justifier_read (void);
|
||||
extern unsigned int gamepad_1_read (void);
|
||||
extern unsigned int gamepad_2_read (void);
|
||||
extern void gamepad_1_write (unsigned int data);
|
||||
extern void gamepad_2_write (unsigned int data);
|
||||
extern unsigned int wayplay_1_read (void);
|
||||
extern unsigned int wayplay_2_read (void);
|
||||
extern void wayplay_1_write (unsigned int data);
|
||||
extern void wayplay_2_write (unsigned int data);
|
||||
extern unsigned int teamplayer_1_read (void);
|
||||
extern unsigned int teamplayer_2_read (void);
|
||||
extern void teamplayer_1_write (unsigned int data);
|
||||
extern void teamplayer_2_write (unsigned int data);
|
||||
extern unsigned int jcart_read(void);
|
||||
extern void jcart_write(unsigned int data);
|
||||
extern void mouse_write(uint32 data);
|
||||
extern uint32 mouse_read(void);
|
||||
extern uint32 menacer_read (void);
|
||||
extern uint32 justifier_read (void);
|
||||
extern uint32 gamepad_1_read (void);
|
||||
extern uint32 gamepad_2_read (void);
|
||||
extern void gamepad_1_write (uint32 data);
|
||||
extern void gamepad_2_write (uint32 data);
|
||||
extern uint32 wayplay_1_read (void);
|
||||
extern uint32 wayplay_2_read (void);
|
||||
extern void wayplay_1_write (uint32 data);
|
||||
extern void wayplay_2_write (uint32 data);
|
||||
extern uint32 teamplayer_1_read (void);
|
||||
extern uint32 teamplayer_2_read (void);
|
||||
extern void teamplayer_1_write (uint32 data);
|
||||
extern void teamplayer_2_write (uint32 data);
|
||||
extern uint32 jcart_read(uint32 address);
|
||||
extern void jcart_write(uint32 address, uint32 data);
|
||||
|
||||
#endif
|
||||
|
159
source/genesis.c
159
source/genesis.c
@ -24,7 +24,7 @@
|
||||
#include "shared.h"
|
||||
|
||||
uint8 *cart_rom; /* cart_rom NEED to be previously dynamically allocated */
|
||||
uint8 bios_rom[0x800];
|
||||
uint8 bios_rom[0x10000];
|
||||
uint8 work_ram[0x10000]; /* 68K work RAM */
|
||||
uint8 zram[0x2000]; /* Z80 work RAM */
|
||||
uint8 zbusreq; /* /BUSREQ from Z80 */
|
||||
@ -34,9 +34,8 @@ uint8 zirq; /* /IRQ to Z80 */
|
||||
uint32 zbank; /* Address of Z80 bank window */
|
||||
uint8 gen_running;
|
||||
uint32 genromsize;
|
||||
uint32 rom_size;
|
||||
int32 resetline;
|
||||
uint8 *rom_readmap[8];
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown functions */
|
||||
@ -55,86 +54,115 @@ void gen_init (void)
|
||||
m68k_init();
|
||||
z80_init(0,0,0,z80_irq_callback);
|
||||
|
||||
/* default 68000 mapping */
|
||||
for (i=16; i<24; i++)
|
||||
/* initialize 68k default address space */
|
||||
for (i=0x0; i<0x100; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = ILLEGAL;
|
||||
m68k_readmap_16[i] = ILLEGAL;
|
||||
m68k_writemap_8[i] = ILLEGAL;
|
||||
m68k_writemap_16[i] = ILLEGAL;
|
||||
m68k_memory_map[i].base = work_ram;
|
||||
m68k_memory_map[i].read8 = NULL;
|
||||
m68k_memory_map[i].read16 = NULL;
|
||||
m68k_memory_map[i].write8 = NULL;
|
||||
m68k_memory_map[i].write16 = NULL;
|
||||
zbank_memory_map[i].read = NULL;
|
||||
zbank_memory_map[i].write = NULL;
|
||||
}
|
||||
|
||||
/* initialize 68k memory map */
|
||||
for (i=0x80; i<0xe0; i++)
|
||||
{
|
||||
/* illegal area */
|
||||
m68k_memory_map[i].read8 = m68k_lockup_r_8;
|
||||
m68k_memory_map[i].read16 = m68k_lockup_r_16;
|
||||
m68k_memory_map[i].write8 = m68k_lockup_w_8;
|
||||
m68k_memory_map[i].write16 = m68k_lockup_w_16;
|
||||
zbank_memory_map[i].read = zbank_lockup_r;
|
||||
zbank_memory_map[i].write = zbank_lockup_w;
|
||||
}
|
||||
|
||||
/* Z80, I/O, CONTROL */
|
||||
m68k_readmap_8[20] = SYSTEM_IO;
|
||||
m68k_readmap_16[20] = SYSTEM_IO;
|
||||
m68k_writemap_8[20] = SYSTEM_IO;
|
||||
m68k_writemap_16[20] = SYSTEM_IO;
|
||||
/* Z80 bus */
|
||||
m68k_memory_map[0xa0].read8 = z80_read_byte;
|
||||
m68k_memory_map[0xa0].read16 = z80_read_word;
|
||||
m68k_memory_map[0xa0].write8 = z80_write_byte;
|
||||
m68k_memory_map[0xa0].write16 = z80_write_word;
|
||||
zbank_memory_map[0xa0].read = zbank_lockup_r;
|
||||
zbank_memory_map[0xa0].write = zbank_lockup_w;
|
||||
|
||||
/* I/O & Control registers */
|
||||
m68k_memory_map[0xa1].read8 = ctrl_io_read_byte;
|
||||
m68k_memory_map[0xa1].read16 = ctrl_io_read_word;
|
||||
m68k_memory_map[0xa1].write8 = ctrl_io_write_byte;
|
||||
m68k_memory_map[0xa1].write16 = ctrl_io_write_word;
|
||||
zbank_memory_map[0xa1].read = zbank_read_ctrl_io;
|
||||
zbank_memory_map[0xa1].write = zbank_write_ctrl_io;
|
||||
|
||||
/* SEGA PICO */
|
||||
if (system_hw == SYSTEM_PICO)
|
||||
{
|
||||
m68k_readmap_8[16] = PICO_HW;
|
||||
m68k_readmap_16[16] = PICO_HW;
|
||||
m68k_writemap_8[16] = PICO_HW;
|
||||
m68k_writemap_16[16] = PICO_HW;
|
||||
m68k_memory_map[0x80].read8 = pico_read_byte;
|
||||
m68k_memory_map[0x80].read16 = pico_read_word;
|
||||
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
|
||||
|
||||
/* Notaz: there is no IO CONTROL area (Z80/YM2612/IO) */
|
||||
m68k_readmap_8[20] = UNUSED;
|
||||
m68k_readmap_16[20] = UNUSED;
|
||||
m68k_writemap_8[20] = UNUSED;
|
||||
m68k_writemap_16[20] = UNUSED;
|
||||
/* there is no I/O area (Notaz) */
|
||||
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
|
||||
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
|
||||
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
|
||||
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
|
||||
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
|
||||
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
|
||||
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
|
||||
}
|
||||
|
||||
/* VDP */
|
||||
for (i=24; i<28; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = VDP;
|
||||
m68k_readmap_16[i] = VDP;
|
||||
m68k_writemap_8[i] = VDP;
|
||||
m68k_writemap_16[i] = VDP;
|
||||
}
|
||||
|
||||
/* WRAM */
|
||||
for (i=28; i<32; i++)
|
||||
{
|
||||
m68k_readmap_8[i] = WRAM;
|
||||
m68k_readmap_16[i] = WRAM;
|
||||
m68k_writemap_8[i] = WRAM;
|
||||
m68k_writemap_16[i] = WRAM;
|
||||
}
|
||||
m68k_memory_map[0xc0].read8 = vdp_read_byte;
|
||||
m68k_memory_map[0xc0].read16 = vdp_read_word;
|
||||
m68k_memory_map[0xc0].write8 = vdp_write_byte;
|
||||
m68k_memory_map[0xc0].write16 = vdp_write_word;
|
||||
m68k_memory_map[0xc8].read8 = vdp_read_byte;
|
||||
m68k_memory_map[0xc8].read16 = vdp_read_word;
|
||||
m68k_memory_map[0xc8].write8 = vdp_write_byte;
|
||||
m68k_memory_map[0xc8].write16 = vdp_write_word;
|
||||
m68k_memory_map[0xd0].read8 = vdp_read_byte;
|
||||
m68k_memory_map[0xd0].read16 = vdp_read_word;
|
||||
m68k_memory_map[0xd0].write8 = vdp_write_byte;
|
||||
m68k_memory_map[0xd0].write16 = vdp_write_word;
|
||||
m68k_memory_map[0xd8].read8 = vdp_read_byte;
|
||||
m68k_memory_map[0xd8].read16 = vdp_read_word;
|
||||
m68k_memory_map[0xd8].write8 = vdp_write_byte;
|
||||
m68k_memory_map[0xd8].write16 = vdp_write_word;
|
||||
zbank_memory_map[0xc0].read = zbank_read_vdp;
|
||||
zbank_memory_map[0xc0].write = zbank_write_vdp;
|
||||
zbank_memory_map[0xc8].read = zbank_read_vdp;
|
||||
zbank_memory_map[0xc8].write = zbank_write_vdp;
|
||||
zbank_memory_map[0xd0].read = zbank_read_vdp;
|
||||
zbank_memory_map[0xd0].write = zbank_write_vdp;
|
||||
zbank_memory_map[0xd8].read = zbank_read_vdp;
|
||||
zbank_memory_map[0xd8].write = zbank_write_vdp;
|
||||
}
|
||||
|
||||
void gen_reset (unsigned int hard_reset)
|
||||
void gen_reset (uint32 hard_reset)
|
||||
{
|
||||
if (hard_reset)
|
||||
{
|
||||
/* Clear RAM */
|
||||
memset (work_ram, 0, sizeof (work_ram));
|
||||
memset (zram, 0, sizeof (zram));
|
||||
memset (work_ram, 0x00, sizeof (work_ram));
|
||||
memset (zram, 0x00, sizeof (zram));
|
||||
|
||||
/* Reset ROM mapping */
|
||||
/* TMSS BIOS */
|
||||
if (config.bios_enabled == 3)
|
||||
{
|
||||
rom_readmap[0] = &bios_rom[0];
|
||||
rom_size = 0x800;
|
||||
m68k_memory_map[0].base = bios_rom;
|
||||
}
|
||||
else
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[0];
|
||||
rom_size = genromsize;
|
||||
}
|
||||
|
||||
uint8 i;
|
||||
for (i=1; i<8; i++) rom_readmap[i] = &cart_rom[i << 19];
|
||||
}
|
||||
|
||||
gen_running = 1;
|
||||
resetline = -1;
|
||||
|
||||
zreset = 0; /* Z80 is reset */
|
||||
zbusreq = 0; /* Z80 has control of the Z bus */
|
||||
zbusack = 1; /* Z80 is busy using the Z bus */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
zbank = 0; /* Assume default bank is 000000-007FFF */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
resetline = -1;
|
||||
|
||||
/* Reset CPUs */
|
||||
m68k_pulse_reset ();
|
||||
@ -155,14 +183,9 @@ void gen_shutdown (void)
|
||||
/*-----------------------------------------------------------------------
|
||||
Bus controller chip functions
|
||||
-----------------------------------------------------------------------*/
|
||||
unsigned int gen_busack_r (void)
|
||||
void gen_busreq_w (uint32 state)
|
||||
{
|
||||
return zbusack;
|
||||
}
|
||||
|
||||
void gen_busreq_w (unsigned int state)
|
||||
{
|
||||
int z80_cycles_to_run;
|
||||
uint32 z80_cycles_to_run;
|
||||
|
||||
input_raz (); /* from Gens */
|
||||
|
||||
@ -175,7 +198,8 @@ void gen_busreq_w (unsigned int state)
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
z80_run(z80_cycles_to_run);
|
||||
current_z80 = z80_cycles_to_run - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -195,9 +219,9 @@ void gen_busreq_w (unsigned int state)
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
}
|
||||
|
||||
void gen_reset_w (unsigned int state)
|
||||
void gen_reset_w (uint32 state)
|
||||
{
|
||||
int z80_cycles_to_run;
|
||||
uint32 z80_cycles_to_run;
|
||||
|
||||
if (state)
|
||||
{
|
||||
@ -220,7 +244,8 @@ void gen_reset_w (unsigned int state)
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
z80_run(z80_cycles_to_run);
|
||||
current_z80 = z80_cycles_to_run - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
|
||||
/* Reset Z80 & YM2612 */
|
||||
@ -232,7 +257,7 @@ void gen_reset_w (unsigned int state)
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
}
|
||||
|
||||
void gen_bank_w (unsigned int state)
|
||||
void gen_bank_w (uint32 state)
|
||||
{
|
||||
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
/* Global variables */
|
||||
extern uint8 *cart_rom;
|
||||
extern uint8 bios_rom[0x800];
|
||||
extern uint8 bios_rom[0x10000];
|
||||
extern uint8 work_ram[0x10000];
|
||||
extern uint8 zram[0x2000];
|
||||
extern uint8 zbusreq;
|
||||
@ -36,18 +36,15 @@ extern uint8 zirq;
|
||||
extern uint32 zbank;
|
||||
extern uint8 gen_running;
|
||||
extern uint32 genromsize;
|
||||
extern uint32 rom_size;
|
||||
extern int32 resetline;
|
||||
extern uint8 *rom_readmap[8];
|
||||
|
||||
/* Function prototypes */
|
||||
extern void gen_init(void);
|
||||
extern void gen_reset(unsigned int hard_reset);
|
||||
extern void gen_reset(uint32 hard_reset);
|
||||
extern void gen_shutdown(void);
|
||||
extern unsigned int gen_busack_r(void);
|
||||
extern void gen_busreq_w(unsigned int state);
|
||||
extern void gen_reset_w(unsigned int state);
|
||||
extern void gen_bank_w(unsigned int state);
|
||||
extern void gen_busreq_w(uint32 state);
|
||||
extern void gen_reset_w(uint32 state);
|
||||
extern void gen_bank_w(uint32 state);
|
||||
extern int z80_irq_callback(int param);
|
||||
extern void set_softreset(void);
|
||||
|
||||
|
@ -153,15 +153,6 @@ unsigned int m68k_read_memory_8(unsigned int address);
|
||||
unsigned int m68k_read_memory_16(unsigned int address);
|
||||
unsigned int m68k_read_memory_32(unsigned int address);
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
unsigned int m68k_read_immediate_16(unsigned int address);
|
||||
unsigned int m68k_read_immediate_32(unsigned int address);
|
||||
|
||||
/* Read data relative to the PC */
|
||||
unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||
unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||
|
||||
/* Memory access for the disassembler */
|
||||
unsigned int m68k_read_disassembler_8 (unsigned int address);
|
||||
unsigned int m68k_read_disassembler_16 (unsigned int address);
|
||||
@ -172,6 +163,30 @@ void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *base;
|
||||
unsigned int (*read8)(unsigned int address);
|
||||
unsigned int (*read16)(unsigned int address);
|
||||
void (*write8)(unsigned int address, unsigned int data);
|
||||
void (*write16)(unsigned int address, unsigned int data);
|
||||
} _m68k_memory_map;
|
||||
|
||||
_m68k_memory_map m68k_memory_map[256];
|
||||
|
||||
|
||||
/* Read data immediately following the PC */
|
||||
#define m68k_read_immediate_16(address) *(uint16 *)(m68k_memory_map[((address)>>16)&0xff].base + ((address) & 0xffff))
|
||||
#define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2))
|
||||
|
||||
/* Read data relative to the PC */
|
||||
#define m68k_read_pcrelative_8(address) READ_BYTE(m68k_memory_map[((address)>>16)&0xff].base, (address) & 0xffff)
|
||||
#define m68k_read_pcrelative_16(address) m68k_read_immediate_16(address)
|
||||
#define m68k_read_pcrelative_32(address) m68k_read_immediate_32(address)
|
||||
|
||||
/* Special call to simulate undocumented 68k behavior when move.l with a
|
||||
* predecrement destination mode is executed.
|
||||
* To simulate real 68k behavior, first write the high word to
|
||||
@ -302,7 +317,8 @@ void m68k_init(void);
|
||||
void m68k_pulse_reset(void);
|
||||
|
||||
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||
int m68k_execute(int num_cycles);
|
||||
//int m68k_execute(int num_cycles);
|
||||
void m68k_run (int cyc);
|
||||
|
||||
/* These functions let you read/write/modify the number of cycles left to run
|
||||
* while m68k_execute() is running.
|
||||
@ -318,7 +334,7 @@ void m68k_end_timeslice(void); /* End timeslice now */
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
* Setting IRQ to 0 will clear an interrupt request.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level);
|
||||
//void m68k_set_irq(unsigned int int_level);
|
||||
|
||||
|
||||
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||
|
@ -67,7 +67,7 @@
|
||||
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||
*/
|
||||
#define M68K_SEPARATE_READS OPT_OFF
|
||||
#define M68K_SEPARATE_READS OPT_ON
|
||||
|
||||
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||
* predecrement destination EA mode instead of m68k_write_32().
|
||||
@ -157,7 +157,7 @@
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||
|
||||
|
||||
/* Turn ON to enable logging of illegal instruction calls.
|
||||
|
@ -783,7 +783,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
|
||||
/* Execute some instructions until we use up num_cycles clock cycles */
|
||||
/* ASG: removed per-instruction interrupt checks */
|
||||
int m68k_execute(int num_cycles)
|
||||
INLINE int m68k_execute(int num_cycles)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(!CPU_STOPPED)
|
||||
@ -841,6 +841,50 @@ int m68k_execute(int num_cycles)
|
||||
return num_cycles;
|
||||
}
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
INLINE void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
uint old_level = CPU_INT_LEVEL;
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
|
||||
/* A transition from < 7 to 7 always interrupts (NMI) */
|
||||
/* Note: Level 7 can also level trigger like a normal IRQ */
|
||||
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
|
||||
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
|
||||
else
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
extern uint16 irq_status;
|
||||
extern uint32 count_m68k;
|
||||
|
||||
void m68k_run (int cyc)
|
||||
{
|
||||
int temp;
|
||||
while (count_m68k < cyc)
|
||||
{
|
||||
/* check interrupt updates */
|
||||
if (irq_status & 0x10)
|
||||
{
|
||||
irq_status &= ~0x10;
|
||||
|
||||
/* hardware latency */
|
||||
temp = irq_status >> 8;
|
||||
if (temp) count_m68k += m68k_execute(temp);
|
||||
|
||||
/* interrupt level */
|
||||
temp = irq_status & 6;
|
||||
if (temp == 6) irq_status |= 0x20;
|
||||
m68k_set_irq(temp);
|
||||
}
|
||||
|
||||
/* execute a single instruction */
|
||||
count_m68k += m68k_execute(1);
|
||||
}
|
||||
}
|
||||
|
||||
int m68k_cycles_run(void)
|
||||
{
|
||||
@ -866,24 +910,6 @@ void m68k_end_timeslice(void)
|
||||
SET_CYCLES(0);
|
||||
}
|
||||
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
uint old_level = CPU_INT_LEVEL;
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
|
||||
/* A transition from < 7 to 7 always interrupts (NMI) */
|
||||
/* Note: Level 7 can also level trigger like a normal IRQ */
|
||||
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
|
||||
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
|
||||
else
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
void m68k_init(void)
|
||||
{
|
||||
static uint emulation_initialized = 0;
|
||||
|
@ -1116,37 +1116,62 @@ INLINE uint m68ki_read_imm_32(void)
|
||||
INLINE uint m68ki_read_8_fc(uint address, uint fc)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
return m68k_read_memory_8(ADDRESS_68K(address));
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
|
||||
if (temp->read8) return (*temp->read8)(address);
|
||||
else return READ_BYTE(temp->base, (address) & 0xffff);
|
||||
}
|
||||
INLINE uint m68ki_read_16_fc(uint address, uint fc)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
return m68k_read_memory_16(ADDRESS_68K(address));
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->read16) return (*temp->read16)(address);
|
||||
else return *(uint16 *)(temp->base + ((address) & 0xffff));
|
||||
}
|
||||
INLINE uint m68ki_read_32_fc(uint address, uint fc)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
return m68k_read_memory_32(ADDRESS_68K(address));
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->read16) return ((*temp->read16)(address) << 16) | ((*temp->read16)(address + 2));
|
||||
else return m68k_read_immediate_32(address);
|
||||
}
|
||||
|
||||
INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_8(ADDRESS_68K(address), value);
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write8) (*temp->write8)(address,value);
|
||||
else WRITE_BYTE(temp->base, (address) & 0xffff, value);
|
||||
}
|
||||
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_16(ADDRESS_68K(address), value);
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write16) (*temp->write16)(address,value);
|
||||
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value;
|
||||
}
|
||||
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68k_write_memory_32(ADDRESS_68K(address), value);
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write16)
|
||||
{
|
||||
(*temp->write16)(address,value>>16);
|
||||
(*temp->write16)(address+2,value&0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
*(uint16 *)(temp->base + ((address) & 0xffff)) = value >> 16;
|
||||
temp = &m68k_memory_map[((address + 2)>>16)&0xff];
|
||||
*(uint16 *)(temp->base + ((address + 2) & 0xffff)) = value;
|
||||
}
|
||||
}
|
||||
|
||||
#if M68K_SIMULATE_PD_WRITES
|
||||
|
1117
source/mem68k.c
1117
source/mem68k.c
File diff suppressed because it is too large
Load Diff
@ -24,28 +24,48 @@
|
||||
#ifndef _MEM68K_H_
|
||||
#define _MEM68K_H_
|
||||
|
||||
enum {
|
||||
SRAM,
|
||||
EEPROM,
|
||||
J_CART,
|
||||
SVP_DRAM,
|
||||
SVP_CELL,
|
||||
CART_HW,
|
||||
REALTEC_ROM,
|
||||
VDP,
|
||||
SYSTEM_IO,
|
||||
UNUSED,
|
||||
ILLEGAL,
|
||||
WRAM,
|
||||
UMK3_HACK,
|
||||
PICO_HW,
|
||||
ROM
|
||||
};
|
||||
/* unused areas */
|
||||
extern uint32 m68k_read_bus_8(uint32 address);
|
||||
extern uint32 m68k_read_bus_16(uint32 address);
|
||||
extern void m68k_unused_8_w (uint32 address, uint32 data);
|
||||
extern void m68k_unused_16_w (uint32 address, uint32 data);
|
||||
|
||||
extern uint8 m68k_readmap_8[32];
|
||||
extern uint8 m68k_readmap_16[32];
|
||||
extern uint8 m68k_writemap_8[32];
|
||||
extern uint8 m68k_writemap_16[32];
|
||||
/* illegal areas */
|
||||
extern uint32 m68k_lockup_r_8 (uint32 address);
|
||||
extern uint32 m68k_lockup_r_16 (uint32 address);
|
||||
extern void m68k_lockup_w_8 (uint32 address, uint32 data);
|
||||
extern void m68k_lockup_w_16 (uint32 address, uint32 data);
|
||||
|
||||
/* eeprom */
|
||||
extern uint32 eeprom_read_byte(uint32 address);
|
||||
extern uint32 eeprom_read_word(uint32 address);
|
||||
extern void eeprom_write_byte(uint32 address, uint32 data);
|
||||
extern void eeprom_write_word(uint32 address, uint32 data);
|
||||
|
||||
/* Z80 bus */
|
||||
extern uint32 z80_read_byte(uint32 address);
|
||||
extern uint32 z80_read_word(uint32 address);
|
||||
extern void z80_write_byte(uint32 address, uint32 data);
|
||||
extern void z80_write_word(uint32 address, uint32 data);
|
||||
|
||||
/* I/O & Control registers */
|
||||
extern uint32 ctrl_io_read_byte(uint32 address);
|
||||
extern uint32 ctrl_io_read_word(uint32 address);
|
||||
extern void ctrl_io_write_byte(uint32 address, uint32 data);
|
||||
extern void ctrl_io_write_word(uint32 address, uint32 data);
|
||||
|
||||
/* VDP */
|
||||
extern uint32 vdp_read_byte(uint32 address);
|
||||
extern uint32 vdp_read_word(uint32 address);
|
||||
extern void vdp_write_byte(uint32 address, uint32 data);
|
||||
extern void vdp_write_word(uint32 address, uint32 data);
|
||||
|
||||
/* PICO */
|
||||
extern uint32 pico_read_byte(uint32 address);
|
||||
extern uint32 pico_read_word(uint32 address);
|
||||
|
||||
uint8 m68k_readmap[256];
|
||||
uint8 m68k_writemap[256];
|
||||
uint32 pico_current;
|
||||
|
||||
#endif /* _MEM68K_H_ */
|
||||
|
313
source/membnk.c
313
source/membnk.c
@ -26,14 +26,8 @@
|
||||
Handlers for access to unused addresses and those which make the
|
||||
machine lock up.
|
||||
*/
|
||||
static inline void z80bank_unused_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank unused write %06X = %02X\n", address, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int z80bank_unused_r(unsigned int address)
|
||||
uint32 zbank_unused_r(uint32 address)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank unused read %06X\n", address);
|
||||
@ -41,15 +35,14 @@ static inline unsigned int z80bank_unused_r(unsigned int address)
|
||||
return (address & 1) ? 0x00 : 0xFF;
|
||||
}
|
||||
|
||||
static inline void z80bank_lockup_w(unsigned int address, unsigned int data)
|
||||
void zbank_unused_w(uint32 address, uint32 data)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank lockup write %06X = %02X\n", address, data);
|
||||
error("Z80 bank unused write %06X = %02X\n", address, data);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
}
|
||||
|
||||
static inline unsigned int z80bank_lockup_r(unsigned int address)
|
||||
uint32 zbank_lockup_r(uint32 address)
|
||||
{
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank lockup read %06X\n", address);
|
||||
@ -58,132 +51,84 @@ static inline unsigned int z80bank_lockup_r(unsigned int address)
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
Z80 memory handlers
|
||||
*/
|
||||
void z80_write_banked_memory (unsigned int address, unsigned int data)
|
||||
void zbank_lockup_w(uint32 address, uint32 data)
|
||||
{
|
||||
int offset = address >> 19;
|
||||
#ifdef LOGERROR
|
||||
error("Z80 bank lockup write %06X = %02X\n", address, data);
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
}
|
||||
|
||||
switch (m68k_writemap_8[offset])
|
||||
{
|
||||
case VDP:
|
||||
/* Valid VDP addresses */
|
||||
if (((address >> 16) & 0x07) == 0)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
/* I/O & Control registers */
|
||||
|
||||
uint32 zbank_read_ctrl_io(uint32 address)
|
||||
{
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* Data port */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
vdp_data_w(data << 8 | data);
|
||||
return;
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) return zbank_unused_r(address);
|
||||
else return (io_read((address >> 1) & 0x0f));
|
||||
|
||||
case 0x04: /* Control port */
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
case 0x11: /* BUSACK */
|
||||
if (address & 1) return zbank_unused_r(address);
|
||||
else return (0xfe | zbusack);
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* PSG */
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(0, data);
|
||||
return;
|
||||
case 0x30: /* TIME */
|
||||
if (cart_hw.time_r) return cart_hw.time_r(address);
|
||||
else return zbank_unused_r(address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x12: /* RESET */
|
||||
case 0x20: /* MEGA-CD */
|
||||
case 0x40: /* TMSS */
|
||||
case 0x41: /* BOOTROM */
|
||||
case 0x44: /* RADICA */
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
return zbank_unused_r(address);
|
||||
|
||||
case 0x1c: /* Test register */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
default: /* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
|
||||
case SYSTEM_IO:
|
||||
{
|
||||
unsigned int base = address >> 8;
|
||||
|
||||
/* Z80 (access prohibited) */
|
||||
if (base <= 0xa0ff)
|
||||
{
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
default: /* Invalid address */
|
||||
return zbank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
|
||||
/* CONTROL registers */
|
||||
if (base <= 0xa1ff)
|
||||
void zbank_write_ctrl_io(uint32 address, uint32 data)
|
||||
{
|
||||
switch (base & 0xff)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip (only gets /LWR) */
|
||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
case 0x00: /* I/O chip */
|
||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||
else zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
if (address & 1) z80bank_unused_w(address, data);
|
||||
if (address & 1) zbank_unused_w(address, data);
|
||||
else gen_busreq_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
if (address & 1) z80bank_unused_w(address, data);
|
||||
if (address & 1) zbank_unused_w(address, data);
|
||||
else gen_reset_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart_hw.time_w) return cart_hw.time_w(address, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
if (cart_hw.time_w) cart_hw.time_w(address, data);
|
||||
else zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x41: /* BOOTROM */
|
||||
if (address & 1)
|
||||
{
|
||||
if (data & 1)
|
||||
{
|
||||
rom_readmap[0] = &cart_rom[0];
|
||||
rom_size = genromsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
rom_readmap[0] = &bios_rom[0];
|
||||
rom_size = 0x800;
|
||||
}
|
||||
m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom;
|
||||
|
||||
/* autodetect BIOS ROM file */
|
||||
if (!(config.bios_enabled & 2))
|
||||
{
|
||||
config.bios_enabled |= 2;
|
||||
memcpy(bios_rom, cart_rom, 0x800);
|
||||
memset(cart_rom, 0, 0x500000);
|
||||
memset(cart_rom, 0, genromsize);
|
||||
}
|
||||
}
|
||||
else z80bank_unused_w (address, data);
|
||||
else zbank_unused_w (address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
@ -191,177 +136,81 @@ void z80_write_banked_memory (unsigned int address, unsigned int data)
|
||||
case 0x40: /* TMSS */
|
||||
case 0x44: /* RADICA */
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
z80bank_unused_w(address, data);
|
||||
zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
zbank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
|
||||
case ROM:
|
||||
WRITE_BYTE(rom_readmap[offset], address & 0x7ffff, data);
|
||||
return;
|
||||
/* VDP */
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) WRITE_BYTE(sram.sram, address - sram.start, data);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case EEPROM:
|
||||
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, data, 0);
|
||||
else z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case CART_HW:
|
||||
cart_hw.regs_w(address, data);
|
||||
return;
|
||||
|
||||
case UNUSED:
|
||||
z80bank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case ILLEGAL:
|
||||
z80bank_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
default: /* WRAM */
|
||||
/* Mamono Hunter Youko - Dai 7 no Keishou need this */
|
||||
WRITE_BYTE(work_ram, address & 0xffff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int z80_read_banked_memory(unsigned int address)
|
||||
{
|
||||
int offset = address >> 19;
|
||||
|
||||
switch (m68k_readmap_8[offset])
|
||||
{
|
||||
case WRAM: /* NOTE: can't be read on some Genesis models (!), only japanese ones ??? */
|
||||
return READ_BYTE(work_ram, address);
|
||||
|
||||
case SYSTEM_IO:
|
||||
{
|
||||
unsigned int base = address >> 8;
|
||||
|
||||
/* Z80 (access prohibited) */
|
||||
if (base <= 0xa0ff) return z80bank_lockup_r(address);
|
||||
|
||||
/* I/O & CONTROL registers */
|
||||
if (base <= 0xa1ff)
|
||||
{
|
||||
switch (base & 0xff)
|
||||
uint32 zbank_read_vdp(uint32 address)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) return z80bank_unused_r(address);
|
||||
return (io_read((address >> 1) & 0x0f));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
if (address & 0x01) return 0xff;
|
||||
else return (zbusack | 0xfe);
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart_hw.time_r) return cart_hw.time_r(address);
|
||||
else z80bank_unused_r(address);
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x12: /* RESET */
|
||||
case 0x20: /* MEGA-CD */
|
||||
case 0x40: /* TMSS */
|
||||
case 0x41: /* BOOTROM */
|
||||
case 0x44: /* RADICA */
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
return z80bank_unused_r(address);
|
||||
|
||||
default: /* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
}
|
||||
|
||||
case VDP:
|
||||
/* Valid VDP addresses */
|
||||
if (((address >> 16) & 0x07) == 0)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
switch (address & 0xfd)
|
||||
{
|
||||
case 0x00: /* DATA */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8);
|
||||
|
||||
case 0x01: /* DATA */
|
||||
case 0x03:
|
||||
return (vdp_data_r() & 0xff);
|
||||
|
||||
case 0x04: /* CTRL */
|
||||
case 0x06:
|
||||
return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
|
||||
|
||||
case 0x05: /* CTRL */
|
||||
case 0x07:
|
||||
return (vdp_ctrl_r() & 0xff);
|
||||
|
||||
case 0x08: /* HVC */
|
||||
case 0x0a:
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
return (vdp_hvc_r() >> 8);
|
||||
|
||||
case 0x09: /* HVC */
|
||||
case 0x0b:
|
||||
case 0x0d:
|
||||
case 0x0f:
|
||||
return (vdp_hvc_r() & 0xff);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
return (z80bank_unused_r(address) | 0xff);
|
||||
return zbank_unused_r(address);
|
||||
|
||||
default: /* Invalid address */
|
||||
return z80bank_lockup_r(address);
|
||||
return zbank_lockup_r(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid address */
|
||||
return (z80bank_lockup_r (address));
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) return READ_BYTE(sram.sram, address - sram.start);
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
void zbank_write_vdp(uint32 address, uint32 data)
|
||||
{
|
||||
switch (address & 0xfc)
|
||||
{
|
||||
case 0x00: /* Data port */
|
||||
vdp_data_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case EEPROM:
|
||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0);
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
case 0x04: /* Control port */
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case CART_HW:
|
||||
return cart_hw.regs_r(address);
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
if (address & 1) psg_write(0, data);
|
||||
else zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case UNUSED:
|
||||
return z80bank_unused_r(address);
|
||||
case 0x1c: /* TEST register */
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case ILLEGAL:
|
||||
return z80bank_lockup_r(address);
|
||||
|
||||
case UMK3_HACK:
|
||||
return READ_BYTE(&cart_rom[offset<<19], address & 0x7ffff);
|
||||
|
||||
default: /* ROM */
|
||||
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
|
||||
default: /* Invalid address */
|
||||
zbank_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,19 @@
|
||||
#ifndef _MEMBNK_H_
|
||||
#define _MEMBNK_H_
|
||||
|
||||
/* Function prototypes */
|
||||
extern void z80_write_banked_memory(unsigned int address, unsigned int data);
|
||||
extern unsigned int z80_read_banked_memory(unsigned int address);
|
||||
extern uint32 zbank_unused_r(uint32 address);
|
||||
extern void zbank_unused_w(uint32 address, uint32 data);
|
||||
extern uint32 zbank_lockup_r(uint32 address);
|
||||
extern void zbank_lockup_w(uint32 address, uint32 data);
|
||||
extern uint32 zbank_read_ctrl_io(uint32 address);
|
||||
extern void zbank_write_ctrl_io(uint32 address, uint32 data);
|
||||
extern uint32 zbank_read_vdp(uint32 address);
|
||||
extern void zbank_write_vdp(uint32 address, uint32 data);
|
||||
|
||||
struct _zbank_memory_map
|
||||
{
|
||||
unsigned int (*read)(unsigned int address);
|
||||
void (*write)(unsigned int address, unsigned int data);
|
||||
} zbank_memory_map[256];
|
||||
|
||||
#endif /* _MEMBNK_H_ */
|
||||
|
@ -1,93 +0,0 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* 68k memory from VDP handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
unsigned int vdp_dma_r(unsigned int address)
|
||||
{
|
||||
int offset = address >> 19;
|
||||
|
||||
switch (m68k_readmap_16[offset])
|
||||
{
|
||||
case ROM:
|
||||
if (svp) address -= 2;
|
||||
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
|
||||
|
||||
case UMK3_HACK:
|
||||
return *(uint16 *)(&cart_rom[offset << 19] + (address & 0x7ffff));
|
||||
|
||||
case SVP_DRAM:
|
||||
address -= 2;
|
||||
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||
|
||||
case SVP_CELL:
|
||||
address -= 2;
|
||||
switch (address >> 16)
|
||||
{
|
||||
case 0x39:
|
||||
address >>= 1;
|
||||
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
|
||||
return ((uint16 *)svp->dram)[address];
|
||||
|
||||
case 0x3A:
|
||||
address >>= 1;
|
||||
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
|
||||
return ((uint16 *)svp->dram)[address];
|
||||
|
||||
default:
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
case SYSTEM_IO:
|
||||
/* Z80 area */
|
||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||
(e.g. Z80 isn't reset and 68000 has the bus) */
|
||||
if (address <= 0xa0ffff) return (zbusack ? *(uint16 *)(work_ram + (address & 0xffff)) : 0xffff);
|
||||
|
||||
/* The I/O chip and work RAM try to drive the data bus which
|
||||
results in both values being combined in random ways when read.
|
||||
We return the I/O chip values which seem to have precedence, */
|
||||
if (address <= 0xa1001f)
|
||||
{
|
||||
int temp = io_read((address >> 1) & 0x0f);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
|
||||
case SRAM:
|
||||
if (address <= sram.end) return *(uint16 *)(sram.sram + (address - sram.start));
|
||||
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
|
||||
|
||||
case EEPROM:
|
||||
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
|
||||
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
|
||||
|
||||
case J_CART:
|
||||
return jcart_read();
|
||||
|
||||
default:
|
||||
return *(uint16 *)(work_ram + (address & 0xffff));
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/***************************************************************************************
|
||||
* Genesis Plus 1.2a
|
||||
* 68k memory from VDP handler
|
||||
*
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
****************************************************************************************/
|
||||
#ifndef _MEMVDP_H_
|
||||
#define _MEMVDP_H_
|
||||
|
||||
/* Function prototypes */
|
||||
extern unsigned int vdp_dma_r(unsigned int address);
|
||||
|
||||
#endif /* _MEMVDP_H_ */
|
116
source/memz80.c
116
source/memz80.c
@ -63,118 +63,66 @@ static inline unsigned int z80_lockup_r(unsigned int address)
|
||||
*/
|
||||
static inline unsigned int z80_vdp_r(unsigned int address)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
switch (address & 0xfd)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x02:
|
||||
return (vdp_data_r() >> 8) & 0xff;
|
||||
case 0x00: /* DATA */
|
||||
return (vdp_data_r() >> 8);
|
||||
|
||||
case 0x01: /* VDP data port */
|
||||
case 0x03:
|
||||
case 0x01: /* DATA */
|
||||
return (vdp_data_r() & 0xff);
|
||||
|
||||
case 0x04: /* VDP control port */
|
||||
case 0x06:
|
||||
case 0x04: /* CTRL */
|
||||
return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
|
||||
|
||||
case 0x05: /* VDP control port */
|
||||
case 0x07:
|
||||
case 0x05: /* CTRL */
|
||||
return (vdp_ctrl_r() & 0xff);
|
||||
|
||||
case 0x08: /* HV counter */
|
||||
case 0x0a:
|
||||
case 0x08: /* HVC */
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
return (vdp_hvc_r() >> 8) & 0xff;
|
||||
return (vdp_hvc_r() >> 8);
|
||||
|
||||
case 0x09: /* HV counter */
|
||||
case 0x0b:
|
||||
case 0x09: /* HVC */
|
||||
case 0x0d:
|
||||
case 0x0f:
|
||||
return (vdp_hvc_r() & 0xff);
|
||||
|
||||
case 0x10: /* Unused (PSG) */
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x13:
|
||||
case 0x14:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
return z80_lockup_r (address);
|
||||
|
||||
case 0x18: /* Unused */
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
return z80_unused_r(address);
|
||||
|
||||
case 0x1c: /* Unused (test register) */
|
||||
case 0x1c:
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
return z80_unused_r(address);
|
||||
|
||||
default: /* Invalid VDP addresses */
|
||||
default: /* Invalid address */
|
||||
return z80_lockup_r(address);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void z80_vdp_w(unsigned int address, unsigned int data)
|
||||
{
|
||||
switch (address & 0xff)
|
||||
switch (address & 0xfc)
|
||||
{
|
||||
case 0x00: /* VDP data port */
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x00: /* Data port */
|
||||
vdp_data_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x04: /* VDP control port */
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x04: /* Control port */
|
||||
vdp_ctrl_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
case 0x08: /* Unused (HV counter) */
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
z80_lockup_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* PSG */
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(1, data);
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
if (address & 1) psg_write(0, data);
|
||||
else z80_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
case 0x12:
|
||||
case 0x14:
|
||||
case 0x16:
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
case 0x1a:
|
||||
case 0x1b:
|
||||
case 0x18: /* Unused */
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x1c: /* Test register */
|
||||
case 0x1d:
|
||||
case 0x1e:
|
||||
case 0x1f:
|
||||
vdp_test_w(data << 8 | data);
|
||||
return;
|
||||
|
||||
default: /* Invalid VDP addresses */
|
||||
default: /* Invalid address */
|
||||
z80_lockup_w(address, data);
|
||||
return;
|
||||
}
|
||||
@ -195,11 +143,16 @@ unsigned int cpu_readmem16(unsigned int address)
|
||||
return fm_read(1, address & 3);
|
||||
|
||||
case 3: /* VDP */
|
||||
if ((address & 0xff00) == 0x7f00) return z80_vdp_r (address);
|
||||
return (z80_unused_r(address) | 0xff);
|
||||
if ((address >> 8) == 0x7f) return z80_vdp_r (address);
|
||||
return z80_unused_r(address);
|
||||
|
||||
default: /* V-bus bank */
|
||||
return z80_read_banked_memory(zbank | (address & 0x7fff));
|
||||
{
|
||||
address = zbank | (address & 0x7fff);
|
||||
int slot = address >> 16;
|
||||
if (zbank_memory_map[slot].read) return (*zbank_memory_map[slot].read)(address);
|
||||
else return READ_BYTE(m68k_memory_map[slot].base, address&0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,13 +171,13 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
switch(address & 0xff00)
|
||||
switch(address >> 8)
|
||||
{
|
||||
case 0x6000:
|
||||
case 0x60:
|
||||
gen_bank_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x7f00:
|
||||
case 0x7f:
|
||||
z80_vdp_w(address, data);
|
||||
return;
|
||||
|
||||
@ -235,10 +188,15 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
return;
|
||||
|
||||
default: /* V-bus bank */
|
||||
z80_write_banked_memory(zbank | (address & 0x7fff), data);
|
||||
{
|
||||
address = zbank | (address & 0x7fff);
|
||||
int slot = address >> 16;
|
||||
if (zbank_memory_map[slot].write) (*zbank_memory_map[slot].write)(address, data);
|
||||
else WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Port handlers. Ports are unused when not in Mark III compatability mode.
|
||||
|
@ -74,7 +74,11 @@ void set_config_defaults(void)
|
||||
|
||||
/* system options */
|
||||
config.freeze_auto = -1;
|
||||
#ifdef HW_RVL
|
||||
config.sram_auto = 0; /* assume we always got SDCARD */
|
||||
#else
|
||||
config.sram_auto = -1;
|
||||
#endif
|
||||
config.region_detect = 0;
|
||||
config.force_dtack = 0;
|
||||
config.bios_enabled = 0;
|
||||
|
@ -791,22 +791,6 @@ void optionmenu ()
|
||||
****************************************************************************/
|
||||
static u8 device = 0;
|
||||
|
||||
/****************************************************************************
|
||||
* fat_is_mounted
|
||||
* to check whether FAT media are detected.
|
||||
***************************************************************************/
|
||||
|
||||
bool FatIsMounted(PARTITION_INTERFACE partition) {
|
||||
char prefix[] = "fatX:/";
|
||||
prefix[3] = partition + '0';
|
||||
DIR_ITER *dir = diropen(prefix);
|
||||
if (dir) {
|
||||
dirclose(dir);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int loadsavemenu (int which)
|
||||
{
|
||||
int prevmenu = menu;
|
||||
@ -955,7 +939,8 @@ int loadmenu ()
|
||||
dvd_motor_off();
|
||||
dvd_on = 0;
|
||||
count = 3 + dvd_on;
|
||||
break;
|
||||
menu = load_menu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ static void init_machine()
|
||||
bitmap.viewport.x = 0;
|
||||
bitmap.viewport.y = 0;
|
||||
bitmap.remap = 1;
|
||||
bitmap.data = memalign (32, bitmap.width * bitmap.height * bitmap.granularity);
|
||||
bitmap.data = texturemem;
|
||||
|
||||
/* default system */
|
||||
input.system[0] = SYSTEM_GAMEPAD;
|
||||
@ -145,7 +145,7 @@ int main (int argc, char *argv[])
|
||||
if (fatInitDefault() == true)
|
||||
{
|
||||
use_FAT = 1;
|
||||
fatEnableReadAhead (PI_DEFAULT, 6, 64);
|
||||
// fatEnableReadAhead (PI_DEFAULT, 6, 64);
|
||||
}
|
||||
|
||||
/* Restore User Configuration */
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "shared.h"
|
||||
#include "ogc_input.h"
|
||||
//#include <asndlib.h>
|
||||
|
||||
/* global datas */
|
||||
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
|
||||
@ -49,15 +50,16 @@ static void AudioSwitchBuffers()
|
||||
AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len);
|
||||
DCFlushRange(soundbuffer[playbuffer], dma_len);
|
||||
AUDIO_StartDMA();
|
||||
//ASND_SetVoice(0, VOICE_STEREO_16BIT, 48000, 0, soundbuffer[playbuffer], dma_len, 255, 255, AudioSwitchBuffers);
|
||||
|
||||
/* increment soundbuffers index */
|
||||
playbuffer++;
|
||||
playbuffer &= 0xf;
|
||||
if (playbuffer == mixbuffer)
|
||||
{
|
||||
playbuffer--;
|
||||
if ( playbuffer < 0 ) playbuffer = 15;
|
||||
}
|
||||
playbuffer++;
|
||||
playbuffer &= 0xf;
|
||||
|
||||
IsPlaying = 1;
|
||||
}
|
||||
@ -68,12 +70,14 @@ void ogc_audio__init(void)
|
||||
AUDIO_Init (NULL);
|
||||
AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ);
|
||||
AUDIO_RegisterDMACallback (AudioSwitchBuffers);
|
||||
//ASND_Init();
|
||||
memset(soundbuffer, 0, 16 * 3840);
|
||||
}
|
||||
|
||||
void ogc_audio__reset(void)
|
||||
{
|
||||
AUDIO_StopDMA ();
|
||||
//ASND_Pause(1);
|
||||
IsPlaying = 0;
|
||||
mixbuffer = 0;
|
||||
playbuffer = 0;
|
||||
@ -82,5 +86,9 @@ void ogc_audio__reset(void)
|
||||
void ogc_audio__update(void)
|
||||
{
|
||||
/* restart Audio DMA if needed */
|
||||
if (!IsPlaying) AudioSwitchBuffers();
|
||||
if (!IsPlaying)
|
||||
{
|
||||
//ASND_Pause(0);
|
||||
AudioSwitchBuffers();
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +604,6 @@ void ogc_input__set_defaults(void)
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
u32 exp;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
/* WIIMOTE */
|
||||
@ -648,6 +647,8 @@ void ogc_input__set_defaults(void)
|
||||
}
|
||||
|
||||
#ifdef HW_RVL
|
||||
u32 exp;
|
||||
VIDEO_WaitVSync();
|
||||
int j;
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
|
@ -43,6 +43,7 @@ u8 *texturemem; /*** Texture Data ***/
|
||||
/*** GX ***/
|
||||
#define TEX_WIDTH 360 * 2
|
||||
#define TEX_HEIGHT 576
|
||||
#define TEX_SIZE TEX_WIDTH * TEX_HEIGHT * 2
|
||||
#define DEFAULT_FIFO_SIZE 256 * 1024
|
||||
#define HASPECT 320
|
||||
#define VASPECT 240
|
||||
@ -610,41 +611,11 @@ void ogc_video__update()
|
||||
/* load texture */
|
||||
GX_LoadTexObj (&texobj, GX_TEXMAP0);
|
||||
}
|
||||
|
||||
|
||||
/* texture map is now directly done by the line renderer */
|
||||
if (config.ntsc && !(reg[12]&1))
|
||||
{
|
||||
int h, w;
|
||||
|
||||
/* texture and bitmap buffers (buffers pitch is fixed to 720*2 pixels) */
|
||||
long long int *dst = (long long int *)texturemem;
|
||||
long long int *src1 = (long long int *)(bitmap.data); /* line n */
|
||||
long long int *src2 = src1 + 180; /* line n+1 */
|
||||
long long int *src3 = src2 + 180; /* line n+2 */
|
||||
long long int *src4 = src3 + 180; /* line n+3 */
|
||||
|
||||
/* update texture texels */
|
||||
for (h = 0; h < vheight; h++)
|
||||
{
|
||||
for (w = 0; w < vwidth; w++)
|
||||
{
|
||||
*dst++ = *src1++;
|
||||
*dst++ = *src2++;
|
||||
*dst++ = *src3++;
|
||||
*dst++ = *src4++;
|
||||
}
|
||||
|
||||
/* jump to next four lines */
|
||||
src1 += stride;
|
||||
src2 += stride;
|
||||
src3 += stride;
|
||||
src4 += stride;
|
||||
}
|
||||
}
|
||||
/* texture is now directly mapped by the line renderer */
|
||||
|
||||
/* update texture cache */
|
||||
DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
|
||||
DCFlushRange (texturemem, TEX_SIZE);
|
||||
GX_InvalidateTexAll ();
|
||||
|
||||
/* render textured quad */
|
||||
|
@ -99,39 +99,94 @@ void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned
|
||||
(SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2,
|
||||
(SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 );
|
||||
|
||||
#ifdef NGC
|
||||
/* directly fill the RGB565 texture */
|
||||
/* one tile is 32 byte = 4x4 pixels */
|
||||
/* tiles are stored continuously in texture memory */
|
||||
in_width = SMS_NTSC_OUT_WIDTH(in_width) >> 2;
|
||||
int offset = ((in_width << 5) * (vline >> 2)) + ((vline & 3) * 8);
|
||||
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(texturemem + offset);
|
||||
offset = 0;
|
||||
#else
|
||||
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]);
|
||||
int n;
|
||||
#endif
|
||||
int n;
|
||||
input += in_extra;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
SMS_NTSC_COLOR_IN( 0, ntsc, sms_ntsc_black );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 0, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 1, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 1, ntsc, sms_ntsc_black );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 2, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 3, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
|
||||
SMS_NTSC_COLOR_IN( 2, ntsc, sms_ntsc_black );
|
||||
#ifdef NGC
|
||||
SMS_NTSC_RGB_OUT( 4, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 5, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
offset ++;
|
||||
SMS_NTSC_RGB_OUT( 6, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
|
||||
#else
|
||||
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
1178
source/render.c
1178
source/render.c
File diff suppressed because it is too large
Load Diff
@ -34,16 +34,19 @@ extern int render_init(void);
|
||||
extern void palette_init(void);
|
||||
extern void render_reset(void);
|
||||
extern void render_shutdown(void);
|
||||
extern void render_line(int line, uint8 odd_frame);
|
||||
extern void render_line(uint32 line, uint32 overscan);
|
||||
extern void parse_satb(uint32 line);
|
||||
extern void remap_buffer(uint32 line,uint32 width);
|
||||
extern void window_clip(uint8 reg_12, uint8 reg_17);
|
||||
|
||||
#ifndef NGC
|
||||
extern void color_update_8(int index, uint16 data);
|
||||
extern void color_update_15(int index, uint16 data);
|
||||
extern void color_update_32(int index, uint16 data);
|
||||
#endif
|
||||
extern void color_update_16(int index, uint16 data);
|
||||
extern void parse_satb(int line);
|
||||
extern void (*color_update)(int index, uint16 data);
|
||||
extern void remap_buffer(int line,int width);
|
||||
|
||||
void (*color_update)(int index, uint16 data);
|
||||
|
||||
#endif /* _RENDER_H_ */
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "mem68k.h"
|
||||
#include "memz80.h"
|
||||
#include "membnk.h"
|
||||
#include "memvdp.h"
|
||||
#include "gen_io.h"
|
||||
#include "gen_input.h"
|
||||
#include "state.h"
|
||||
|
@ -670,7 +670,7 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
|
||||
}
|
||||
|
||||
/* set algorithm connection */
|
||||
static void setup_connection( FM_CH *CH, int ch )
|
||||
INLINE void setup_connection( FM_CH *CH, int ch )
|
||||
{
|
||||
INT32 *carrier = &out_fm[ch];
|
||||
|
||||
@ -1397,7 +1397,7 @@ INLINE void CSMKeyControll(FM_CH *CH)
|
||||
}
|
||||
}
|
||||
|
||||
static void INTERNAL_TIMER_A()
|
||||
INLINE void INTERNAL_TIMER_A()
|
||||
{
|
||||
if (ym2612.OPN.ST.mode & 0x01)
|
||||
{
|
||||
@ -1416,7 +1416,7 @@ static void INTERNAL_TIMER_A()
|
||||
}
|
||||
}
|
||||
|
||||
static void INTERNAL_TIMER_B(int step)
|
||||
INLINE void INTERNAL_TIMER_B(int step)
|
||||
{
|
||||
if (ym2612.OPN.ST.mode & 0x02)
|
||||
{
|
||||
|
@ -25,13 +25,13 @@
|
||||
static unsigned char state[0x24000];
|
||||
static unsigned int bufferptr;
|
||||
|
||||
void load_param(void *param, unsigned int size)
|
||||
static inline void load_param(void *param, unsigned int size)
|
||||
{
|
||||
memcpy(param, &state[bufferptr], size);
|
||||
bufferptr+= size;
|
||||
}
|
||||
|
||||
void save_param(void *param, unsigned int size)
|
||||
static inline void save_param(void *param, unsigned int size)
|
||||
{
|
||||
memcpy(&state[bufferptr], param, size);
|
||||
bufferptr+= size;
|
||||
@ -39,27 +39,18 @@ void save_param(void *param, unsigned int size)
|
||||
|
||||
void state_load(unsigned char *buffer)
|
||||
{
|
||||
uint32 tmp32;
|
||||
uint16 tmp16;
|
||||
uint8 temp_reg[0x20];
|
||||
unsigned long inbytes, outbytes;
|
||||
|
||||
/* get compressed state size & uncompress state file */
|
||||
memcpy(&inbytes, buffer, 4);
|
||||
/* reset buffer pointer */
|
||||
bufferptr = 0;
|
||||
|
||||
#ifdef NGC
|
||||
/* uncompress savestate */
|
||||
unsigned long inbytes, outbytes;
|
||||
memcpy(&inbytes, buffer, 4);
|
||||
outbytes = 0x24000;
|
||||
uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes);
|
||||
#else
|
||||
outbytes = inbytes;
|
||||
memcpy(state, buffer + 4, outbytes);
|
||||
#endif
|
||||
|
||||
/* SYSTEM RESET */
|
||||
/* reset system */
|
||||
system_reset();
|
||||
rom_readmap[0] = &cart_rom[0];
|
||||
rom_size = genromsize;
|
||||
m68k_memory_map[0].base = default_rom;
|
||||
|
||||
// GENESIS
|
||||
load_param(work_ram, sizeof(work_ram));
|
||||
@ -73,6 +64,7 @@ void state_load(unsigned char *buffer)
|
||||
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));
|
||||
@ -86,8 +78,7 @@ void state_load(unsigned char *buffer)
|
||||
load_param(&dmafill, sizeof(dmafill));
|
||||
load_param(&hint_pending, sizeof(hint_pending));
|
||||
load_param(&vint_pending, sizeof(vint_pending));
|
||||
load_param(&vint_triggered, sizeof(vint_triggered));
|
||||
load_param(&hvint_updated, sizeof(hvint_updated));
|
||||
load_param(&irq_status, sizeof(irq_status));
|
||||
vdp_restore(temp_reg);
|
||||
|
||||
// FM
|
||||
@ -98,6 +89,8 @@ void state_load(unsigned char *buffer)
|
||||
load_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
|
||||
|
||||
// 68000
|
||||
uint16 tmp16;
|
||||
uint32 tmp32;
|
||||
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D0, tmp32);
|
||||
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D1, tmp32);
|
||||
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D2, tmp32);
|
||||
@ -124,11 +117,7 @@ void state_load(unsigned char *buffer)
|
||||
|
||||
int state_save(unsigned char *buffer)
|
||||
{
|
||||
uint32 tmp32;
|
||||
uint16 tmp16;
|
||||
unsigned long inbytes, outbytes;
|
||||
|
||||
/* save state */
|
||||
/* reset buffer pointer */
|
||||
bufferptr = 0;
|
||||
|
||||
// GENESIS
|
||||
@ -155,8 +144,7 @@ int state_save(unsigned char *buffer)
|
||||
save_param(&dmafill, sizeof(dmafill));
|
||||
save_param(&hint_pending, sizeof(hint_pending));
|
||||
save_param(&vint_pending, sizeof(vint_pending));
|
||||
save_param(&vint_triggered, sizeof(vint_triggered));
|
||||
save_param(&hvint_updated, sizeof(hvint_updated));
|
||||
save_param(&irq_status, sizeof(irq_status));
|
||||
|
||||
// FM
|
||||
save_param(fm_reg,sizeof(fm_reg));
|
||||
@ -165,6 +153,8 @@ int state_save(unsigned char *buffer)
|
||||
save_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
|
||||
|
||||
// 68000
|
||||
uint16 tmp16;
|
||||
uint32 tmp32;
|
||||
tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4);
|
||||
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
|
||||
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
|
||||
@ -188,18 +178,10 @@ int state_save(unsigned char *buffer)
|
||||
// Z80
|
||||
save_param(&Z80, sizeof(Z80_Regs));
|
||||
|
||||
inbytes = bufferptr;
|
||||
|
||||
#ifdef NGC
|
||||
/* compress state file */
|
||||
outbytes = 0x26000;
|
||||
unsigned long inbytes = bufferptr;
|
||||
unsigned long outbytes = 0x26000;
|
||||
compress2 ((Bytef *)(buffer + 4), &outbytes, (Bytef *)state, inbytes, 9);
|
||||
#else
|
||||
outbytes = inbytes;
|
||||
memcpy(buffer + 4, state, outbytes);
|
||||
#endif
|
||||
|
||||
/* write compressed size in the first 32 bits for decompression */
|
||||
memcpy(buffer, &outbytes, 4);
|
||||
|
||||
/* return total size */
|
||||
|
162
source/system.c
162
source/system.c
@ -43,60 +43,9 @@ uint32 line_z80;
|
||||
int32 current_z80;
|
||||
uint8 odd_frame;
|
||||
uint8 interlaced;
|
||||
uint32 frame_cnt;
|
||||
uint8 system_hw;
|
||||
|
||||
/****************************************************************
|
||||
* CPU execution managment
|
||||
****************************************************************/
|
||||
|
||||
/* Interrupt Manager
|
||||
this is called before each new executed instruction
|
||||
only if interrupts have been updated
|
||||
*/
|
||||
static inline void update_interrupts(void)
|
||||
{
|
||||
uint8 latency = hvint_updated;
|
||||
hvint_updated = -1;
|
||||
|
||||
/* VDP hardware latency */
|
||||
if (latency) count_m68k += m68k_execute(latency);
|
||||
|
||||
/* Level 6 interrupt */
|
||||
if (vint_pending && (reg[1] & 0x20))
|
||||
{
|
||||
vint_triggered = 1;
|
||||
m68k_set_irq(6);
|
||||
}
|
||||
/* Level 4 interrupt */
|
||||
else if (hint_pending && (reg[0] & 0x10))
|
||||
{
|
||||
m68k_set_irq(4);
|
||||
}
|
||||
/* Clear all interrupts */
|
||||
else
|
||||
{
|
||||
m68k_set_irq(0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void m68k_run (int cyc)
|
||||
{
|
||||
while (count_m68k < cyc)
|
||||
{
|
||||
/* check interrupts */
|
||||
if (hvint_updated >= 0) update_interrupts();
|
||||
|
||||
/* execute a single instruction */
|
||||
count_m68k += m68k_execute(1);
|
||||
}
|
||||
}
|
||||
|
||||
void z80_run (int cyc)
|
||||
{
|
||||
current_z80 = cyc - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
static inline void audio_update (void);
|
||||
|
||||
/****************************************************************
|
||||
* Virtual Genesis initialization
|
||||
@ -128,7 +77,6 @@ void system_reset (void)
|
||||
current_z80 = 0;
|
||||
odd_frame = 0;
|
||||
interlaced = 0;
|
||||
frame_cnt = 0;
|
||||
|
||||
/* Cart Hardware reset */
|
||||
cart_hw_reset();
|
||||
@ -161,7 +109,11 @@ void system_shutdown (void)
|
||||
****************************************************************/
|
||||
int system_frame (int do_skip)
|
||||
{
|
||||
int line;
|
||||
if (!gen_running)
|
||||
{
|
||||
update_input();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reset cycles counts */
|
||||
count_m68k = 0;
|
||||
@ -171,37 +123,31 @@ int system_frame (int do_skip)
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
|
||||
/* increment frame counter */
|
||||
frame_cnt ++;
|
||||
|
||||
if (!gen_running)
|
||||
{
|
||||
update_input();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clear VBLANK & DMA BUSY flags */
|
||||
status &= 0xFFF5;
|
||||
|
||||
/* Look for interlace mode change */
|
||||
uint8 old_interlaced = interlaced;
|
||||
interlaced = (reg[12] & 2) >> 1;
|
||||
/* update display settings */
|
||||
int line;
|
||||
int reset = resetline;
|
||||
int vdp_height = bitmap.viewport.h;
|
||||
int end_line = vdp_height + bitmap.viewport.y;
|
||||
int start_line = lines_per_frame - bitmap.viewport.y;
|
||||
int old_interlaced = interlaced;
|
||||
interlaced = (reg[12] >> 1) & 3;
|
||||
if (old_interlaced != interlaced)
|
||||
{
|
||||
bitmap.viewport.changed = 2;
|
||||
im2_flag = ((reg[12] & 6) == 6) ? 1 : 0;
|
||||
im2_flag = (interlaced == 3);
|
||||
odd_frame = 1;
|
||||
}
|
||||
|
||||
/* Toggle even/odd field flag (interlaced modes only) */
|
||||
odd_frame ^= 1;
|
||||
if (odd_frame && interlaced) status |= 0x0010;
|
||||
|
||||
/* update VDP status */
|
||||
status &= 0xFFF5; // clear VBLANK and DMA flags
|
||||
if (odd_frame && interlaced) status |= 0x0010; // even/odd field flag (interlaced modes only)
|
||||
else status &= 0xFFEF;
|
||||
|
||||
/* Reset HCounter */
|
||||
h_counter = reg[10];
|
||||
/* Reload H Counter */
|
||||
int h_counter = reg[10];
|
||||
|
||||
/* Parse sprites for line 0 (done on line 261 or 312) */
|
||||
/* parse sprites for line 0 (done on last line) */
|
||||
parse_satb (0x80);
|
||||
|
||||
/* Line processing */
|
||||
@ -220,8 +166,8 @@ int system_frame (int do_skip)
|
||||
aim_z80 += z80cycles_per_line;
|
||||
aim_m68k += m68cycles_per_line;
|
||||
|
||||
/* Check "soft reset" */
|
||||
if (line == resetline)
|
||||
/* Soft Reset ? */
|
||||
if (line == reset)
|
||||
{
|
||||
#ifdef NGC
|
||||
/* wait for RESET button to be released */
|
||||
@ -231,15 +177,15 @@ int system_frame (int do_skip)
|
||||
}
|
||||
|
||||
/* Horizontal Interrupt */
|
||||
if (line <= bitmap.viewport.h)
|
||||
if (line <= vdp_height)
|
||||
{
|
||||
if(--h_counter < 0)
|
||||
{
|
||||
h_counter = reg[10];
|
||||
hint_pending = 1;
|
||||
hvint_updated = 0;
|
||||
if (reg[0] & 0x10) irq_status = (irq_status & 0xff) | 0x14;
|
||||
|
||||
/* adjust timings to take decrement in account */
|
||||
/* adjust timings to take further decrement in account (see below) */
|
||||
if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
|
||||
}
|
||||
|
||||
@ -247,22 +193,17 @@ int system_frame (int do_skip)
|
||||
/* during this period, any VRAM/CRAM/VSRAM writes should NOT be taken in account before next line */
|
||||
/* as a result, current line is shortened */
|
||||
/* fix Lotus 1, Lotus 2 RECS, Striker, Zero the Kamikaze Squirell */
|
||||
if ((line < bitmap.viewport.h)&&(h_counter == 0)) aim_m68k -= 36;
|
||||
}
|
||||
if ((line < vdp_height) && (h_counter == 0)) aim_m68k -= 36;
|
||||
|
||||
/* Check if there is any DMA in progess */
|
||||
/* update DMA timings */
|
||||
if (dma_length) dma_update();
|
||||
|
||||
/* Render Line */
|
||||
if (!do_skip)
|
||||
{
|
||||
render_line(line,odd_frame);
|
||||
if (line < (bitmap.viewport.h-1)) parse_satb(0x81 + line);
|
||||
}
|
||||
|
||||
/* Vertical Retrace */
|
||||
if (line == bitmap.viewport.h)
|
||||
if (line == vdp_height)
|
||||
{
|
||||
/* render overscan */
|
||||
if ((line < end_line) && (!do_skip)) render_line(line, 1);
|
||||
|
||||
/* update inputs */
|
||||
update_input();
|
||||
|
||||
@ -275,24 +216,51 @@ int system_frame (int do_skip)
|
||||
|
||||
/* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */
|
||||
m68k_run(line_m68k + 84);
|
||||
if (zreset && !zbusreq) z80_run(line_z80 + 39);
|
||||
if (zreset && !zbusreq)
|
||||
{
|
||||
current_z80 = line_z80 + 39 - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
else count_z80 = line_z80 + 39;
|
||||
|
||||
/* Vertical Interrupt */
|
||||
status |= 0x80;
|
||||
vint_pending = 1;
|
||||
hvint_updated = 36; /* Tyrants, Mega-Lo-Mania & Ex Mutant need some cycles to read VINT flag */
|
||||
if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416; // 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant)
|
||||
}
|
||||
else if (!do_skip)
|
||||
{
|
||||
/* render scanline and parse sprites for line n+1 */
|
||||
render_line(line, 0);
|
||||
if (line < (vdp_height-1)) parse_satb(0x81 + line);
|
||||
}
|
||||
else if (zirq)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update DMA timings */
|
||||
if (dma_length) dma_update();
|
||||
|
||||
/* render overscan */
|
||||
if ((line < end_line) || (line >= start_line))
|
||||
{
|
||||
if (!do_skip) render_line(line, 1);
|
||||
}
|
||||
|
||||
/* clear any pending Z80 interrupt */
|
||||
if (zirq)
|
||||
{
|
||||
zirq = 0;
|
||||
z80_set_irq_line(0, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Process line */
|
||||
m68k_run(aim_m68k);
|
||||
if (zreset == 1 && zbusreq == 0) z80_run(aim_z80);
|
||||
if (zreset == 1 && zbusreq == 0)
|
||||
{
|
||||
current_z80 = aim_z80 - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
else count_z80 = aim_z80;
|
||||
|
||||
/* SVP chip */
|
||||
@ -372,7 +340,7 @@ void audio_shutdown(void)
|
||||
|
||||
static int ll, rr;
|
||||
|
||||
void audio_update (void)
|
||||
static inline void audio_update (void)
|
||||
{
|
||||
int i;
|
||||
int l, r;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define z80cycles_per_line 228
|
||||
#define m68cycles_per_line 488
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 *data; /* Bitmap data */
|
||||
@ -90,7 +91,6 @@ extern uint32 line_z80;
|
||||
extern int32 current_z80;
|
||||
extern uint8 interlaced;
|
||||
extern uint8 odd_frame;
|
||||
extern uint32 frame_cnt;
|
||||
extern uint8 system_hw;
|
||||
|
||||
/* Function prototypes */
|
||||
@ -100,8 +100,6 @@ extern void system_shutdown (void);
|
||||
extern int system_frame(int skip);
|
||||
extern int audio_init (int rate);
|
||||
extern void audio_shutdown (void);
|
||||
extern void audio_update (void);
|
||||
extern void z80_run (int cyc);
|
||||
|
||||
#endif /* _SYSTEM_H_ */
|
||||
|
||||
|
371
source/vdp.c
371
source/vdp.c
@ -31,7 +31,7 @@
|
||||
/* Mark a pattern as dirty */
|
||||
#define MARK_BG_DIRTY(addr) \
|
||||
{ \
|
||||
int name = (addr >> 5) & 0x7FF; \
|
||||
name = (addr >> 5) & 0x7FF; \
|
||||
if(bg_name_dirty[name] == 0) bg_name_list[bg_list_index++] = name; \
|
||||
bg_name_dirty[name] |= (1 << ((addr >> 2) & 0x07)); \
|
||||
}
|
||||
@ -50,8 +50,7 @@ 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 vint_triggered; /* 1= Frame interrupt has been triggered */
|
||||
int8 hvint_updated; /* >= 0: Interrupt lines updated */
|
||||
uint16 irq_status; /* Interrupt lines updated */
|
||||
|
||||
/* Global variables */
|
||||
uint16 ntab; /* Name table A base address */
|
||||
@ -68,8 +67,7 @@ uint8 playfield_shift; /* Width of planes A, B (in bits) */
|
||||
uint8 playfield_col_mask; /* Vertical scroll mask */
|
||||
uint16 playfield_row_mask; /* Horizontal scroll mask */
|
||||
uint32 y_mask; /* Name table Y-index bits mask */
|
||||
int16 h_counter; /* Raster counter */
|
||||
int16 hc_latch; /* latched HCounter (INT2) */
|
||||
uint16 hc_latch; /* latched HCounter (INT2) */
|
||||
uint16 v_counter; /* VDP scanline counter */
|
||||
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
|
||||
uint32 dma_length; /* Current DMA remaining bytes */
|
||||
@ -91,6 +89,8 @@ static uint16 sat_addr_mask; /* Index bits of SAT */
|
||||
static uint32 dma_endCycles; /* 68k cycles to DMA end */
|
||||
static uint8 dma_type; /* Type of DMA */
|
||||
|
||||
static inline void vdp_reg_w(unsigned int r, unsigned int d);
|
||||
|
||||
/* DMA Timings
|
||||
|
||||
According to the manual, here's a table that describes the transfer
|
||||
@ -183,11 +183,9 @@ void vdp_reset(void)
|
||||
|
||||
hint_pending = 0;
|
||||
vint_pending = 0;
|
||||
vint_triggered = 0;
|
||||
hvint_updated = -1;
|
||||
irq_status = 0;
|
||||
|
||||
h_counter = 0;
|
||||
hc_latch = -1;
|
||||
hc_latch = 0;
|
||||
v_counter = 0;
|
||||
|
||||
dmafill = 0;
|
||||
@ -221,6 +219,7 @@ void vdp_reset(void)
|
||||
vdp_reg_w(10, 0xff); /* HINT disabled */
|
||||
vdp_reg_w(12, 0x81); /* H40 mode */
|
||||
vdp_reg_w(15, 0x02); /* auto increment */
|
||||
window_clip(1,0);
|
||||
}
|
||||
|
||||
/* default latency */
|
||||
@ -325,6 +324,7 @@ void dma_update()
|
||||
*/
|
||||
static inline void dma_copy(void)
|
||||
{
|
||||
int name;
|
||||
int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
|
||||
if (!length) length = 0x10000;
|
||||
@ -355,6 +355,7 @@ static inline void dma_vbus (void)
|
||||
{
|
||||
uint32 base, source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE;
|
||||
uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
uint32 temp;
|
||||
|
||||
if (!length) length = 0x10000;
|
||||
base = source;
|
||||
@ -364,15 +365,49 @@ static inline void dma_vbus (void)
|
||||
dma_length = length;
|
||||
dma_update();
|
||||
|
||||
/* proceed DMA */
|
||||
switch (source >> 21)
|
||||
{
|
||||
case 5:
|
||||
do
|
||||
{
|
||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||
(e.g. Z80 isn't reset and 68000 has the bus) */
|
||||
if (source <= 0xa0ffff) temp = (zbusack ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff);
|
||||
|
||||
/* The I/O chip and work RAM try to drive the data bus which results
|
||||
in both values being combined in random ways when read.
|
||||
We return the I/O chip values which seem to have precedence, */
|
||||
else if (source <= 0xa1001f)
|
||||
{
|
||||
temp = io_read((source >> 1) & 0x0f);
|
||||
temp = (temp << 8 | temp);
|
||||
}
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
else temp = *(uint16 *)(work_ram + (source & 0xffff));
|
||||
|
||||
source += 2;
|
||||
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
||||
data_write (temp);
|
||||
}
|
||||
while (--length);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
if (svp) source = source - 2;
|
||||
|
||||
default:
|
||||
do
|
||||
{
|
||||
unsigned int temp = vdp_dma_r(source);
|
||||
temp = *(uint16 *)(m68k_memory_map[source>>16].base + (source & 0xffff));
|
||||
source += 2;
|
||||
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
||||
data_write (temp);
|
||||
}
|
||||
while (--length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* update length & source address registers */
|
||||
reg[19] = length & 0xFF;
|
||||
@ -385,6 +420,7 @@ static inline void dma_vbus (void)
|
||||
/* VRAM FILL */
|
||||
static inline void dma_fill(unsigned int data)
|
||||
{
|
||||
int name;
|
||||
int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
|
||||
if (!length) length = 0x10000;
|
||||
|
||||
@ -475,6 +511,7 @@ static inline void data_write (unsigned int data)
|
||||
*(uint16 *) &vram[addr & 0xFFFE] = data;
|
||||
|
||||
/* Update the pattern cache */
|
||||
int name;
|
||||
MARK_BG_DIRTY (addr);
|
||||
}
|
||||
break;
|
||||
@ -566,132 +603,11 @@ void vdp_ctrl_w(unsigned int data)
|
||||
}
|
||||
|
||||
|
||||
unsigned int vdp_ctrl_r(void)
|
||||
{
|
||||
/*
|
||||
* Return vdp status
|
||||
*
|
||||
* Bits are
|
||||
* 0 0:1 ntsc:pal
|
||||
* 1 DMA Busy
|
||||
* 2 During HBlank
|
||||
* 3 During VBlank
|
||||
* 4 Frame Interlace 0:even 1:odd
|
||||
* 5 Sprite collision
|
||||
* 6 Too many sprites per line
|
||||
* 7 v interrupt occurred
|
||||
* 8 Write FIFO full
|
||||
* 9 Write FIFO empty
|
||||
* 10 - 15 Next word on bus
|
||||
*/
|
||||
|
||||
/* update FIFO flags */
|
||||
fifo_update();
|
||||
if (fifo_write_cnt < 4)
|
||||
{
|
||||
status &= 0xFEFF;
|
||||
if (fifo_write_cnt == 0) status |= 0x200;
|
||||
}
|
||||
else status ^= 0x200;
|
||||
|
||||
/* update DMA Busy flag */
|
||||
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
|
||||
status &= 0xFFFD;
|
||||
|
||||
unsigned int temp = status | vdp_pal;
|
||||
|
||||
/* display OFF: VBLANK flag is set */
|
||||
if (!(reg[1] & 0x40)) temp |= 0x8;
|
||||
|
||||
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2) */
|
||||
if ((count_m68k <= (line_m68k + 84)) || (count_m68k > (line_m68k + m68cycles_per_line))) temp |= 0x4;
|
||||
|
||||
/* clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
/* clear SPR/SCOL flags */
|
||||
status &= 0xFF9F;
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
void vdp_data_w(unsigned int data)
|
||||
{
|
||||
/* Clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
if (dmafill)
|
||||
{
|
||||
dma_fill(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update VDP FIFO (during HDISPLAY only) */
|
||||
if (!(status&8) && (reg[1]&0x40))
|
||||
{
|
||||
fifo_update();
|
||||
if (fifo_write_cnt == 0)
|
||||
{
|
||||
/* reset cycle counter */
|
||||
fifo_lastwrite = count_m68k;
|
||||
|
||||
/* FIFO is not empty anymore */
|
||||
status &= 0xFDFF;
|
||||
}
|
||||
|
||||
/* increase write counter */
|
||||
fifo_write_cnt ++;
|
||||
|
||||
/* is FIFO full ? */
|
||||
if (fifo_write_cnt >= 4)
|
||||
{
|
||||
status |= 0x100;
|
||||
|
||||
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
||||
if (fifo_write_cnt > 4) count_m68k = fifo_lastwrite + fifo_latency;
|
||||
}
|
||||
}
|
||||
|
||||
/* write data */
|
||||
data_write(data);
|
||||
}
|
||||
|
||||
unsigned int vdp_data_r(void)
|
||||
{
|
||||
uint16 temp = 0;
|
||||
|
||||
/* Clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
switch (code & 0x0F)
|
||||
{
|
||||
case 0x00: /* VRAM */
|
||||
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
||||
break;
|
||||
|
||||
case 0x08: /* CRAM */
|
||||
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
||||
temp = UNPACK_CRAM (temp);
|
||||
break;
|
||||
|
||||
case 0x04: /* VSRAM */
|
||||
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment address register */
|
||||
addr += reg[15];
|
||||
|
||||
/* return data */
|
||||
return (temp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The reg[] array is updated at the *end* of this function, so the new
|
||||
register data can be compared with the previous data.
|
||||
*/
|
||||
void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
static inline void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
/* Check if Mode 4 (SMS mode) has been activated
|
||||
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
|
||||
@ -702,18 +618,43 @@ void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
switch(r)
|
||||
{
|
||||
case 0x00: /* CTRL #1 */
|
||||
if ((d&0x10) != (reg[0]&0x10)) hvint_updated = 0;
|
||||
/* Check if HINT has been enabled or disabled */
|
||||
if (hint_pending && ((d&0x10) != (reg[0]&0x10)))
|
||||
{
|
||||
irq_status &= 0x20;
|
||||
irq_status |= 0x10;
|
||||
if (vint_pending && (reg[1] & 0x20))
|
||||
{
|
||||
irq_status |= 6;
|
||||
}
|
||||
else if (d & 0x10)
|
||||
{
|
||||
irq_status |= 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01: /* CTRL #2 */
|
||||
/* Sesame Street Counting Cafe need to execute one instruction */
|
||||
if ((d&0x20) != (reg[1]&0x20)) hvint_updated = 1;
|
||||
/* Check if VINT has been enabled or disabled */
|
||||
if (vint_pending && ((d&0x20) != (reg[1]&0x20)))
|
||||
{
|
||||
irq_status &= 0x20;
|
||||
irq_status |= 0x110;
|
||||
if (d & 0x20)
|
||||
{
|
||||
irq_status |= 6;
|
||||
}
|
||||
else if (hint_pending && (reg[0] & 0x10))
|
||||
{
|
||||
irq_status |= 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Check if the viewport height has actually been changed */
|
||||
if((reg[1] & 8) != (d & 8))
|
||||
{
|
||||
/* Update the height of the viewport */
|
||||
bitmap.viewport.oh = bitmap.viewport.h;
|
||||
bitmap.viewport.h = (d & 8) ? 240 : 224;
|
||||
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
|
||||
bitmap.viewport.changed = 1;
|
||||
@ -732,7 +673,7 @@ void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
- Deadly Moves aka Power Athlete (set display ON)
|
||||
*/
|
||||
reg[1] = d;
|
||||
render_line(v_counter,odd_frame);
|
||||
render_line(v_counter, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -780,13 +721,15 @@ void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
if((reg[0x0C] & 1) != (d & 1))
|
||||
{
|
||||
/* Update the width of the viewport */
|
||||
bitmap.viewport.ow = bitmap.viewport.w;
|
||||
bitmap.viewport.w = (d & 1) ? 320 : 256;
|
||||
if (config.overscan) bitmap.viewport.x = (d & 1) ? 16 : 12;
|
||||
bitmap.viewport.changed = 1;
|
||||
|
||||
/* update HC table */
|
||||
hctab = (d & 1) ? cycle2hc40 : cycle2hc32;
|
||||
|
||||
/* update clipping */
|
||||
window_clip(d,reg[17]);
|
||||
}
|
||||
|
||||
/* See if the S/TE mode bit has changed */
|
||||
@ -820,6 +763,10 @@ void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
playfield_row_mask = row_mask_table[(d >> 4) & 3];
|
||||
y_mask = y_mask_table[(d & 3)];
|
||||
break;
|
||||
|
||||
case 0x11: /* update clipping */
|
||||
window_clip(reg[12],d);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write new register value */
|
||||
@ -827,9 +774,130 @@ void vdp_reg_w(unsigned int r, unsigned int d)
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int vdp_ctrl_r(void)
|
||||
{
|
||||
/*
|
||||
* Return vdp status
|
||||
*
|
||||
* Bits are
|
||||
* 0 0:1 ntsc:pal
|
||||
* 1 DMA Busy
|
||||
* 2 During HBlank
|
||||
* 3 During VBlank
|
||||
* 4 Frame Interlace 0:even 1:odd
|
||||
* 5 Sprite collision
|
||||
* 6 Too many sprites per line
|
||||
* 7 v interrupt occurred
|
||||
* 8 Write FIFO full
|
||||
* 9 Write FIFO empty
|
||||
* 10 - 15 Next word on bus
|
||||
*/
|
||||
|
||||
/* update FIFO flags */
|
||||
fifo_update();
|
||||
if (fifo_write_cnt < 4)
|
||||
{
|
||||
status &= 0xFEFF;
|
||||
if (fifo_write_cnt == 0) status |= 0x200;
|
||||
}
|
||||
else status ^= 0x200;
|
||||
|
||||
/* update DMA Busy flag */
|
||||
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
|
||||
status &= 0xFFFD;
|
||||
|
||||
unsigned int temp = status | vdp_pal;
|
||||
|
||||
/* display OFF: VBLANK flag is set */
|
||||
if (!(reg[1] & 0x40)) temp |= 0x8;
|
||||
|
||||
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2) */
|
||||
if ((count_m68k <= (line_m68k + 84)) || (count_m68k > (line_m68k + m68cycles_per_line))) temp |= 0x4;
|
||||
|
||||
/* clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
/* clear SPR/SCOL flags */
|
||||
status &= 0xFF9F;
|
||||
|
||||
return (temp);
|
||||
}
|
||||
|
||||
void vdp_data_w(unsigned int data)
|
||||
{
|
||||
/* Clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
if (dmafill)
|
||||
{
|
||||
dma_fill(data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update VDP FIFO (during HDISPLAY only) */
|
||||
if (!(status&8) && (reg[1]&0x40))
|
||||
{
|
||||
fifo_update();
|
||||
if (fifo_write_cnt == 0)
|
||||
{
|
||||
/* reset cycle counter */
|
||||
fifo_lastwrite = count_m68k;
|
||||
|
||||
/* FIFO is not empty anymore */
|
||||
status &= 0xFDFF;
|
||||
}
|
||||
|
||||
/* increase write counter */
|
||||
fifo_write_cnt ++;
|
||||
|
||||
/* is FIFO full ? */
|
||||
if (fifo_write_cnt >= 4)
|
||||
{
|
||||
status |= 0x100;
|
||||
|
||||
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
||||
if (fifo_write_cnt > 4) count_m68k = fifo_lastwrite + fifo_latency;
|
||||
}
|
||||
}
|
||||
|
||||
/* write data */
|
||||
data_write(data);
|
||||
}
|
||||
|
||||
unsigned int vdp_data_r(void)
|
||||
{
|
||||
uint16 temp = 0;
|
||||
|
||||
/* Clear pending flag */
|
||||
pending = 0;
|
||||
|
||||
switch (code & 0x0F)
|
||||
{
|
||||
case 0x00: /* VRAM */
|
||||
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
||||
break;
|
||||
|
||||
case 0x08: /* CRAM */
|
||||
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
||||
temp = UNPACK_CRAM (temp);
|
||||
break;
|
||||
|
||||
case 0x04: /* VSRAM */
|
||||
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment address register */
|
||||
addr += reg[15];
|
||||
|
||||
/* return data */
|
||||
return (temp);
|
||||
}
|
||||
|
||||
unsigned int vdp_hvc_r(void)
|
||||
{
|
||||
uint8 hc = (hc_latch == -1) ? hctab[count_m68k%488] : (hc_latch & 0xFF);
|
||||
uint8 hc = (hc_latch & 0x100) ? (hc_latch & 0xFF) : hctab[count_m68k % m68cycles_per_line];
|
||||
uint8 vc = vctab[v_counter];
|
||||
|
||||
/* interlace mode 2 */
|
||||
@ -848,13 +916,26 @@ void vdp_test_w(unsigned int value)
|
||||
|
||||
int vdp_int_ack_callback(int int_level)
|
||||
{
|
||||
if (vint_triggered)
|
||||
|
||||
if (irq_status&0x20)
|
||||
{
|
||||
vint_pending = 0;
|
||||
vint_triggered = 0;
|
||||
status &= ~0x0080; /* clear VINT flag */
|
||||
status &= ~0x80; /* clear VINT flag */
|
||||
}
|
||||
else hint_pending = 0;
|
||||
hvint_updated = 0;
|
||||
else
|
||||
{
|
||||
hint_pending = 0;
|
||||
}
|
||||
|
||||
irq_status = 0x10;
|
||||
if (vint_pending && (reg[1] & 0x20))
|
||||
{
|
||||
irq_status |= 6;
|
||||
}
|
||||
else if (hint_pending && (reg[0] & 0x10))
|
||||
{
|
||||
irq_status |= 4;
|
||||
}
|
||||
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
@ -38,8 +38,7 @@ extern uint16 status;
|
||||
extern uint8 dmafill;
|
||||
extern uint8 hint_pending;
|
||||
extern uint8 vint_pending;
|
||||
extern uint8 vint_triggered;
|
||||
extern int8 hvint_updated;
|
||||
extern uint16 irq_status;
|
||||
|
||||
/* Global variables */
|
||||
extern uint16 ntab;
|
||||
@ -56,8 +55,7 @@ extern uint8 playfield_shift;
|
||||
extern uint8 playfield_col_mask;
|
||||
extern uint16 playfield_row_mask;
|
||||
extern uint32 y_mask;
|
||||
extern int16 h_counter;
|
||||
extern int16 hc_latch;
|
||||
extern uint16 hc_latch;
|
||||
extern uint16 v_counter;
|
||||
extern uint8 im2_flag;
|
||||
extern uint32 dma_length;
|
||||
@ -85,7 +83,6 @@ extern unsigned int vdp_ctrl_r(void);
|
||||
extern void vdp_data_w(unsigned int data);
|
||||
extern unsigned int vdp_data_r(void);
|
||||
extern unsigned int vdp_hvc_r(void);
|
||||
extern void vdp_reg_w(unsigned int r, unsigned int d);
|
||||
extern void dma_update();
|
||||
extern void vdp_test_w(unsigned int value);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user