From 0165ac387f39b87a9617b40089fceaa8eb21f04b Mon Sep 17 00:00:00 2001 From: ekeeke31 Date: Thu, 4 Dec 2008 19:32:22 +0000 Subject: [PATCH] huge update --- history.txt | 11 +- source/cart_hw/cart_hw.c | 483 ++++++++-------- source/cart_hw/cart_hw.h | 8 +- source/cart_hw/svp/svp.c | 22 + source/cart_hw/svp/svp.h | 3 + source/gen_input.c | 66 +-- source/gen_input.h | 36 +- source/genesis.c | 159 ++--- source/genesis.h | 13 +- source/m68k/m68k.h | 38 +- source/m68k/m68kconf.h | 4 +- source/m68k/m68kcpu.c | 64 ++- source/m68k/m68kcpu.h | 37 +- source/mem68k.c | 1117 +++++++++++++----------------------- source/mem68k.h | 62 +- source/membnk.c | 313 +++------- source/membnk.h | 17 +- source/memvdp.c | 93 --- source/memvdp.h | 29 - source/memz80.c | 116 ++-- source/ngc/config.c | 4 + source/ngc/gui/menu.c | 19 +- source/ngc/ngc.c | 4 +- source/ngc/ogc_audio.c | 14 +- source/ngc/ogc_input.c | 3 +- source/ngc/ogc_video.c | 35 +- source/ntsc/sms_ntsc.c | 59 +- source/render.c | 1178 +++++++++++++++++++++----------------- source/render.h | 11 +- source/shared.h | 1 - source/sound/fm.c | 6 +- source/state.c | 54 +- source/system.c | 162 +++--- source/system.h | 4 +- source/vdp.c | 371 +++++++----- source/vdp.h | 7 +- 36 files changed, 2160 insertions(+), 2463 deletions(-) delete mode 100644 source/memvdp.c delete mode 100644 source/memvdp.h diff --git a/history.txt b/history.txt index 4f6592a..177a6a8 100644 --- a/history.txt +++ b/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 diff --git a/source/cart_hw/cart_hw.c b/source/cart_hw/cart_hw.c index 5bd941e..a43802b 100644 --- a/source/cart_hw/cart_hw.c +++ b/source/cart_hw/cart_hw.c @@ -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: diff --git a/source/cart_hw/cart_hw.h b/source/cart_hw/cart_hw.h index a7eec0a..05d0c5c 100644 --- a/source/cart_hw/cart_hw.h +++ b/source/cart_hw/cart_hw.h @@ -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(); diff --git a/source/cart_hw/svp/svp.c b/source/cart_hw/svp/svp.c index a999591..4e9f19c 100644 --- a/source/cart_hw/svp/svp.c +++ b/source/cart_hw/svp/svp.c @@ -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)); +} + diff --git a/source/cart_hw/svp/svp.h b/source/cart_hw/svp/svp.h index e46c210..af02d17 100644 --- a/source/cart_hw/svp/svp.h +++ b/source/cart_hw/svp/svp.h @@ -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 diff --git a/source/gen_input.c b/source/gen_input.c index 8e585d1..62fb7c2 100644 --- a/source/gen_input.c +++ b/source/gen_input.c @@ -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); diff --git a/source/gen_input.h b/source/gen_input.h index 4254bd5..4918c21 100644 --- a/source/gen_input.h +++ b/source/gen_input.h @@ -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 diff --git a/source/genesis.c b/source/genesis.c index a9ca234..f0d6fb7 100644 --- a/source/genesis.c +++ b/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; } diff --git a/source/genesis.h b/source/genesis.h index c632fe8..2fa9b80 100644 --- a/source/genesis.h +++ b/source/genesis.h @@ -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); diff --git a/source/m68k/m68k.h b/source/m68k/m68k.h index c2536a9..7e74480 100644 --- a/source/m68k/m68k.h +++ b/source/m68k/m68k.h @@ -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. */ diff --git a/source/m68k/m68kconf.h b/source/m68k/m68kconf.h index bcb72b6..a64de89 100644 --- a/source/m68k/m68kconf.h +++ b/source/m68k/m68kconf.h @@ -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. diff --git a/source/m68k/m68kcpu.c b/source/m68k/m68kcpu.c index f88675c..65224e2 100644 --- a/source/m68k/m68kcpu.c +++ b/source/m68k/m68kcpu.c @@ -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; diff --git a/source/m68k/m68kcpu.h b/source/m68k/m68kcpu.h index ad174ce..a446c71 100644 --- a/source/m68k/m68kcpu.h +++ b/source/m68k/m68kcpu.h @@ -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 diff --git a/source/mem68k.c b/source/mem68k.c index 2b53ca7..e73e552 100644 --- a/source/mem68k.c +++ b/source/mem68k.c @@ -24,21 +24,9 @@ #include "m68kcpu.h" #include "shared.h" -uint8 m68k_readmap_8[32]; -uint8 m68k_readmap_16[32]; -uint8 m68k_writemap_8[32]; -uint8 m68k_writemap_16[32]; - - -uint8 pico_current; -static uint8 pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F}; - - -static inline unsigned int m68k_read_bus_8(unsigned int address) +uint32 m68k_read_bus_8(uint32 address) { #ifdef LOGERROR - if ((address != 0xa11100) && (address != 0xc00004) && (address != 0xc00006)) - { error("Unused read8 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0)); error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1)); @@ -56,20 +44,14 @@ static inline unsigned int m68k_read_bus_8(unsigned int address) error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5)); error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6)); error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7)); - } #endif - int bus_addr = (REG_PC & 0xffffe) | (address & 1); - int offset = bus_addr >> 19; + return m68k_read_pcrelative_8(REG_PC | (address&1)); - if (offset > 8) return READ_BYTE(work_ram, bus_addr & 0xffff); - else return READ_BYTE(rom_readmap[offset], bus_addr & 0x7ffff); } -static inline unsigned int m68k_read_bus_16(unsigned int address) +uint32 m68k_read_bus_16(uint32 address) { #ifdef LOGERROR - if ((address != 0xa11100) && (address != 0xc00004) && (address != 0xc00006)) - { error("Unused read16 %08X (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); error("D0 = %x \n", m68k_get_reg (NULL, M68K_REG_D0)); error("D1 = %x \n", m68k_get_reg (NULL, M68K_REG_D1)); @@ -87,27 +69,22 @@ static inline unsigned int m68k_read_bus_16(unsigned int address) error("A5 = %x \n", m68k_get_reg (NULL, M68K_REG_A5)); error("A6 = %x \n", m68k_get_reg (NULL, M68K_REG_A6)); error("A7 = %x \n", m68k_get_reg (NULL, M68K_REG_A7)); - } #endif - int bus_addr = REG_PC & 0xfffffe; - int offset = bus_addr >> 19; - - if (offset > 8) return *(uint16 *)(work_ram + (bus_addr & 0xffff)); - else return *(uint16 *)(rom_readmap[offset] + (bus_addr & 0x7ffff)); + return m68k_read_pcrelative_16(REG_PC); } -static inline void m68k_unused_8_w (unsigned int address, unsigned int value) +void m68k_unused_8_w (uint32 address, uint32 data) { #ifdef LOGERROR - error("Unused write8 %08X = %02X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC)); + error("Unused write8 %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif } -static inline void m68k_unused_16_w (unsigned int address, unsigned int value) +void m68k_unused_16_w (uint32 address, uint32 data) { #ifdef LOGERROR - error("Unused write16 %08X = %04X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC)); + error("Unused write16 %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif } @@ -117,25 +94,25 @@ static inline void m68k_unused_16_w (unsigned int address, unsigned int value) (cycle power to restart). */ -static inline void m68k_lockup_w_8 (unsigned int address, unsigned int value) +void m68k_lockup_w_8 (uint32 address, uint32 data) { #ifdef LOGERROR - error ("Lockup %08X = %02X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif gen_running = config.force_dtack; if (!gen_running) m68k_end_timeslice (); } -static inline void m68k_lockup_w_16 (unsigned int address, unsigned int value) +void m68k_lockup_w_16 (uint32 address, uint32 data) { #ifdef LOGERROR - error ("Lockup %08X = %04X (%08X)\n", address, value, m68k_get_reg (NULL, M68K_REG_PC)); + error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC)); #endif gen_running = config.force_dtack; if (!gen_running) m68k_end_timeslice (); } -static inline unsigned int m68k_lockup_r_8 (unsigned int address) +uint32 m68k_lockup_r_8 (uint32 address) { #ifdef LOGERROR error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); @@ -145,7 +122,7 @@ static inline unsigned int m68k_lockup_r_8 (unsigned int address) return -1; } -static inline unsigned int m68k_lockup_r_16 (unsigned int address) +uint32 m68k_lockup_r_16 (uint32 address) { #ifdef LOGERROR error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC)); @@ -155,275 +132,226 @@ static inline unsigned int m68k_lockup_r_16 (unsigned int address) return -1; } +/* PICO data */ +static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F}; + /*--------------------------------------------------------------------------*/ /* 68000 memory handlers */ /*--------------------------------------------------------------------------*/ -unsigned int m68k_read_memory_8(unsigned int address) + +/******* EEPROM **********************************************/ + +uint32 eeprom_read_byte(uint32 address) { - int offset = address >> 19; + if (address == eeprom.type.sda_out_adr) + return eeprom_read(address, 0); + else + return READ_BYTE(cart_rom, address); +} - switch (m68k_readmap_8[offset]) - { - case WRAM: - return READ_BYTE(work_ram, address & 0xffff); +uint32 eeprom_read_word(uint32 address) +{ + if (address == (eeprom.type.sda_out_adr & 0xfffffe)) + return eeprom_read(address, 1); + else + return *(uint16 *)(cart_rom + address); +} - case SYSTEM_IO: - { - unsigned int base = address >> 8; +void eeprom_write_byte(uint32 address, uint32 data) +{ + if ((address == eeprom.type.sda_in_adr) || + (address == eeprom.type.scl_adr)) + eeprom_write(address, data, 0); + else + m68k_unused_8_w(address, data); +} - /* Z80 */ - if (base <= 0xa0ff) +void eeprom_write_word(uint32 address, uint32 data) +{ + if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || + (address == (eeprom.type.scl_adr&0xfffffe))) + eeprom_write(address, data, 1); + else + m68k_unused_16_w (address, data); +} + + +/******* Z80 *************************************************/ + +uint32 z80_read_byte(uint32 address) { - /* Z80 controls Z bus ? */ if (zbusack) return m68k_read_bus_8(address); - /* Read data from Z bus */ - switch (base & 0x60) + switch ((address >> 13) & 3) { - case 0x40: /* YM2612 */ + case 2: /* YM2612 */ return fm_read(0, address & 3); - case 0x60: /* VDP */ - if (base == 0xa07f) return m68k_lockup_r_8(address); - return (m68k_read_bus_8(address) | 0xff); + case 3: /* MISC */ + if ((address & 0xff00) == 0x7f00) + return m68k_lockup_r_8(address); /* VDP */ + else + return (m68k_read_bus_8(address) | 0xff); default: /* ZRAM */ return zram[address & 0x1fff]; } } - /* I/O & CONTROL registers */ - if (base <= 0xa1ff) +uint32 z80_read_word(uint32 address) +{ + if (zbusack) return m68k_read_bus_16(address); + + switch ((address >> 13) & 3) { - switch (base & 0xff) + case 2: /* YM2612 */ { - case 0x00: /* I/O chip */ - if (address & 0xe0) return m68k_read_bus_8(address); - return (io_read((address >> 1) & 0x0f)); + int temp = fm_read(0, address & 3); + return (temp << 8 | temp); + } - case 0x11: /* BUSACK */ - return (zbusack | (address & 1) | (m68k_read_bus_8(address) & 0xFE)); + case 3: /* MISC */ + if ((address & 0xff00) == 0x7f00) + return m68k_lockup_r_16(address); /* VDP */ + else + return (m68k_read_bus_16(address) | 0xffff); - case 0x30: /* TIME */ - if (cart_hw.time_r) return cart_hw.time_r(address); - else return m68k_read_bus_8(address); - - case 0x10: /* MEMORY MODE */ - case 0x12: /* RESET */ - case 0x20: /* MEGA-CD */ - case 0x40: /* TMSS */ - case 0x41: /* BOOTROM */ - case 0x44: /* RADICA */ - case 0x50: /* SVP REGISTERS */ - return m68k_read_bus_8(address); - - default: /* Invalid address */ - return m68k_lockup_r_8(address); + default: /* ZRAM */ + { + int temp = zram[address & 0x1fff]; + return (temp << 8 | temp); + } } } - /* Invalid address */ - return m68k_lockup_r_8(address); - } - - case VDP: - - /* Valid VDP addresses */ - if (((address >> 16) & 0x07) == 0) - { - switch (address & 0xff) +void z80_write_byte(uint32 address, uint32 data) +{ + if (zbusack) { - case 0x00: /* DATA */ - case 0x02: - return (vdp_data_r() >> 8); + m68k_unused_8_w(address, data); + return; + } - case 0x01: /* DATA */ - case 0x03: - return (vdp_data_r() & 0xff); + switch ((address >> 13) & 3) + { + case 2: /* YM2612 */ + fm_write(0, address & 3, data); + return; - case 0x04: /* CTRL */ - case 0x06: - return ((m68k_read_bus_8(address) & 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: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: /* Unused */ - return m68k_read_bus_8(address); - - default: /* Invalid address */ - return m68k_lockup_r_8(address); - } - } - - /* Invalid address */ - return (m68k_lockup_r_8 (address)); - - case SRAM: - if (address <= sram.end) return READ_BYTE(sram.sram, address - sram.start); - return READ_BYTE(rom_readmap[offset], address & 0x7ffff); - - case EEPROM: - if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0); - return READ_BYTE(rom_readmap[offset], address & 0x7ffff); - - case CART_HW: - return cart_hw.regs_r(address); - - case UNUSED: - return m68k_read_bus_8(address); - - case ILLEGAL: - return m68k_lockup_r_8(address); - - case UMK3_HACK: - return READ_BYTE(&cart_rom[offset << 19], address & 0x7ffff); - - case PICO_HW: - switch (address & 0xff) + case 3: + switch ((address >> 8) & 0x7f) { - case 0x01: /* VERSION register */ - return (0x40); + case 0x60: /* Bank register */ + gen_bank_w(data & 1); + return; - case 0x03: /* IO register */ + case 0x7f: /* VDP */ + m68k_lockup_w_8(address, data); + return; + + default: + m68k_unused_8_w(address, data); + return; + } + + default: /* ZRAM */ + zram[address & 0x1fff] = data; + count_m68k++; /* Z80 bus latency (Pacman 2: New Adventures) */ + return; + } + } + +void z80_write_word(uint32 address, uint32 data) + { + /* Z80 still hold the bus ? */ + if (zbusack) + { + m68k_unused_16_w(address, data); + return; + } + + switch ((address >> 13) & 3) { - uint8 retval = 0xff; - if (input.pad[0] & INPUT_B) retval &= ~0x10; - if (input.pad[0] & INPUT_A) retval &= ~0x80; - if (input.pad[0] & INPUT_UP) retval &= ~0x01; - if (input.pad[0] & INPUT_DOWN) retval &= ~0x02; - if (input.pad[0] & INPUT_LEFT) retval &= ~0x04; - if (input.pad[0] & INPUT_RIGHT) retval &= ~0x08; - retval &= ~0x20; - retval &= ~0x40; - return retval; - } + case 2: /* YM2612 */ + fm_write (0, address & 3, data >> 8); + return; - case 0x05: /* MSB PEN X coordinate */ - return (input.analog[0][0] >> 8); + case 3: + switch ((address >> 8) & 0x7f) + { + case 0x60: /* Bank register */ + gen_bank_w ((data >> 8) & 1); + return; - case 0x07: /* LSB PEN X coordinate */ - return (input.analog[0][0] & 0xff); - - case 0x09: /* MSB PEN Y coordinate */ - return (input.analog[0][1] >> 8); - - case 0x0b: /* LSB PEN Y coordinate */ - return (input.analog[0][1] & 0xff); - - case 0x0d: /* PAGE register */ - return pico_page[pico_current]; /* TODO */ - - case 0x10: /* PCM registers */ - case 0x11: - case 0x12: - case 0x13: - return 0x80; /* TODO */ + case 0x7f: /* VDP */ + m68k_lockup_w_16(address, data); + return; default: - return m68k_read_bus_8(address); + m68k_unused_16_w(address, data); + return; } - default: /* ROM */ - return READ_BYTE(rom_readmap[offset], address & 0x7ffff); + default: /* ZRAM */ + zram[address & 0x1fff] = data >> 8; + return; } } - -unsigned int m68k_read_memory_16 (unsigned int address) -{ - int offset = address >> 19; - - switch (m68k_readmap_16[offset]) - { - case WRAM: - return *(uint16 *)(work_ram + (address & 0xffff)); - - case SVP_DRAM: - return *(uint16 *)(svp->dram + (address & 0x1fffe)); - - case SVP_CELL: - switch (address >> 16) - { - case 0x39: - address >>= 1; - address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5); - return *(uint16 *)(svp->dram + (address & 0x1fffe)); - case 0x3A: - address >>= 1; - address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4); - return *(uint16 *)(svp->dram + (address & 0x1fffe)); - - default: - return m68k_read_bus_16(address); - } - - case SYSTEM_IO: - { - unsigned int base = address >> 8; - - /* Z80 */ - if (base <= 0xa0ff) - { - /* Z80 controls Z bus ? */ - if (zbusack) return m68k_read_bus_16(address); +/******* I/O & CTRL ******************************************/ - /* Read data from Z bus */ - switch (base & 0x60) +uint32 ctrl_io_read_byte(uint32 address) { - case 0x40: /* YM2612 */ + /* I/O & CONTROL REGISTERS */ + switch ((address >> 8) & 0xff) { - int temp = fm_read(0, address & 3); - return (temp << 8 | temp); - } + case 0x00: /* I/O chip */ + if (address & 0xe0) + return m68k_read_bus_8(address); + else + return (io_read((address >> 1) & 0x0f)); - case 0x60: /* VDP */ - if (base == 0xa07f) return m68k_lockup_r_16(address); - return (m68k_read_bus_16(address) | 0xffff); + case 0x11: /* BUSACK */ + if (address & 1) + return m68k_read_bus_8(address); + else + return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack); - default: /* ZRAM */ - { - int temp = zram[address & 0x1fff]; - return (temp << 8 | temp); - } + case 0x30: /* TIME */ + if (cart_hw.time_r) + return cart_hw.time_r(address); + else + return m68k_read_bus_8(address); + + case 0x10: /* MEMORY MODE */ + case 0x12: /* RESET */ + case 0x20: /* MEGA-CD */ + case 0x40: /* TMSS */ + case 0x41: /* BOOTROM */ + case 0x44: /* RADICA */ + case 0x50: /* SVP REGISTERS */ + return m68k_read_bus_8(address); + + default: /* Invalid address */ + return m68k_lockup_r_8(address); } } - /* CONTROL registers */ - if (base <= 0xa1ff) +uint32 ctrl_io_read_word(uint32 address) { - switch (base & 0xff) + switch ((address >> 8) & 0xff) { case 0x00: /* I/O chip */ { - if (address & 0xe0) return m68k_read_bus_16(address); + if (address & 0xe0) + return m68k_read_bus_16(address); int temp = io_read((address >> 1) & 0x0f); return (temp << 8 | temp); } case 0x11: /* BUSACK */ - return ((m68k_read_bus_16(address) & 0xfeff) | (zbusack << 8)); + return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8)); case 0x50: /* SVP */ if (svp) @@ -436,17 +364,23 @@ unsigned int m68k_read_memory_16 (unsigned int address) case 4: { - unsigned int temp = svp->ssp1601.gr[SSP_PM0].h; + uint32 temp = svp->ssp1601.gr[SSP_PM0].h; svp->ssp1601.gr[SSP_PM0].h &= ~1; return temp; } + + default: + return m68k_read_bus_16(address); } } + else return m68k_read_bus_16(address); case 0x30: /* TIME */ - if (cart_hw.time_r) return cart_hw.time_r(address); - else return m68k_read_bus_16(address); + if (cart_hw.time_r) + return cart_hw.time_r(address); + else + return m68k_read_bus_16(address); case 0x10: /* MEMORY MODE */ case 0x12: /* RESET */ @@ -456,282 +390,57 @@ unsigned int m68k_read_memory_16 (unsigned int address) case 0x44: /* RADICA */ return m68k_read_bus_16(address); - default: /* Invalid address */ - return m68k_lockup_r_16(address); - } - } - - /* Invalid address */ - return m68k_lockup_r_16 (address); - } - - case VDP: - - /* Valid VDP addresses */ - if (((address >> 16) & 0x07) == 0) - { - switch (address & 0xfc) - { - case 0x00: /* DATA */ - return vdp_data_r(); - - case 0x04: /* CTRL */ - return ((vdp_ctrl_r() & 0x3FF) | (m68k_read_bus_16(address) & 0xFC00)); - - case 0x08: /* HVC */ - case 0x0c: - return vdp_hvc_r(); - - case 0x18: /* Unused */ - case 0x1c: - return m68k_read_bus_16(address); - - default: - return m68k_lockup_r_16(address); - } - } - - /* Invalid address */ - return m68k_lockup_r_16 (address); - - case SRAM: - if (address <= sram.end) return *(uint16 *)(sram.sram + (address - sram.start)); - return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff)); - - case EEPROM: - if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1); - return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff)); - - case J_CART: - return jcart_read(); - - case REALTEC_ROM: - return *(uint16 *)(&cart_rom[0x7e000] + (address & 0x1fff)); - - case UNUSED: - return m68k_read_bus_16(address); - - case ILLEGAL: - return m68k_lockup_r_16(address); - - case UMK3_HACK: - return *(uint16 *)(&cart_rom[offset << 19] + (address & 0x7ffff)); - - case PICO_HW: - switch (address & 0xff) - { - case 0x00: /* VERSION register */ - return (0x40); - - case 0x02: /* IO register */ - { - uint8 retval = 0xff; - if (input.pad[0] & INPUT_B) retval &= ~0x10; - if (input.pad[0] & INPUT_A) retval &= ~0x80; - if (input.pad[0] & INPUT_UP) retval &= ~0x01; - if (input.pad[0] & INPUT_DOWN) retval &= ~0x02; - if (input.pad[0] & INPUT_LEFT) retval &= ~0x04; - if (input.pad[0] & INPUT_RIGHT) retval &= ~0x08; - retval &= ~0x20; - retval &= ~0x40; - return retval; - } - - case 0x04: /* MSB PEN X coordinate */ - return (input.analog[0][0] >> 8); - - case 0x06: /* LSB PEN X coordinate */ - return (input.analog[0][0] & 0xff); - - case 0x08: /* MSB PEN Y coordinate */ - return (input.analog[0][1] >> 8); - - case 0x0a: /* LSB PEN Y coordinate */ - return (input.analog[0][1] & 0xff); - - case 0x0c: /* PAGE register */ - return pico_page[pico_current]; /* TODO */ - - case 0x10: /* PCM data register */ - return 0x8000; /* TODO */ - - case 0x12: /* PCM control registe */ - return 0x8000; /* TODO */ - - default: - return m68k_read_bus_16(address); - } - - default: /* ROM */ - return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff)); - } -} - - -unsigned int m68k_read_memory_32(unsigned int address) -{ - /* Split into 2 reads */ - return ((m68k_read_memory_16 (address) << 16) | - (m68k_read_memory_16 ((address+ 2)&0xffffff))); -} - - -void m68k_write_memory_8(unsigned int address, unsigned int value) -{ - int offset = address >> 19; - - switch (m68k_writemap_8[offset]) - { - case VDP: - /* Valid VDP addresses */ - if (((address >> 16) & 0x07) == 0) - { - switch (address & 0xff) - { - case 0x00: /* Data port */ - case 0x01: - case 0x02: - case 0x03: - vdp_data_w(value << 8 | value); - return; - - case 0x04: /* Control port */ - case 0x05: - case 0x06: - case 0x07: - vdp_ctrl_w(value << 8 | value); - return; - - case 0x10: /* Unused */ - case 0x12: - case 0x14: - case 0x16: - m68k_unused_8_w(address, value); - return; - - case 0x11: /* PSG */ - case 0x13: - case 0x15: - case 0x17: - psg_write(0, value); - return; - - case 0x18: /* Unused */ - case 0x19: - case 0x1a: - case 0x1b: - m68k_unused_8_w(address, value); - return; - - case 0x1c: /* Test register */ - case 0x1d: - case 0x1e: - case 0x1f: - vdp_test_w(value << 8 | value); - return; - - default: /* Invalid address */ - m68k_lockup_w_8(address, value); - return; + default: /* Invalid address */ + return m68k_lockup_r_16(address); } } - /* Invalid address */ - m68k_lockup_w_8(address, value); - return; - - - case SYSTEM_IO: - { - unsigned int base = address >> 8; - - /* Z80 */ - if (base <= 0xa0ff) - { - /* Writes are ignored when the Z80 hogs the Z-bus */ - if (zbusack) - { - m68k_unused_8_w (address, value); - return; - } - - /* Read data from Z bus */ - switch (base & 0x60) - { - case 0x40: /* YM2612 */ - fm_write(0, address & 3, value); - return; - - case 0x60: - switch (base & 0x7f) - { - case 0x60: /* Bank register */ - gen_bank_w(value & 1); - return; - - case 0x7f: /* VDP */ - m68k_lockup_w_8(address, value); - return; - - default: - m68k_unused_8_w(address, value); - return; - } - - default: /* ZRAM */ - zram[address & 0x1fff] = value; - count_m68k ++; - return; - } - } - - /* CONTROL registers */ - if (base <= 0xa1ff) +void ctrl_io_write_byte(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, value); - else m68k_unused_8_w(address, value); + case 0x00: /* I/O chip */ + if ((address & 0xe1) == 0x01) + io_write((address >> 1) & 0x0f, data); /* get /LWR only */ + else + m68k_unused_8_w(address, data); return; case 0x11: /* BUSREQ */ - if (address & 1) m68k_unused_8_w(address, value); - else gen_busreq_w(value & 1); + if (address & 1) + m68k_unused_8_w(address, data); + else + gen_busreq_w(data & 1); return; case 0x12: /* RESET */ - if (address & 1) m68k_unused_8_w(address, value); - else gen_reset_w(value & 1); + if (address & 1) + m68k_unused_8_w(address, data); + else + gen_reset_w(data & 1); return; case 0x30: /* TIME */ - if (cart_hw.time_w) cart_hw.time_w(address, value); - else m68k_unused_8_w(address, value); + if (cart_hw.time_w) + cart_hw.time_w(address, data); + else + m68k_unused_8_w(address, data); return; case 0x41: /* BOOTROM */ if (address & 1) { - if (value & 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 m68k_unused_8_w (address, value); + else m68k_unused_8_w (address, data); return; case 0x10: /* MEMORY MODE */ @@ -739,216 +448,71 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) case 0x40: /* TMSS */ case 0x44: /* RADICA */ case 0x50: /* SVP REGISTERS */ - m68k_unused_8_w(address, value); + m68k_unused_8_w(address, data); return; default: /* Invalid address */ - m68k_lockup_w_8(address, value); + m68k_lockup_w_8(address, data); return; } } - /* Invalid address */ - m68k_lockup_w_8(address, value); - return; - } - - case ROM: - WRITE_BYTE(rom_readmap[offset], address & 0x7ffff, value); - return; - - case SRAM: - if (address <= sram.end) WRITE_BYTE(sram.sram, address - sram.start, value); - else m68k_unused_8_w(address, value); - return; - - case EEPROM: - if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, value, 0); - else m68k_unused_8_w(address, value); - return; - - case CART_HW: - cart_hw.regs_w(address, value); - return; - - case UNUSED: - m68k_unused_8_w(address, value); - return; - - case ILLEGAL: - m68k_lockup_w_8(address, value); - return; - - case PICO_HW: - switch (address & 0xff) - { - case 0x19: - case 0x1b: - case 0x1d: - case 0x1f: /* TMSS register */ - return; - - default: - m68k_unused_8_w(address, value); - return; - } - - default: /* WRAM */ - WRITE_BYTE(work_ram, address & 0xffff, value); - return; - } -} - - -void m68k_write_memory_16 (unsigned int address, unsigned int value) -{ - int offset = address >> 19; - - switch (m68k_writemap_16[offset]) - { - case SVP_DRAM: - *(uint16 *)(svp->dram + (address & 0x1fffe)) = value; - if ((address == 0x30fe06) && value) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06; - if ((address == 0x30fe08) && value) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08; - return; - - case VDP: - /* Valid VDP addresses */ - if (((address >> 16) & 0x07) == 0) - { - switch (address & 0xfc) - { - case 0x00: /* DATA */ - vdp_data_w(value); - return; - - case 0x04: /* CTRL */ - vdp_ctrl_w(value); - return; - - case 0x10: /* PSG */ - case 0x14: - psg_write(0, value & 0xff); - return; - - case 0x18: /* Unused */ - m68k_unused_16_w(address, value); - return; - - case 0x1c: /* Test register */ - vdp_test_w(value); - return; - - default: /* Invalid address */ - m68k_lockup_w_16 (address, value); - return; - } - } - - /* Invalid address */ - m68k_lockup_w_16 (address, value); - return; - - - case SYSTEM_IO: - { - unsigned int base = address >> 8; - - /* Z80 */ - if (base <= 0xa0ff) - { - /* Writes are ignored when the Z80 hogs the Z-bus */ - if (zbusack) - { - m68k_unused_16_w (address, value); - return; - } - - /* Write into Z80 address space */ - switch (base & 0x60) - { - case 0x40: /* YM2612 */ - fm_write (0, address & 3, value >> 8); - return; - - case 0x60: - switch (base & 0x7f) - { - case 0x60: /* Bank register */ - gen_bank_w ((value >> 8) & 1); - return; - - case 0x7f: /* VDP */ - m68k_lockup_w_16(address, value); - return; - - default: - m68k_unused_16_w(address, value); - return; - } - - default: /* ZRAM */ - zram[address & 0x1fff] = value >> 8; - return; - } - } - - /* CONTROL registers */ - if (base <= 0xa1ff) +void ctrl_io_write_word(uint32 address, uint32 data) { - switch (base & 0xff) + switch ((address >> 8) & 0xff) { case 0x00: /* I/O chip */ - if (address & 0xe0) m68k_unused_16_w (address, value); - else io_write ((address >> 1) & 0x0f, value & 0xff); + if (address & 0xe0) + m68k_unused_16_w (address, data); + else + io_write ((address >> 1) & 0x0f, data & 0xff); return; case 0x11: /* BUSREQ */ - gen_busreq_w ((value >> 8) & 1); + gen_busreq_w ((data >> 8) & 1); return; case 0x12: /* RESET */ - gen_reset_w ((value >> 8) & 1); + gen_reset_w ((data >> 8) & 1); return; case 0x50: /* SVP REGISTERS */ - if (svp && ((address & 0xfd) == 0)) + if (svp) + { + if (address & 0xfd) + m68k_unused_16_w(address, data); + else { /* just guessing here (Notaz) */ - svp->ssp1601.gr[SSP_XST].h = value; + svp->ssp1601.gr[SSP_XST].h = data; svp->ssp1601.gr[SSP_PM0].h |= 2; svp->ssp1601.emu_status &= ~SSP_WAIT_PM0; - return; } - m68k_unused_16_w(address, value); + } + else + m68k_unused_16_w (address, data); return; case 0x30: /* TIME */ if (cart_hw.time_w) { - cart_hw.time_w(address & 0xfe, value >> 8); - cart_hw.time_w(address, value & 0xff); + cart_hw.time_w(address & 0xfe, data >> 8); + cart_hw.time_w(address, data & 0xff); } - else m68k_unused_16_w (address, value); + else + m68k_unused_16_w (address, data); return; case 0x41: /* BOOTROM */ - if (value & 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); } return; @@ -956,76 +520,191 @@ void m68k_write_memory_16 (unsigned int address, unsigned int value) case 0x20: /* MEGA-CD */ case 0x40: /* TMSS */ case 0x44: /* RADICA */ - m68k_unused_16_w (address, value); + m68k_unused_16_w (address, data); return; default: /* Unused */ - m68k_lockup_w_16 (address, value); + m68k_lockup_w_16 (address, data); return; } } - /* Invalid address */ - m68k_lockup_w_16 (address, value); - return; - } - case ROM: - *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff)) = value; +/******* VDP *************************************************/ + +uint32 vdp_read_byte(uint32 address) +{ + switch (address & 0xfd) + { + case 0x00: /* DATA */ + return (vdp_data_r() >> 8); + + case 0x01: /* DATA */ + return (vdp_data_r() & 0xff); + + case 0x04: /* CTRL */ + return ((m68k_read_pcrelative_8(REG_PC) & 0xfc) | ((vdp_ctrl_r() >> 8) & 3)); + + case 0x05: /* CTRL */ + return (vdp_ctrl_r() & 0xff); + + case 0x08: /* HVC */ + case 0x0c: + return (vdp_hvc_r() >> 8); + + case 0x09: /* HVC */ + case 0x0d: + return (vdp_hvc_r() & 0xff); + + case 0x18: /* Unused */ + case 0x19: + case 0x1c: + case 0x1d: + return m68k_read_bus_8(address); + + default: /* Invalid address */ + return m68k_lockup_r_8(address); + } +} + +uint32 vdp_read_word(uint32 address) +{ + switch (address & 0xfc) + { + case 0x00: /* DATA */ + return vdp_data_r(); + + case 0x04: /* CTRL */ + return ((vdp_ctrl_r() & 0x3FF) | (m68k_read_pcrelative_16(REG_PC) & 0xFC00)); + + case 0x08: /* HVC */ + case 0x0c: + return vdp_hvc_r(); + + case 0x18: /* Unused */ + case 0x1c: + return m68k_read_bus_16(address); + + default: /* Invalid address */ + return m68k_lockup_r_16(address); + } +} + +void vdp_write_byte(uint32 address, uint32 data) +{ + switch (address & 0xfc) + { + case 0x00: /* Data port */ + vdp_data_w(data << 8 | data); + return; + + case 0x04: /* Control port */ + vdp_ctrl_w(data << 8 | data); + return; + + case 0x10: /* PSG */ + case 0x14: + if (address & 1) psg_write(0, data); + else m68k_unused_8_w(address, data); + return; + + case 0x18: /* Unused */ + m68k_unused_8_w(address, data); + return; + + case 0x1c: /* TEST register */ + vdp_test_w(data << 8 | data); + return; + + default: /* Invalid address */ + m68k_lockup_w_8(address, data); + return; + } +} + +void vdp_write_word(uint32 address, uint32 data) + { + switch (address & 0xfc) + { + case 0x00: /* DATA */ + vdp_data_w(data); return; - case SRAM: - if (address <= sram.end) *(uint16 *)(sram.sram + (address - sram.start)) = value; - else m68k_unused_16_w (address, value); + case 0x04: /* CTRL */ + vdp_ctrl_w(data); return; - case EEPROM: - if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe))) - eeprom_write(address, value, 1); - else m68k_unused_16_w (address, value); + case 0x10: /* PSG */ + case 0x14: + psg_write(0, data & 0xff); + return; + + case 0x18: /* Unused */ + m68k_unused_16_w(address, data); return; - case J_CART: - jcart_write(value); + case 0x1c: /* Test register */ + vdp_test_w(data); return; - case UNUSED: - m68k_unused_16_w (address, value); + default: /* Invalid address */ + m68k_lockup_w_16 (address, data); return; + } + } - case ILLEGAL: - m68k_lockup_w_16 (address, value); - return; - case PICO_HW: - switch (address & 0xff) - { - case 0x10: /* PCM data register */ - return; /* TODO */ - - case 0x12: /* PCM control resiter */ - return; /* TODO */ - - case 0x18: - case 0x1a: - case 0x1c: - case 0x1e: /* TMSS register */ - return; +/******* PICO ************************************************/ + +uint32 pico_read_byte(uint32 address) +{ + /* PICO */ + switch (address & 0xff) + { + case 0x01: /* VERSION register */ + return (0x40); + + case 0x03: /* IO register */ + { + uint8 retval = 0xff; + if (input.pad[0] & INPUT_B) retval &= ~0x10; + if (input.pad[0] & INPUT_A) retval &= ~0x80; + if (input.pad[0] & INPUT_UP) retval &= ~0x01; + if (input.pad[0] & INPUT_DOWN) retval &= ~0x02; + if (input.pad[0] & INPUT_LEFT) retval &= ~0x04; + if (input.pad[0] & INPUT_RIGHT) retval &= ~0x08; + retval &= ~0x20; + retval &= ~0x40; + return retval; + } + + case 0x05: /* MSB PEN X coordinate */ + return (input.analog[0][0] >> 8); + + case 0x07: /* LSB PEN X coordinate */ + return (input.analog[0][0] & 0xff); + + case 0x09: /* MSB PEN Y coordinate */ + return (input.analog[0][1] >> 8); + + case 0x0b: /* LSB PEN Y coordinate */ + return (input.analog[0][1] & 0xff); + + case 0x0d: /* PAGE register */ + return pico_page[pico_current]; /* TODO */ + + case 0x10: /* PCM registers */ + case 0x11: + case 0x12: + case 0x13: + return 0x80; /* TODO */ default: - m68k_unused_16_w(address, value); - return; - } - - default: /* WRAM */ - *(uint16 *)(work_ram + (address & 0xffff)) = value; - return; + return m68k_read_bus_8(address); } } -void m68k_write_memory_32 (unsigned int address, unsigned int value) +uint32 pico_read_word(uint32 address) { - /* Split into 2 writes */ - m68k_write_memory_16 (address, value >> 16); - m68k_write_memory_16 ((address+2) & 0xffffff, value & 0xffff); + return ((m68k_read_bus_8(address) << 8) | pico_read_byte(address | 1)); } diff --git a/source/mem68k.h b/source/mem68k.h index d6634e7..cba9042 100644 --- a/source/mem68k.h +++ b/source/mem68k.h @@ -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_ */ diff --git a/source/membnk.c b/source/membnk.c index 9f6cd41..604898d 100644 --- a/source/membnk.c +++ b/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; } } diff --git a/source/membnk.h b/source/membnk.h index 332a3b1..32fcd31 100644 --- a/source/membnk.h +++ b/source/membnk.h @@ -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_ */ diff --git a/source/memvdp.c b/source/memvdp.c deleted file mode 100644 index 0521950..0000000 --- a/source/memvdp.c +++ /dev/null @@ -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)); - } -} diff --git a/source/memvdp.h b/source/memvdp.h deleted file mode 100644 index 5e6b237..0000000 --- a/source/memvdp.h +++ /dev/null @@ -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_ */ diff --git a/source/memz80.c b/source/memz80.c index f081344..9d95e8d 100644 --- a/source/memz80.c +++ b/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. diff --git a/source/ngc/config.c b/source/ngc/config.c index 7f51378..ab65d38 100644 --- a/source/ngc/config.c +++ b/source/ngc/config.c @@ -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; diff --git a/source/ngc/gui/menu.c b/source/ngc/gui/menu.c index f638116..6787981 100644 --- a/source/ngc/gui/menu.c +++ b/source/ngc/gui/menu.c @@ -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; } } diff --git a/source/ngc/ngc.c b/source/ngc/ngc.c index ba87105..2a28a8a 100644 --- a/source/ngc/ngc.c +++ b/source/ngc/ngc.c @@ -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 */ diff --git a/source/ngc/ogc_audio.c b/source/ngc/ogc_audio.c index 619a5ce..dbd0903 100644 --- a/source/ngc/ogc_audio.c +++ b/source/ngc/ogc_audio.c @@ -21,6 +21,7 @@ #include "shared.h" #include "ogc_input.h" +//#include /* 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(); + } } diff --git a/source/ngc/ogc_input.c b/source/ngc/ogc_input.c index effbb31..79fd202 100644 --- a/source/ngc/ogc_input.c +++ b/source/ngc/ogc_input.c @@ -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++) { diff --git a/source/ngc/ogc_video.c b/source/ngc/ogc_video.c index ab420cc..4ffe616 100644 --- a/source/ngc/ogc_video.c +++ b/source/ngc/ogc_video.c @@ -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 */ diff --git a/source/ntsc/sms_ntsc.c b/source/ntsc/sms_ntsc.c index 2a733d3..e862b29 100644 --- a/source/ntsc/sms_ntsc.c +++ b/source/ntsc/sms_ntsc.c @@ -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 diff --git a/source/render.c b/source/render.c index ad28fea..aa068a8 100644 --- a/source/render.c +++ b/source/render.c @@ -42,34 +42,19 @@ typedef struct }clip_t; /* Function prototypes */ -void render_obj(int line, uint8 *buf, uint8 *table); -void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd); -void render_ntw(int line, uint8 *buf); -void render_ntw_im2(int line, uint8 *buf, uint8 odd); -void render_ntx(int which, int line, uint8 *buf); -void render_ntx_im2(int which, int line, uint8 *buf, uint8 odd); -void render_ntx_vs(int which, int line, uint8 *buf); -void update_bg_pattern_cache(void); -void get_hscroll(int line, int shift, uint16 *scroll); -void window_clip(int line); -int make_lut_bg(int bx, int ax); -int make_lut_obj(int bx, int sx); -int make_lut_bg_ste(int bx, int ax); -int make_lut_obj_ste(int bx, int sx); -int make_lut_bgobj_ste(int bx, int sx); -void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width); -void make_name_lut(void); -void (*color_update)(int index, uint16 data); -void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length); -#ifndef NGC -void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length); -void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length); -#endif - -#ifndef LSB_FIRST -static uint32 ATTR_MSB; -#endif +static void render_obj(uint32 line, uint8 *buf, uint8 *table); +static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table); +static void render_bg(uint32 line, uint32 width); +static void render_bg_im2(uint32 line, uint32 width, uint32 odd); +static void render_bg_vs(uint32 line, uint32 width); +static void make_name_lut(void); +static uint32 make_lut_bg(uint32 bx, uint32 ax); +static uint32 make_lut_obj(uint32 bx, uint32 sx); +static uint32 make_lut_bg_ste(uint32 bx, uint32 ax); +static uint32 make_lut_obj_ste(uint32 bx, uint32 sx); +static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx); +#undef ALIGN_LONG #ifdef ALIGN_LONG /* Or change the names if you depend on these from elsewhere.. */ #undef READ_LONG @@ -184,7 +169,7 @@ static __inline__ void WRITE_LONG(void *address, uint32 data) src++; #else #define DRAW_COLUMN(ATTR, LINE) \ - ATTR_MSB = ATTR >> 16; \ + attr_msb = ATTR >> 16; \ atex = atex_table[(ATTR_MSB >> 13) & 7]; \ src = (uint32 *)&bg_pattern_cache[(ATTR_MSB & 0x1FFF) << 6 | (LINE)]; \ WRITE_LONG(dst, READ_LONG(src) | atex); \ @@ -216,9 +201,9 @@ static __inline__ void WRITE_LONG(void *address, uint32 data) *dst++ = (*src++ | atex); #else #define DRAW_COLUMN(ATTR, LINE) \ - ATTR_MSB = ATTR >> 16; \ - atex = atex_table[(ATTR_MSB >> 13) & 7]; \ - src = (uint32 *)&bg_pattern_cache[(ATTR_MSB & 0x1FFF) << 6 | (LINE)]; \ + attr_msb = ATTR >> 16; \ + atex = atex_table[(attr_msb >> 13) & 7]; \ + src = (uint32 *)&bg_pattern_cache[(attr_msb & 0x1FFF) << 6 | (LINE)]; \ *dst++ = (*src++ | atex); \ *dst++ = (*src++ | atex); \ atex = atex_table[(ATTR >> 13) & 7]; \ @@ -266,10 +251,10 @@ static __inline__ void WRITE_LONG(void *address, uint32 data) src++; #else #define DRAW_COLUMN_IM2(ATTR, LINE) \ - ATTR_MSB = ATTR >> 16; \ - atex = atex_table[(ATTR_MSB >> 13) & 7]; \ - offs = (ATTR_MSB & 0x03FF) << 7 | (ATTR_MSB & 0x1800) << 6 | (LINE); \ - if(ATTR_MSB & 0x1000) offs ^= 0x40; \ + attr_msb = ATTR >> 16; \ + atex = atex_table[(attr_msb >> 13) & 7]; \ + offs = (attr_msb & 0x03FF) << 7 | (attr_msb & 0x1800) << 6 | (LINE); \ + if(attr_msb & 0x1000) offs ^= 0x40; \ src = (uint32 *)&bg_pattern_cache[offs]; \ WRITE_LONG(dst, READ_LONG(src) | atex); \ dst++; \ @@ -306,10 +291,10 @@ static __inline__ void WRITE_LONG(void *address, uint32 data) *dst++ = (*src++ | atex); #else #define DRAW_COLUMN_IM2(ATTR, LINE) \ - ATTR_MSB = ATTR >> 16; \ - atex = atex_table[(ATTR_MSB >> 13) & 7]; \ - offs = (ATTR_MSB & 0x03FF) << 7 | (ATTR_MSB & 0x1800) << 6 | (LINE); \ - if(ATTR_MSB & 0x1000) offs ^= 0x40; \ + attr_msb = ATTR >> 16; \ + atex = atex_table[(attr_msb >> 13) & 7]; \ + offs = (attr_msb & 0x03FF) << 7 | (attr_msb & 0x1800) << 6 | (LINE); \ + if(attr_msb & 0x1000) offs ^= 0x40; \ src = (uint32 *)&bg_pattern_cache[offs]; \ *dst++ = (*src++ | atex); \ *dst++ = (*src++ | atex); \ @@ -335,7 +320,7 @@ static __inline__ void WRITE_LONG(void *address, uint32 data) #define DRAW_SPRITE_TILE \ for(i=0; i<8; i++) \ { \ - if ((lb[i] & 0x80) && ((lb[i] | src[i]) & 0x0F)) status |= 0x20; \ + if ((lb[i] & 0x80) && (lb[i] & 0x0F) && (src[i] & 0x0F)) status |= 0x20; \ lb[i] = table[(lb[i] << 8) |(src[i] | palette)]; \ } @@ -376,7 +361,7 @@ struct uint16 xpos; uint16 attr; uint8 size; - uint8 index; + uint8 index; // unused } object_info[20]; /* Pixel look-up tables and table base address */ @@ -409,7 +394,7 @@ static uint8 ntb_buf[0x400]; /* Plane B line buffer */ static uint8 obj_buf[0x400]; /* Object layer line buffer */ /* Sprite line buffer data */ -static uint8 object_index_count; +static uint32 object_index_count; /* 3:3:3 to 5:6:5 RGB pixel extrapolation tables @@ -584,41 +569,186 @@ void render_shutdown(void) } /*--------------------------------------------------------------------------*/ -/* Line render function */ +/* Helper functions (cache update, hscroll, window clip) */ /*--------------------------------------------------------------------------*/ -#ifdef NGC -static inline void remap_texture(uint8 *src, uint16 *dst, int tile_cnt) + +static inline void update_bg_pattern_cache(uint32 index) +{ + int i; + uint8 x, y, c; + uint16 name; + uint8 *dst; + uint32 bp; +#ifdef LSB_FIRST + uint8 shift_table[8] = {12, 8, 4, 0, 28, 24, 20, 16}; +#else + uint8 shift_table[8] = {28, 24, 20, 16, 12, 8, 4, 0}; +#endif + + for(i = 0; i < index; i ++) + { + name = bg_name_list[i]; + bg_name_list[i] = 0; + + for(y = 0; y < 8; y ++) + { + if(bg_name_dirty[name] & (1 << y)) + { + dst = &bg_pattern_cache[name << 6]; + bp = *(uint32 *)&vram[(name << 5) | (y << 2)]; + + for(x = 0; x < 8; x ++) + { + c = (bp >> shift_table[x]) & 0x0F; + dst[0x00000 | (y << 3) | (x)] = (c); /* hf=0, vf=0: normal */ + dst[0x20000 | (y << 3) | (x ^ 7)] = (c); /* hf=1, vf=0: horizontal flipped */ + dst[0x40000 | ((y ^ 7) << 3) | (x)] = (c); /* hf=0, vf=1: vertical flipped */ + dst[0x60000 | ((y ^ 7) << 3) | (x ^ 7)] = (c); /* hf=1, vf=1: horizontal & vertical flipped */ + } + } + } + bg_name_dirty[name] = 0; + } +} + +static inline uint32 get_hscroll(uint32 line) +{ + switch(reg[11] & 3) + { + case 0: /* Full-screen */ + return *(uint32 *)&vram[hscb]; + + case 1: /* First 8 lines */ + return *(uint32 *)&vram[hscb + ((line & 7) << 2)]; + + case 2: /* Every 8 lines */ + return *(uint32 *)&vram[hscb + ((line & ~7) << 2)]; + + default: /* Every line */ + return *(uint32 *)&vram[hscb + (line << 2)]; + } +} + +/* Update Window Clipping (only called when registers change) */ +void window_clip(uint8 reg_12, uint8 reg_17) +{ + /* Window size and invert flags */ + int hp = (reg_17 & 0x1f); + int hf = (reg_17 >> 7) & 1; + + /* Display size */ + int sw = (reg_12 & 1) ? 20 : 16; + + /* Clear clipping data */ + memset(&clip, 0, sizeof(clip)); + + /* Perform horizontal clipping; the results are applied in reverse + if the horizontal inversion flag is set */ + int a = hf; + int w = hf ^ 1; + + if(hp) + { + if(hp > sw) + { + /* Plane W takes up entire line */ + clip[w].right = sw; + clip[w].enable = 1; + } + else + { + /* Window takes left side, Plane A takes right side */ + clip[w].right = hp; + clip[a].left = hp; + clip[a].right = sw; + clip[0].enable = clip[1].enable = 1; + } + } + else + { + /* Plane A takes up entire line */ + clip[a].right = sw; + clip[a].enable = 1; + } +} + +/*--------------------------------------------------------------------------*/ +/* Remap functions */ +/*--------------------------------------------------------------------------*/ + +#ifndef NGC +static inline void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length) +{ + int count; + for(count = 0; count < length; count += 1) + { + *dst++ = table[*src++]; + } +} + +static inline void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length) +{ + int count; + for(count = 0; count < length; count += 1) + { + *dst++ = table[*src++]; + } +} + +static inline void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length) +{ + int count; + for(count = 0; count < length; count += 1) + { + *dst++ = table[*src++]; + } +} + +#else +static inline void remap_texture(uint8 *src, uint16 *dst, uint32 tiles) { int count; uint16 *table = pixel_16; - for(count = 0; count < tile_cnt; count ++) + for(count = 0; count < tiles; count ++) { /* one tile is 4 pixels wide */ *dst++ = table[*src++]; *dst++ = table[*src++]; *dst++ = table[*src++]; *dst++ = table[*src++]; - - /* skip next three 4-pixels lines */ dst += 12; } } #endif -void remap_buffer(int line, int width) + +static inline void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, uint32 width) +{ + int i; + for(i = 0; i < width; i += 1) + { + *dst++ = table[(*srcb++ << 8) | (*srca++)]; + } +} + +/*--------------------------------------------------------------------------*/ +/* Line render function */ +/*--------------------------------------------------------------------------*/ + +void remap_buffer(uint32 line, uint32 width) { /* get line offset from framebuffer */ - int vline = (line + bitmap.viewport.y) % lines_per_frame; + line = (line + bitmap.viewport.y) % lines_per_frame; /* double resolution mode */ - if (config.render && interlaced) vline = (vline * 2) + odd_frame; + if (config.render && interlaced) line = (line * 2) + odd_frame; /* NTSC Filter */ if (config.ntsc) { - if (reg[12]&1) md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, vline); - else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, vline); + if (reg[12]&1) md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line); + else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line); return; } @@ -627,11 +757,11 @@ void remap_buffer(int line, int width) /* one tile is 32 byte = 4x4 pixels */ /* tiles are stored continuously in texture memory */ width = width >> 2; - int offset = ((width << 5) * (vline >> 2)) + ((vline & 3) * 8); + int offset = ((width << 5) * (line >> 2)) + ((line & 3) * 8); remap_texture(tmp_buf+0x20-bitmap.viewport.x, (uint16 *)(texturemem + offset), width); #else - void *out =((void *)&bitmap.data[(vline * bitmap.pitch)]); + void *out =((void *)&bitmap.data[(line * bitmap.pitch)]); switch(bitmap.depth) { case 8: @@ -650,446 +780,477 @@ void remap_buffer(int line, int width) #endif } -void render_line(int line, uint8 odd_frame) +void render_line(uint32 line, uint32 overscan) { - /* check if we are inside display area (including vertical borders) */ - int min = bitmap.viewport.h + bitmap.viewport.y; - int max = lines_per_frame - bitmap.viewport.y; - if ((line >= min) && (line < max)) return; + uint32 width = bitmap.viewport.w; + uint32 x_offset = bitmap.viewport.x; - uint8 *lb = tmp_buf; - int width = bitmap.viewport.w; - - /* vertical borders or display OFF */ - if ((line >= bitmap.viewport.h) || (!(reg[1] & 0x40))) + /* background color (display OFF or borders) */ + if (overscan || !(reg[1] & 0x40)) { - memset(&lb[0x20], 0x40, width); + width += 2 * x_offset; + memset(&tmp_buf[0x20 - x_offset], 0x40, width); } else { - update_bg_pattern_cache(); - window_clip(line); + uint8 *lb = tmp_buf; + /* update pattern generator */ + if (bg_list_index) + { + update_bg_pattern_cache(bg_list_index); + bg_list_index = 0; + } + + /* double-resolution mode */ if(im2_flag) { - if (clip[0].enable) render_ntx_im2(0, line, nta_buf, odd_frame); - render_ntx_im2(1, line, ntb_buf, odd_frame); - if (clip[1].enable) render_ntw_im2(line, nta_buf, odd_frame); - } - else - { - if(reg[11] & 4) + uint32 odd = odd_frame; + + /* render BG layers */ + render_bg_im2(line, width, odd); + + if (reg[12] & 8) { - if (clip[0].enable) render_ntx_vs(0, line, nta_buf); - render_ntx_vs(1, line, ntb_buf); + /* Shadow & Highlight */ + merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width); + memset(&obj_buf[0x20], 0, width); + if (object_index_count) render_obj_im2(line, odd, obj_buf, lut[3]); + merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width); } else { - if (clip[0].enable) render_ntx(0, line, nta_buf); - render_ntx(1, line, ntb_buf); + merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width); + if (object_index_count) render_obj_im2(line, odd, lb, lut[1]); } - if (clip[1].enable) render_ntw(line, nta_buf); - } - - if(reg[12] & 8) - { - merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width); - memset(&obj_buf[0x20], 0, width); - - if(im2_flag) render_obj_im2(line, obj_buf, lut[3], odd_frame); - else render_obj(line, obj_buf, lut[3]); - - merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width); } else { - merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width); - if(im2_flag) render_obj_im2(line, lb, lut[1], odd_frame); - else render_obj(line, lb, lut[1]); - } + /* render BG layers */ + if(reg[11] & 4) render_bg_vs(line, width); + else render_bg(line, width); - /* Mode 4 feature only (unemulated, no games rely on this) */ - /*if(!(reg[1] & 0x04) && (reg[0] & 0x20)) memset(&lb[0x20], 0x40, 0x08);*/ - } - - /* horizontal borders */ - if (config.overscan) - { - memset(&lb[0x20 - bitmap.viewport.x], 0x40, bitmap.viewport.x); - memset(&lb[0x20 + bitmap.viewport.w], 0x40, bitmap.viewport.x); - width += 2 * bitmap.viewport.x; - } - - /* LightGun mark */ - if ((input.dev[4] == DEVICE_LIGHTGUN) && (config.gun_cursor)) - { - int dy = v_counter - input.analog[0][1]; - - if (abs(dy) < 6) - { - int i; - int start = input.analog[0][0] - 4; - int end = start + 8; - if (start < 0) start = 0; - if (end > bitmap.viewport.w) end = bitmap.viewport.w; - for (i=start; i> 3) << width)]; - dst = (uint32 *)&buf[0x20 + (clip[1].left << 4)]; - - for(column = clip[1].left; column < clip[1].right; column ++) - { - atbuf = nt[column]; - DRAW_COLUMN(atbuf, v_line) - } -} - -void render_ntw_im2(int line, uint8 *buf, uint8 odd) -{ - int column, v_line, width; - uint32 *nt, *src, *dst, atex, atbuf, offs; - - v_line = ((line & 7) << 1 | odd) << 3; - width = (reg[12] & 1) ? 7 : 6; - nt = (uint32 *)&vram[ntwb | ((line >> 3) << width)]; - dst = (uint32 *)&buf[0x20 + (clip[1].left << 4)]; - - for(column = clip[1].left; column < clip[1].right; column ++) - { - atbuf = nt[column]; - DRAW_COLUMN_IM2(atbuf, v_line) - } -} - -/*--------------------------------------------------------------------------*/ -/* Background plane rendering */ -/*--------------------------------------------------------------------------*/ - -void render_ntx(int which, int line, uint8 *buf) -{ - int column; - int start, end; - int index; - int shift; - int v_line; - uint32 atex, atbuf, *src, *dst; - uint16 xscroll = 0; - int y_scroll; - uint32 *nt; - uint32 *vs; - uint16 table[2] = {ntab,ntbb}; - uint8 xshift[2] = {0,2}; -#ifdef LSB_FIRST - uint8 vsr_shift[2] = {0,16}; -#else - uint8 vsr_shift[2] = {16,0}; -#endif - - get_hscroll(line, xshift[which], &xscroll); - shift = (xscroll & 0x0F); - index = playfield_col_mask + 1 - ((xscroll >> 4) & playfield_col_mask); - - if(which) - { - start = 0; - end = (reg[12] & 1) ? 20 : 16; - } - else - { - start = clip[0].left; - end = clip[0].right; - index = (index + clip[0].left) & playfield_col_mask; - } - - vs = (uint32 *)&vsram[0]; - y_scroll = (vs[0] >> vsr_shift[which]) & 0x3FF; - y_scroll = (line + y_scroll) & playfield_row_mask; - v_line = (y_scroll & 7) << 3; - nt = (uint32 *)&vram[table[which] + (((y_scroll >> 3) << playfield_shift) & y_mask)]; - - if(shift) - { - dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; - - /* Window bug */ - if (start) atbuf = nt[(index) & playfield_col_mask]; - else atbuf = nt[(index-1) & playfield_col_mask]; - - DRAW_COLUMN(atbuf, v_line); - } - - dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; - - for(column = start; column < end; column ++, index ++) - { - atbuf = nt[index & playfield_col_mask]; - DRAW_COLUMN(atbuf, v_line) - } -} - -void render_ntx_im2(int which, int line, uint8 *buf, uint8 odd) -{ - int column; - int start, end; - int index; - int shift; - int v_line; - uint32 atex, atbuf, *src, *dst; - uint16 xscroll = 0; - int y_scroll; - uint32 *nt; - uint32 *vs; - uint32 offs; - uint16 table[2] = {ntab,ntbb}; - uint8 xshift[2] = {0,2}; -#ifdef LSB_FIRST - uint8 vsr_shift[2] = {1,17}; -#else - uint8 vsr_shift[2] = {17,1}; -#endif - - get_hscroll(line, xshift[which], &xscroll); - shift = (xscroll & 0x0F); - index = playfield_col_mask + 1 - ((xscroll >> 4) & playfield_col_mask); - - if(which) - { - start = 0; - end = (reg[12] & 1) ? 20 : 16; - } - else - { - start = clip[0].left; - end = clip[0].right; - index = (index + clip[0].left) & playfield_col_mask; - } - - vs = (uint32 *)&vsram[0]; - y_scroll = (vs[0] >> vsr_shift[which]) & 0x3FF; - y_scroll = (line + y_scroll) & playfield_row_mask; - v_line = (((y_scroll & 7) << 1) | odd) << 3; - nt = (uint32 *)&vram[table[which] + (((y_scroll >> 3) << playfield_shift) & y_mask)]; - - if(shift) - { - dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; - - /* Window bug */ - if (start) atbuf = nt[(index) & playfield_col_mask]; - else atbuf = nt[(index-1) & playfield_col_mask]; - DRAW_COLUMN_IM2(atbuf, v_line); - } - - dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; - for(column = start; column < end; column ++, index ++) - { - atbuf = nt[index & playfield_col_mask]; - DRAW_COLUMN_IM2(atbuf, v_line) - } -} - -void render_ntx_vs(int which, int line, uint8 *buf) -{ - int column; - int start, end; - int index; - int shift; - int v_line; - uint32 atex, atbuf, *src, *dst; - uint16 xscroll = 0; - int y_scroll; - uint32 *nt; - uint32 *vs; - uint16 table[2] = {ntab,ntbb}; - uint8 xshift[2] = {0,2}; -#ifdef LSB_FIRST - uint8 vsr_shift[2] = {0,16}; -#else - uint8 vsr_shift[2] = {16,0}; -#endif - - get_hscroll(line, xshift[which], &xscroll); - shift = (xscroll & 0x0F); - index = playfield_col_mask + 1 - ((xscroll >> 4) & playfield_col_mask); - - if(which) - { - start = 0; - end = (reg[12] & 1) ? 20 : 16; - } - else - { - start = clip[0].left; - end = clip[0].right; - index = (index + clip[0].left) & playfield_col_mask; - } - - vs = (uint32 *)&vsram[0]; - - if(shift) - { - dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; - y_scroll = (line & playfield_row_mask); - v_line = (y_scroll & 7) << 3; - nt = (uint32 *)&vram[table[which] + (((y_scroll >> 3) << playfield_shift) & y_mask)]; - - /* Window bug */ - if (start) atbuf = nt[(index) & playfield_col_mask]; - else atbuf = nt[(index-1) & playfield_col_mask]; - - DRAW_COLUMN(atbuf, v_line); - } - - dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; - - for(column = start; column < end; column ++, index ++) - { - y_scroll = (vs[column] >> vsr_shift[which]) & 0x3FF; - y_scroll = (line + y_scroll) & playfield_row_mask; - v_line = (y_scroll & 7) << 3; - nt = (uint32 *)&vram[table[which] + (((y_scroll >> 3) << playfield_shift) & y_mask)]; - atbuf = nt[index & playfield_col_mask]; - DRAW_COLUMN(atbuf, v_line) - } -} - -/*--------------------------------------------------------------------------*/ -/* Helper functions (cache update, hscroll, window clip) */ -/*--------------------------------------------------------------------------*/ - -void update_bg_pattern_cache(void) -{ - int i; - uint8 x, y, c; - uint16 name; -#ifdef LSB_FIRST - uint8 shift_table[8] = {12, 8, 4, 0, 28, 24, 20, 16}; - #else - uint8 shift_table[8] = {28, 24, 20, 16, 12, 8, 4, 0}; - #endif - - if(!bg_list_index) return; - - for(i = 0; i < bg_list_index; i ++) - { - name = bg_name_list[i]; - bg_name_list[i] = 0; - - for(y = 0; y < 8; y ++) + /* borders */ + if (x_offset) { - if(bg_name_dirty[name] & (1 << y)) - { - uint8 *dst = &bg_pattern_cache[name << 6]; - uint32 bp = *(uint32 *)&vram[(name << 5) | (y << 2)]; + memset(&lb[0x20 - x_offset], 0x40, x_offset); + memset(&lb[0x20 + width], 0x40, x_offset); + width += 2 * x_offset; + } - for(x = 0; x < 8; x ++) + /* LightGun mark */ + if ((input.dev[4] == DEVICE_LIGHTGUN) && (config.gun_cursor)) + { + int dy = v_counter - input.analog[0][1]; + + if (abs(dy) < 6) + { + int i; + int start = input.analog[0][0] - 4; + int end = start + 8; + if (start < 0) start = 0; + if (end > bitmap.viewport.w) end = bitmap.viewport.w; + for (i=start; i> shift_table[x]) & 0x0F; - dst[0x00000 | (y << 3) | (x)] = (c); /* hf=0, vf=0: normal */ - dst[0x20000 | (y << 3) | (x ^ 7)] = (c); /* hf=1, vf=0: horizontal flipped */ - dst[0x40000 | ((y ^ 7) << 3) | (x)] = (c); /* hf=0, vf=1: vertical flipped */ - dst[0x60000 | ((y ^ 7) << 3) | (x ^ 7)] = (c); /* hf=1, vf=1: horizontal & vertical flipped */ + lb[0x20+i] = 0xff; } } } - bg_name_dirty[name] = 0; } - bg_list_index = 0; + + /* pixel color remapping */ + remap_buffer(line,width); } -void get_hscroll(int line, int shift, uint16 *scroll) +static void render_bg(uint32 line, uint32 width) { - switch(reg[11] & 3) + uint32 column, atex, atbuf, *src, *dst; +#ifndef LSB_FIRST + uint32 attr_msb; +#endif + + /* common data */ + uint32 xscroll = get_hscroll(line); + uint32 pf_col_mask = playfield_col_mask; + uint32 pf_row_mask = playfield_row_mask; + uint32 pf_shift = playfield_shift; + uint32 pf_y_mask = y_mask; + uint32 *vs = (uint32 *)&vsram[0]; + + /* B Plane */ + uint8 *buf = ntb_buf; + uint32 start = 0; + uint32 end = width >> 4; + +#ifdef LSB_FIRST + uint32 shift = (xscroll >> 16) & 0x0F; + uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); + uint32 y_scroll = (line + ((vs[0] >> 16) & 0x3FF)) & pf_row_mask; +#else + uint32 shift = (xscroll & 0x0F); + uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); + uint32 y_scroll = (line + (vs[0] & 0x3FF)) & pf_row_mask; +#endif + + uint32 v_line = (y_scroll & 7) << 3; + uint32 *nt = (uint32 *)&vram[ntbb + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + + if(shift) { - case 0: /* Full-screen */ - *scroll = *(uint16 *)&vram[hscb + shift]; - break; - - case 1: /* First 8 lines */ - *scroll = *(uint16 *)&vram[hscb + ((line & 7) << 2) + shift]; - break; - - case 2: /* Every 8 lines */ - *scroll = *(uint16 *)&vram[hscb + ((line & ~7) << 2) + shift]; - break; - - case 3: /* Every line */ - *scroll = *(uint16 *)&vram[hscb + (line << 2) + shift]; - break; + dst = (uint32 *)&buf[0x10 + shift]; + atbuf = nt[(index-1) & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line); } - *scroll &= 0x03FF; -} + dst = (uint32 *)&buf[0x20 + shift]; + for(column = 0; column < end; column ++, index ++) + { + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line) + } -void window_clip(int line) -{ - /* Window size and invert flags */ - int hp = (reg[17] & 0x1F); - int hf = (reg[17] >> 7) & 1; - int vp = (reg[18] & 0x1F) << 3; - int vf = (reg[18] >> 7) & 1; - - /* Display size */ - int sw = (reg[12] & 1) ? 20 : 16; - - /* Clear clipping data */ - memset(&clip, 0, sizeof(clip)); - - /* Check if line falls within window range */ - if(vf == (line >= vp)) + /* Window and Plane A */ + buf = nta_buf; + uint32 a = (reg[18] & 0x1F) << 3; + uint32 w = (reg[18] >> 7) & 1; + if (w == (line >= a)) { /* Window takes up entire line */ - clip[1].right = sw; - clip[1].enable = 1; + a = 0; + w = 1; } else { - /* Perform horizontal clipping; the results are applied in reverse - if the horizontal inversion flag is set */ - int a = hf; - int w = hf ^ 1; + /* Window and Plane A share the line */ + a = clip[0].enable; + w = clip[1].enable; + } - if(hp) + /* Plane A */ + if (a) + { + /* set for Plane A */ + start = clip[0].left; + end = clip[0].right; + +#ifdef LSB_FIRST + shift = (xscroll & 0x0F); + index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); + y_scroll = (line + (vs[0] & 0x3FF)) & pf_row_mask; +#else + shift = (xscroll >> 16) & 0x0F; + index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); + y_scroll = (line + ((vs[0] >> 16) & 0x3FF)) & pf_row_mask; +#endif + + v_line = (y_scroll & 7) << 3; + nt = (uint32 *)&vram[ntab + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + + if(shift) { - if(hp > sw) - { - /* Plane W takes up entire line */ - clip[w].right = sw; - clip[w].enable = 1; - } - else - { - /* Window takes left side, Plane A takes right side */ - clip[w].right = hp; - clip[a].left = hp; - clip[a].right = sw; - clip[0].enable = clip[1].enable = 1; - } + dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; + + /* Window bug */ + if (start) atbuf = nt[index & pf_col_mask]; + else atbuf = nt[(index-1) & pf_col_mask]; + + DRAW_COLUMN(atbuf, v_line); } - else + + dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; + for(column = start; column < end; column ++, index ++) { - /* Plane A takes up entire line */ - clip[a].right = sw; - clip[a].enable = 1; + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line) + } + + /* set for Window */ + start = clip[1].left; + end = clip[1].right; + } + + /* Window */ + if (w) + { + v_line = (line & 7) << 3; + nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))]; + dst = (uint32 *)&buf[0x20 + (start << 4)]; + for(column = start; column < end; column ++) + { + atbuf = nt[column]; + DRAW_COLUMN(atbuf, v_line) + } + } +} + +static void render_bg_vs(uint32 line, uint32 width) +{ + uint32 column, atex, atbuf, *src, *dst; +#ifndef LSB_FIRST + uint32 attr_msb; +#endif + + /* common data */ + uint32 xscroll = get_hscroll(line); + uint32 pf_col_mask = playfield_col_mask; + uint32 pf_row_mask = playfield_row_mask; + uint32 pf_shift = playfield_shift; + uint32 pf_y_mask = y_mask; + uint32 *vs = (uint32 *)&vsram[0]; + + /* B Plane */ + uint8 *buf = ntb_buf; + uint32 start = 0; + uint32 end = width >> 4; + +#ifdef LSB_FIRST + uint32 shift = (xscroll >> 16) & 0x0F; + uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); +#else + uint32 shift = (xscroll & 0x0F); + uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); +#endif + + uint32 y_scroll, v_line, *nt; + + if(shift) + { + y_scroll = (line & pf_row_mask); + v_line = (y_scroll & 7) << 3; + nt = (uint32 *)&vram[ntbb + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + dst = (uint32 *)&buf[0x10 + shift]; + atbuf = nt[(index-1) & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line); + } + + dst = (uint32 *)&buf[0x20 + shift]; + for(column = start; column < end; column ++, index ++) + { +#ifdef LSB_FIRST + y_scroll = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; +#else + y_scroll = (line + (vs[column] & 0x3FF)) & pf_row_mask; +#endif + v_line = (y_scroll & 7) << 3; + nt = (uint32 *)&vram[ntbb + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line) + } + + /* Window and Plane A */ + buf = nta_buf; + uint32 a = (reg[18] & 0x1F) << 3; + uint32 w = (reg[18] >> 7) & 1; + if (w == (line >= a)) + { + /* Window takes up entire line */ + a = 0; + w = 1; + } + else + { + /* Window and Plane A share the line */ + a = clip[0].enable; + w = clip[1].enable; + } + + /* Plane A*/ + if (a) + { + /* set for Plane A */ + start = clip[0].left; + end = clip[0].right; + +#ifdef LSB_FIRST + shift = (xscroll & 0x0F); + index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); +#else + shift = (xscroll >> 16) & 0x0F; + index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); +#endif + + if(shift) + { + dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; + y_scroll = (line & pf_row_mask); + v_line = (y_scroll & 7) << 3; + nt = (uint32 *)&vram[ntab + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + + /* Window bug */ + if (start) atbuf = nt[index & pf_col_mask]; + else atbuf = nt[(index-1) & pf_col_mask]; + + DRAW_COLUMN(atbuf, v_line); + } + + dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; + for(column = start; column < end; column ++, index ++) + { +#ifdef LSB_FIRST + y_scroll = (line + (vs[column] & 0x3FF)) & pf_row_mask; +#else + y_scroll = (line + ((vs[column] >> 16) & 0x3FF)) & pf_row_mask; +#endif + v_line = (y_scroll & 7) << 3; + nt = (uint32 *)&vram[ntab + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN(atbuf, v_line) + } + + /* set for Window */ + start = clip[1].left; + end = clip[1].right; + } + + /* Window */ + if (w) + { + v_line = (line & 7) << 3; + nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))]; + dst = (uint32 *)&buf[0x20 + (start << 4)]; + for(column = start; column < end; column ++) + { + atbuf = nt[column]; + DRAW_COLUMN(atbuf, v_line) + } + } +} + +static void render_bg_im2(uint32 line, uint32 width, uint32 odd) +{ + uint32 column, atex, atbuf, offs, *src, *dst; +#ifndef LSB_FIRST + uint32 attr_msb; +#endif + + /* common data */ + uint32 xscroll = get_hscroll(line); + uint32 pf_col_mask = playfield_col_mask; + uint32 pf_row_mask = playfield_row_mask; + uint32 pf_shift = playfield_shift; + uint32 pf_y_mask = y_mask; + uint32 *vs = (uint32 *)&vsram[0]; + + /* B Plane */ + uint8 *buf = ntb_buf; + uint32 start = 0; + uint32 end = width >> 4; + +#ifdef LSB_FIRST + uint32 shift = (xscroll >> 16) & 0x0F; + uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask); + uint32 y_scroll = (line + ((vs[0] >> 17) & 0x3FF)) & pf_row_mask; /* IM2 specific */ +#else + uint32 shift = (xscroll & 0x0F); + uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask); + uint32 y_scroll = (line + ((vs[0] >> 1) & 0x3FF)) & pf_row_mask; /* IM2 specific */ +#endif + + uint32 v_line = (((y_scroll & 7) << 1) | odd) << 3; /* IM2 specific */ + uint32 *nt = (uint32 *)&vram[ntbb + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + + if(shift) + { + dst = (uint32 *)&buf[0x10 + shift]; + atbuf = nt[(index-1) & pf_col_mask]; + DRAW_COLUMN_IM2(atbuf, v_line); /* IM2 specific */ + } + + dst = (uint32 *)&buf[0x20 + shift]; + for(column = 0; column < end; column ++, index ++) + { + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN_IM2(atbuf, v_line) /* IM2 specific */ + } + + /* Window and Plane A */ + buf = nta_buf; + uint32 a = (reg[18] & 0x1F) << 3; + uint32 w = (reg[18] >> 7) & 1; + if (w == (line >= a)) + { + /* Window takes up entire line */ + a = 0; + w = 1; + } + else + { + /* Window and Plane A share the line */ + a = clip[0].enable; + w = clip[1].enable; + } + + /* Plane A */ + if (a) + { + /* set for Plane A */ + start = clip[0].left; + end = clip[0].right; + +#ifdef LSB_FIRST + shift = (xscroll & 0x0F); + index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask); + y_scroll = (line + ((vs[0] >> 1) & 0x3FF)) & pf_row_mask; /* IM2 specific */ +#else + shift = (xscroll >> 16) & 0x0F; + index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask); + y_scroll = (line + ((vs[0] >> 17) & 0x3FF)) & pf_row_mask; /* IM2 specific */ +#endif + + v_line = (((y_scroll & 7) << 1) | odd) << 3; /* IM2 specific */ + nt = (uint32 *)&vram[ntab + (((y_scroll >> 3) << pf_shift) & pf_y_mask)]; + + if(shift) + { + dst = (uint32 *)&buf[0x10 + shift + (start<<4)]; + + /* Window bug */ + if (start) atbuf = nt[index & pf_col_mask]; + else atbuf = nt[(index-1) & pf_col_mask]; + + DRAW_COLUMN_IM2(atbuf, v_line); /* IM2 specific */ + } + + dst = (uint32 *)&buf[0x20 + shift + (start<<4)]; + for(column = start; column < end; column ++, index ++) + { + atbuf = nt[index & pf_col_mask]; + DRAW_COLUMN_IM2(atbuf, v_line) /* IM2 specific */ + } + + /* set for Window */ + start = clip[1].left; + end = clip[1].right; + } + + /* Window */ + if (w) + { + v_line = ((line & 7) << 1 | odd) << 3; /* IM2 specific */ + nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))]; + dst = (uint32 *)&buf[0x20 + (start << 4)]; + for(column = start; column < end; column ++) + { + atbuf = nt[column]; + DRAW_COLUMN_IM2(atbuf, v_line) /* IM2 specific */ } } } @@ -1102,7 +1263,7 @@ void window_clip(int line) /* Input (bx): d5-d0=color, d6=priority, d7=unused */ /* Input (ax): d5-d0=color, d6=priority, d7=unused */ /* Output: d5-d0=color, d6=priority, d7=unused */ -int make_lut_bg(int bx, int ax) +static uint32 make_lut_bg(uint32 bx, uint32 ax) { int bf, bp, b; int af, ap, a; @@ -1131,7 +1292,7 @@ int make_lut_bg(int bx, int ax) /* Input (bx): d5-d0=color, d6=priority, d7=sprite pixel marker */ /* Input (sx): d5-d0=color, d6=priority, d7=unused */ /* Output: d5-d0=color, d6=zero, d7=sprite pixel marker */ -int make_lut_obj(int bx, int sx) +static uint32 make_lut_obj(uint32 bx, uint32 sx) { int bf, bp, bs, b; int sf, sp, s; @@ -1169,7 +1330,7 @@ int make_lut_obj(int bx, int sx) /* Input (bx): d5-d0=color, d6=priority, d7=unused */ /* Input (sx): d5-d0=color, d6=priority, d7=unused */ /* Output: d5-d0=color, d6=priority, d7=intensity select (half/normal) */ -int make_lut_bg_ste(int bx, int ax) +static uint32 make_lut_bg_ste(uint32 bx, uint32 ax) { int bf, bp, b; int af, ap, a; @@ -1202,7 +1363,7 @@ int make_lut_bg_ste(int bx, int ax) /* Input (bx): d5-d0=color, d6=priority, d7=sprite pixel marker */ /* Input (sx): d5-d0=color, d6=priority, d7=unused */ /* Output: d5-d0=color, d6=priority, d7=sprite pixel marker */ -int make_lut_obj_ste(int bx, int sx) +static uint32 make_lut_obj_ste(uint32 bx, uint32 sx) { int bf, bs; int sf; @@ -1226,7 +1387,7 @@ int make_lut_obj_ste(int bx, int sx) /* Input (bx): d5-d0=color, d6=priority, d7=intensity (half/normal) */ /* Input (sx): d5-d0=color, d6=priority, d7=sprite marker */ /* Output: d5-d0=color, d6=intensity (half/normal), d7=(double/invalid) */ -int make_lut_bgobj_ste(int bx, int sx) +static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx) { int c; @@ -1354,55 +1515,6 @@ int make_lut_bgobj_ste(int bx, int sx) return (c); } -/*--------------------------------------------------------------------------*/ -/* Remap functions */ -/*--------------------------------------------------------------------------*/ -#ifndef NGC -void remap_8(uint8 *src, uint8 *dst, uint8 *table, int length) -{ - int count; - for(count = 0; count < length; count += 1) - { - *dst++ = table[*src++]; - } -} - -void remap_32(uint8 *src, uint32 *dst, uint32 *table, int length) -{ - int count; - for(count = 0; count < length; count += 1) - { - *dst++ = table[*src++]; - } -} -#endif - -void remap_16(uint8 *src, uint16 *dst, uint16 *table, int length) -{ - int count; - for(count = 0; count < length; count += 1) - { - *dst++ = table[*src++]; - } -} - - -/*--------------------------------------------------------------------------*/ -/* Merge functions */ -/*--------------------------------------------------------------------------*/ - -void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width) -{ - int i; - for(i = 0; i < width; i += 1) - { - uint8 a = srca[i]; - uint8 b = srcb[i]; - uint8 c = table[(b << 8) | (a)]; - dst[i] = c; - } -} - /*--------------------------------------------------------------------------*/ /* Color update functions */ /*--------------------------------------------------------------------------*/ @@ -1482,30 +1594,24 @@ void color_update_16(int index, uint16 data) /* Object render functions */ /*--------------------------------------------------------------------------*/ -void parse_satb(int line) +void parse_satb(uint32 line) { - static uint8 sizetab[] = {8, 16, 24, 32}; - uint8 link = 0; - uint16 *p, *q; - uint16 ypos; - uint8 size; - int count; - int height; + uint8 sizetab[] = {8, 16, 24, 32}; + uint32 link = 0; + uint32 count, ypos, size, height; - int limit = (reg[12] & 1) ? 20 : 16; - int total = (reg[12] & 1) ? 80 : 64; + uint32 limit = (reg[12] & 1) ? 20 : 16; + uint32 total = limit << 2; + + uint16 *p = (uint16 *) &vram[satb]; + uint16 *q = (uint16 *) &sat[0]; object_index_count = 0; for(count = 0; count < total; count += 1) { - q = (uint16 *) &sat[link << 3]; - - ypos = q[0]; - if(im2_flag) ypos = (ypos >> 1) & 0x1FF; - else ypos &= 0x1FF; - - size = q[1] >> 8; + ypos = (q[link] >> im2_flag) & 0x1FF; + size = q[link + 1] >> 8; height = sizetab[size & 3]; if((line >= ypos) && (line < (ypos + height))) @@ -1520,21 +1626,19 @@ void parse_satb(int line) // using xpos from internal satb stops sprite x // scrolling in bloodlin.bin, // but this seems to go against the test prog - p = (uint16 *) &vram[satb + (link << 3)]; - object_info[object_index_count].ypos = q[0]; - object_info[object_index_count].xpos = p[3]; - object_info[object_index_count].attr = p[2]; + object_info[object_index_count].attr = p[link + 2]; + object_info[object_index_count].xpos = p[link + 3]; + object_info[object_index_count].ypos = ypos; object_info[object_index_count].size = size; - object_info[object_index_count].index = count; - object_index_count += 1; + ++object_index_count; } - link = q[1] & 0x7F; + link = (q[link + 1] & 0x7F) << 2; if(link == 0) break; } } -void render_obj(int line, uint8 *buf, uint8 *table) +static void render_obj(uint32 line, uint8 *buf, uint8 *table) { uint16 ypos; uint16 attr; @@ -1543,7 +1647,7 @@ void render_obj(int line, uint8 *buf, uint8 *table) uint8 size; uint8 *src; - int count; + int count,i; int pixelcount = 0; int width; int height; @@ -1552,7 +1656,6 @@ void render_obj(int line, uint8 *buf, uint8 *table) int sol_flag = 0; int left = 0x80; int right = 0x80 + bitmap.viewport.w; - int i; uint8 *s, *lb; uint16 name, index; @@ -1562,8 +1665,7 @@ void render_obj(int line, uint8 *buf, uint8 *table) for(count = 0; count < object_index_count; count += 1) { - xpos = object_info[count].xpos; - xpos &= 0x1ff; + xpos = object_info[count].xpos & 0x1ff; /* sprite masking */ if(xpos != 0) sol_flag = 1; @@ -1578,7 +1680,6 @@ void render_obj(int line, uint8 *buf, uint8 *table) if(((xpos + width) >= left) && (xpos < right)) { ypos = object_info[count].ypos; - ypos &= 0x1ff; attr = object_info[count].attr; attr_mask = (attr & 0x1800); @@ -1595,6 +1696,8 @@ void render_obj(int line, uint8 *buf, uint8 *table) lb = (uint8 *)&buf[0x20 + (xpos - 0x80)]; /* number of tiles to draw */ + /* adjusted for sprite limit */ + if (pixelcount > bitmap.viewport.w) width -= (pixelcount - bitmap.viewport.w); width >>= 3; for(column = 0; column < width; column += 1, lb+=8) @@ -1612,7 +1715,7 @@ void render_obj(int line, uint8 *buf, uint8 *table) } } -void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd) +static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table) { uint16 ypos; uint16 attr; @@ -1621,7 +1724,7 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd) uint8 size; uint8 *src; - int count; + int count,i; int pixelcount = 0; int width; int height; @@ -1630,7 +1733,6 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd) int sol_flag = 0; int left = 0x80; int right = 0x80 + bitmap.viewport.w; - int i; uint8 *s, *lb; uint16 name, index; @@ -1641,8 +1743,7 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd) for(count = 0; count < object_index_count; count += 1) { - xpos = object_info[count].xpos; - xpos &= 0x1ff; + xpos = object_info[count].xpos & 0x1ff; /* sprite masking */ if(xpos != 0) sol_flag = 1; @@ -1657,7 +1758,6 @@ void render_obj_im2(int line, uint8 *buf, uint8 *table, uint8 odd) if(((xpos + width) >= left) && (xpos < right)) { ypos = object_info[count].ypos; - ypos = (ypos >> 1) & 0x1ff; attr = object_info[count].attr; attr_mask = (attr & 0x1800); diff --git a/source/render.h b/source/render.h index 3da6635..ff0c8be 100644 --- a/source/render.h +++ b/source/render.h @@ -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_ */ diff --git a/source/shared.h b/source/shared.h index daaba21..61f0ba2 100644 --- a/source/shared.h +++ b/source/shared.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" diff --git a/source/sound/fm.c b/source/sound/fm.c index 1d14f3b..05ebc60 100644 --- a/source/sound/fm.c +++ b/source/sound/fm.c @@ -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) { diff --git a/source/state.c b/source/state.c index 3b5e44a..5c90f15 100644 --- a/source/state.c +++ b/source/state.c @@ -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 */ diff --git a/source/system.c b/source/system.c index 9b1cc9f..6c8de13 100644 --- a/source/system.c +++ b/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; diff --git a/source/system.h b/source/system.h index 3276dab..b90f087 100644 --- a/source/system.h +++ b/source/system.h @@ -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_ */ diff --git a/source/vdp.c b/source/vdp.c index e44377b..3233caf 100644 --- a/source/vdp.c +++ b/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; } diff --git a/source/vdp.h b/source/vdp.h index c7c9722..1af0a36 100644 --- a/source/vdp.h +++ b/source/vdp.h @@ -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);