+added Game Genie hardware emulation (Game Genie ROM is now fully supported)

This commit is contained in:
ekeeke31 2009-07-29 15:34:25 +00:00
parent c8c71b9bff
commit d112fb72a2
13 changed files with 302 additions and 26 deletions

View File

@ -1,22 +1,24 @@
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------
Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke) Genesis Plus GX 1.4.0 (??/??/????) (Eke-Eke)
--------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------
[Core] [Core]
------ ------
* optimized SN76489 core * modified SN76489 cut-off frequency
* modified SN76489 cut-off frequency (thanks to Steve Snake) * implemented optimized SN76489 core from Blargg that uses Blip Buffer linear synthesis (Noise Channel is now linear interpolated)
* modified SN76489 core to use Blip Buffer linear synthesis , Noise channel is now linear averaged (thanks to Blargg)
* added an option to boost SN76489 Noise Channel * added an option to boost SN76489 Noise Channel
* removed now outdated Gens YM2612 core * removed outdated Gens YM2612 core
* improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware) * 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. * fixed YM2612 context saving/loading.
* added 3 Band Equalizer for improved & fully configurable sound filtering (taken from Softdev's NeoCD Redux) * added 3-Band EQ for fully configurable sound filtering (credits to Neil C / Etanza Systems)
* improved sprites masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his test program) * 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 * fixed lightgun autodetection: fixes cursor position in Lethal Enforcers II
* improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS instructions timing accuracy * improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS 68k instructions timing accuracy
* lots of code cleanup & core optimizations * various code cleanup & core optimizations
[Gamecube/Wii] [Gamecube/Wii]
@ -24,8 +26,8 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
* fixed stability issues and some (potential) memory leaks * fixed stability issues and some (potential) memory leaks
* added internal screenshot feature * added internal screenshot feature
* improved lightgun cursors * improved lightgun cursors
* new FONT & GUI engines: use internal IPL FONT, GX hardware & multithreading for fast rendering. * implemented 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 interface: incl. IR pointing, ROM snapshots, menu effects, sound effects, BGM... (check the README for more details)

View File

@ -151,6 +151,9 @@ void cart_hw_reset()
/* SVP chip */ /* SVP chip */
if (svp) svp_reset(); if (svp) svp_reset();
/* Game Genie hardware */
if (config.lock_on == CART_GG) ggenie_reset();
} }
/* cart hardware detection */ /* cart hardware detection */
@ -222,6 +225,11 @@ void cart_hw_init()
} }
} }
/**********************************************
GAME GENIE
***********************************************/
if (config.lock_on == CART_GG) ggenie_init();
/********************************************** /**********************************************
SVP CHIP SVP CHIP
***********************************************/ ***********************************************/

View File

@ -27,6 +27,12 @@
#ifndef _CART_HW_H_ #ifndef _CART_HW_H_
#define _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 */ /* Hardware description */
typedef struct typedef struct
{ {

217
source/cart_hw/ggenie.c Normal file
View File

@ -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<i;j++)
{
if (ggenie.addr[i] == ggenie.addr[j])
{
/* disable code for later initialization */
data &= ~(1 << i);
}
}
/* ave old value and patch ROM if enabled */
if (data & (1 << i))
{
ggenie.old[i] = *(uint16 *)(cart_rom + ggenie.addr[i]);
*(uint16 *)(cart_rom + ggenie.addr[i]) = ggenie.data[i];
}
}
}
}
}
/* update internal register */
ggenie.regs[offset] = data;
}
static uint32 ggenie_read_regs(uint32 address)
{
if (address < 0x40) return ggenie.regs[address >> 1];
else return *(uint16 *)(cart_rom + address);
}

30
source/cart_hw/ggenie.h Normal file
View File

@ -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);

View File

