diff --git a/HISTORY.txt b/HISTORY.txt index eba4f47..db569b4 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -1,22 +1,24 @@ --------------------------------------------------------------------------------------------------------- -Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke) +Genesis Plus GX 1.4.0 (??/??/????) (Eke-Eke) --------------------------------------------------------------------------------------------------------- [Core] ------ -* optimized SN76489 core -* modified SN76489 cut-off frequency (thanks to Steve Snake) -* modified SN76489 core to use Blip Buffer linear synthesis , Noise channel is now linear averaged (thanks to Blargg) +* modified SN76489 cut-off frequency +* implemented optimized SN76489 core from Blargg that uses Blip Buffer linear synthesis (Noise Channel is now linear interpolated) * added an option to boost SN76489 Noise Channel -* removed now outdated Gens YM2612 core -* improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware) +* removed outdated Gens YM2612 core +* improved YM2612 core general accuracy (SSG-EG, CSM mode,...) (based upon Nemesis recent tests on real MD) +* improved YM2612 LFO emulation (fixes "Spider-Man & Venom : Separation Anxiety" intro music) * fixed YM2612 context saving/loading. -* added 3 Band Equalizer for improved & fully configurable sound filtering (taken from Softdev's NeoCD Redux) -* improved sprites masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his test program) +* added 3-Band EQ for fully configurable sound filtering (credits to Neil C / Etanza Systems) +* implemented faster and better FIR resampler, removed libsamplerate support (thanks to Blargg and AamirM), Virtua Racing now plays fullspeed +when High Quality FM is enabled. +* improved VDP sprite masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his sprite test program) * fixed lightgun autodetection: fixes cursor position in Lethal Enforcers II -* improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS instructions timing accuracy -* lots of code cleanup & core optimizations +* improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS 68k instructions timing accuracy +* various code cleanup & core optimizations [Gamecube/Wii] @@ -24,8 +26,8 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke) * fixed stability issues and some (potential) memory leaks * added internal screenshot feature * improved lightgun cursors -* new FONT & GUI engines: use internal IPL FONT, GX hardware & multithreading for fast rendering. -* new interface: incl. IR pointing, ROM snapshots, menu effects, sound effects, BGM... (check the README for more details) +* implemented new FONT & GUI engines: use internal IPL FONT, GX hardware & multithreading for fast rendering. +* implemented new interface: incl. IR pointing, ROM snapshots, menu effects, sound effects, BGM... (check the README for more details) diff --git a/source/cart_hw/cart_hw.c b/source/cart_hw/cart_hw.c index d469916..ef2b97d 100644 --- a/source/cart_hw/cart_hw.c +++ b/source/cart_hw/cart_hw.c @@ -151,6 +151,9 @@ void cart_hw_reset() /* SVP chip */ if (svp) svp_reset(); + + /* Game Genie hardware */ + if (config.lock_on == CART_GG) ggenie_reset(); } /* cart hardware detection */ @@ -222,6 +225,11 @@ void cart_hw_init() } } + /********************************************** + GAME GENIE + ***********************************************/ + if (config.lock_on == CART_GG) ggenie_init(); + /********************************************** SVP CHIP ***********************************************/ diff --git a/source/cart_hw/cart_hw.h b/source/cart_hw/cart_hw.h index bc36d9c..2a883f0 100644 --- a/source/cart_hw/cart_hw.h +++ b/source/cart_hw/cart_hw.h @@ -27,6 +27,12 @@ #ifndef _CART_HW_H_ #define _CART_HW_H_ +/* Lock-ON cartridge devices */ +#define NO_CART 0 /* no connections */ +#define CART_GG 1 /* game genie */ +#define CART_AR 2 /* action replay */ +#define CART_SK 3 /* Sonic & Knuckles */ + /* Hardware description */ typedef struct { diff --git a/source/cart_hw/ggenie.c b/source/cart_hw/ggenie.c new file mode 100644 index 0000000..0f17d50 --- /dev/null +++ b/source/cart_hw/ggenie.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * Genesis Plus + * Game Genie Hardware emulation + * + * Copyright (C) 2009 Eke-Eke (GCN/Wii port) + * + * Based on documentation from Charles McDonald + * (http://cgfm2.emuviews.com/txt/genie.txt) + * + * 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" + +static struct +{ + uint8 enabled; + uint8 rom[0x10000]; + uint16 regs[0x20]; + uint16 old[6]; + uint16 data[6]; + uint32 addr[6]; +} ggenie; + +static void ggenie_write_byte(uint32 address, uint32 data); +static void ggenie_write_word(uint32 address, uint32 data); +static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type); +static uint32 ggenie_read_regs(uint32 address); + +void ggenie_init(void) +{ + memset(&ggenie,0,sizeof(ggenie)); + + /* load Game Genie ROM program */ + FILE *f = fopen(GAMEGENIE_ROM,"rb"); + if (!f) return; + fread(ggenie.rom,1,0x8000,f); + fclose(f); + + /* $0000-$7fff mirrored into $8000-$ffff */ + memcpy(ggenie.rom+0x8000,ggenie.rom,0x8000); + +#ifdef LSB_FIRST + /* Byteswap ROM */ + int i; + uint8 temp; + for(i = 0; i < 0x10000; i += 2) + { + temp = ggenie.rom[i]; + ggenie.rom[i] = ggenie.rom[i+1]; + ggenie.rom[i+1] = temp; + } +#endif + + /* set flag */ + ggenie.enabled = 1; +} + +void ggenie_reset(void) +{ + if (!ggenie.enabled) return; + + /* restore patched ROM */ + int i; + for (i=0; i<6; i++) + { + if (ggenie.regs[0] & (1 << i)) + *(uint16 *)(cart_rom + ggenie.addr[i]) = ggenie.old[i]; + } + + /* reset internal state */ + memset(ggenie.regs,0,sizeof(ggenie.regs)); + memset(ggenie.old,0,sizeof(ggenie.old)); + memset(ggenie.data,0,sizeof(ggenie.data)); + memset(ggenie.addr,0,sizeof(ggenie.addr)); + + /* default slot mapping */ + /* reads are mapped to Game Genie ROM */ + /* writes are mapped to Game Genie internal registers */ + m68k_memory_map[0].base = ggenie.rom; + m68k_memory_map[0].write8 = ggenie_write_byte; + m68k_memory_map[0].write16 = ggenie_write_word; + m68k_memory_map[0].read16 = NULL; +} + + +/* Byte write handler */ +/* Note: 2nd revision of the Game Genie software use byte writes to set registe values on exit */ +static void ggenie_write_byte(uint32 address, uint32 data) +{ + /* Lock bit */ + if (ggenie.regs[0] & 0x100) return; + + /* Register offset */ + uint8 offset = (address >> 1) & 0x1f; + + /* Write internal register (lower or upper BYTE) */ + ggenie_write_regs(offset,data,address & 1); +} + +/* Word write handler */ +static void ggenie_write_word(uint32 address, uint32 data) +{ + /* Lock bit */ + if (ggenie.regs[0] & 0x100) return; + + /* Register offset */ + uint8 offset = (address >> 1) & 0x1f; + + /* Write internal register (full WORD) */ + ggenie_write_regs(offset,data,2); +} + +static void ggenie_write_regs(uint8 offset, uint32 data, uint8 type) +{ + /* access type */ + switch (type) + { + case 0: /* upper byte write */ + data = (ggenie.regs[offset] & 0x00ff) | ((data & 0xff) << 8); + break; + + case 1: /* lower byte write */ + data = (ggenie.regs[offset] & 0xff00) | (data & 0xff); + break; + + default: + break; + } + + /* Mode Register */ + if (!offset) + { + /* by default, registers are write only */ + m68k_memory_map[0].read16 = NULL; + + /* MODE bits */ + if (data & 0x400) + { + /* $0000-$7ffff reads mapped to Cartridge ROM */ + m68k_memory_map[0].base = cart_rom; + } + else + { + /* $0000-$7ffff reads mapped to Game Genie ROM */ + m68k_memory_map[0].base = ggenie.rom; + + if (data & 0x200) + { + /* $0000-$7ffff reads mapped to Game Genie Registers */ + /* code doing this should execute in RAM so we don't need to modify base address */ + m68k_memory_map[0].read16 = ggenie_read_regs; + } + } + + /* LOCK bit */ + if ((data & 0x100) && !(ggenie.regs[0] & 0x100)) + { + /* patch ROM when GG program exits (LOCK bit set) */ + /* this is done here to handle patched program reads faster & more easily */ + /* on real HW, address decoding would be done on each reads */ + int i,j; + for (i=0; i<6; i++) + { + /* decode patch address */ + /* note: Charles's documment is wrong, first register holds bits 23-16 of patch address */ + ggenie.addr[i] = (ggenie.regs[2+3*i] << 16) | ggenie.regs[3+3*i]; + + /* decode patch data */ + ggenie.data[i] = ggenie.regs[4+3*i]; + + /* patch is enabled ? */ + if (data & (1 << i)) + { + /* first look if address has not already been patched */ + for (j=0;j> 1]; + else return *(uint16 *)(cart_rom + address); +} + diff --git a/source/cart_hw/ggenie.h b/source/cart_hw/ggenie.h new file mode 100644 index 0000000..f60069c --- /dev/null +++ b/source/cart_hw/ggenie.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * Genesis Plus + * Game Genie Hardware emulation + * + * Copyright (C) 2009 Eke-Eke (GCN/Wii port) + * + * Based on documentation from Charles McDonald + * (http://cgfm2.emuviews.com/txt/genie.txt) + * + * 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 + ***************************************************************************/ + +/* global variables */ +extern int gamegenie; + +/* Function prototypes */ +extern void ggenie_init(void); +extern void ggenie_reset(void); diff --git a/source/gx/config.c b/source/gx/config.c index c62ee32..c30377a 100644 --- a/source/gx/config.c +++ b/source/gx/config.c @@ -80,6 +80,7 @@ void config_default(void) config.force_dtack = 0; config.addr_error = 1; config.bios_enabled = 0; + config.lock_on = NO_CART; /* video options */ config.xshift = 0; diff --git a/source/gx/config.h b/source/gx/config.h index 031c717..abc2a52 100644 --- a/source/gx/config.h +++ b/source/gx/config.h @@ -43,6 +43,7 @@ typedef struct uint8 force_dtack; uint8 addr_error; uint8 bios_enabled; + uint8 lock_on; int16 xshift; int16 yshift; int16 xscale; diff --git a/source/gx/gui/menu.c b/source/gx/gui/menu.c index 7d0aaa5..25674dc 100644 --- a/source/gx/gui/menu.c +++ b/source/gx/gui/menu.c @@ -230,12 +230,13 @@ static gui_item items_audio[8] = }; /* System options menu */ -static gui_item items_system[5] = +static gui_item items_system[6] = { {NULL,NULL,"Console Region: AUTO", "Select system region", 52,132,276,48}, {NULL,NULL,"System Lockups: OFF", "Enable/disable original system lock-ups", 52,132,276,48}, {NULL,NULL,"68k Address Error: ON", "Enable/disable 68k Address Error", 52,132,276,48}, {NULL,NULL,"System BIOS: OFF", "Enable/disable TMSS BIOS support", 52,132,276,48}, + {NULL,NULL,"Lock-on: OFF", "Select Lock-On cartridge type", 52,132,276,48}, {NULL,NULL,"SVP Cycles: 1500", "Adjust SVP chip emulation speed", 52,132,276,48} }; @@ -410,7 +411,7 @@ static gui_menu menu_system = { "System Settings", 0,0, - 5,4,6, + 6,4,6, items_system, buttons_list, bg_list, @@ -833,16 +834,18 @@ static void systemmenu () sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON"); sprintf (items[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF"); sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF"); + if (config.lock_on == CART_GG) sprintf (items[4].text, "Lock-On: GAME GENIE"); + else sprintf (items[4].text, "Lock-On: OFF"); if (svp) { - sprintf (items[4].text, "SVP Cycles: %d", SVP_cycles); - m->max_items = 5; + sprintf (items[5].text, "SVP Cycles: %d", SVP_cycles); + m->max_items = 6; } else { - m->max_items = 4; - m->offset = 0; + m->max_items = 5; + if (m->offset > 1) m->offset =1; } GUI_InitMenu(m); @@ -909,7 +912,13 @@ static void systemmenu () } break; - case 4: /*** SVP emulation ***/ + case 4: /*** Cart Lock-On ***/ + config.lock_on++; + if (config.lock_on > CART_GG) config.lock_on = NO_CART; + if (config.lock_on == CART_GG) sprintf (items[4].text, "Lock-On: GAME GENIE"); + else sprintf (items[4].text, "Lock-On: OFF"); + + case 5: /*** SVP emulation ***/ GUI_OptionBox(m,0,"SVP Cycles",(void *)&SVP_cycles,1,1,1500,1); sprintf (items[4].text, "SVP Cycles: %d", SVP_cycles); break; diff --git a/source/gx/main.c b/source/gx/main.c index 82a8ee7..1852920 100644 --- a/source/gx/main.c +++ b/source/gx/main.c @@ -54,14 +54,11 @@ static void Power_Off(void) ***************************************************************************/ static void load_bios(void) { - char pathname[MAXPATHLEN]; - /* reset BIOS found flag */ config.bios_enabled &= ~2; /* open BIOS file */ - sprintf (pathname, "%s/BIOS.bin",DEFAULT_PATH); - FILE *fp = fopen(pathname, "rb"); + FILE *fp = fopen(BIOS_ROM, "rb"); if (fp == NULL) return; /* read file */ diff --git a/source/gx/osd.h b/source/gx/osd.h index bb2d5ef..88fd1d9 100644 --- a/source/gx/osd.h +++ b/source/gx/osd.h @@ -25,7 +25,10 @@ #include "config.h" #include "file_mem.h" -#define DEFAULT_PATH "/genplus" +#define DEFAULT_PATH "/genplus" +#define GAMEGENIE_ROM "/genplus/ggenie.bin" +#define BIOS_ROM "/genplus/bios.bin" + #ifdef HW_RVL #define VERSION "version 1.3.2cW" #else diff --git a/source/shared.h b/source/shared.h index 7eb4978..cec2d94 100644 --- a/source/shared.h +++ b/source/shared.h @@ -26,6 +26,7 @@ #include "cart_hw.h" #include "eeprom.h" #include "sram.h" +#include "ggenie.h" #include "svp.h" #include "osd.h" diff --git a/source/sound/ym2612.c b/source/sound/ym2612.c index d3abe6b..1fd440f 100644 --- a/source/sound/ym2612.c +++ b/source/sound/ym2612.c @@ -1909,7 +1909,8 @@ void YM2612Update(int length) { int i; int lt,rt; - int16 *bufL,*bufR; + int16 *bufL = 0; + int16 *bufR = 0; /* Output samples buffers */ int16 *bufFIR = Fir_Resampler_buffer(); diff --git a/source/system.c b/source/system.c index ca2394b..2eb4525 100644 --- a/source/system.c +++ b/source/system.c @@ -220,7 +220,7 @@ void system_init (void) ****************************************************************/ void system_reset (void) { - /* Cartridge Hardware */ + /* Cartridge Hardware (should be done first !) */ cart_hw_reset(); /* Genesis Hardware */