mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 03:31:49 +01:00
+added Game Genie hardware emulation (Game Genie ROM is now fully supported)
This commit is contained in:
parent
c8c71b9bff
commit
d112fb72a2
26
HISTORY.txt
26
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)
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
***********************************************/
|
||||
|
@ -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
|
||||
{
|
||||
|
217
source/cart_hw/ggenie.c
Normal file
217
source/cart_hw/ggenie.c
Normal 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
30
source/cart_hw/ggenie.h
Normal 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);
|
@ -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;
|
||||
|
@ -43,6 +43,7 @@ typedef struct
|
||||
uint8 force_dtack;
|
||||
uint8 addr_error;
|
||||
uint8 bios_enabled;
|
||||
uint8 lock_on;
|
||||
int16 xshift;
|
||||
int16 yshift;
|
||||
int16 xscale;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "cart_hw.h"
|
||||
#include "eeprom.h"
|
||||
#include "sram.h"
|
||||
#include "ggenie.h"
|
||||
#include "svp.h"
|
||||
#include "osd.h"
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user