@ -80,6 +80,7 @@ void config_default(void)
config.force_dtack = 0; config.force_dtack = 0;
config.addr_error = 1; config.addr_error = 1;
config.bios_enabled = 0; config.bios_enabled = 0;
config.lock_on = NO_CART;
/* video options */ /* video options */
config.xshift = 0; config.xshift = 0;

View File

@ -43,6 +43,7 @@ typedef struct
uint8 force_dtack; uint8 force_dtack;
uint8 addr_error; uint8 addr_error;
uint8 bios_enabled; uint8 bios_enabled;
uint8 lock_on;
int16 xshift; int16 xshift;
int16 yshift; int16 yshift;
int16 xscale; int16 xscale;

View File

@ -230,12 +230,13 @@ static gui_item items_audio[8] =
}; };
/* System options menu */ /* 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,"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,"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,"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,"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} {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", "System Settings",
0,0, 0,0,
5,4,6, 6,4,6,
items_system, items_system,
buttons_list, buttons_list,
bg_list, bg_list,
@ -833,16 +834,18 @@ static void systemmenu ()
sprintf (items[1].text, "System Lockups: %s", config.force_dtack ? "OFF" : "ON"); 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[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF"); sprintf (items[3].text, "System 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) if (svp)
{ {
sprintf (items[4].text, "SVP Cycles: %d", SVP_cycles); sprintf (items[5].text, "SVP Cycles: %d", SVP_cycles);
m->max_items = 5; m->max_items = 6;
} }
else else
{ {
m->max_items = 4; m->max_items = 5;
m->offset = 0; if (m->offset > 1) m->offset =1;
} }
GUI_InitMenu(m); GUI_InitMenu(m);
@ -909,7 +912,13 @@ static void systemmenu ()
} }
break; 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); GUI_OptionBox(m,0,"SVP Cycles",(void *)&SVP_cycles,1,1,1500,1);
sprintf (items[4].text, "SVP Cycles: %d", SVP_cycles); sprintf (items[4].text, "SVP Cycles: %d", SVP_cycles);
break; break;

View File

@ -54,14 +54,11 @@ static void Power_Off(void)
***************************************************************************/ ***************************************************************************/
static void load_bios(void) static void load_bios(void)
{ {
char pathname[MAXPATHLEN];
/* reset BIOS found flag */ /* reset BIOS found flag */
config.bios_enabled &= ~2; config.bios_enabled &= ~2;
/* open BIOS file */ /* open BIOS file */
sprintf (pathname, "%s/BIOS.bin",DEFAULT_PATH); FILE *fp = fopen(BIOS_ROM, "rb");
FILE *fp = fopen(pathname, "rb");
if (fp == NULL) return; if (fp == NULL) return;
/* read file */ /* read file */

View File

@ -25,7 +25,10 @@
#include "config.h" #include "config.h"
#include "file_mem.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 #ifdef HW_RVL
#define VERSION "version 1.3.2cW" #define VERSION "version 1.3.2cW"
#else #else

View File

@ -26,6 +26,7 @@
#include "cart_hw.h" #include "cart_hw.h"
#include "eeprom.h" #include "eeprom.h"
#include "sram.h" #include "sram.h"
#include "ggenie.h"
#include "svp.h" #include "svp.h"
#include "osd.h" #include "osd.h"

View File

@ -1909,7 +1909,8 @@ void YM2612Update(int length)
{ {
int i; int i;
int lt,rt; int lt,rt;
int16 *bufL,*bufR; int16 *bufL = 0;
int16 *bufR = 0;
/* Output samples buffers */ /* Output samples buffers */
int16 *bufFIR = Fir_Resampler_buffer(); int16 *bufFIR = Fir_Resampler_buffer();

View File

@ -220,7 +220,7 @@ void system_init (void)
****************************************************************/ ****************************************************************/
void system_reset (void) void system_reset (void)
{ {
/* Cartridge Hardware */ /* Cartridge Hardware (should be done first !) */
cart_hw_reset(); cart_hw_reset();
/* Genesis Hardware */ /* Genesis Hardware */