From 785190f0b6ae401048dcfd316d94fa75e7f08313 Mon Sep 17 00:00:00 2001 From: dborth Date: Wed, 10 Sep 2008 05:57:37 +0000 Subject: [PATCH] upgrade to snes9x 1.51 --- source/ngc/dvd.cpp | 16 +- source/ngc/dvd.h | 1 + source/ngc/menu.cpp | 3 + source/ngc/menudraw.cpp | 4 +- source/ngc/s9xconfig.cpp | 26 +- source/ngc/smbop.cpp | 4 + source/ngc/snes9xGX.cpp | 13 +- source/ngc/snes9xGX.h | 5 - source/snes9x/3d.h | 36 +- source/snes9x/65c816.h | 35 +- source/snes9x/apu.cpp | 203 +- source/snes9x/apu.h | 44 +- source/snes9x/apudebug.cpp | 175 +- source/snes9x/apumem.h | 267 +- source/snes9x/bsx.cpp | 328 +- source/snes9x/bsx.h | 39 +- source/snes9x/c4.cpp | 71 +- source/snes9x/c4.h | 35 +- source/snes9x/c4emu.cpp | 156 +- source/snes9x/cheats.cpp | 133 +- source/snes9x/cheats.h | 58 +- source/snes9x/cheats2.cpp | 73 +- source/snes9x/clip.cpp | 35 +- source/snes9x/controls.cpp | 578 +- source/snes9x/controls.h | 57 +- source/snes9x/copyright.h | 37 +- source/snes9x/cpu.cpp | 56 +- source/snes9x/cpuaddr.h | 37 +- source/snes9x/cpuexec.cpp | 226 +- source/snes9x/cpuexec.h | 42 +- source/snes9x/cpumacro.h | 41 +- source/snes9x/cpuops.cpp | 203 +- source/snes9x/cpuops.h | 35 +- source/snes9x/crosshairs.cpp | 37 +- source/snes9x/crosshairs.h | 35 +- source/snes9x/data.cpp | 35 +- source/snes9x/debug.cpp | 72 +- source/snes9x/debug.h | 35 +- source/snes9x/display.h | 41 +- source/snes9x/dma.cpp | 2283 +++--- source/snes9x/dma.h | 37 +- source/snes9x/dsp1.cpp | 242 +- source/snes9x/dsp1.h | 55 +- source/snes9x/dsp1emu.c.inc | 179 + source/snes9x/dsp2emu.c.inc | 39 +- source/snes9x/dsp3emu.c.inc | 49 +- source/snes9x/dsp4emu.c.inc | 35 +- source/snes9x/font.h | 50 +- source/snes9x/fxdbg.cpp | 51 +- source/snes9x/fxemu.cpp | 75 +- source/snes9x/fxemu.h | 35 +- source/snes9x/fxinst.cpp | 59 +- source/snes9x/fxinst.h | 81 +- source/snes9x/getset.h | 130 +- source/snes9x/gfx.cpp | 533 +- source/snes9x/gfx.h | 55 +- source/snes9x/globals.cpp | 49 +- source/snes9x/language.h | 57 +- source/snes9x/memmap.cpp | 6302 +++++++---------- source/snes9x/memmap.h | 404 +- source/snes9x/messages.h | 36 +- source/snes9x/missing.h | 35 +- source/snes9x/obc1.cpp | 71 +- source/snes9x/obc1.h | 37 +- source/snes9x/pixform.h | 37 +- source/snes9x/port.h | 55 +- source/snes9x/ppu.cpp | 303 +- source/snes9x/ppu.h | 82 +- source/snes9x/sa1.cpp | 75 +- source/snes9x/sa1.h | 35 +- source/snes9x/sa1cpu.cpp | 39 +- source/snes9x/sar.h | 35 +- source/snes9x/screenshot.h | 35 +- source/snes9x/sdd1.cpp | 37 +- source/snes9x/sdd1.h | 35 +- source/snes9x/sdd1emu.cpp | 45 +- source/snes9x/sdd1emu.h | 35 +- source/snes9x/seta.cpp | 35 +- source/snes9x/seta.h | 35 +- source/snes9x/seta010.cpp | 119 +- source/snes9x/seta011.cpp | 39 +- source/snes9x/seta018.cpp | 37 +- source/snes9x/snapshot.cpp | 1902 +++-- source/snes9x/snapshot.h | 38 +- source/snes9x/snes9x.cpp | 184 +- source/snes9x/snes9x.h | 99 +- source/snes9x/soundux.cpp | 435 +- source/snes9x/soundux.h | 37 +- source/snes9x/spc700.cpp | 68 +- source/snes9x/spc700.h | 88 +- source/snes9x/spc7110.cpp | 256 +- source/snes9x/spc7110.h | 35 +- source/snes9x/srtc.cpp | 99 +- source/snes9x/srtc.h | 35 +- source/snes9x/tile.cpp | 35 +- source/snes9x/tile.h | 35 +- source/snes9x/unused/2xsai.cpp | 1305 ++++ source/snes9x/unused/2xsaiwin.cpp | 821 +++ source/snes9x/unused/Makefile.in | 403 ++ source/snes9x/unused/Makefile.mingw | 193 + source/snes9x/unused/loadzip.cpp | 66 +- source/snes9x/unused/logger.cpp | 338 + source/snes9x/unused/logger.h | 178 + source/snes9x/unused/makeasm.bat | 14 + source/snes9x/unused/movie.cpp | 912 ++- source/snes9x/{ => unused}/movie.h | 64 +- source/snes9x/unused/netplay.cpp | 243 +- source/snes9x/unused/netplay.h | 42 +- source/snes9x/unused/offsets.cpp | 481 ++ source/snes9x/unused/reader.cpp | 41 +- source/snes9x/unused/reader.h | 37 +- source/snes9x/unused/screenshot.cpp | 60 +- source/snes9x/unused/server.cpp | 246 +- source/snes9x/unused/snaporig.cpp | 45 +- source/snes9x/unused/snaporig.h | 41 +- .../snes9x/unused/snes9x_default_config.cfg | 81 + source/snes9x/unused/sound.cpp | 356 + source/snes9x/unused/xenofarm.sh | 113 + source/snes9x/unused/xenofarm_gdb_cmd | 14 + 119 files changed, 16321 insertions(+), 8538 deletions(-) create mode 100644 source/snes9x/unused/2xsai.cpp create mode 100644 source/snes9x/unused/2xsaiwin.cpp create mode 100644 source/snes9x/unused/Makefile.in create mode 100644 source/snes9x/unused/Makefile.mingw create mode 100644 source/snes9x/unused/logger.cpp create mode 100644 source/snes9x/unused/logger.h create mode 100644 source/snes9x/unused/makeasm.bat rename source/snes9x/{ => unused}/movie.h (83%) create mode 100644 source/snes9x/unused/offsets.cpp create mode 100644 source/snes9x/unused/snes9x_default_config.cfg create mode 100644 source/snes9x/unused/sound.cpp create mode 100644 source/snes9x/unused/xenofarm.sh create mode 100644 source/snes9x/unused/xenofarm_gdb_cmd diff --git a/source/ngc/dvd.cpp b/source/ngc/dvd.cpp index 60d5eaf..098ff60 100644 --- a/source/ngc/dvd.cpp +++ b/source/ngc/dvd.cpp @@ -31,6 +31,7 @@ extern int maxfiles; u64 dvddir = 0; u64 dvdrootdir = 0; int dvddirlength = 0; +bool isWii = false; #ifdef HW_DOL /** DVD I/O Address base **/ @@ -59,7 +60,7 @@ dvd_read (void *dst, unsigned int len, u64 offset) DCInvalidateRange ((void *) buffer, len); - if(offset < 0x57057C00 || (isWii == true && offset < 0x118244F00LL)) // don't read past the end of the DVD + if(offset < 0x57057C00 || (isWii && offset < 0x118244F00LL)) // don't read past the end of the DVD { #ifdef HW_DOL @@ -542,5 +543,18 @@ int dvd_driveid() return (int)inquiry[2]; } + #endif +void SetDVDDriveType() +{ + #ifdef HW_RVL + isWii = true; + #else + int drvid = dvd_driveid (); + if ( drvid == 4 || drvid == 6 || drvid == 8 ) + isWii = false; + else + isWii = true; + #endif +} diff --git a/source/ngc/dvd.h b/source/ngc/dvd.h index 8adbf3e..9dfe705 100644 --- a/source/ngc/dvd.h +++ b/source/ngc/dvd.h @@ -16,5 +16,6 @@ int LoadDVDFile (unsigned char *buffer); bool TestDVD(); int dvd_read (void *dst, unsigned int len, u64 offset); bool SwitchDVDFolder(char dir[]); +void SetDVDDriveType(); #endif diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 4a4bed2..0767386 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -402,6 +402,9 @@ void CheatMenu() if ( (gc_sx < -70) || (wm_sx < -70) || (wp & WPAD_BUTTON_HOME) || (wp & WPAD_CLASSIC_BUTTON_HOME) ) break; + if ( (p & PAD_BUTTON_B) || (wp & (WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)) ) + break; + /*** Check buttons, perform actions ***/ if ( (p & PAD_BUTTON_A) || selectit || (wp & (WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A)) ) { diff --git a/source/ngc/menudraw.cpp b/source/ngc/menudraw.cpp index 34c1e98..4fefc86 100644 --- a/source/ngc/menudraw.cpp +++ b/source/ngc/menudraw.cpp @@ -472,7 +472,7 @@ DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsiz int n = 1; int line_height; - ypos = 65; + ypos = 45; if (screenheight == 480) ypos += 52; @@ -581,7 +581,7 @@ RunMenu (char items[][50], int maxitems, char *title, int fontsize, int x) wm_ay = WPAD_StickY (0,0); wp = WPAD_ButtonsDown (0); #endif - + VIDEO_WaitVSync(); // slow things down a bit so we don't overread the pads diff --git a/source/ngc/s9xconfig.cpp b/source/ngc/s9xconfig.cpp index 9c703c8..68d39aa 100644 --- a/source/ngc/s9xconfig.cpp +++ b/source/ngc/s9xconfig.cpp @@ -17,10 +17,7 @@ #include "snes9xGX.h" #include "smbop.h" -START_EXTERN_C struct SGCSettings GCSettings; -bool8 isWii; -END_EXTERN_C void DefaultSettings () @@ -63,25 +60,24 @@ DefaultSettings () /****************** SNES9x Settings ***********************/ - /*** Default ALL to false ***/ + // Default ALL to false memset (&Settings, 0, sizeof (Settings)); - /*** General ***/ - + // General Settings.MouseMaster = false; Settings.SuperScopeMaster = false; Settings.MultiPlayer5Master = false; Settings.JustifierMaster = false; Settings.ShutdownMaster = false; - Settings.CyclesPercentage = 100; // snes9x 1.50 and earlier + //Settings.CyclesPercentage = 100; // snes9x 1.50 and earlier Settings.ApplyCheats = true; - /* Eke-Eke: specific to snes9x 1.51 */ - // Settings.BlockInvalidVRAMAccess = true; - // Settings.HDMATimingHack = 100; + // Specific to snes9x 1.51 + Settings.BlockInvalidVRAMAccess = true; + Settings.HDMATimingHack = 100; - /*** Sound defaults. On GC this is 32Khz/16bit/Stereo/InterpolatedSound ***/ + // Sound defaults. On GC this is 32Khz/16bit/Stereo/InterpolatedSound Settings.APUEnabled = true; Settings.NextAPUEnabled = true; Settings.SoundPlaybackRate = 32000; @@ -92,19 +88,19 @@ DefaultSettings () Settings.InterpolatedSound = true; Settings.ReverseStereo = false; - /*** Graphics ***/ + // Graphics Settings.Transparency = true; Settings.SupportHiRes = true; Settings.SkipFrames = 10; Settings.TurboSkipFrames = 19; Settings.DisplayFrameRate = false; - // Settings.AutoDisplayMessages = 1; /*** eke-eke snes9x 1.51 ***/ + Settings.AutoDisplayMessages = 1; // SNES9x 1.51 - /* Eke-Eke: frame timings in 50hz and 60hz cpu mode */ + // Frame timings in 50hz and 60hz cpu mode Settings.FrameTimePAL = 20000; Settings.FrameTimeNTSC = 16667; - /*** SDD1 - Star Ocean Returns -;) ***/ + // SDD1 - Star Ocean Returns Settings.SDD1Pack = true; Settings.ForceNTSC = 0; diff --git a/source/ngc/smbop.cpp b/source/ngc/smbop.cpp index 764e0a8..a348e35 100644 --- a/source/ngc/smbop.cpp +++ b/source/ngc/smbop.cpp @@ -94,7 +94,11 @@ ConnectShare (bool silent) strlen(GCSettings.smbpwd) == 0 || strlen(GCSettings.smbshare) == 0 || strlen(GCSettings.smbip) == 0) + { + if(!silent) + WaitPrompt((char*) "Invalid network settings. Check SNES9xGX.xml."); return false; + } if(!networkInit) networkInit = InitializeNetwork(silent); diff --git a/source/ngc/snes9xGX.cpp b/source/ngc/snes9xGX.cpp index 22234ec..873ca5e 100644 --- a/source/ngc/snes9xGX.cpp +++ b/source/ngc/snes9xGX.cpp @@ -290,7 +290,7 @@ emulate () NGCFreezeGame ( GCSettings.SaveMethod, SILENT ); } } - + // GUI Stuff /* gui_alloc(); @@ -404,15 +404,8 @@ main () DVD_Init (); #endif - #ifdef FORCE_WII - isWii = TRUE; - #else - int drvid = dvd_driveid (); - if ( drvid == 4 || drvid == 6 || drvid == 8 ) - isWii = FALSE; - else - isWii = TRUE; - #endif + // Check if DVD drive belongs to a Wii + SetDVDDriveType(); // Load preferences if(!LoadPrefs()) diff --git a/source/ngc/snes9xGX.h b/source/ngc/snes9xGX.h index ff20f2a..87e7bc5 100644 --- a/source/ngc/snes9xGX.h +++ b/source/ngc/snes9xGX.h @@ -58,11 +58,6 @@ struct SGCSettings{ int widescreen; // 0 - 4:3 aspect, 1 - 16:9 aspect }; -START_EXTERN_C - extern struct SGCSettings GCSettings; -extern bool8 isWii; - -END_EXTERN_C #endif diff --git a/source/snes9x/3d.h b/source/snes9x/3d.h index cec9344..0122ce2 100644 --- a/source/snes9x/3d.h +++ b/source/snes9x/3d.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _3D_H_ #define _3D_H_ @@ -167,6 +186,7 @@ typedef struct GLint texture_size; uint32 num_textures; // 1 if max_texture_size == 256, 2 otherwise GLuint textures [2]; + bool8 initialized; } OpenGLData; extern OpenGLData OpenGL; diff --git a/source/snes9x/65c816.h b/source/snes9x/65c816.h index 9c45fc1..bee73da 100644 --- a/source/snes9x/65c816.h +++ b/source/snes9x/65c816.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _65c816_h_ #define _65c816_h_ diff --git a/source/snes9x/apu.cpp b/source/snes9x/apu.cpp index ad4620e..553530f 100644 --- a/source/snes9x/apu.cpp +++ b/source/snes9x/apu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifdef __DJGPP #include #undef TRUE @@ -163,7 +182,7 @@ extern int32 env_counter_table[32]; int spc_is_dumping=0; int spc_is_dumping_temp; -uint8 spc_dump_dsp[0x100]; +uint8 spc_dump_dsp[0x100]; #ifdef DEBUGGER void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, @@ -173,19 +192,15 @@ void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, bool8 S9xInitAPU () { IAPU.RAM = (uint8 *) malloc (0x10000); - IAPU.ShadowRAM = (uint8 *) malloc (0x10000); - IAPU.CachedSamples = (uint8 *) malloc (0x40000); - - if (!IAPU.RAM || !IAPU.ShadowRAM || !IAPU.CachedSamples) + + if (!IAPU.RAM) { S9xDeinitAPU (); return (FALSE); } memset(IAPU.RAM, 0, 0x10000); - memset(IAPU.ShadowRAM, 0, 0x10000); - memset(IAPU.CachedSamples, 0, 0x40000); - + return (TRUE); } @@ -196,27 +211,19 @@ void S9xDeinitAPU () free ((char *) IAPU.RAM); IAPU.RAM = NULL; } - if (IAPU.ShadowRAM) - { - free ((char *) IAPU.ShadowRAM); - IAPU.ShadowRAM = NULL; - } - if (IAPU.CachedSamples) - { - free ((char *) IAPU.CachedSamples); - IAPU.CachedSamples = NULL; - } } EXTERN_C uint8 APUROM [64]; void S9xResetAPU () { - int i; Settings.APUEnabled = Settings.NextAPUEnabled; + if(Settings.APUEnabled) + APU.Flags &= ~HALTED_FLAG; + ZeroMemory(spc_dump_dsp, 0x100); ZeroMemory(IAPU.RAM, 0x100); memset(IAPU.RAM+0x20, 0xFF, 0x20); @@ -229,19 +236,17 @@ void S9xResetAPU () memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100); } - memcpy (IAPU.ShadowRAM, IAPU.RAM, 0x10000); - - ZeroMemory (IAPU.CachedSamples, 0x40000); ZeroMemory (APU.OutPorts, 4); IAPU.DirectPage = IAPU.RAM; + memmove (APU.ExtraRAM, &IAPU.RAM [0xffc0], sizeof (APUROM)); memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - memmove (APU.ExtraRAM, APUROM, sizeof (APUROM)); IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); APU.Cycles = 0; + APU.OldCycles = -99999999; // For shapshot compatibility APURegisters.YA.W = 0; APURegisters.X = 0; - APURegisters.S = 0xff; - APURegisters.P = 0; + APURegisters.S = 0xef; + APURegisters.P = 0x02; S9xAPUUnpackStatus (); APURegisters.PC = 0; IAPU.APUExecuting = Settings.APUEnabled; @@ -254,7 +259,7 @@ void S9xResetAPU () IAPU.APUTimerCounter = 0; APU.ShowROM = TRUE; IAPU.RAM [0xf1] = 0x80; - + for (i = 0; i < 3; i++) { APU.TimerEnabled [i] = FALSE; @@ -264,18 +269,18 @@ void S9xResetAPU () } for (int j = 0; j < 0x80; j++) APU.DSP [j] = 0; - + IAPU.TwoCycles = IAPU.OneCycle * 2; - + for (i = 0; i < 256; i++) S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle; - + APU.DSP [APU_ENDX] = 0; APU.DSP [APU_KOFF] = 0; APU.DSP [APU_KON] = 0; APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED; APU.KeyedChannels = 0; - + S9xResetSound (TRUE); S9xSetEchoEnable (0); } @@ -318,7 +323,7 @@ void S9xSetAPUDSP (uint8 byte) } else S9xSetSoundMute (FALSE); - + SoundData.noise_rate = env_counter_table[byte & 0x1f]; } break; @@ -370,7 +375,7 @@ void S9xSetAPUDSP (uint8 byte) { #ifdef DEBUGGER if (Settings.TraceSoundDSP) - S9xTraceSoundDSP ("[%d] Master volume left:%d\n", + S9xTraceSoundDSP ("[%d] Master volume left:%d\n", ICPU.Scanline, (signed char) byte); #endif S9xSetMasterVolume ((signed char) byte, @@ -420,7 +425,7 @@ void S9xSetAPUDSP (uint8 byte) #endif byte = 0; break; - + case APU_KOFF: // if (byte) { @@ -434,10 +439,10 @@ void S9xSetAPUDSP (uint8 byte) if ((byte & mask) != 0) { #ifdef DEBUGGER - + if (Settings.TraceSoundDSP) S9xTraceSoundDSP ("%d,", c); -#endif +#endif if (APU.KeyedChannels & mask) { { @@ -484,7 +489,7 @@ void S9xSetAPUDSP (uint8 byte) { uint8 mask = 1; #ifdef DEBUGGER - + if (Settings.TraceSoundDSP) S9xTraceSoundDSP ("[%d] Key on:", ICPU.Scanline); #endif @@ -495,7 +500,7 @@ void S9xSetAPUDSP (uint8 byte) #ifdef DEBUGGER if (Settings.TraceSoundDSP) S9xTraceSoundDSP ("%d,", c); -#endif +#endif // Pac-In-Time requires that channels can be key-on // regardeless of their current state. if((APU.DSP [APU_KOFF] & mask) ==0) @@ -517,7 +522,7 @@ void S9xSetAPUDSP (uint8 byte) } spc_is_dumping_temp = byte; return; - + case APU_VOL_LEFT + 0x00: case APU_VOL_LEFT + 0x10: case APU_VOL_LEFT + 0x20: @@ -531,7 +536,7 @@ void S9xSetAPUDSP (uint8 byte) { #ifdef DEBUGGER if (Settings.TraceSoundDSP) - S9xTraceSoundDSP ("[%d] %d volume left: %d\n", + S9xTraceSoundDSP ("[%d] %d volume left: %d\n", ICPU.Scanline, reg>>4, (signed char) byte); #endif S9xSetSoundVolume (reg >> 4, (signed char) byte, @@ -551,14 +556,14 @@ void S9xSetAPUDSP (uint8 byte) { #ifdef DEBUGGER if (Settings.TraceSoundDSP) - S9xTraceSoundDSP ("[%d] %d volume right: %d\n", + S9xTraceSoundDSP ("[%d] %d volume right: %d\n", ICPU.Scanline, reg >>4, (signed char) byte); #endif S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1], (signed char) byte); } break; - + case APU_P_LOW + 0x00: case APU_P_LOW + 0x10: case APU_P_LOW + 0x20: @@ -574,7 +579,7 @@ void S9xSetAPUDSP (uint8 byte) #endif S9xSetSoundHertz (reg >> 4, ((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 8); break; - + case APU_P_HIGH + 0x00: case APU_P_HIGH + 0x10: case APU_P_HIGH + 0x20: @@ -588,10 +593,10 @@ void S9xSetAPUDSP (uint8 byte) S9xTraceSoundDSP ("[%d] %d freq high: %d\n", ICPU.Scanline, reg>>4, byte); #endif - S9xSetSoundHertz (reg >> 4, + S9xSetSoundHertz (reg >> 4, (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8); break; - + case APU_SRCN + 0x00: case APU_SRCN + 0x10: case APU_SRCN + 0x20: @@ -606,7 +611,7 @@ void S9xSetAPUDSP (uint8 byte) ICPU.Scanline, reg>>4, byte); #endif break; - + case APU_ADSR1 + 0x00: case APU_ADSR1 + 0x10: case APU_ADSR1 + 0x20: @@ -623,12 +628,12 @@ void S9xSetAPUDSP (uint8 byte) ICPU.Scanline, reg>>4, byte); #endif { - S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, + S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, APU.DSP [reg + 1]); } } break; - + case APU_ADSR2 + 0x00: case APU_ADSR2 + 0x10: case APU_ADSR2 + 0x20: @@ -641,7 +646,7 @@ void S9xSetAPUDSP (uint8 byte) { #ifdef DEBUGGER if (Settings.TraceSoundDSP) - S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n", + S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n", ICPU.Scanline, reg>>4, byte); #endif { @@ -650,7 +655,7 @@ void S9xSetAPUDSP (uint8 byte) } } break; - + case APU_GAIN + 0x00: case APU_GAIN + 0x10: case APU_GAIN + 0x20: @@ -672,7 +677,7 @@ void S9xSetAPUDSP (uint8 byte) } } break; - + case APU_ENVX + 0x00: case APU_ENVX + 0x10: case APU_ENVX + 0x20: @@ -682,7 +687,7 @@ void S9xSetAPUDSP (uint8 byte) case APU_ENVX + 0x60: case APU_ENVX + 0x70: break; - + case APU_OUTX + 0x00: case APU_OUTX + 0x10: case APU_OUTX + 0x20: @@ -692,7 +697,7 @@ void S9xSetAPUDSP (uint8 byte) case APU_OUTX + 0x60: case APU_OUTX + 0x70: break; - + case APU_DIR: #ifdef DEBUGGER if (Settings.TraceSoundDSP) @@ -700,7 +705,7 @@ void S9xSetAPUDSP (uint8 byte) ICPU.Scanline, byte); #endif break; - + case APU_PMON: if (byte != APU.DSP [APU_PMON]) { @@ -730,7 +735,7 @@ void S9xSetAPUDSP (uint8 byte) S9xSetFrequencyModulationEnable (byte); } break; - + case APU_EON: if (byte != APU.DSP [APU_EON]) { @@ -760,18 +765,18 @@ void S9xSetAPUDSP (uint8 byte) S9xSetEchoEnable (byte); } break; - + case APU_EFB: S9xSetEchoFeedback ((signed char) byte); break; - + case APU_ESA: break; - + case APU_EDL: S9xSetEchoDelay (byte & 0xf); break; - + case APU_C0: case APU_C1: case APU_C2: @@ -787,10 +792,10 @@ void S9xSetAPUDSP (uint8 byte) //printf ("Write %02x to unknown APU register %02x\n", byte, reg); break; } - + KeyOnPrev|=KeyOn; KeyOn=0; - + if (reg < 0x80) APU.DSP [reg] = byte; } @@ -856,13 +861,13 @@ void S9xSetAPUControl (uint8 byte) APU.TimerEnabled [0] = byte & 1; APU.TimerEnabled [1] = (byte & 2) >> 1; APU.TimerEnabled [2] = (byte & 4) >> 2; - + if (byte & 0x10) IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0; - + if (byte & 0x20) IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0; - + if (byte & 0x80) { if (!APU.ShowROM) @@ -885,7 +890,7 @@ void S9xSetAPUControl (uint8 byte) void S9xSetAPUTimer (uint16 Address, uint8 byte) { IAPU.RAM [Address] = byte; - + switch (Address) { case 0xfa: @@ -906,12 +911,21 @@ void S9xSetAPUTimer (uint16 Address, uint8 byte) } } -void S9xUpdateAPUTimer (void) +void S9xAPUExecute (void) { - while ((CPU.Cycles << SNES_APUTIMER_ACCURACY) >= IAPU.NextAPUTimerPos) + while ((CPU.Cycles << SNES_APU_ACCURACY) >= IAPU.NextAPUTimerPos) { - IAPU.NextAPUTimerPos += SNES_APUTIMER2_CYCLE_SHIFT; - + // catch up the APU timers + if (IAPU.APUExecuting) + { + while (APU.Cycles < IAPU.NextAPUTimerPos) + APU_EXECUTE1(); + } + else + APU.Cycles = IAPU.NextAPUTimerPos; + + IAPU.NextAPUTimerPos += SNES_APUTIMER2_CYCLE_SCALED; + if (APU.TimerEnabled [2]) { APU.Timer [2] ++; @@ -919,17 +933,17 @@ void S9xUpdateAPUTimer (void) { IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; APU.Timer [2] = 0; - #ifdef SPC700_SHUTDOWN + #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; - #endif + #endif } } if (++IAPU.APUTimerCounter == 8) { IAPU.APUTimerCounter = 0; - + if (APU.TimerEnabled [0]) { APU.Timer [0]++; @@ -937,10 +951,10 @@ void S9xUpdateAPUTimer (void) { IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; APU.Timer [0] = 0; - #ifdef SPC700_SHUTDOWN + #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; - #endif + #endif } } @@ -951,14 +965,23 @@ void S9xUpdateAPUTimer (void) { IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; APU.Timer [1] = 0; - #ifdef SPC700_SHUTDOWN + #ifdef SPC700_SHUTDOWN IAPU.WaitCounter++; IAPU.APUExecuting = TRUE; - #endif + #endif } } } } + + // catch up the current cycles + if (IAPU.APUExecuting) + { + while (APU.Cycles < (CPU.Cycles << SNES_APU_ACCURACY)) + APU_EXECUTE1(); + } + else + APU.Cycles = (CPU.Cycles << SNES_APU_ACCURACY); } uint8 S9xGetAPUDSP () @@ -981,10 +1004,18 @@ uint8 S9xGetAPUDSP () case APU_OUTX + 0x50: case APU_OUTX + 0x60: case APU_OUTX + 0x70: + if(Settings.FakeMuteFix) + { + // hack that is off by default: fixes Terranigma desync + return (0); + } + else + { if (SoundData.channels [reg >> 4].state == SOUND_SILENT) return (0); return (int8) (SoundData.channels [reg >> 4].out_sample >> 8); - + } + case APU_ENVX + 0x00: case APU_ENVX + 0x10: case APU_ENVX + 0x20: @@ -994,7 +1025,7 @@ uint8 S9xGetAPUDSP () case APU_ENVX + 0x60: case APU_ENVX + 0x70: return (S9xGetEnvelopeHeight (reg >> 4)); - + case APU_ENDX: // To fix speech in Magical Drop 2 6/11/00 // APU.DSP [APU_ENDX] = 0; @@ -1003,6 +1034,6 @@ uint8 S9xGetAPUDSP () default: break; } - + return (byte); } diff --git a/source/snes9x/apu.h b/source/snes9x/apu.h index 90b562b..9c3d949 100644 --- a/source/snes9x/apu.h +++ b/source/snes9x/apu.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _apu_h_ #define _apu_h_ @@ -158,8 +177,8 @@ struct SIAPU uint8 *WaitAddress1; uint8 *WaitAddress2; uint32 WaitCounter; - uint8 *ShadowRAM; - uint8 *CachedSamples; + uint8 *ShadowRAM; // unused + uint8 *CachedSamples; // unused uint8 _Carry; uint8 _Zero; uint8 _Overflow; @@ -173,7 +192,7 @@ struct SIAPU struct SAPU { - int32 Cycles; + int32 OldCycles; // unused bool8 ShowROM; uint32 Flags; uint8 KeyedChannels; @@ -184,6 +203,7 @@ struct SAPU uint16 TimerTarget [3]; bool8 TimerEnabled [3]; bool8 TimerValueWritten [3]; + int32 Cycles; }; EXTERN_C struct SAPU APU; @@ -216,7 +236,7 @@ void S9xSetAPUControl (uint8 byte); void S9xSetAPUDSP (uint8 byte); uint8 S9xGetAPUDSP (); void S9xSetAPUTimer (uint16 Address, uint8 byte); -void S9xUpdateAPUTimer (void); +void S9xAPUExecute (void); bool8 S9xInitSound (int quality, bool8 stereo, int buffer_size); void S9xOpenCloseSoundTracingFile (bool8); void S9xPrintAPUState (); diff --git a/source/snes9x/apudebug.cpp b/source/snes9x/apudebug.cpp index 58a268a..495979a 100644 --- a/source/snes9x/apudebug.cpp +++ b/source/snes9x/apudebug.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,85 +159,83 @@ **********************************************************************************/ + + #include "snes9x.h" #include "spc700.h" #include "apu.h" #include "soundux.h" #include "cpuexec.h" -#ifdef SPCTOOL -#include "spctool/spc700.h" -#endif - #ifdef DEBUGGER extern int32 env_counter_table[32]; FILE *apu_trace = NULL; static char *S9xMnemonics [256] = { - "NOP", "TCALL 0", "SET1 $%02X.0", "BBS $%02X.0,$%04X", - "OR A,$%02X", "OR A,!$%04X", "OR A,(X)", "OR A,[$%02X+X]", - "OR A,#$%02X", "OR $%02X,$%02X", "OR1 C,$%04X.%d", "ASL $%02X", - "MOV !$%04X,Y", "PUSH PSW", "TSET1 !$%04X", "BRK", - "BPL $%04X", "TCALL 1", "CLR1 $%02X.0", "BBC $%02X.0,$%04X", - "OR A,$%02X+X", "OR A,!$%04X+X", "OR A,!$%04X+Y", "OR A,[$%02X]+Y", - "OR $%02X,#$%02X", "OR (X),(Y)", "DECW $%02X", "ASL $%02X+X", - "ASL A", "DEC X", "CMP X,!$%04X", "JMP [!$%04X+X]", - "CLRP", "TCALL 2", "SET1 $%02X.1", "BBS $%02X.1,$%04X", - "AND A,$%02X", "AND A,!$%04X", "AND A,(X)", "AND A,[$%02X+X]", - "AND A,#$%02X", "AND $%02X,$%02X", "OR1 C,/$%04X.%d", "ROL $%02X", - "ROL !$%04X", "PUSH A", "CBNE $%02X,$%04X", "BRA $%04X", - "BMI $%04X", "TCALL 3", "CLR1 $%02X.1", "BBC $%02X.1,$%04X", - "AND A,$%02X+X", "AND A,!$%04X+X", "AND A,!$%04X+Y", "AND A,[$%02X]+Y", - "AND $%02X,#$%02X", "AND (X),(Y)", "INCW $%02X", "ROL $%02X+X", - "ROL A", "INC X", "CMP X,$%02X", "CALL !$%04X", - "SETP", "TCALL 4", "SET1 $%02X.2", "BBS $%02X.2,$%04X", - "EOR A,$%02X", "EOR A,!$%04X", "EOR A,(X)", "EOR A,[$%02X+X]", - "EOR A,#$%02X", "EOR $%02X,$%02X", "AND1 C,$%04X.%d", "LSR $%02X", - "LSR !$%04X", "PUSH X", "TCLR1 !$%04X", "PCALL $%02X", - "BVC $%04X", "TCALL 5", "CLR1 $%02X.2", "BBC $%02X.2,$%04X", - "EOR A,$%02X+X", "EOR A,!$%04X+X", "EOR A,!$%04X+Y", "EOR A,[$%02X]+Y", - "EOR $%02X,#$%02X", "EOR (X),(Y)", "CMPW YA,$%02X", "LSR $%02X+X", - "LSR A", "MOV X,A", "CMP Y,!$%04X", "JMP !$%04X", - "CLRC", "TCALL 6", "SET1 $%02X.3", "BBS $%02X.3,$%04X", - "CMP A,$%02X", "CMP A,!$%04X", "CMP A,(X)", "CMP A,[$%02X+X]", - "CMP A,#$%02X", "CMP $%02X,$%02X", "AND1 C,/$%04X.%d", "ROR $%02X", - "ROR !$%04X", "PUSH Y", "DBNZ $%02X,$%04X", "RET", - "BVS $%04X", "TCALL 7", "CLR1 $%02X.3", "BBC $%02X.3,$%04X", - "CMP A,$%02X+X", "CMP A,!$%04X+X", "CMP A,!$%04X+Y", "CMP A,[$%02X]+Y", - "CMP $%02X,#$%02X", "CMP (X),(Y)", "ADDW YA,$%02X", "ROR $%02X+X", - "ROR A", "MOV A,X", "CMP Y,$%02X", "RET1", - "SETC", "TCALL 8", "SET1 $%02X.4", "BBS $%02X.4,$%04X", - "ADC A,$%02X", "ADC A,!$%04X", "ADC A,(X)", "ADC A,[$%02X+X]", - "ADC A,#$%02X", "ADC $%02X,$%02X", "EOR1 C,$%04X.%d", "DEC $%02X", - "DEC !$%04X", "MOV Y,#$%02X", "POP PSW", "MOV $%02X,#$%02X", - "BCC $%04X", "TCALL 9", "CLR1 $%02X.4", "BBC $%02X.4,$%04X", - "ADC A,$%02X+X", "ADC A,!$%04X+X", "ADC A,!$%04X+Y", "ADC A,[$%02X]+Y", - "ADC $%02X,#$%02X", "ADC (X),(Y)", "SUBW YA,$%02X", "DEC $%02X+X", - "DEC A", "MOV X,SP", "DIV YA,X", "XCN A", - "EI", "TCALL 10", "SET1 $%02X.5", "BBS $%02X.5,$%04X", - "SBC A,$%02X", "SBC A,!$%04X", "SBC A,(X)", "SBC A,[$%02X+X]", - "SBC A,#$%02X", "SBC $%02X,$%02X", "MOV1 C,$%04X.%d", "INC $%02X", - "INC !$%04X", "CMP Y,#$%02X", "POP A", "MOV (X)+,A", - "BCS $%04X", "TCALL 11", "CLR1 $%02X.5", "BBC $%02X.5,$%04X", - "SBC A,$%02X+X", "SBC A,!$%04X+X", "SBC A,!$%04X+Y", "SBC A,[$%02X]+Y", - "SBC $%02X,#$%02X", "SBC (X),(Y)", "MOVW YA,$%02X", "INC $%02X+X", - "INC A", "MOV SP,X", "DAS A", "MOV A,(X)+", - "DI", "TCALL 12", "SET1 $%02X.6", "BBS $%02X.6,$%04X", - "MOV $%02X,A", "MOV !$%04X,A", "MOV (X),A", "MOV [$%02X+X],A", - "CMP X,#$%02X", "MOV !$%04X,X", "MOV1 $%04X.%d,C", "MOV $%02X,Y", - "ASL !$%04X", "MOV X,#$%02X", "POP X", "MUL YA", - "BNE $%04X", "TCALL 13", "CLR1 $%02X.6", "BBC $%02X.6,$%04X", - "MOV $%02X+X,A", "MOV !$%04X+X,A", "MOV !$%04X+Y,A", "MOV [$%02X]+Y,A", - "MOV $%02X,X", "MOV $%02X+Y,X", "MOVW $%02X,YA", "MOV $%02X+X,Y", - "DEC Y", "MOV A,Y", "CBNE $%02X+X,$%04X", "DAA A", - "CLRV", "TCALL 14", "SET1 $%02X.7", "BBS $%02X.7,$%04X", - "MOV A,$%02X", "MOV A,!$%04X", "MOV A,(X)", "MOV A,[$%02X+X]", - "MOV A,#$%02X", "MOV X,!$%04X", "NOT1 $%04X.%d", "MOV Y,$%02X", - "MOV Y,!$%04X", "NOTC", "POP Y", "SLEEP", - "BEQ $%04X", "TCALL 15", "CLR1 $%02X.7", "BBC $%02X.7,$%04X", - "MOV A,$%02X+X", "MOV A,!$%04X+X", "MOV A,!$%04X+Y", "MOV A,[$%02X]+Y", - "MOV X,$%02X", "MOV X,$%02X+Y", "MOV $%02X,$%02X", "MOV Y,$%02X+X", + "NOP", "TCALL 0", "SET1 $%02X.0", "BBS $%02X.0,$%04X", + "OR A,$%02X", "OR A,!$%04X", "OR A,(X)", "OR A,[$%02X+X]", + "OR A,#$%02X", "OR $%02X,$%02X", "OR1 C,$%04X.%d", "ASL $%02X", + "MOV !$%04X,Y", "PUSH PSW", "TSET1 !$%04X", "BRK", + "BPL $%04X", "TCALL 1", "CLR1 $%02X.0", "BBC $%02X.0,$%04X", + "OR A,$%02X+X", "OR A,!$%04X+X", "OR A,!$%04X+Y", "OR A,[$%02X]+Y", + "OR $%02X,#$%02X", "OR (X),(Y)", "DECW $%02X", "ASL $%02X+X", + "ASL A", "DEC X", "CMP X,!$%04X", "JMP [!$%04X+X]", + "CLRP", "TCALL 2", "SET1 $%02X.1", "BBS $%02X.1,$%04X", + "AND A,$%02X", "AND A,!$%04X", "AND A,(X)", "AND A,[$%02X+X]", + "AND A,#$%02X", "AND $%02X,$%02X", "OR1 C,/$%04X.%d", "ROL $%02X", + "ROL !$%04X", "PUSH A", "CBNE $%02X,$%04X", "BRA $%04X", + "BMI $%04X", "TCALL 3", "CLR1 $%02X.1", "BBC $%02X.1,$%04X", + "AND A,$%02X+X", "AND A,!$%04X+X", "AND A,!$%04X+Y", "AND A,[$%02X]+Y", + "AND $%02X,#$%02X", "AND (X),(Y)", "INCW $%02X", "ROL $%02X+X", + "ROL A", "INC X", "CMP X,$%02X", "CALL !$%04X", + "SETP", "TCALL 4", "SET1 $%02X.2", "BBS $%02X.2,$%04X", + "EOR A,$%02X", "EOR A,!$%04X", "EOR A,(X)", "EOR A,[$%02X+X]", + "EOR A,#$%02X", "EOR $%02X,$%02X", "AND1 C,$%04X.%d", "LSR $%02X", + "LSR !$%04X", "PUSH X", "TCLR1 !$%04X", "PCALL $%02X", + "BVC $%04X", "TCALL 5", "CLR1 $%02X.2", "BBC $%02X.2,$%04X", + "EOR A,$%02X+X", "EOR A,!$%04X+X", "EOR A,!$%04X+Y", "EOR A,[$%02X]+Y", + "EOR $%02X,#$%02X", "EOR (X),(Y)", "CMPW YA,$%02X", "LSR $%02X+X", + "LSR A", "MOV X,A", "CMP Y,!$%04X", "JMP !$%04X", + "CLRC", "TCALL 6", "SET1 $%02X.3", "BBS $%02X.3,$%04X", + "CMP A,$%02X", "CMP A,!$%04X", "CMP A,(X)", "CMP A,[$%02X+X]", + "CMP A,#$%02X", "CMP $%02X,$%02X", "AND1 C,/$%04X.%d", "ROR $%02X", + "ROR !$%04X", "PUSH Y", "DBNZ $%02X,$%04X", "RET", + "BVS $%04X", "TCALL 7", "CLR1 $%02X.3", "BBC $%02X.3,$%04X", + "CMP A,$%02X+X", "CMP A,!$%04X+X", "CMP A,!$%04X+Y", "CMP A,[$%02X]+Y", + "CMP $%02X,#$%02X", "CMP (X),(Y)", "ADDW YA,$%02X", "ROR $%02X+X", + "ROR A", "MOV A,X", "CMP Y,$%02X", "RET1", + "SETC", "TCALL 8", "SET1 $%02X.4", "BBS $%02X.4,$%04X", + "ADC A,$%02X", "ADC A,!$%04X", "ADC A,(X)", "ADC A,[$%02X+X]", + "ADC A,#$%02X", "ADC $%02X,$%02X", "EOR1 C,$%04X.%d", "DEC $%02X", + "DEC !$%04X", "MOV Y,#$%02X", "POP PSW", "MOV $%02X,#$%02X", + "BCC $%04X", "TCALL 9", "CLR1 $%02X.4", "BBC $%02X.4,$%04X", + "ADC A,$%02X+X", "ADC A,!$%04X+X", "ADC A,!$%04X+Y", "ADC A,[$%02X]+Y", + "ADC $%02X,#$%02X", "ADC (X),(Y)", "SUBW YA,$%02X", "DEC $%02X+X", + "DEC A", "MOV X,SP", "DIV YA,X", "XCN A", + "EI", "TCALL 10", "SET1 $%02X.5", "BBS $%02X.5,$%04X", + "SBC A,$%02X", "SBC A,!$%04X", "SBC A,(X)", "SBC A,[$%02X+X]", + "SBC A,#$%02X", "SBC $%02X,$%02X", "MOV1 C,$%04X.%d", "INC $%02X", + "INC !$%04X", "CMP Y,#$%02X", "POP A", "MOV (X)+,A", + "BCS $%04X", "TCALL 11", "CLR1 $%02X.5", "BBC $%02X.5,$%04X", + "SBC A,$%02X+X", "SBC A,!$%04X+X", "SBC A,!$%04X+Y", "SBC A,[$%02X]+Y", + "SBC $%02X,#$%02X", "SBC (X),(Y)", "MOVW YA,$%02X", "INC $%02X+X", + "INC A", "MOV SP,X", "DAS A", "MOV A,(X)+", + "DI", "TCALL 12", "SET1 $%02X.6", "BBS $%02X.6,$%04X", + "MOV $%02X,A", "MOV !$%04X,A", "MOV (X),A", "MOV [$%02X+X],A", + "CMP X,#$%02X", "MOV !$%04X,X", "MOV1 $%04X.%d,C", "MOV $%02X,Y", + "ASL !$%04X", "MOV X,#$%02X", "POP X", "MUL YA", + "BNE $%04X", "TCALL 13", "CLR1 $%02X.6", "BBC $%02X.6,$%04X", + "MOV $%02X+X,A", "MOV !$%04X+X,A", "MOV !$%04X+Y,A", "MOV [$%02X]+Y,A", + "MOV $%02X,X", "MOV $%02X+Y,X", "MOVW $%02X,YA", "MOV $%02X+X,Y", + "DEC Y", "MOV A,Y", "CBNE $%02X+X,$%04X", "DAA A", + "CLRV", "TCALL 14", "SET1 $%02X.7", "BBS $%02X.7,$%04X", + "MOV A,$%02X", "MOV A,!$%04X", "MOV A,(X)", "MOV A,[$%02X+X]", + "MOV A,#$%02X", "MOV X,!$%04X", "NOT1 $%04X.%d", "MOV Y,$%02X", + "MOV Y,!$%04X", "NOTC", "POP Y", "SLEEP", + "BEQ $%04X", "TCALL 15", "CLR1 $%02X.7", "BBC $%02X.7,$%04X", + "MOV A,$%02X+X", "MOV A,!$%04X+X", "MOV A,!$%04X+Y", "MOV A,[$%02X]+Y", + "MOV X,$%02X", "MOV X,$%02X+Y", "MOV $%02X,$%02X", "MOV Y,$%02X+X", "INC Y", "MOV Y,A", "DBNZ Y,$%04X", "STOP" }; @@ -331,7 +346,7 @@ void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0, int S9xTraceAPU () { char buffer [200]; - + uint8 b = S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM); if (apu_trace == NULL) apu_trace = fopen ("apu_trace.log", "wb"); @@ -346,7 +361,7 @@ int S9xAPUOPrint (char *buffer, uint16 Address) uint8 *p = IAPU.RAM + Address; int mode = Modes [*p]; int bytes = ModesToBytes [mode]; - + switch (bytes) { case 1: @@ -407,8 +422,8 @@ int S9xAPUOPrint (char *buffer, uint16 Address) APUCheckCarry () ? 'C' : 'c', CPU.V_Counter, CPU.Cycles, - APU.Cycles); - + APU.Cycles >> SNES_APU_ACCURACY); + return (bytes); } @@ -478,7 +493,7 @@ void S9xPrintAPUState () printf ("left: %d, right: %d, ", ch->volume_left, ch->volume_right); - static char* envelope [] = + static char* envelope [] = { "silent", "attack", "decay", "sustain", "release", "gain", "inc_lin", "inc_bent", "dec_lin", "dec_exp" diff --git a/source/snes9x/apumem.h b/source/snes9x/apumem.h index 158fd57..df9a3f1 100644 --- a/source/snes9x/apumem.h +++ b/source/snes9x/apumem.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,162 +159,152 @@ **********************************************************************************/ + #ifndef _apumemory_h_ #define _apumemory_h_ START_EXTERN_C -extern uint8 W4; extern uint8 APUROM[64]; END_EXTERN_C +static INLINE uint8 apu_get_reg (uint8 Address) +{ + switch (Address) + { + case 0xf0: // -w TEST + return 0; + + case 0xf1: // -w CONTROL + return 0; + + case 0xf2: // rw DSPADDR + return (IAPU.RAM[Address]); + + case 0xf3: // rw DSPDATA + return (S9xGetAPUDSP()); + + case 0xf4: // r- CPUI0 + case 0xf5: // r- CPUI1 + case 0xf6: // r- CPUI2 + case 0xf7: // r- CPUI3 + #ifdef SPC700_SHUTDOWN + IAPU.WaitAddress2 = IAPU.WaitAddress1; + IAPU.WaitAddress1 = IAPU.PC; + #endif + return (IAPU.RAM[Address]); + + case 0xf8: // rw - Normal RAM + case 0xf9: // rw - Normal RAM + return (IAPU.RAM[Address]); + + case 0xfa: // -w T0TARGET + case 0xfb: // -w T1TARGET + case 0xfc: // -w T2TARGET + return 0; + + case 0xfd: // r- T0OUT + case 0xfe: // r- T1OUT + case 0xff: // r- T2OUT + #ifdef SPC700_SHUTDOWN + IAPU.WaitAddress2 = IAPU.WaitAddress1; + IAPU.WaitAddress1 = IAPU.PC; + #endif + uint8 t = IAPU.RAM[Address] & 0xF; + IAPU.RAM[Address] = 0; + return (t); + } + + return 0; +} + +static INLINE void apu_set_reg (uint8 byte, uint8 Address) +{ + switch (Address) + { + case 0xf0: // -w TEST + //printf("Write %02X to APU 0xF0!\n", byte); + return; + + case 0xf1: // -w CONTROL + S9xSetAPUControl(byte); + return; + + case 0xf2: // rw DSPADDR + IAPU.RAM[Address] = byte; + return; + + case 0xf3: // rw DSPDATA + S9xSetAPUDSP(byte); + return; + + case 0xf4: // -w CPUO0 + case 0xf5: // -w CPUO1 + case 0xf6: // -w CPUO2 + case 0xf7: // -w CPUO3 + APU.OutPorts[Address - 0xf4] = byte; + return; + + case 0xf8: // rw - Normal RAM + case 0xf9: // rw - Normal RAM + IAPU.RAM[Address] = byte; + return; + + case 0xfa: // -w T0TARGET + case 0xfb: // -w T1TARGET + case 0xfc: // -w T2TARGET + IAPU.RAM[Address] = byte; + if (byte == 0) + APU.TimerTarget[Address - 0xfa] = 0x100; + else + APU.TimerTarget[Address - 0xfa] = byte; + return; + + case 0xfd: // r- T0OUT + case 0xfe: // r- T1OUT + case 0xff: // r- T2OUT + return; + } +} + INLINE uint8 S9xAPUGetByteZ (uint8 Address) { - if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) - { - if (Address >= 0xf4 && Address <= 0xf7) - { -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress2 = IAPU.WaitAddress1; - IAPU.WaitAddress1 = IAPU.PC; -#endif - return (IAPU.RAM [Address]); - } - if (Address >= 0xfd) - { -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress2 = IAPU.WaitAddress1; - IAPU.WaitAddress1 = IAPU.PC; -#endif - uint8 t = IAPU.RAM [Address]; - IAPU.RAM [Address] = 0; - return (t); - } + if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) + return (apu_get_reg(Address)); else - if (Address == 0xf3) - return (S9xGetAPUDSP ()); - - return (IAPU.RAM [Address]); - } - else - return (IAPU.DirectPage [Address]); + return (IAPU.DirectPage[Address]); } INLINE void S9xAPUSetByteZ (uint8 byte, uint8 Address) { if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) - { - if (Address == 0xf3) - S9xSetAPUDSP (byte); - else - if (Address >= 0xf4 && Address <= 0xf7) - APU.OutPorts [Address - 0xf4] = byte; - else - if (Address == 0xf1) - S9xSetAPUControl (byte); - else - if (Address < 0xfd) - { - IAPU.RAM [Address] = byte; - if (Address >= 0xfa) - { - if (byte == 0) - APU.TimerTarget [Address - 0xfa] = 0x100; - else - APU.TimerTarget [Address - 0xfa] = byte; - } - } - } + apu_set_reg(byte, Address); else - IAPU.DirectPage [Address] = byte; + IAPU.DirectPage[Address] = byte; } INLINE uint8 S9xAPUGetByte (uint32 Address) { Address &= 0xffff; - if (Address <= 0xff && Address >= 0xf0) - { - if (Address >= 0xf4 && Address <= 0xf7) - { -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress2 = IAPU.WaitAddress1; - IAPU.WaitAddress1 = IAPU.PC; -#endif - return (IAPU.RAM [Address]); - } - else - if (Address == 0xf3) - return (S9xGetAPUDSP ()); - if (Address >= 0xfd) - { -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress2 = IAPU.WaitAddress1; - IAPU.WaitAddress1 = IAPU.PC; -#endif - uint8 t = IAPU.RAM [Address]; - IAPU.RAM [Address] = 0; - return (t); - } - return (IAPU.RAM [Address]); - } + return (apu_get_reg(Address & 0xff)); else - return (IAPU.RAM [Address]); + return (IAPU.RAM[Address]); } INLINE void S9xAPUSetByte (uint8 byte, uint32 Address) { Address &= 0xffff; - if (Address <= 0xff && Address >= 0xf0) - { - if (Address == 0xf3) - S9xSetAPUDSP (byte); + apu_set_reg(byte, Address & 0xff); else - if (Address >= 0xf4 && Address <= 0xf7) - APU.OutPorts [Address - 0xf4] = byte; - else - if (Address == 0xf1) - S9xSetAPUControl (byte); - else - if (Address < 0xfd) - { - IAPU.RAM [Address] = byte; - if (Address >= 0xfa) - { - if (byte == 0) - APU.TimerTarget [Address - 0xfa] = 0x100; - else - APU.TimerTarget [Address - 0xfa] = byte; - } - } - } - else - { -#if 0 -if (Address >= 0x2500 && Address <= 0x2504) -printf ("%06d %04x <- %02x\n", ICPU.Scanline, Address, byte); -if (Address == 0x26c6) -{ - extern FILE *apu_trace; - extern FILE *trace; - APU.Flags |= TRACE_FLAG; - CPU.Flags |= TRACE_FLAG; - if (apu_trace == NULL) - apu_trace = fopen ("aputrace.log", "wb"); - if (trace == NULL) - trace = fopen ("trace.log", "wb"); - printf ("TRACING SWITCHED ON\n"); -} -#endif if (Address < 0xffc0) - IAPU.RAM [Address] = byte; + IAPU.RAM[Address] = byte; else { - APU.ExtraRAM [Address - 0xffc0] = byte; + APU.ExtraRAM[Address - 0xffc0] = byte; if (!APU.ShowROM) - IAPU.RAM [Address] = byte; + IAPU.RAM[Address] = byte; } - } } -#endif +#endif // _apumemory_h_ diff --git a/source/snes9x/bsx.cpp b/source/snes9x/bsx.cpp index d2c00eb..ef66f3f 100644 --- a/source/snes9x/bsx.cpp +++ b/source/snes9x/bsx.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + // Anonymous wrote: // Large thanks to John Weidman for all his initial research // Thanks to Seph3 for his modem notes @@ -227,9 +246,9 @@ static int is_bsx(unsigned char *); static void BSX_Map_SNES(void) { // These maps will be partially overwritten - + int c; - + // Banks 00->3F and 80->BF for (c = 0; c < 0x400; c += 16) { @@ -237,7 +256,7 @@ static void BSX_Map_SNES(void) Map[c + 1] = Map[c + 0x801] = RAM; BlockIsRAM[c + 0] = BlockIsRAM[c + 0x800] = TRUE; BlockIsRAM[c + 1] = BlockIsRAM[c + 0x801] = TRUE; - + Map[c + 2] = Map[c + 0x802] = (uint8 *) MAP_PPU; Map[c + 3] = Map[c + 0x803] = (uint8 *) MAP_PPU; Map[c + 4] = Map[c + 0x804] = (uint8 *) MAP_CPU; @@ -250,9 +269,9 @@ static void BSX_Map_SNES(void) static void BSX_Map_LoROM(void) { // These maps will be partially overwritten - + int i, c; - + // Banks 00->3F and 80->BF for (c = 0; c < 0x400; c += 16) { @@ -263,16 +282,16 @@ static void BSX_Map_LoROM(void) BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; } } - + // Banks 40->7F and C0->FF for (c = 0; c < 0x400; c += 16) { for (i = c; i < c + 8; i++) Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize]; - + for (i = c + 8; i < c + 16; i++) Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize] - 0x8000; - + for (i = c; i < c + 16; i++) { BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; @@ -284,9 +303,9 @@ static void BSX_Map_LoROM(void) static void BSX_Map_HiROM(void) { // These maps will be partially overwritten - + int i, c; - + // Banks 00->3F and 80->BF for (c = 0; c < 0x400; c += 16) { @@ -297,7 +316,7 @@ static void BSX_Map_HiROM(void) BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; } } - + // Banks 40->7F and C0->FF for (c = 0; c < 0x400; c += 16) { @@ -313,7 +332,7 @@ static void BSX_Map_HiROM(void) static void BSX_Map_MMC(void) { int c; - + // Banks 01->0E:5000-5FFF for (c = 0x010; c < 0x0F0; c += 16) { @@ -325,7 +344,7 @@ static void BSX_Map_MMC(void) static void BSX_Map_FlashIO(void) { int c; - + if (BSX.MMC[0x0C] || BSX.MMC[0x0D]) { // Bank C0:0000, 2AAA, 5555, FF00-FF1F @@ -341,7 +360,7 @@ static void BSX_Map_FlashIO(void) static void BSX_Map_SRAM(void) { int c; - + // Banks 10->17:5000-5FFF for (c = 0x100; c < 0x180; c += 16) { @@ -354,9 +373,9 @@ static void BSX_Map_SRAM(void) static void map_psram_mirror_sub(uint32 bank) { int i, c; - + bank <<= 4; - + if (BSX.MMC[0x02]) { for (c = 0; c < 0x100; c += 16) @@ -375,10 +394,10 @@ static void map_psram_mirror_sub(uint32 bank) { for (i = c; i < c + 8; i++) Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; - + for (i = c + 8; i < c + 16; i++) Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE] - 0x8000; - + for (i = c; i < c + 16; i++) { BlockIsRAM[i + bank] = TRUE; @@ -391,7 +410,7 @@ static void map_psram_mirror_sub(uint32 bank) static void BSX_Map_PSRAM(void) { int c; - + // Banks 70->77:0000-FFFF // FIXME: could be toggled by $03 for (c = 0; c < 0x80; c++) @@ -400,7 +419,7 @@ static void BSX_Map_PSRAM(void) BlockIsRAM[c + 0x700] = TRUE; BlockIsROM[c + 0x700] = FALSE; } - + // Banks 20->3F:6000-7FFF mirrors 70->77:6000-7FFF for (c = 0x200; c < 0x400; c += 16) { @@ -411,15 +430,15 @@ static void BSX_Map_PSRAM(void) BlockIsROM[c + 6] = FALSE; BlockIsROM[c + 7] = FALSE; } - + if (!BSX.MMC[0x05]) // Banks 40->4F:0000-FFFF mirrors 70->77:0000-7FFF map_psram_mirror_sub(0x40); - + if (!BSX.MMC[0x06]) // Banks 50->5F:0000-FFFF mirrors 70->77:0000-7FFF map_psram_mirror_sub(0x50); - + // FIXME if (!BSX.MMC[0x03]) // Banks 60->6F:0000-FFFF mirrors 70->77:0000-7FFF (?) @@ -429,7 +448,7 @@ static void BSX_Map_PSRAM(void) static void BSX_Map_BIOS(void) { int i,c; - + // Banks 00->1F:8000-FFFF if (BSX.MMC[0x07]) { @@ -443,7 +462,7 @@ static void BSX_Map_BIOS(void) } } } - + // Banks 80->9F:8000-FFFF if (BSX.MMC[0x08]) { @@ -462,7 +481,7 @@ static void BSX_Map_BIOS(void) static void BSX_Map_RAM(void) { int c; - + // Banks 7E->7F for (c = 0; c < 16; c++) { @@ -478,9 +497,9 @@ static void BSX_Map_RAM(void) static void BSX_Map_Dirty(void) { // for the quick bank change - + int i, c; - + // Banks 00->1F and 80->9F:8000-FFFF if (BSX.MMC[0x02]) { @@ -515,21 +534,21 @@ static void BSX_Map(void) for (int i = 0; i < 32; i++) printf("BS: MMC %02X: %d\n", i, BSX.MMC[i]); #endif - + memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC)); - + // Do a quick bank change if (BSX.dirty2 && !BSX.dirty) { BSX_Map_Dirty(); BSX_Map_BIOS(); - + BSX.dirty2 = FALSE; - - Memory.WriteProtectROM(); + + Memory.map_WriteProtectROM(); return; } - + if (BSX.MMC[0x01]) { MapROM = PSRAM; @@ -540,27 +559,27 @@ static void BSX_Map(void) MapROM = FlashROM; FlashSize = FLASH_SIZE; } - + BSX_Map_SNES(); - + if (BSX.MMC[0x02]) BSX_Map_HiROM(); else BSX_Map_LoROM(); - + BSX_Map_PSRAM(); BSX_Map_SRAM(); BSX_Map_RAM(); - + BSX_Map_BIOS(); BSX_Map_FlashIO(); BSX_Map_MMC(); - + // Monitor new register changes BSX.dirty = FALSE; BSX.dirty2 = FALSE; - - Memory.WriteProtectROM(); + + Memory.map_WriteProtectROM(); } static uint8 BSX_Get_Bypass_FlashIO(uint16 offset) @@ -594,17 +613,17 @@ uint8 S9xGetBSX(uint32 address) uint8 bank = (address >> 16) & 0xFF; uint16 offset = address & 0xFFFF; uint8 t = 0; - + // MMC if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) return BSX.MMC[bank]; - + // Flash IO if (bank == 0xC0) { // default: read-through mode t = BSX_Get_Bypass_FlashIO(offset); - + // note: may be more registers, purposes unknown switch (offset) { @@ -612,12 +631,12 @@ uint8 S9xGetBSX(uint32 address) if (BSX.flash_enable) t = 0x80; // status register? break; - + case 0x5555: if (BSX.flash_enable) t = 0x80; // ??? break; - + case 0xFF00: case 0xFF02: case 0xFF04: @@ -634,7 +653,7 @@ uint8 S9xGetBSX(uint32 address) break; } } - + return t; } @@ -642,7 +661,7 @@ void S9xSetBSX(uint8 byte, uint32 address) { uint8 bank = (address >> 16) & 0xFF; uint16 offset = address & 0xFFFF; - + // MMC if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) { @@ -665,7 +684,7 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX.dirty = TRUE; } break; - + case 0x07: case 0x08: if (BSX.MMC[bank] != byte) @@ -674,7 +693,7 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX.dirty2 = TRUE; } break; - + case 0x0E: BSX.MMC[bank] = byte; if (byte && (BSX.dirty || BSX.dirty2)) @@ -682,13 +701,13 @@ void S9xSetBSX(uint8 byte, uint32 address) break; } } - + // Flash IO if (bank == 0xC0) { BSX.old_write = BSX.new_write; BSX.new_write = address; - + // ???: double writes to the desired address will bypass // flash registers if (BSX.old_write == BSX.new_write && BSX.write_enable) @@ -696,7 +715,7 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX_Set_Bypass_FlashIO(offset, byte); return; } - + // flash command handling // note: incomplete switch (offset) @@ -711,16 +730,16 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX.read_enable = TRUE; } break; - + case 0x2AAA: BSX.flash_command <<= 8; BSX.flash_command |= byte; break; - + case 0x5555: BSX.flash_command <<= 8; BSX.flash_command |= byte; - + switch (BSX.flash_command & 0xFFFFFF) { case 0xAA55F0: @@ -729,7 +748,7 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX.write_enable = FALSE; BSX.read_enable = FALSE; break; - + case 0xAA55A0: // enable writing to flash BSX.old_write = 0; @@ -738,20 +757,20 @@ void S9xSetBSX(uint8 byte, uint32 address) BSX.write_enable = TRUE; BSX_Map(); break; - + case 0xAA5570: // turn on write-protection BSX.write_enable = FALSE; BSX_Map(); break; - + case 0xAA5580: case 0xAA5510: // ??? break; - + } - + break; } } @@ -760,7 +779,7 @@ void S9xSetBSX(uint8 byte, uint32 address) uint8 S9xGetBSXPPU(uint16 address) { uint8 t = 0; - + if (address >= 0x2188 && address <= 0x219F) { // known read registers @@ -770,44 +789,44 @@ uint8 S9xGetBSXPPU(uint16 address) case 0x2188: t = BSX.PPU[0x2188]; break; - + // Test register high? (r/w) case 0x2189: t = BSX.PPU[0x2189]; break; - + case 0x218A: t = BSX.PPU[0x218A]; break; - + case 0x218C: t = BSX.PPU[0x218C]; break; - + // Transmission number low? (r/w) case 0x218E: t = BSX.PPU[0x218E]; break; - + // Transmission number high? (r/w) case 0x218F: t = BSX.PPU[0x218F]; break; - + // Status register? (r) case 0x2190: t = BSX.PPU[0x2190]; break; - + // Data register? (r/w) case 0x2192: t = BSX.PPU[0x2192]; - + // test t = BSX.test2192[BSX.out_index++]; if (BSX.out_index == 32) BSX.out_index = 0; - + BSX_RTC.ticks++; if (BSX_RTC.ticks >= 1000) { @@ -826,45 +845,45 @@ uint8 S9xGetBSXPPU(uint16 address) } if (BSX_RTC.hours >= 24) BSX_RTC.hours = 0; - + BSX.test2192[10] = BSX_RTC.seconds; BSX.test2192[11] = BSX_RTC.minutes; BSX.test2192[12] = BSX_RTC.hours; - + break; - + // Transmission status? (r/w) case 0x2193: // Data ready when bits 2/3 clear? t = BSX.PPU[0x2193] & ~0x0C; break; - + // Reset? (r/w) case 0x2194: t = BSX.PPU[0x2194]; break; - + // Unknown (r) case 0x2196: t = BSX.PPU[0x2196]; break; - + // Unknown (r/w) case 0x2197: t = BSX.PPU[0x2197]; break; - + // Modem protocol? (r/w) case 0x2199: t = BSX.PPU[0x2199]; break; - + default: t = OpenBus; break; } } - + return t; } @@ -879,68 +898,68 @@ void S9xSetBSXPPU(uint8 byte, uint16 address) case 0x2188: BSX.PPU[0x2188] = byte; break; - + // Test register high? (r/w) case 0x2189: BSX.PPU[0x2189] = byte; break; - + case 0x218A: BSX.PPU[0x218A] = byte; break; - + case 0x218B: BSX.PPU[0x218B] = byte; break; - + case 0x218C: BSX.PPU[0x218C] = byte; break; - + // Transmission number low? (r/w) case 0x218E: BSX.PPU[0x218E] = byte; break; - + // Transmission number high? (r/w) case 0x218F: BSX.PPU[0x218F] = byte; - + // ? BSX.PPU[0x218E] >>= 1; BSX.PPU[0x218E] = BSX.PPU[0x218F] - BSX.PPU[0x218E]; BSX.PPU[0x218F] >>= 1; - + BSX.PPU[0x2190] = 0x80; // ? break; - + // Strobe assert? (w) case 0x2191: BSX.PPU[0x2191] = byte; BSX.out_index = 0; break; - + // Data register? (r/w) case 0x2192: BSX.PPU[0x2192] = 0x01; // ? BSX.PPU[0x2190] = 0x80; // ? break; - + // Transmission status? (r/w) case 0x2193: BSX.PPU[0x2193] = byte; break; - + // Reset? (r/w) case 0x2194: BSX.PPU[0x2194] = byte; break; - + // Unknown (r/w) case 0x2197: BSX.PPU[0x2197] = byte; break; - + // Modem protocol? (r/w) case 0x2199: // Lots of modem strings written here when @@ -951,27 +970,34 @@ void S9xSetBSXPPU(uint8 byte, uint16 address) } } -uint8 * S9xGetPasePointerBSX(uint32 address) +uint8 * S9xGetBasePointerBSX(uint32 address) { return MapROM; } static bool8 BSX_LoadBIOS(void) { -#ifndef NGC FILE *fp; - char path[_MAX_PATH + 1]; + char path[_MAX_PATH + 1], name[_MAX_PATH + 1]; bool8 r = FALSE; - + strcpy(path, S9xGetDirectory(BIOS_DIR)); strcat(path, SLASH_STR); - strcat(path, "BS-X.bios"); - - fp = fopen(path, "rb"); + strcpy(name, path); + strcat(name, "BS-X.bin"); + + fp = fopen(name, "rb"); + if (!fp) + { + strcpy(name, path); + strcat(name, "BS-X.bios"); + fp = fopen(name, "rb"); + } + if (fp) { size_t size; - + size = fread((void *) BIOSROM, 1, BIOS_SIZE, fp); fclose(fp); if (size == BIOS_SIZE) @@ -984,65 +1010,61 @@ static bool8 BSX_LoadBIOS(void) else printf("BS: BIOS not found!\n"); #endif - + return r; -#else - return false; -#endif - } void S9xInitBSX(void) { Settings.BS = FALSE; - - if (!memcmp(&ROM[0x7FC0], "Satellaview BS-X ", 21)) + + if (!memcmp(&Memory.ROM[0x7FC0], "Satellaview BS-X ", 21)) { // BS-X itself - + Settings.BS = TRUE; Settings.BSXItself = TRUE; - + Memory.LoROM = TRUE; Memory.HiROM = FALSE; - - memmove(BIOSROM, ROM, BIOS_SIZE); - + + memmove(BIOSROM, Memory.ROM, BIOS_SIZE); + FlashMode = FALSE; FlashSize = FLASH_SIZE; - + BSX.bootup = TRUE; } else { Settings.BSXItself = FALSE; - + int r1, r2; - - r1 = (is_bsx(ROM + 0x7FC0) == 1); - r2 = (is_bsx(ROM + 0xFFC0) == 1); + + r1 = (is_bsx(Memory.ROM + 0x7FC0) == 1); + r2 = (is_bsx(Memory.ROM + 0xFFC0) == 1); Settings.BS = (r1 | r2) ? TRUE : FALSE; - + if (Settings.BS) { // BS games - + Memory.LoROM = r1 ? TRUE : FALSE; Memory.HiROM = r2 ? TRUE : FALSE; - - uint8 *header = r1 ? ROM + 0x7FC0 : ROM + 0xFFC0; - + + uint8 *header = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0; + FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE; FlashSize = (header[0x19] & 0x20) ? PSRAM_SIZE : FLASH_SIZE; - + #ifdef BSX_DEBUG for (int i = 0; i <= 0x1F; i++) printf("BS: ROM Header %02X: %02X\n", i, header[i]); printf("BS: FlashMode: %d, FlashSize: %x\n", FlashMode, FlashSize); #endif - + BSX.bootup = Settings.BSXBootup; - + if (!BSX_LoadBIOS()) { BSX.bootup = FALSE; @@ -1050,18 +1072,18 @@ void S9xInitBSX(void) } } } - + if (Settings.BS) { MapROM = NULL; - FlashROM = ROM; - + FlashROM = Memory.ROM; + time_t t; struct tm *tmr; - + time(&t); tmr = localtime(&t); - + BSX_RTC.ticks = 0; memcpy(BSX.test2192, init2192, sizeof(init2192)); BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec; @@ -1077,12 +1099,12 @@ void S9xInitBSX(void) void S9xResetBSX(void) { if (Settings.BSXItself) - memset(ROM, 0, FLASH_SIZE); - + memset(Memory.ROM, 0, FLASH_SIZE); + memset(BSX.PPU, 0, sizeof(BSX.PPU)); memset(BSX.MMC, 0, sizeof(BSX.MMC)); memset(BSX.prevMMC, 0, sizeof(BSX.prevMMC)); - + BSX.dirty = FALSE; BSX.dirty2 = FALSE; BSX.flash_enable = FALSE; @@ -1091,22 +1113,22 @@ void S9xResetBSX(void) BSX.flash_command = 0; BSX.old_write = 0; BSX.new_write = 0; - + BSX.out_index = 0; memset(BSX.output, 0, sizeof(BSX.output)); - + // starting from the bios if (BSX.bootup) BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; else { BSX.MMC[0x02] = FlashMode ? 0x80: 0; - + // per bios: run from psram or flash card if (FlashSize == PSRAM_SIZE) { memcpy(PSRAM, FlashROM, PSRAM_SIZE); - + BSX.MMC[0x01] = 0x80; BSX.MMC[0x03] = 0x80; BSX.MMC[0x04] = 0x80; @@ -1119,10 +1141,10 @@ void S9xResetBSX(void) BSX.MMC[0x05] = 0x80; BSX.MMC[0x06] = 0x80; } - + BSX.MMC[0x0E] = 0x80; } - + BSX_Map(); } @@ -1130,17 +1152,17 @@ void S9xFixBSXAfterSnapshotLoad(void) { uint8 temp[16]; bool8 pd1, pd2; - + pd1 = BSX.dirty; pd2 = BSX.dirty2; memcpy(temp, BSX.MMC, sizeof(BSX.MMC)); - + memcpy(BSX.MMC, BSX.prevMMC, sizeof(BSX.MMC)); BSX_Map(); - + memcpy(BSX.MMC, temp, sizeof(BSX.MMC)); BSX.dirty = pd1; - BSX.dirty2 = pd2; + BSX.dirty2 = pd2; } static bool valid_normal_bank(unsigned char bankbyte) diff --git a/source/snes9x/bsx.h b/source/snes9x/bsx.h index 34ad708..abf74ab 100644 --- a/source/snes9x/bsx.h +++ b/source/snes9x/bsx.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _BSX_H_ #define _BSX_H_ @@ -164,15 +183,17 @@ struct SBSX uint8 test2192[32]; }; +START_EXTERN_C extern struct SBSX BSX; uint8 S9xGetBSX(uint32); void S9xSetBSX(uint8, uint32); uint8 S9xGetBSXPPU(uint16); void S9xSetBSXPPU(uint8, uint16); -uint8 * S9xGetPasePointerBSX(uint32); +uint8 * S9xGetBasePointerBSX(uint32); void S9xInitBSX(void); void S9xResetBSX(void); void S9xFixBSXAfterSnapshotLoad(void); +END_EXTERN_C #endif diff --git a/source/snes9x/c4.cpp b/source/snes9x/c4.cpp index 312f94c..6c82d26 100644 --- a/source/snes9x/c4.cpp +++ b/source/snes9x/c4.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include #include "c4.h" @@ -164,22 +183,22 @@ void C4TransfWireFrame () c4x = (double) C4WFXVal; c4y = (double) C4WFYVal; c4z = (double) C4WFZVal - 0x95; - + // Rotate X tanval = -(double) C4WFX2Val * 3.14159265 * 2 / 128; c4y2 = c4y * cos (tanval) - c4z * sin (tanval); c4z2 = c4y * sin (tanval) + c4z * cos (tanval); - + // Rotate Y tanval = -(double)C4WFY2Val*3.14159265*2/128; c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); c4z = c4x * - sin (tanval) + c4z2 * cos (tanval); - + // Rotate Z tanval = -(double) C4WFDist * 3.14159265*2 / 128; c4x = c4x2 * cos (tanval) - c4y2 * sin (tanval); c4y = c4x2 * sin (tanval) + c4y2 * cos (tanval); - + // Scale C4WFXVal = (short) (c4x*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); C4WFYVal = (short) (c4y*(double)C4WFScale/(0x90*(c4z+0x95))*0x95); @@ -190,22 +209,22 @@ void C4TransfWireFrame2 () c4x = (double)C4WFXVal; c4y = (double)C4WFYVal; c4z = (double)C4WFZVal; - + // Rotate X tanval = -(double) C4WFX2Val * 3.14159265 * 2 / 128; c4y2 = c4y * cos (tanval) - c4z * sin (tanval); c4z2 = c4y * sin (tanval) + c4z * cos (tanval); - + // Rotate Y tanval = -(double) C4WFY2Val * 3.14159265 * 2 / 128; c4x2 = c4x * cos (tanval) + c4z2 * sin (tanval); c4z = c4x * -sin (tanval) + c4z2 * cos (tanval); - + // Rotate Z tanval = -(double)C4WFDist * 3.14159265 * 2 / 128; c4x = c4x2 * cos (tanval) - c4y2 * sin (tanval); c4y = c4x2 * sin (tanval) + c4y2 * cos (tanval); - + // Scale C4WFXVal =(short)(c4x * (double)C4WFScale / 0x100); C4WFYVal =(short)(c4y * (double)C4WFScale / 0x100); @@ -221,21 +240,21 @@ void C4CalcWireFrame () C4WFYVal = (short) (256 * (double) C4WFYVal / abs (C4WFXVal)); if (C4WFXVal < 0) C4WFXVal = -256; - else + else C4WFXVal = 256; } else { - if (C4WFYVal != 0) + if (C4WFYVal != 0) { C4WFDist = abs(C4WFYVal)+1; C4WFXVal = (short) (256 * (double)C4WFXVal / abs (C4WFYVal)); if (C4WFYVal < 0) C4WFYVal = -256; - else + else C4WFYVal = 256; } - else + else C4WFDist = 0; } } @@ -248,19 +267,19 @@ short C41FDistVal; void C4Op1F () { - if (C41FXVal == 0) + if (C41FXVal == 0) { - if (C41FYVal > 0) + if (C41FYVal > 0) C41FAngleRes = 0x80; - else + else C41FAngleRes = 0x180; } - else + else { tanval = (double) C41FYVal / C41FXVal; C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); C41FAngleRes = C41FAngleRes; - if (C41FXVal< 0) + if (C41FXVal< 0) C41FAngleRes += 0x100; C41FAngleRes &= 0x1FF; } @@ -283,7 +302,7 @@ void C4Op0D() #ifdef ZSNES_C4 EXTERN_C void C4LoaDMem(char *C4RAM) { - memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), + memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), C4GetMemPointer(READ_3WORD(C4RAM+0x1f40)), READ_WORD(C4RAM+0x1f43)); } diff --git a/source/snes9x/c4.h b/source/snes9x/c4.h index f8349e1..9bc9d83 100644 --- a/source/snes9x/c4.h +++ b/source/snes9x/c4.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _C4_H_ #define _C4_H_ diff --git a/source/snes9x/c4emu.cpp b/source/snes9x/c4emu.cpp index 8af64ae..ea80989 100644 --- a/source/snes9x/c4emu.cpp +++ b/source/snes9x/c4emu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,9 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + +#ifndef ZSNES_C4 #ifdef HAVE_CONFIG_H #include #endif @@ -194,7 +214,7 @@ static void C4ConvOAM(void){ int16 SprX, SprY; uint8 SprName, SprAttr; uint8 SprCount; - + globalX=READ_WORD(Memory.C4RAM+0x0621); globalY=READ_WORD(Memory.C4RAM+0x0623); OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); @@ -208,62 +228,59 @@ static void C4ConvOAM(void){ if(Memory.C4RAM[0x0620]!=0){ SprCount=128-Memory.C4RAM[0x626]; uint8 offset=(Memory.C4RAM[0x626]&3)*2; - for(int prio=0x30; prio>=0; prio-=0x10){ - uint8 *srcptr=Memory.C4RAM+0x220; - for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ - if((srcptr[4]&0x30)!=prio) continue; - SprX=READ_WORD(srcptr)-globalX; - SprY=READ_WORD(srcptr+2)-globalY; - SprName=srcptr[5]; - SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? + uint8 *srcptr=Memory.C4RAM+0x220; + for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ + SprX=READ_WORD(srcptr)-globalX; + SprY=READ_WORD(srcptr+2)-globalY; + SprName=srcptr[5]; + SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? - uint8 *sprptr=C4GetMemPointer(READ_3WORD(srcptr+7)); - if(*sprptr!=0){ - int16 X, Y; - for(int SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){ - X=(int8)sprptr[1]; - if(SprAttr&0x40){ // flip X - X=-X-((sprptr[0]&0x20)?16:8); + uint8 *sprptr=C4GetMemPointer(READ_3WORD(srcptr+7)); + if(*sprptr!=0){ + int16 X, Y; + for(int SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){ + X=(int8)sprptr[1]; + if(SprAttr&0x40){ // flip X + X=-X-((sprptr[0]&0x20)?16:8); + } + X+=SprX; + if(X>=-16 && X<=272){ + Y=(int8)sprptr[2]; + if(SprAttr&0x80){ + Y=-Y-((sprptr[0]&0x20)?16:8); } - X+=SprX; - if(X>=-16 && X<=272){ - Y=(int8)sprptr[2]; - if(SprAttr&0x80){ - Y=-Y-((sprptr[0]&0x20)?16:8); - } - Y+=SprY; - if(Y>=-16 && Y<=224){ - OAMptr[0]=X&0xff; - OAMptr[1]=(uint8)Y; - OAMptr[2]=SprName+sprptr[3]; - OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition? - *OAMptr2 &= ~(3<=-16 && Y<=224){ + OAMptr[0]=X&0xff; + OAMptr[1]=(uint8)Y; + OAMptr[2]=SprName+sprptr[3]; + OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition? + *OAMptr2 &= ~(3<0){ - OAMptr[0]=(uint8)SprX; - OAMptr[1]=(uint8)SprY; - OAMptr[2]=SprName; - OAMptr[3]=SprAttr; - *OAMptr2 &= ~(3<0){ + // XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224? + OAMptr[0]=(uint8)SprX; + OAMptr[1]=(uint8)SprY; + OAMptr[2]=SprName; + OAMptr[3]=SprAttr; + *OAMptr2 &= ~(3< add an A and a C Y+=C; } @@ -516,7 +533,7 @@ static void C4BitPlaneWave(){ 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E }; - + uint8 *dst=Memory.C4RAM; uint32 waveptr=Memory.C4RAM[0x1f83]; uint16 mask1=0xc0c0; @@ -585,7 +602,7 @@ static void C4SprDisintegrate() #ifdef DEBUGGER if((Cx&~1)!=width/2 || (Cy&~1)!=height/2) printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width/2, height/2); #endif - + scaleX=(int16)READ_WORD(Memory.C4RAM+0x1f86); scaleY=(int16)READ_WORD(Memory.C4RAM+0x1f8f); StartX=-Cx*scaleX+(Cx<<8); @@ -593,7 +610,7 @@ static void C4SprDisintegrate() src=Memory.C4RAM+0x600; memset(Memory.C4RAM, 0, width*height/2); - + for(uint32 y=StartY, i=0; i=0) { left = SAR((int32)tan1*y, 16) - - READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f80) + READ_WORD(Memory.C4RAM+0x1f86); right = SAR((int32)tan2*y, 16) - - READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f80) + READ_WORD(Memory.C4RAM+0x1f86) + READ_WORD(Memory.C4RAM+0x1f93); @@ -842,7 +860,7 @@ void S9xSetC4 (uint8 byte, uint16 Address) printf("25 Multiply!\n"); if(Memory.C4RAM[0x1f4d]!=2) printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); #endif - { + { int32 foo=READ_3WORD(Memory.C4RAM+0x1f80); int32 bar=READ_3WORD(Memory.C4RAM+0x1f83); foo*=bar; @@ -928,7 +946,7 @@ void S9xSetC4 (uint8 byte, uint16 Address) if(byte != 0) printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); if(READ_WORD(Memory.C4RAM+0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM+0x1f45) + READ_WORD(Memory.C4RAM+0x1f43)) > 0x6c00) printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM+0x1f45)); #endif - memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), + memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)), READ_WORD(Memory.C4RAM+0x1f43)); } @@ -1067,4 +1085,4 @@ int16 C4CosTable[512] = { 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 }; - +#endif diff --git a/source/snes9x/cheats.cpp b/source/snes9x/cheats.cpp index 50907f3..0a94e39 100644 --- a/source/snes9x/cheats.cpp +++ b/source/snes9x/cheats.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include #include @@ -201,7 +220,7 @@ const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) { char new_code [12]; - + if (strlen (code) != 9 || *(code + 4) != '-' || !S9xAllHex (code, 4) || !S9xAllHex (code + 5, 4)) return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); @@ -212,7 +231,7 @@ const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) static char *real_hex = "0123456789ABCDEF"; static char *genie_hex = "DF4709156BC8A23E"; - + for (int i = 2; i < 10; i++) { if (islower (new_code [i])) @@ -249,9 +268,7 @@ void S9xStartCheatSearch (SCheatData *d) memmove (d->CWRAM, d->RAM, 0x20000); memmove (d->CSRAM, d->SRAM, 0x10000); memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); - memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); - memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); - memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 3); + memset ((char *) d->ALL_BITS, 0xff, 0x32000 >> 3); } #define BIT_CLEAR(a,v) \ @@ -287,7 +304,7 @@ void S9xStartCheatSearch (SCheatData *d) (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) -void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) { int l; @@ -315,7 +332,7 @@ void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->WRAM_BITS, i); } - + for (i = 0; i < 0x10000 - l; i++) { if (TEST_BIT (d->SRAM_BITS, i) && @@ -327,7 +344,7 @@ void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->SRAM_BITS, i); } - + for (i = 0; i < 0x2000 - l; i++) { if (TEST_BIT (d->IRAM_BITS, i) && @@ -353,7 +370,7 @@ void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->WRAM_BITS, i); } - + for (i = 0; i < 0x10000 - l; i++) { if (TEST_BIT (d->SRAM_BITS, i) && @@ -365,7 +382,7 @@ void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->SRAM_BITS, i); } - + for (i = 0; i < 0x2000 - l; i++) { if (TEST_BIT (d->IRAM_BITS, i) && @@ -378,10 +395,14 @@ void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, BIT_CLEAR (d->IRAM_BITS, i); } } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); } -void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, uint32 value, +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update) { int l; @@ -410,7 +431,7 @@ void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->WRAM_BITS, i); } - + for (i = 0; i < 0x10000 - l; i++) { if (TEST_BIT (d->SRAM_BITS, i) && @@ -422,7 +443,7 @@ void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->SRAM_BITS, i); } - + for (i = 0; i < 0x2000 - l; i++) { if (TEST_BIT (d->IRAM_BITS, i) && @@ -448,7 +469,7 @@ void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->WRAM_BITS, i); } - + for (i = 0; i < 0x10000 - l; i++) { if (TEST_BIT (d->SRAM_BITS, i) && @@ -460,7 +481,7 @@ void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, else BIT_CLEAR (d->SRAM_BITS, i); } - + for (i = 0; i < 0x2000 - l; i++) { if (TEST_BIT (d->IRAM_BITS, i) && @@ -473,6 +494,70 @@ void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, BIT_CLEAR (d->IRAM_BITS, i); } } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); +} + +void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, bool8 update) +{ + int l; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + int i; + + { + + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, i, (int)value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, i+0x20000, (int)value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, i+0x30000, (int)value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR (d->WRAM_BITS, i); + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR (d->SRAM_BITS, i); } void S9xOutputCheatSearchResults (SCheatData *d) diff --git a/source/snes9x/cheats.h b/source/snes9x/cheats.h index 3786602..199189f 100644 --- a/source/snes9x/cheats.h +++ b/source/snes9x/cheats.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _CHEATS_H_ #define _CHEATS_H_ @@ -154,7 +173,7 @@ struct SCheat char name [22]; }; -#define MAX_CHEATS 75 +#define MAX_CHEATS 150 struct SCheatData { @@ -166,11 +185,24 @@ struct SCheatData uint8 *RAM; uint8 *FillRAM; uint8 *SRAM; - uint32 WRAM_BITS [0x20000 >> 3]; - uint32 SRAM_BITS [0x10000 >> 3]; - uint32 IRAM_BITS [0x2000 >> 3]; + uint32 ALL_BITS [(0x32000 >> 5)]; +#define WRAM_BITS ALL_BITS +#define SRAM_BITS ALL_BITS + (0x20000 >> 5) +#define IRAM_BITS ALL_BITS + (0x30000 >> 5) + uint8 CWatchRAM [0x32000]; }; + +struct Watch { + bool on; + int size; + int format; + uint32 address; + char buf[12]; + char desc[32]; +}; +extern Watch watches [16]; + typedef enum { S9X_LESS_THAN, S9X_GREATER_THAN, S9X_LESS_THAN_OR_EQUAL, @@ -207,6 +239,8 @@ void S9xSearchForChange (SCheatData *, S9xCheatComparisonType cmp, void S9xSearchForValue (SCheatData *, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update); +void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 address, bool8 update); void S9xOutputCheatSearchResults (SCheatData *); #endif diff --git a/source/snes9x/cheats2.cpp b/source/snes9x/cheats2.cpp index c2da72e..55fb2dd 100644 --- a/source/snes9x/cheats2.cpp +++ b/source/snes9x/cheats2.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include #include @@ -148,16 +167,40 @@ #include "cheats.h" #include "memmap.h" +#ifndef INLINE +#define INLINE inline +#endif + extern SCheatData Cheat; +Watch watches [16]; + +// read a byte without altering CPU +INLINE uint8 S9xGetByteFree (uint32 Address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + uint8 rv = S9xGetByte (Address); + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; + return rv; +} +INLINE void S9xSetByteFree (uint8 Byte, uint32 Address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + S9xSetByte (Byte, Address); + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; +} void S9xInitCheatData () { Cheat.RAM = Memory.RAM; - Cheat.SRAM = ::SRAM; + Cheat.SRAM = Memory.SRAM; Cheat.FillRAM = Memory.FillRAM; } -void S9xAddCheat (bool8 enable, bool8 save_current_value, +void S9xAddCheat (bool8 enable, bool8 save_current_value, uint32 address, uint8 byte) { if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) @@ -171,7 +214,7 @@ void S9xAddCheat (bool8 enable, bool8 save_current_value, #endif if (save_current_value) { - Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address); + Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByteFree (address); Cheat.c [Cheat.num_cheats].saved = TRUE; } Cheat.num_cheats++; @@ -223,7 +266,7 @@ void S9xRemoveCheat (uint32 which1) int block = ((address&0xffffff) >> MEMMAP_SHIFT); uint8 *ptr = Memory.Map [block]; - + if (ptr >= (uint8 *) CMemory::MAP_LAST) *(ptr + (address & 0xffff)) = Cheat.c [which1].saved_byte; else @@ -236,11 +279,11 @@ void S9xApplyCheat (uint32 which1) uint32 address = Cheat.c [which1].address; if (!Cheat.c [which1].saved) - Cheat.c [which1].saved_byte = S9xGetByte (address); + Cheat.c [which1].saved_byte = S9xGetByteFree (address); int block = ((address&0xffffff) >> MEMMAP_SHIFT); uint8 *ptr = Memory.Map [block]; - + if (ptr >= (uint8 *) CMemory::MAP_LAST) *(ptr + (address & 0xffff)) = Cheat.c [which1].byte; else @@ -273,7 +316,7 @@ bool8 S9xLoadCheatFile (const char *filename) uint8 data [28]; if (!fs) - return (FALSE); + return (FALSE); while (fread ((void *) data, 1, 28, fs) == 28) { diff --git a/source/snes9x/clip.cpp b/source/snes9x/clip.cpp index 0196da4..13947d3 100644 --- a/source/snes9x/clip.cpp +++ b/source/snes9x/clip.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "ppu.h" diff --git a/source/snes9x/controls.cpp b/source/snes9x/controls.cpp index adcf489..bf99517 100644 --- a/source/snes9x/controls.cpp +++ b/source/snes9x/controls.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include #include @@ -162,7 +181,14 @@ #include "cpuexec.h" #include "snapshot.h" #include "spc7110.h" -#include "movie.h" +//#include "movie.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#ifdef __WIN32__ +#define snprintf _snprintf // needs ANSI compliant name +#endif using namespace std; @@ -190,16 +216,16 @@ static set pollmap[NUMCTLS+1]; static vector multis; struct exemulti { int32 pos; - bool data1; + bool8 data1; s9xcommand_t *script; }; static set exemultis; static struct { int16 x, y; - int V_adj; bool V_var; - int H_adj; bool H_var; - bool mapped; + int16 V_adj; bool8 V_var; + int16 H_adj; bool8 H_var; + bool8 mapped; } pseudopointer[8]; static uint8 pseudobuttons[256]; @@ -247,7 +273,7 @@ static struct { static struct { int16 x[2], y[2]; uint8 buttons; - bool offscreen[2]; + bool8 offscreen[2]; uint32 ID[2]; struct crosshair crosshair[2]; } justifier; @@ -257,100 +283,77 @@ static struct { uint8 read_idx[2 /* ports */][2 /* per port */]; +bool8 pad_read = 0, pad_read_last = 0; + #define FLAG_IOBIT0 (Memory.FillRAM[0x4213]&0x40) #define FLAG_IOBIT1 (Memory.FillRAM[0x4213]&0x80) #define FLAG_IOBIT(n) ((n)?(FLAG_IOBIT1):(FLAG_IOBIT0)) -static bool FLAG_LATCH=false; -static int curcontrollers[2]={ NONE, NONE }; -static int newcontrollers[2]={ JOYPAD0, NONE }; +static bool8 FLAG_LATCH=false; +static int32 curcontrollers[2]={ NONE, NONE }; +static int32 newcontrollers[2]={ JOYPAD0, NONE }; /*******************/ // Note: these should be in asciibetical order! -static const char *command_names[]={ - "BGLayeringHack", - "BeginRecordingMovie", - "ClipWindows", - "Debugger", - "DecEmuTurbo", - "DecFrameRate", - "DecFrameTime", - "DecTurboSpeed", - "DumpSPC7110Log", - "EmuTurbo", - "EndRecordingMovie", - "ExitEmu", - "IncEmuTurbo", - "IncFrameRate", - "IncFrameTime", - "IncTurboSpeed", - "InterpolateSound", - "LoadFreezeFile", - "LoadMovie", - "LoadOopsFile", - "Mode7Interpolate", - "Pause", - "QuickLoad000", "QuickLoad001", "QuickLoad002", "QuickLoad003", "QuickLoad004", "QuickLoad005", "QuickLoad006", "QuickLoad007", "QuickLoad008", "QuickLoad009", "QuickLoad010", - "QuickSave000", "QuickSave001", "QuickSave002", "QuickSave003", "QuickSave004", "QuickSave005", "QuickSave006", "QuickSave007", "QuickSave008", "QuickSave009", "QuickSave010", - "Reset", - "SaveFreezeFile", - "SaveSPC", - "Screenshot", - "SoftReset", - "SoundChannel0", "SoundChannel1", "SoundChannel2", "SoundChannel3", "SoundChannel4", "SoundChannel5", "SoundChannel6", "SoundChannel7", - "SoundChannelsOn", - "SwapJoypads", - "SynchronizeSound", - "ToggleBG0", "ToggleBG1", "ToggleBG2", "ToggleBG3", - "ToggleEmuTurbo", - "ToggleHDMA", - "ToggleSprites", - "ToggleTransparency", +#define THE_COMMANDS \ + S(BGLayeringHack), \ + S(BeginRecordingMovie), \ + S(ClipWindows), \ + S(Debugger), \ + S(DecEmuTurbo), \ + S(DecFrameRate), \ + S(DecFrameTime), \ + S(DecTurboSpeed), \ + S(DumpSPC7110Log), \ + S(EmuTurbo), \ + S(EndRecordingMovie), \ + S(ExitEmu), \ + S(IncEmuTurbo), \ + S(IncFrameRate), \ + S(IncFrameTime), \ + S(IncTurboSpeed), \ + S(InterpolateSound), \ + S(LoadFreezeFile), \ + S(LoadMovie), \ + S(LoadOopsFile), \ +/* S(Mode7Interpolate),*/ \ + S(Pause), \ + S(QuickLoad000), S(QuickLoad001), S(QuickLoad002), S(QuickLoad003), S(QuickLoad004), S(QuickLoad005), S(QuickLoad006), S(QuickLoad007), S(QuickLoad008), S(QuickLoad009), S(QuickLoad010), \ + S(QuickSave000), S(QuickSave001), S(QuickSave002), S(QuickSave003), S(QuickSave004), S(QuickSave005), S(QuickSave006), S(QuickSave007), S(QuickSave008), S(QuickSave009), S(QuickSave010), \ + S(Reset), \ + S(SaveFreezeFile), \ + S(SaveSPC), \ + S(Screenshot), \ + S(SeekToFrame), \ + S(SoftReset), \ + S(SoundChannel0), S(SoundChannel1), S(SoundChannel2), S(SoundChannel3), S(SoundChannel4), S(SoundChannel5), S(SoundChannel6), S(SoundChannel7), \ + S(SoundChannelsOn), \ + S(SwapJoypads), \ + S(SynchronizeSound), \ + S(ToggleBG0), S(ToggleBG1), S(ToggleBG2), S(ToggleBG3), \ + S(ToggleEmuTurbo), \ + S(ToggleHDMA), \ + S(ToggleSprites), \ + S(ToggleTransparency), \ + // end + +#define S(x) x + +enum command_numbers { + THE_COMMANDS + LAST_COMMAND // must be last! +}; + +#undef S +#define S(x) #x + +static const char *command_names[LAST_COMMAND+1]={ + THE_COMMANDS NULL // This MUST be last! }; -enum command_numbers { - BGLayeringHack, - BeginRecordingMovie, - ClipWindows, - Debugger, - DecEmuTurbo, - DecFrameRate, - DecFrameTime, - DecTurboSpeed, - DumpSPC7110Log, - EmuTurbo, - EndRecordingMovie, - ExitEmu, - IncEmuTurbo, - IncFrameRate, - IncFrameTime, - IncTurboSpeed, - InterpolateSound, - LoadFreezeFile, - LoadMovie, - LoadOopsFile, - Mode7Interpolate, - Pause, - QuickLoad000, QuickLoad001, QuickLoad002, QuickLoad003, QuickLoad004, QuickLoad005, QuickLoad006, QuickLoad007, QuickLoad008, QuickLoad009, QuickLoad010, - QuickSave000, QuickSave001, QuickSave002, QuickSave003, QuickSave004, QuickSave005, QuickSave006, QuickSave007, QuickSave008, QuickSave009, QuickSave010, - Reset, - SaveFreezeFile, - SaveSPC, - Screenshot, - SoftReset, - SoundChannel0, SoundChannel1, SoundChannel2, SoundChannel3, SoundChannel4, SoundChannel5, SoundChannel6, SoundChannel7, - SoundChannelsOn, - SwapJoypads, - SynchronizeSound, - ToggleBG0, ToggleBG1, ToggleBG2, ToggleBG3, - ToggleEmuTurbo, - ToggleHDMA, - ToggleSprites, - ToggleTransparency, - - LAST_COMMAND // must be last! -}; +#undef S +#undef THE_COMMANDS static const char *color_names[32]={ "Trans", "Black", "25Grey", "50Grey", "75Grey", "White", "Red", "Orange", "Yellow", "Green", "Cyan", "Sky", "Blue", "Violet", "MagicPink", "Purple", @@ -451,7 +454,7 @@ void S9xControlsSoftReset(void){ void S9xUnmapAllControls(void){ int i; - + S9xControlsReset(); keymap.clear(); for(i=0; i<(int)multis.size(); i++){ @@ -478,7 +481,7 @@ void S9xUnmapAllControls(void){ mouse[i].cur_x=mouse[i].cur_y=0; mouse[i].buttons=1; mouse[i].ID=InvalidControlID; - if(!(mouse[i].crosshair.set&1)) mouse[i].crosshair.img=1; + if(!(mouse[i].crosshair.set&1)) mouse[i].crosshair.img=0; // no image for mouse because its only logical position is game-specific, not known by the emulator if(!(mouse[i].crosshair.set&2)) mouse[i].crosshair.fg=5; if(!(mouse[i].crosshair.set&4)) mouse[i].crosshair.bg=1; justifier.x[i]=justifier.y[i]=0; @@ -650,9 +653,9 @@ bool S9xVerifyControllers(void){ void S9xGetController(int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4){ int i; - + *controller=CTL_NONE; - *id1=*id2=*id3=*id4=0; + *id1=*id2=*id3=*id4=-1; if(port<0 || port>1) return; switch(i=newcontrollers[port]){ case MP5: @@ -676,6 +679,7 @@ void S9xGetController(int port, enum controllers *controller, int8 *id1, int8 *i case SUPERSCOPE: *controller=CTL_SUPERSCOPE; + *id1=1; return; case ONE_JUSTIFIER: case TWO_JUSTIFIERS: @@ -687,64 +691,61 @@ void S9xGetController(int port, enum controllers *controller, int8 *id1, int8 *i void S9xReportControllers(void){ int port, i; - char buf[79], *c; - + static char buf[128]; // static because S9xMessage keeps our pointer instead of copying + char *c=buf; + S9xVerifyControllers(); for(port=0; port<2; port++){ - sprintf(buf, "Controller Port %d: ", port+1); - c=buf+19; + c+=sprintf(c, "Port %d: ", port+1); switch(newcontrollers[port]){ case NONE: - strcat(c, ""); + c+=sprintf(c, ". "); break; case MP5: - strcat(c, "MP5 with pads"); - c+=13; + c+=sprintf(c, "MP5 with pads"); for(i=0; i<4; i++){ if(mp5[port].pads[i]==NONE){ - strcat(c, " "); - c+=7; + c+=sprintf(c, " . "); } else { - sprintf(c, " #%d", mp5[port].pads[i]+1-JOYPAD0); - c+=3; + c+=sprintf(c, " #%d. ", mp5[port].pads[i]+1-JOYPAD0); } } break; case JOYPAD0: case JOYPAD1: case JOYPAD2: case JOYPAD3: case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: - sprintf(c, "Pad %d", newcontrollers[port]-JOYPAD0+1); + c+=sprintf(c, "Pad #%d. ", (int)(newcontrollers[port]-JOYPAD0+1)); break; case MOUSE0: case MOUSE1: - sprintf(c, "Mouse %d", newcontrollers[port]-MOUSE0+1); + c+=sprintf(c, "Mouse #%d. ", (int)(newcontrollers[port]-MOUSE0+1)); break; case SUPERSCOPE: - if(port==0) strcat(c, "Superscope (cannot fire)"); - else strcat(c, "Superscope"); + if(port==0) c+=sprintf(c, "Superscope (cannot fire). "); + else c+=sprintf(c, "Superscope. "); break; case ONE_JUSTIFIER: - if(port==0) strcat(c, "Blue Justifier (cannot fire)"); - else strcat(c, "Blue Justifier"); + if(port==0) c+=sprintf(c, "Blue Justifier (cannot fire). "); + else c+=sprintf(c, "Blue Justifier. "); break; case TWO_JUSTIFIERS: - if(port==0) strcat(c, "Blue and Pink Justifiers (cannot fire)"); - else strcat(c, "Blue and Pink Justifiers"); + if(port==0) c+=sprintf(c, "Blue and Pink Justifiers (cannot fire). "); + else c+=sprintf(c, "Blue and Pink Justifiers. "); break; } - S9xMessage(S9X_INFO, S9X_CONFIG_INFO, buf); } + S9xMessage(S9X_INFO, S9X_CONFIG_INFO, buf); } char *S9xGetCommandName(s9xcommand_t command){ string s; char c; - + switch(command.type){ case S9xButtonJoypad: if(command.button.joypad.buttons==0) return strdup("None"); @@ -878,7 +879,7 @@ char *S9xGetCommandName(s9xcommand_t command){ case S9xAxisPort: case S9xPointerPort: return strdup("BUG: Port should have handled this instead of calling S9xGetCommandName()"); - + case S9xNoMapping: return strdup("None"); @@ -1182,7 +1183,7 @@ s9xcommand_t S9xGetCommandT(const char *name){ i=j+1; n++; } while(name[i]!='\0'); c[n].type=S9xNoMapping; c[n].multi_press=3; - + multis.push_back(c); cmd.button.multi_idx=multis.size()-1; cmd.type=S9xButtonMulti; @@ -1291,7 +1292,8 @@ void S9xReportButton(uint32 id, bool pressed){ return; } - if(keymap[id].button_norpt==pressed) return; + if(keymap[id].type==S9xButtonCommand) // skips the "already-pressed check" unless it's a command, as a hack to work around the following problem: + if(keymap[id].button_norpt==pressed) return; // FIXME: this makes the controls "stick" after loading a savestate while recording a movie and holding any button keymap[id].button_norpt=pressed; S9xApplyCommand(keymap[id], pressed, 0); } @@ -1463,11 +1465,13 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ x=t; t=st; st=x; } if(data1){ + if(!Settings.UpAndDown) // if up+down isn't allowed AND we are NOT playing a movie, + { if(cmd.button.joypad.buttons&(SNES_LEFT_MASK|SNES_RIGHT_MASK)){ // if we're pressing left or right, then unpress and unturbo // them both first so we don't end up hittnig left AND right // accidentally. Note though that the user can still do it on - // purpose, bu specifying a single button that presses both. + // purpose, if Settings.UpAndDown = true. // This is a feature, look up glitches in tLoZ:aLttP to find // out why. joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK|SNES_RIGHT_MASK); @@ -1478,6 +1482,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK|SNES_DOWN_MASK); joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK|SNES_DOWN_MASK); } + }//end up+down protection joypad[cmd.button.joypad.idx].buttons |= r; joypad[cmd.button.joypad.idx].turbos |= t; joypad[cmd.button.joypad.idx].buttons ^= s; @@ -1490,7 +1495,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ } } return; - + case S9xButtonMouse: i=0; if(cmd.button.mouse.left) i|=0x40; @@ -1501,7 +1506,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ mouse[cmd.button.mouse.idx].buttons &= ~i; } return; - + case S9xButtonSuperscope: i=0; if(cmd.button.scope.fire) i|=SUPERSCOPE_FIRE; @@ -1519,7 +1524,10 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ } } superscope.next_buttons |= i&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR|SUPERSCOPE_PAUSE); - if((superscope.next_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR)) && +#ifndef NGC + if(!S9xMovieActive()) // PPU modification during non-recordable command screws up movie synchronization +#endif + if((superscope.next_buttons&(SUPERSCOPE_FIRE|SUPERSCOPE_CURSOR)) && curcontrollers[1]==SUPERSCOPE && !(superscope.phys_buttons&SUPERSCOPE_OFFSCREEN)){ DoGunLatch(superscope.x, superscope.y); @@ -1542,7 +1550,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ justifier.buttons &= ~i; } return; - + case S9xButtonCommand: if(((enum command_numbers)cmd.button.command)>=LAST_COMMAND){ fprintf(stderr, "Unknown command %04x\n", cmd.button.command); @@ -1563,7 +1571,12 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ S9xReset(); break; case SoftReset: - S9xSoftReset(); +#ifndef NGC + S9xMovieUpdateOnReset (); + if(S9xMoviePlaying()) + S9xMovieStop (TRUE); +#endif + S9xSoftReset(); break; case EmuTurbo: Settings.TurboMode = TRUE; @@ -1700,14 +1713,17 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ #endif } break; - case Mode7Interpolate: +/* case Mode7Interpolate: Settings.Mode7Interpolate ^= TRUE; S9xDisplayStateChange ("Mode 7 Interpolation", Settings.Mode7Interpolate); - break; + break;*/ case Pause: Settings.Paused ^= 1; S9xDisplayStateChange ("Pause", Settings.Paused); +#if defined(NETPLAY_SUPPORT) && !defined(__WIN32__) + S9xNPSendPause(Settings.Paused); +#endif break; case QuickLoad000: case QuickLoad001: case QuickLoad002: case QuickLoad003: case QuickLoad004: case QuickLoad005: case QuickLoad006: case QuickLoad007: case QuickLoad008: case QuickLoad009: case QuickLoad010: { @@ -1716,8 +1732,8 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ char drive [_MAX_DRIVE]; char dir [_MAX_DIR]; char ext [_MAX_EXT]; - _splitpath (Memory.ROMFilename, drive, dir, def, ext); + _splitpath (Memory.ROMFilename, drive, dir, def, ext); sprintf (filename, "%s%s%s.%03d", S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000); @@ -1732,7 +1748,6 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ { static char *digits = "t123456789"; _splitpath (Memory.ROMFilename, drive, dir, def, ext); - sprintf (filename, "%s%s%s.zs%c", S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, digits [i - QuickLoad000]); @@ -1777,6 +1792,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ char drive [_MAX_DRIVE]; char dir [_MAX_DIR]; char ext [_MAX_EXT]; + _splitpath (Memory.ROMFilename, drive, dir, def, ext); strcpy (ext, "spc"); _makepath (filename, drive, S9xGetDirectory (SPC_DIR), @@ -1810,24 +1826,24 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ Settings.SoundSync); break; case ToggleBG0: - PPU.BG_Forced ^= 1; - S9xDisplayStateChange ("BG#0", !(PPU.BG_Forced & 1)); + Settings.BG_Forced ^= 1; + S9xDisplayStateChange ("BG#0", !(Settings.BG_Forced & 1)); break; case ToggleBG1: - PPU.BG_Forced ^= 2; - S9xDisplayStateChange ("BG#1", !(PPU.BG_Forced & 2)); + Settings.BG_Forced ^= 2; + S9xDisplayStateChange ("BG#1", !(Settings.BG_Forced & 2)); break; case ToggleBG2: - PPU.BG_Forced ^= 4; - S9xDisplayStateChange ("BG#2", !(PPU.BG_Forced & 4)); + Settings.BG_Forced ^= 4; + S9xDisplayStateChange ("BG#2", !(Settings.BG_Forced & 4)); break; case ToggleBG3: - PPU.BG_Forced ^= 8; - S9xDisplayStateChange ("BG#3", !(PPU.BG_Forced & 8)); + Settings.BG_Forced ^= 8; + S9xDisplayStateChange ("BG#3", !(Settings.BG_Forced & 8)); break; case ToggleSprites: - PPU.BG_Forced ^= 16; - S9xDisplayStateChange ("Sprites", !(PPU.BG_Forced & 16)); + Settings.BG_Forced ^= 16; + S9xDisplayStateChange ("Sprites", !(Settings.BG_Forced & 16)); break; case ToggleHDMA: Settings.DisableHDMA = !Settings.DisableHDMA; @@ -1842,10 +1858,11 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ case DumpSPC7110Log: if(Settings.SPC7110) Do7110Logging(); break; - + case BeginRecordingMovie: #ifndef NGC if(S9xMovieActive()) S9xMovieStop(FALSE); + S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, //MOVIE_OPT_FROM_SNAPSHOT @@ -1853,7 +1870,7 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ NULL, 0); #endif break; - + case LoadMovie: #ifndef NGC if(S9xMovieActive()) S9xMovieStop(FALSE); @@ -1899,12 +1916,37 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ S9xSetInfoString(buf); break; + case SeekToFrame: { +#ifndef NGC + if (!S9xMovieActive()) + + { + S9xSetInfoString("No movie in progress."); + return; + } + + char msg[128]; + sprintf(msg, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); + + const char *frameno = S9xStringInput(msg); + if (!frameno) + return; + int frameDest = atoi(frameno); + if (frameDest > 0 && frameDest > (int)S9xMovieGetFrameCounter()) + { + int distance = frameDest - S9xMovieGetFrameCounter(); + Settings.HighSpeedSeek = distance; + } +#endif + } // braces for vlocalitylocality + break; + case LAST_COMMAND: break; /* no default, so we get compiler warnings */ } } return; - + case S9xPointer: if(cmd.pointer.aim_mouse0){ mouse[0].cur_x=data1; @@ -1992,10 +2034,10 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ } else { if(cmd.axis.pointer.invert) data1=-data1; if(cmd.axis.pointer.HV){ - if(!pseudopointer[cmd.axis.pointer.idx].V_adj) pseudopointer[cmd.axis.pointer.idx].V_adj=(int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767; + if(!pseudopointer[cmd.axis.pointer.idx].V_adj) pseudopointer[cmd.axis.pointer.idx].V_adj=(int16)((int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767); pseudopointer[cmd.axis.pointer.idx].V_var=(cmd.axis.pointer.speed_type==0); } else { - if(!pseudopointer[cmd.axis.pointer.idx].H_adj) pseudopointer[cmd.axis.pointer.idx].H_adj=(int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767; + if(!pseudopointer[cmd.axis.pointer.idx].H_adj) pseudopointer[cmd.axis.pointer.idx].H_adj=(int16)((int32)data1*ptrspeeds[cmd.axis.pointer.speed_type]/32767); pseudopointer[cmd.axis.pointer.idx].H_var=(cmd.axis.pointer.speed_type==0); } } @@ -2039,12 +2081,14 @@ void S9xApplyCommand(s9xcommand_t cmd, int16 data1, int16 data2){ if(i>=0){ struct exemulti *e=new struct exemulti; e->pos=i; - e->data1=data1; + e->data1=data1!=0; e->script=multis[cmd.button.multi_idx]; exemultis.insert(e); } return; + + default: fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); return; @@ -2056,7 +2100,10 @@ static void do_polling(int mp){ set::iterator itr; if(pollmap[mp].empty()) return; - for(itr=pollmap[mp].begin(); itr!=pollmap[mp].end(); itr++){ +#ifndef NGC + if(S9xMoviePlaying()) return; +#endif + for(itr=pollmap[mp].begin(); itr!=pollmap[mp].end(); itr++){ switch(maptype(keymap[*itr].type)){ case MAP_BUTTON: bool pressed; @@ -2072,13 +2119,45 @@ static void do_polling(int mp){ int16 x, y; if(S9xPollPointer(*itr, &x, &y)) S9xReportPointer(*itr, x, y); break; - + default: break; } } } +static void UpdatePolledMouse(int i) { + int16 j; + j=mouse[i-MOUSE0].cur_x-mouse[i-MOUSE0].old_x; + if(j<-127){ + mouse[i-MOUSE0].delta_x=0xff; + mouse[i-MOUSE0].old_x-=127; + } else if(j<0){ + mouse[i-MOUSE0].delta_x=0x80 | -j; + mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; + } else if(j>127){ + mouse[i-MOUSE0].delta_x=0x7f; + mouse[i-MOUSE0].old_x+=127; + } else { + mouse[i-MOUSE0].delta_x=(uint8)j; + mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; + } + j=mouse[i-MOUSE0].cur_y-mouse[i-MOUSE0].old_y; + if(j<-127){ + mouse[i-MOUSE0].delta_y=0xff; + mouse[i-MOUSE0].old_y-=127; + } else if(j<0){ + mouse[i-MOUSE0].delta_y=0x80 | -j; + mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; + } else if(j>127){ + mouse[i-MOUSE0].delta_y=0x7f; + mouse[i-MOUSE0].old_y+=127; + } else { + mouse[i-MOUSE0].delta_y=(uint8)j; + mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; + } +} + void S9xSetJoypadLatch(bool latch){ if(!latch && FLAG_LATCH){ // 1 written, 'plug in' new controllers now @@ -2103,37 +2182,13 @@ void S9xSetJoypadLatch(bool latch){ case JOYPAD4: case JOYPAD5: case JOYPAD6: case JOYPAD7: do_polling(i); break; - + case MOUSE0: case MOUSE1: do_polling(i); - j=mouse[i-MOUSE0].cur_x-mouse[i-MOUSE0].old_x; - if(j<-127){ - mouse[i-MOUSE0].delta_x=0xff; - mouse[i-MOUSE0].old_x-=127; - } else if(j<0){ - mouse[i-MOUSE0].delta_x=0x80 | -j; - mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; - } else if(j>127){ - mouse[i-MOUSE0].delta_x=0x7f; - mouse[i-MOUSE0].old_x+=127; - } else { - mouse[i-MOUSE0].delta_x=j; - mouse[i-MOUSE0].old_x=mouse[i-MOUSE0].cur_x; - } - j=mouse[i-MOUSE0].cur_y-mouse[i-MOUSE0].old_y; - if(j<-127){ - mouse[i-MOUSE0].delta_y=0xff; - mouse[i-MOUSE0].old_y-=127; - } else if(j<0){ - mouse[i-MOUSE0].delta_y=0x80 | -j; - mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; - } else if(j>127){ - mouse[i-MOUSE0].delta_y=0x7f; - mouse[i-MOUSE0].old_y+=127; - } else { - mouse[i-MOUSE0].delta_y=j; - mouse[i-MOUSE0].old_y=mouse[i-MOUSE0].cur_y; - } +#ifndef NGC + if(!S9xMoviePlaying()) +#endif + UpdatePolledMouse(i); break; case SUPERSCOPE: if(superscope.next_buttons&SUPERSCOPE_FIRE){ @@ -2165,7 +2220,7 @@ void S9xSetJoypadLatch(bool latch){ } uint8 S9xReadJOYSERn(int n){ - int i, j, r; + int i, j, r; if(n>1) n-=0x4016; assert(n==0 || n==1); @@ -2226,7 +2281,7 @@ uint8 S9xReadJOYSERn(int n){ } else { read_idx[n][0]++; return bits|1; - } + } case SUPERSCOPE: if(read_idx[n][0]<8){ return bits|((superscope.read_buttons&(0x80>>read_idx[n][0]++))?1:0); @@ -2264,10 +2319,12 @@ uint8 S9xReadJOYSERn(int n){ void S9xDoAutoJoypad(void){ int n, i, j; - + S9xSetJoypadLatch(1); S9xSetJoypadLatch(0); - +#ifndef NGC + S9xMovieUpdate(false); +#endif for(n=0; n<2; n++){ switch(i=curcontrollers[n]){ case MP5: @@ -2428,7 +2485,8 @@ do_justifier: #ifndef NGC S9xMovieUpdate(); #endif - + pad_read_last = pad_read; + pad_read = false; } void S9xSetControllerCrosshair(enum crosscontrols ctl, int8 idx, const char *fg, const char *bg){ @@ -2516,11 +2574,83 @@ void MovieSetJoypad(int i, uint16 buttons){ joypad[i].buttons=buttons; } +// from movie.cpp, used for MovieGetX functions to avoid platform-dependent byte order in the file +#ifndef NGC +extern void Write16(uint16 v, uint8*& ptr); +extern uint16 Read16(const uint8*& ptr); +#endif +#ifndef NGC +bool MovieGetMouse(int i, uint8 out [5]){ + if(i<0 || i>1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) return false; + const int n = curcontrollers[i]-MOUSE0; + uint8* ptr = out; + Write16(mouse[n].cur_x, ptr); + Write16(mouse[n].cur_y, ptr); + *ptr++ = mouse[n].buttons; + return true; +} + +void MovieSetMouse(int i, const uint8 in [5], bool inPolling){ + if(i<0 || i>1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) return; + const int n = curcontrollers[i]-MOUSE0; + const uint8* ptr = in; + mouse[n].cur_x = Read16(ptr); + mouse[n].cur_y = Read16(ptr); + mouse[n].buttons = *ptr++; + if(inPolling) + UpdatePolledMouse(curcontrollers[i]); +} + +bool MovieGetScope(int i, uint8 out [6]){ + if(i<0 || i>1 || (curcontrollers[i] != SUPERSCOPE)) return false; + uint8* ptr = out; + Write16(superscope.x, ptr); + Write16(superscope.y, ptr); + *ptr++ = superscope.phys_buttons; + *ptr++ = superscope.next_buttons; + return true; +} + +void MovieSetScope(int i, const uint8 in [6]){ + if(i<0 || i>1 || (curcontrollers[i] != SUPERSCOPE)) return; + const uint8* ptr = in; + superscope.x = Read16(ptr); + superscope.y = Read16(ptr); + superscope.phys_buttons = *ptr++; + superscope.next_buttons = *ptr++; +} + +bool MovieGetJustifier(int i, uint8 out [11]){ + if(i<0 || i>1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) return false; + uint8* ptr = out; + Write16(justifier.x[0], ptr); + Write16(justifier.x[1], ptr); + Write16(justifier.y[0], ptr); + Write16(justifier.y[1], ptr); + *ptr++ = justifier.buttons; + *ptr++ = justifier.offscreen[0]; + *ptr++ = justifier.offscreen[1]; + return true; +} + +void MovieSetJustifier(int i, const uint8 in [11]){ + if(i<0 || i>1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) return; + const uint8* ptr = in; + justifier.x[0] = Read16(ptr); + justifier.x[1] = Read16(ptr); + justifier.y[0] = Read16(ptr); + justifier.y[1] = Read16(ptr); + justifier.buttons = *ptr++; + justifier.offscreen[0] = *ptr++; + justifier.offscreen[1] = *ptr++; +} +#endif + void S9xControlPreSave(struct SControlSnapshot *s){ - int i; + int i, j; ZeroMemory(s, sizeof(*s)); - s->ver=1; + s->ver=3; for(i=0; i<2; i++){ s->port1_read_idx[i]=read_idx[0][i]; s->port2_read_idx[i]=read_idx[1][i]; @@ -2529,10 +2659,40 @@ void S9xControlPreSave(struct SControlSnapshot *s){ s->mouse_speed[i]=(mouse[i].buttons&0x30)>>4; } s->justifier_select=((justifier.buttons&JUSTIFIER_SELECT)?1:0); + +#define COPY(x) {memcpy((char*)s->internal+i, &(x), sizeof(x)); i+=sizeof(x);} + i=0; + for(j=0; j<8; j++) + COPY(joypad[j].buttons); + for(j=0; j<2; j++) { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + for(j=0; j<2; j++) COPY(justifier.x[j]); + for(j=0; j<2; j++) COPY(justifier.y[j]); + COPY(justifier.buttons); + for(j=0; j<2; j++) COPY(justifier.offscreen[j]); + for(j=0; j<2; j++) + for(int k=0; k<2; k++) + COPY(mp5[j].pads[k]); + assert(i==sizeof(s->internal)); +#undef COPY + s->pad_read=pad_read; + s->pad_read_last=pad_read_last; } void S9xControlPostLoad(struct SControlSnapshot *s){ - int i; + int i, j; if(curcontrollers[0]==MP5 && s->ver<1){ // Crap. Old snes9x didn't support this. @@ -2553,4 +2713,40 @@ void S9xControlPostLoad(struct SControlSnapshot *s){ justifier.buttons&=~JUSTIFIER_SELECT; } FLAG_LATCH=(Memory.FillRAM[0x4016]&1)==1; + + if(s->ver>1) + { +#define COPY(x) {memcpy(&(x), (char*)s->internal+i, sizeof(x)); i+=sizeof(x);} + i=0; + for(j=0; j<8; j++) + COPY(joypad[j].buttons); + for(j=0; j<2; j++) { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + for(j=0; j<2; j++) COPY(justifier.x[j]); + for(j=0; j<2; j++) COPY(justifier.y[j]); + COPY(justifier.buttons); + for(j=0; j<2; j++) COPY(justifier.offscreen[j]); + for(j=0; j<2; j++) + for(int k=0; k<2; k++) + COPY(mp5[j].pads[k]); + assert(i==sizeof(s->internal)); +#undef COPY + } + if(s->ver>2) + { + pad_read=s->pad_read; + pad_read_last=s->pad_read_last; + } } diff --git a/source/snes9x/controls.h b/source/snes9x/controls.h index e281c74..a81d695 100644 --- a/source/snes9x/controls.h +++ b/source/snes9x/controls.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef FOO_H #define FOO_H @@ -183,7 +202,7 @@ typedef struct { uint8 type; uint8 multi_press:2; uint8 button_norpt:1; - + union { union { struct { @@ -239,7 +258,7 @@ typedef struct { uint8 threshold; // (threshold+1)/256% deflection is a // button press } joypad; - + struct { uint8 idx:3; // Pseudo-pointer number 0-7 uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast @@ -310,7 +329,7 @@ const char **S9xGetAllSnes9xCommands(void); s9xcommand_t S9xGetMapping(uint32 id); void S9xUnmapID(uint32 id); -/* +/* * Button mapping functions. If a button is mapped with poll=TRUE, then * S9xPollButton will be called whenever snes9x feels a need for that mapping. * Otherwise, snes9x will assume you will call S9xReportButton() whenever the @@ -320,7 +339,7 @@ void S9xUnmapID(uint32 id); bool S9xMapButton(uint32 id, s9xcommand_t mapping, bool poll); void S9xReportButton(uint32 id, bool pressed); -/* +/* * Pointer mapping functions. If a button is mapped with poll=TRUE, then * S9xPollPointer will be called whenever snes9x feels a need for that mapping. * Otherwise, snes9x will assume you will call S9xReportPointer() whenever the @@ -335,7 +354,7 @@ void S9xReportButton(uint32 id, bool pressed); bool S9xMapPointer(uint32 id, s9xcommand_t mapping, bool poll); void S9xReportPointer(uint32 id, int16 x, int16 y); -/* +/* * Axis mapping functions. If a button is mapped with poll=TRUE, then * S9xPollAxis will be called whenever snes9x feels a need for that mapping. * Otherwise, snes9x will assume you will call S9xReportAxis() whenever the @@ -378,6 +397,14 @@ bool S9xPollAxis(uint32 id, int16 *value); */ void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2); +/* + * Called before already-read SNES joypad data is being used by the game + * if your port defines SNES_JOY_READ_CALLBACKS + */ +#ifdef SNES_JOY_READ_CALLBACKS +void S9xOnSNESPadRead(); +#endif + /* These are for your use */ s9xcommand_t S9xGetPortCommandT(const char *name); char *S9xGetPortCommandName(s9xcommand_t command); @@ -412,7 +439,9 @@ struct SControlSnapshot { uint8 dummy2[4]; uint8 mouse_speed[2]; uint8 justifier_select; - uint8 dummy3[10]; + uint8 dummy3[8]; + bool8 pad_read, pad_read_last; + uint8 internal[60]; // yes, we need to save this! }; void S9xControlPreSave(struct SControlSnapshot *s); diff --git a/source/snes9x/copyright.h b/source/snes9x/copyright.h index 1079a25..e90dd1a 100644 --- a/source/snes9x/copyright.h +++ b/source/snes9x/copyright.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,13 +158,15 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + /* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and * Jerremy Koot (jkoot@snes9x.com) * - * Super FX C emulator code + * Super FX C emulator code * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. diff --git a/source/snes9x/cpu.cpp b/source/snes9x/cpu.cpp index 8f67a21..d6fb170 100644 --- a/source/snes9x/cpu.cpp +++ b/source/snes9x/cpu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "ppu.h" @@ -162,6 +181,9 @@ #include "obc1.h" #include "bsx.h" #include "snapshot.h" +#ifndef NGC +#include "logger.h" +#endif #ifndef ZSNES_FX @@ -203,12 +225,17 @@ void S9xSoftResetCPU () CPU.NMIActive = FALSE; CPU.IRQActive = FALSE; CPU.WaitingForInterrupt = FALSE; - CPU.InDMA = CPU.InWRAM_DMA = FALSE; + CPU.InDMA = FALSE; + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; CPU.PCBase = NULL; CPU.PBPCAtOpcodeStart = 0xffffffff; CPU.WaitAddress = 0xffffffff; CPU.WaitCounter = 0; CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. + CPU.PrevCycles = -1; CPU.V_Counter = 0; CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -216,7 +243,7 @@ void S9xSoftResetCPU () CPU.AutoSaveTimer = 0; CPU.SRAMModified = FALSE; CPU.BRKTriggered = FALSE; - //CPU.TriedInterleavedMode2 = FALSE; // Reset when ROM image loaded + CPU.IRQPending = 0; Timings.InterlaceField = FALSE; Timings.H_Max = Timings.H_Max_Master; @@ -235,7 +262,7 @@ void S9xSoftResetCPU () ICPU.S9xOpcodes = S9xOpcodesE1; ICPU.S9xOpLengths = S9xOpLengthsM1X1; ICPU.CPUExecuting = TRUE; - + S9xUnpackStatus(); } @@ -244,7 +271,10 @@ void S9xResetCPU () S9xSoftResetCPU (); Registers.SL = 0xFF; Registers.P.W = 0; - SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + Registers.A.W = 0; + Registers.X.W = 0; + Registers.Y.W = 0; + SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); ClearFlags (Decimal); } @@ -259,6 +289,7 @@ END_EXTERN_C void S9xReset (void) { #ifndef NGC + ResetLogger(); S9xResetSaveTimer (FALSE); #endif @@ -282,7 +313,6 @@ void S9xReset (void) S9xSA1Init (); if (Settings.C4) S9xInitC4 (); - #ifndef NGC S9xInitCheatData (); #endif diff --git a/source/snes9x/cpuaddr.h b/source/snes9x/cpuaddr.h index 06a8c1e..bc66a73 100644 --- a/source/snes9x/cpuaddr.h +++ b/source/snes9x/cpuaddr.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _CPUADDR_H_ #define _CPUADDR_H_ @@ -283,7 +302,7 @@ STATIC inline uint32 AbsoluteLongSlow (AccessMode a) { // l // JSR l pushes the old bank in the middle of loading the new. // OpenBus needs to be set to account for this. if(a==JSR) OpenBus = Registers.PB; - + addr |= Immediate8Slow(a)<<16; return addr; } diff --git a/source/snes9x/cpuexec.cpp b/source/snes9x/cpuexec.cpp index 6b7887c..17d301e 100644 --- a/source/snes9x/cpuexec.cpp +++ b/source/snes9x/cpuexec.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "cpuops.h" @@ -163,10 +182,17 @@ extern struct FxInit_s SuperFX; void S9xMainLoop (void) { + if(ICPU.SavedAtOp) + { + ICPU.SavedAtOp = FALSE; + Registers.PCw = CPU.PBPCAtOpcodeStart; + if(CPU.PCBase) + CPU.Cycles -= CPU.MemSpeed; + goto doOp; + } + for (;;) { - APU_EXECUTE(); - if (CPU.Flags) { if (CPU.Flags & NMI_FLAG) @@ -180,11 +206,11 @@ void S9xMainLoop (void) CPU.WaitingForInterrupt = FALSE; Registers.PCw++; } - + S9xOpcode_NMI(); } } - + #ifdef DEBUGGER if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) { @@ -202,26 +228,33 @@ void S9xMainLoop (void) } } #endif - + CHECK_SOUND(); - if (CPU.Flags & IRQ_PENDING_FLAG) + if (CPU.Flags & IRQ_FLAG) { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - Registers.PCw++; - } - - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag(IRQ)) - S9xOpcode_IRQ(); - } + if (CPU.IRQPending) + // FIXME: In case of IRQ during WRAM refresh + CPU.IRQPending = 0; else - CPU.Flags &= ~IRQ_PENDING_FLAG; + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag(IRQ)) + // in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. + S9xOpcode_IRQ(); + } + else + CPU.Flags &= ~IRQ_FLAG; + } } - + if (CPU.Flags & SCAN_KEYS_FLAG) break; @@ -239,14 +272,16 @@ void S9xMainLoop (void) } #endif } - + #ifdef CPU_SHUTDOWN CPU.PBPCAtOpcodeStart = Registers.PBPC; #endif - + doOp: register uint8 Op; register struct SOpcodes *Opcodes; - + + CPU.PrevCycles = CPU.Cycles; + if (CPU.PCBase) { Op = CPU.PCBase[Registers.PCw]; @@ -259,7 +294,7 @@ void S9xMainLoop (void) OpenBus = Op; Opcodes = S9xOpcodesSlow; } - + if ((Registers.PCw&MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) { uint8 *oldPCBase = CPU.PCBase; @@ -268,23 +303,29 @@ void S9xMainLoop (void) if (oldPCBase!=CPU.PCBase || (Registers.PCw&~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) Opcodes = S9xOpcodesSlow; } - + Registers.PCw++; (*Opcodes[Op].S9xOpcode)(); - - S9xUpdateAPUTimer(); - + + if(ICPU.SavedAtOp) + { + ICPU.SavedAtOp = false; + continue; + } + + S9xAPUExecute(); + if (SA1.Executing) S9xSA1MainLoop(); - - if (CPU.Cycles >= CPU.NextEvent) + + while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } - + S9xPackStatus(); APURegisters.PC = IAPU.PC - IAPU.RAM; S9xAPUPackStatus(); - + if (CPU.Flags & SCAN_KEYS_FLAG) { #ifdef DEBUGGER @@ -298,11 +339,11 @@ void S9xMainLoop (void) void S9xSetIRQ (uint32 source) { CPU.IRQActive |= source; - CPU.Flags |= IRQ_PENDING_FLAG; - + CPU.Flags |= IRQ_FLAG; + if (CPU.WaitingForInterrupt) { - // Force IRQ to trigger immediately after WAI - + // Force IRQ to trigger immediately after WAI - // Final Fantasy Mystic Quest crashes without this. CPU.WaitingForInterrupt = FALSE; Registers.PCw++; @@ -316,6 +357,10 @@ void S9xClearIRQ (uint32 source) void S9xDoHEventProcessing (void) { +#ifdef DEBUGGER + char mes[256]; +#endif + #ifdef CPU_SHUTDOWN CPU.WaitCounter++; #endif @@ -323,17 +368,23 @@ void S9xDoHEventProcessing (void) { case HC_HBLANK_START_EVENT: S9xCheckMissingHTimerPosition(Timings.HBlankStart); - + break; - + case HC_HDMA_START_EVENT: if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + { + #ifdef DEBUGGER + sprintf(mes, "*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, IPPU.HDMA); + S9xTraceMessage(mes); + #endif IPPU.HDMA = S9xDoHDMA(IPPU.HDMA); - + } + S9xCheckMissingHTimerPosition(Timings.HDMAStart); - + break; - + case HC_HCOUNTER_MAX_EVENT: #ifndef ZSNES_FX if (Settings.SuperFX) @@ -352,14 +403,12 @@ void S9xDoHEventProcessing (void) #endif CPU.Cycles -= Timings.H_Max; - IAPU.NextAPUTimerPos -= (Timings.H_Max << SNES_APUTIMER_ACCURACY); - if (IAPU.APUExecuting) - APU.Cycles -= Timings.H_Max; - else - APU.Cycles = 0; + IAPU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY); + APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY); + if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) Timings.NMITriggerPos -= Timings.H_Max; - + ICPU.Scanline++; CPU.V_Counter++; @@ -367,9 +416,9 @@ void S9xDoHEventProcessing (void) { CPU.V_Counter = 0; Timings.InterlaceField ^= 1; - + // From byuu: - // [NTSC] + // [NTSC] // interlace mode has 525 scanlines: 263 on the even frame, and 262 on the odd. // non-interlace mode has 524 scanlines: 262 scanlines on both even and odd frames. // [PAL] @@ -379,15 +428,15 @@ void S9xDoHEventProcessing (void) Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL) else Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL) - + Memory.FillRAM[0x213F] ^= 0x80; PPU.RangeTimeOver = 0; - + // FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles. Memory.FillRAM[0x4210] = Model->_5A22; CPU.Flags &= ~NMI_FLAG; Timings.NMITriggerPos = 0xffff; - + ICPU.Frame++; PPU.HVBeamCounterLatched = 0; CPU.Flags |= SCAN_KEYS_FLAG; @@ -403,7 +452,7 @@ void S9xDoHEventProcessing (void) Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360 else Timings.H_Max = Timings.H_Max_Master; // HC=1364 - + if (Model->_5A22 == 2) { if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240 @@ -416,7 +465,7 @@ void S9xDoHEventProcessing (void) } else Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; - + S9xCheckMissingHTimerPosition(0); if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240). @@ -435,7 +484,7 @@ void S9xDoHEventProcessing (void) PPU.OAMAddr = PPU.SavedOAMAddr; uint8 tmp = 0; - + if (PPU.OAMPriorityRotation) tmp = (PPU.OAMAddr & 0xFE) >> 1; if ((PPU.OAMFlip & 1) || PPU.FirstSprite!=tmp) @@ -443,7 +492,7 @@ void S9xDoHEventProcessing (void) PPU.FirstSprite = tmp; IPPU.OBJChanged = TRUE; } - + PPU.OAMFlip = 0; } @@ -458,44 +507,47 @@ void S9xDoHEventProcessing (void) } } - + if (CPU.V_Counter == PPU.ScreenHeight + 3) // FIXME: not true - S9xDoAutoJoypad(); - + { + if (Memory.FillRAM[0x4200] & 1) + S9xDoAutoJoypad(); + } + if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1 S9xStartScreenRefresh(); - + CPU.NextEvent = -1; - + break; - + case HC_HDMA_INIT_EVENT: if (CPU.V_Counter == 0) S9xStartHDMA(); - + S9xCheckMissingHTimerPosition(Timings.HDMAInit); - + break; - + case HC_RENDER_EVENT: if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) - RenderLine(CPU.V_Counter - FIRST_VISIBLE_LINE); - + RenderLine((uint8)(CPU.V_Counter - FIRST_VISIBLE_LINE)); + S9xCheckMissingHTimerPosition(Timings.RenderPos); - + break; - + case HC_WRAM_REFRESH_EVENT: - if (!CPU.InDMA) - { - S9xCheckMissingHTimerPositionRange(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); - CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; - S9xUpdateAPUTimer(); - APU_EXECUTE(); - } - else - S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); - + #ifdef DEBUGGER + sprintf(mes, "*** WRAM Refresh HC:%04d", CPU.Cycles); + S9xTraceMessage(mes); + #endif + S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); + CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; + S9xAPUExecute(); + + S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); + break; case HC_IRQ_1_3_EVENT: @@ -509,9 +561,9 @@ void S9xDoHEventProcessing (void) else if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - + break; } - + S9xReschedule(); } diff --git a/source/snes9x/cpuexec.h b/source/snes9x/cpuexec.h index 11d47a8..101c354 100644 --- a/source/snes9x/cpuexec.h +++ b/source/snes9x/cpuexec.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _CPUEXEC_H_ #define _CPUEXEC_H_ @@ -157,7 +176,7 @@ struct SOpcodes { struct SICPU { - uint8 *Speed; + uint8 *Speed; // unused struct SOpcodes *S9xOpcodes; uint8 *S9xOpLengths; uint8 _Carry; @@ -170,6 +189,7 @@ struct SICPU uint32 Frame; uint32 Scanline; uint32 FrameAdvanceCount; + bool8 SavedAtOp; }; START_EXTERN_C @@ -219,9 +239,9 @@ STATIC inline void CLEAR_IRQ_SOURCE (uint32 M) { CPU.IRQActive &= ~M; if (!CPU.IRQActive) - CPU.Flags &= ~IRQ_PENDING_FLAG; + CPU.Flags &= ~IRQ_FLAG; } - + STATIC inline void S9xFixCycles () { if (CheckEmulation ()) diff --git a/source/snes9x/cpumacro.h b/source/snes9x/cpumacro.h index ebd8b90..f0cd870 100644 --- a/source/snes9x/cpumacro.h +++ b/source/snes9x/cpumacro.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _CPUMACRO_H_ #define _CPUMACRO_H_ @@ -226,10 +245,10 @@ mOPC(OP, Memory, ADDR, WRAP, FUNC) -#define bOP(OP, COND, CHK, E) \ +#define bOP(OP, REL, COND, CHK, E) \ static void Op##OP (void) { \ pair newPC; \ - newPC.W = Relative(JUMP); \ + newPC.W = REL(JUMP); \ BranchCheck##CHK (); \ if(COND){ \ AddCycles(ONE_CYCLE); \ @@ -290,7 +309,7 @@ STATIC inline void ADC (uint8 Work8) { ICPU._Carry = Ans16 >= 0x100; - if (~(Registers.AL ^ Work8) & + if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80) SetOverflow(); else diff --git a/source/snes9x/cpuops.cpp b/source/snes9x/cpuops.cpp index 706a9b8..83e5a9b 100644 --- a/source/snes9x/cpuops.cpp +++ b/source/snes9x/cpuops.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + /*****************************************************************************/ /* CPU-S9xOpcodes.CPP */ /* This file contains all the opcodes */ @@ -162,7 +181,7 @@ #include "dsp1.h" #ifdef SA1_OPCODES -#define AddCycles(n) +#define AddCycles(n) {} #else #define AddCycles(n) CPU.Cycles+=n #endif @@ -811,10 +830,10 @@ static void OpA9M0 (void) { static void OpA9Slow (void) { if(CheckMemory()) { - Registers.AL = Immediate8(READ); + Registers.AL = Immediate8Slow(READ); SetZN(Registers.AL); } else { - Registers.A.W = Immediate16(READ); + Registers.A.W = Immediate16Slow(READ); SetZN(Registers.A.W); } } @@ -1504,51 +1523,39 @@ mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) #ifndef SA1_OPCODES inline void CPUShutdown() { - if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) - { - // Don't skip cycles with a pending NMI or IRQ - could cause delayed - // interrupt. Interrupts are delayed for a few cycles already, but - // the delay could allow the shutdown code to cycle skip again. - // Was causing screen flashing on Top Gear 3000. - - if (CPU.WaitCounter == 0 && - !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) { - CPU.WaitAddress = 0xffffffff; - if (Settings.SA1) - S9xSA1ExecuteDuringSleep (); - CPU.Cycles = CPU.NextEvent; - S9xUpdateAPUTimer(); - if (IAPU.APUExecuting) - { - ICPU.CPUExecuting = FALSE; - do + // Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt. + if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG))) { - APU_EXECUTE1(); - } while (APU.Cycles < CPU.NextEvent); - ICPU.CPUExecuting = TRUE; - } + CPU.WaitAddress = 0xffffffff; + if (Settings.SA1) + S9xSA1ExecuteDuringSleep(); + CPU.Cycles = CPU.NextEvent; + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; + } + else + if (CPU.WaitCounter >= 2) + CPU.WaitCounter = 1; + else + CPU.WaitCounter--; } - else - if (CPU.WaitCounter >= 2) - CPU.WaitCounter = 1; - else - CPU.WaitCounter--; - } } #else inline void CPUShutdown() { - if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) - { - if (CPU.WaitCounter >= 1) + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) { - SA1.Executing = FALSE; - SA1.CPUExecuting = FALSE; + if (CPU.WaitCounter >= 1) + { + SA1.Executing = FALSE; + SA1.CPUExecuting = FALSE; + } + else + CPU.WaitCounter++; } - else - CPU.WaitCounter++; - } } #endif #else @@ -1556,55 +1563,59 @@ inline void CPUShutdown() #endif /* BCC */ -bOP(90E0, !CheckCarry(), 0, 0) -bOP(90E1, !CheckCarry(), 0, 1) -bOP(90Slow, !CheckCarry(), 0, CheckEmulation()) +bOP(90E0, Relative, !CheckCarry(), 0, 0) +bOP(90E1, Relative, !CheckCarry(), 0, 1) +bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) /* BCS */ -bOP(B0E0, CheckCarry(), 0, 0) -bOP(B0E1, CheckCarry(), 0, 1) -bOP(B0Slow, CheckCarry(), 0, CheckEmulation()) +bOP(B0E0, Relative, CheckCarry(), 0, 0) +bOP(B0E1, Relative, CheckCarry(), 0, 1) +bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) /* BEQ */ -bOP(F0E0, CheckZero(), 2, 0) -bOP(F0E1, CheckZero(), 2, 1) -bOP(F0Slow, CheckZero(), 2, CheckEmulation()) +bOP(F0E0, Relative, CheckZero(), 2, 0) +bOP(F0E1, Relative, CheckZero(), 2, 1) +bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) /* BMI */ -bOP(30E0, CheckNegative(), 1, 0) -bOP(30E1, CheckNegative(), 1, 1) -bOP(30Slow, CheckNegative(), 1, CheckEmulation()) +bOP(30E0, Relative, CheckNegative(), 1, 0) +bOP(30E1, Relative, CheckNegative(), 1, 1) +bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) /* BNE */ -bOP(D0E0, !CheckZero(), 1, 0) -bOP(D0E1, !CheckZero(), 1, 1) -bOP(D0Slow, !CheckZero(), 1, CheckEmulation()) +bOP(D0E0, Relative, !CheckZero(), 1, 0) +bOP(D0E1, Relative, !CheckZero(), 1, 1) +bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) /* BPL */ -bOP(10E0, !CheckNegative(), 1, 0) -bOP(10E1, !CheckNegative(), 1, 1) -bOP(10Slow, !CheckNegative(), 1, CheckEmulation()) +bOP(10E0, Relative, !CheckNegative(), 1, 0) +bOP(10E1, Relative, !CheckNegative(), 1, 1) +bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) /* BRA */ -bOP(80E0, 1, X, 0) -bOP(80E1, 1, X, 1) -bOP(80Slow, 1, X, CheckEmulation()) +bOP(80E0, Relative, 1, X, 0) +bOP(80E1, Relative, 1, X, 1) +bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) /* BVC */ -bOP(50E0, !CheckOverflow(), 0, 0) -bOP(50E1, !CheckOverflow(), 0, 1) -bOP(50Slow, !CheckOverflow(), 0, CheckEmulation()) +bOP(50E0, Relative, !CheckOverflow(), 0, 0) +bOP(50E1, Relative, !CheckOverflow(), 0, 1) +bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) /* BVS */ -bOP(70E0, CheckOverflow(), 0, 0) -bOP(70E1, CheckOverflow(), 0, 1) -bOP(70Slow, CheckOverflow(), 0, CheckEmulation()) +bOP(70E0, Relative, CheckOverflow(), 0, 0) +bOP(70E1, Relative, CheckOverflow(), 0, 1) +bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) /* BRL */ static void Op82 (void) { S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); } +static void Op82Slow (void) { + S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); +} + /*****************************************************************************/ /* Flag Instructions ******************************************************* */ @@ -3034,9 +3045,9 @@ static void Op44X0 (void) { static void Op44Slow (void) { uint32 SrcBank; - OpenBus = Registers.DB = Immediate8(NONE); + OpenBus = Registers.DB = Immediate8Slow(NONE); ICPU.ShiftedDB = Registers.DB << 16; - OpenBus = SrcBank = Immediate8(NONE); + OpenBus = SrcBank = Immediate8Slow(NONE); S9xSetByte(OpenBus=S9xGetByte ((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); @@ -3194,15 +3205,9 @@ static void OpCB (void) { // XXX: FIXME if(Settings.Shutdown){ SA1.Cycles = SA1.NextEvent; - if (IAPU.APUExecuting) - { - SA1.Executing = FALSE; - do - { - APU_EXECUTE1 (); - } while (APU.Cycles < SA1.NextEvent); - SA1.Executing = TRUE; - } + SA1.Executing = FALSE; + //S9xAPUExecute(); // FIXME + SA1.Executing = TRUE; } #endif #else // SA1_OPCODES @@ -3218,20 +3223,15 @@ static void OpCB (void) { if (Settings.Shutdown) { CPU.Cycles = CPU.NextEvent; - S9xUpdateAPUTimer(); - if (IAPU.APUExecuting) - { - ICPU.CPUExecuting = FALSE; - do - { - APU_EXECUTE1 (); - } while (APU.Cycles < CPU.NextEvent); - ICPU.CPUExecuting = TRUE; - } - } else { - AddCycles(TWO_CYCLES); -#endif + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; } + else + AddCycles(TWO_CYCLES); +#else + AddCycles(TWO_CYCLES); +#endif } #endif // SA1_OPCODES } @@ -3248,9 +3248,10 @@ extern FILE *trace; extern FILE *trace2; #endif static void Op42 (void) { -#ifndef NGC - uint8 byte = S9xGetWord(Registers.PBPC); +#ifdef DEBUGGER + uint8 byte = (uint8) #endif + S9xGetWord(Registers.PBPC); Registers.PCw++; #ifdef DEBUGGER // Hey, let's use this to trigger debug modes @@ -3610,7 +3611,7 @@ struct SOpcodes S9xOpcodesSlow[256] = { {Op73Slow}, {Op74Slow}, {Op75Slow}, {Op76Slow}, {Op77Slow}, {Op78}, {Op79Slow}, {Op7ASlow}, {Op7B}, {Op7CSlow}, {Op7DSlow}, {Op7ESlow}, {Op7FSlow}, {Op80Slow}, {Op81Slow}, - {Op82}, {Op83Slow}, {Op84Slow}, {Op85Slow}, {Op86Slow}, + {Op82Slow}, {Op83Slow}, {Op84Slow}, {Op85Slow}, {Op86Slow}, {Op87Slow}, {Op88Slow}, {Op89Slow}, {Op8ASlow}, {Op8BSlow}, {Op8CSlow}, {Op8DSlow}, {Op8ESlow}, {Op8FSlow}, {Op90Slow}, {Op91Slow}, {Op92Slow}, {Op93Slow}, {Op94Slow}, {Op95Slow}, diff --git a/source/snes9x/cpuops.h b/source/snes9x/cpuops.h index c6abd0b..06d8c16 100644 --- a/source/snes9x/cpuops.h +++ b/source/snes9x/cpuops.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _CPUOPS_H_ #define _CPUOPS_H_ void S9xOpcode_NMI (); diff --git a/source/snes9x/crosshairs.cpp b/source/snes9x/crosshairs.cpp index 3f32d13..c0ee542 100644 --- a/source/snes9x/crosshairs.cpp +++ b/source/snes9x/crosshairs.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifdef HAVE_CONFIG_H #include #endif @@ -435,7 +454,7 @@ bool S9xLoadCrosshairFile(int idx, const char *filename){ int i, r; char *s; FILE *fp; - + if(idx<1 || idx>31) return false; if((s=(char *)calloc(15*15+1, sizeof(char)))==NULL){ fprintf(stderr, "S9xLoadCrosshairFile: malloc error while reading "); diff --git a/source/snes9x/crosshairs.h b/source/snes9x/crosshairs.h index 02df50f..b9c7ac5 100644 --- a/source/snes9x/crosshairs.h +++ b/source/snes9x/crosshairs.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef CROSSHAIRS_H #define CROSSHAIRS_H diff --git a/source/snes9x/data.cpp b/source/snes9x/data.cpp index 738b45a..6c7b563 100644 --- a/source/snes9x/data.cpp +++ b/source/snes9x/data.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" uint8 add32_32 [32][32] = { diff --git a/source/snes9x/debug.cpp b/source/snes9x/debug.cpp index 0a531aa..073ec6d 100644 --- a/source/snes9x/debug.cpp +++ b/source/snes9x/debug.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include #ifdef HAVE_STRINGS_H #include @@ -170,12 +189,6 @@ static void WhatsUsed (); EXTERN_C SDMA DMA[8]; extern struct SCheatData Cheat; -#ifdef SPCTOOL -#include "spctool/spc700.h" -extern "C" void TraceSPC (unsigned char *PC, unsigned short YA, unsigned char X, - SPCFlags PS, unsigned char *SP); -#endif - FILE *trace = NULL; FILE *trace2 = NULL; struct SBreakPoint S9xBreakpoint[6]; @@ -223,7 +236,7 @@ char *HelpMessage[] = { "bs [Number] [Address] - Enable/Disable Breakpoint", " [Enable example: BS #2 $02:8002]", " [Disable example: BS #2]", - "c - Dump SNES colour palette", + "c - Dump SNES colour palette", "W - Show what SNES hardware features a ROM is using", " which might not be implemented yet.", "w - Show some SNES hardware features used so far in this frame", @@ -718,7 +731,7 @@ uint8 S9xOPrint (char *Line, uint8 Bank, uint16 Address) break; } // XXX: - sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%03d VC:%03ld %02x", + sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04d VC:%03d FC:%02d %02x", Line, Registers.A.W, Registers.X.W, Registers.Y.W, Registers.D.W, Registers.DB, Registers.S.W, CheckEmulation () ? 'E' : 'e', @@ -732,6 +745,7 @@ uint8 S9xOPrint (char *Line, uint8 Bank, uint16 Address) CheckCarry () ? 'C' : 'c', Cycles, CPU.V_Counter, + IPPU.FrameCount, CPU.IRQActive); CPU.Cycles = Cycles; @@ -1229,7 +1243,7 @@ static void ProcessDebugCommand (char *Line) S9xAddCheat (TRUE, TRUE, Address, Byte); return; } - + if (strncasecmp (Line, "dump", 4) == 0) { int Count; @@ -1421,18 +1435,11 @@ static void ProcessDebugCommand (char *Line) extern FILE *apu_trace; if (APU.Flags & TRACE_FLAG) { -#ifdef SPCTOOL - printf ("ENABLED\n"); - _SetSPCDbg (TraceSPC); //Install debug handler -#endif if (apu_trace == NULL) apu_trace = fopen ("aputrace.log", "wb"); } else { -#ifdef SPCTOOL - _SetSPCDbg (NULL); -#endif if (apu_trace) { fclose (apu_trace); @@ -1460,7 +1467,7 @@ static void ProcessDebugCommand (char *Line) printf ("SPC700 sample addresses at 0x%04x:\n", APU.DSP [APU_DIR] << 8); for (int i = 0; i < 256; i++) { - uint8 *dir = IAPU.RAM + + uint8 *dir = IAPU.RAM + (((APU.DSP [APU_DIR] << 8) + i * 4) & 0xffff); int addr = *dir + (*(dir + 1) << 8); @@ -1499,13 +1506,8 @@ static void ProcessDebugCommand (char *Line) { printf ("APU in-ports: %02X %02X %02X %02X\n", IAPU.RAM [0xF4], IAPU.RAM [0xF5], IAPU.RAM [0xF6], IAPU.RAM [0xF7]); -#ifdef SPCTOOL - printf ("APU out-ports: %02X %02X %02X %02X\n", - _SPCOutP [0], _SPCOutP [1], _SPCOutP [2], _SPCOutP [3]); -#else printf ("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts [0], APU.OutPorts [1], APU.OutPorts [2], APU.OutPorts [3]); -#endif printf ("ROM/RAM switch: %s\n", (IAPU.RAM [0xf1] & 0x80) ? "ROM" : "RAM"); for (int i = 0; i < 3; i++) if (APU.TimerEnabled [i]) @@ -1747,7 +1749,7 @@ static void ProcessDebugCommand (char *Line) (Registers.P.W & 1) != 0 ? "C" : "c", (Registers.P.W & 256) != 0 ? "E" : "e"); DPrint (String); -#endif +#endif S9xOPrint (String, Bank, Address); DPrint (String); } @@ -1819,7 +1821,7 @@ static void WhatsUsed () printf ("Screen mode: %d, ", PPU.BGMode); if (PPU.BGMode <= 1 && (Memory.FillRAM [0x2105] & 8)) printf ("(BG#2 Priority)"); - + printf ("Brightness: %d", PPU.Brightness); if (Memory.FillRAM[0x2100] & 0x80) printf (" (screen blanked)"); @@ -1902,7 +1904,7 @@ static void WhatsUsed () { printf ("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X\n", i, PPU.BG[i].VOffset, PPU.BG[i].HOffset, - (PPU.BG[i].SCSize & 1) * 32 + 32, + (PPU.BG[i].SCSize & 1) * 32 + 32, (PPU.BG[i].SCSize & 2) * 16 + 32, PPU.BG[i].BGSize * 8 + 8, PPU.BG[i].SCBase, @@ -1937,7 +1939,7 @@ static void WhatsUsed () printf ("OBJ,"); break; } - + switch ((Memory.FillRAM [0x2130] & 0x30) >> 4) { case 0: s = "always on"; break; @@ -1945,7 +1947,7 @@ static void WhatsUsed () case 2: s = "outside"; break; case 3: s = "always off"; break; } - + printf ("\nSub-screen (%s): ", s); for (i = 0; i < 5; i++) if (Memory.FillRAM[0x212d] & (1 << i)) diff --git a/source/snes9x/debug.h b/source/snes9x/debug.h index 3d193c3..289fd9d 100644 --- a/source/snes9x/debug.h +++ b/source/snes9x/debug.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _DEBUG_H_ #define _DEBUG_H_ diff --git a/source/snes9x/display.h b/source/snes9x/display.h index 9565ab9..c571d71 100644 --- a/source/snes9x/display.h +++ b/source/snes9x/display.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _DISPLAY_H_ #define _DISPLAY_H_ @@ -150,11 +169,11 @@ START_EXTERN_C void S9xSetPalette (); void S9xTextMode (); void S9xGraphicsMode (); -void S9xLoadConfigFiles(char **argv, int argc); -char *S9xParseArgs (char **argv, int argc); void S9xParseArg (char **argv, int &index, int argc); void S9xExtraUsage (); +void S9xLoadConfigFiles(char **argv, int argc); +char *S9xParseArgs (char **argv, int argc); void S9xUsage (); void S9xInitDisplay (int argc, char **argv); void S9xDeinitDisplay (); @@ -171,7 +190,7 @@ void S9xNextController (); bool8 S9xLoadROMImage (const char *string); const char *S9xSelectFilename (const char *def, const char *dir, const char *ext, const char *title); - +const char *S9xStringInput(const char *message); const char *S9xChooseFilename (bool8 read_only); bool8 S9xOpenSnapshotFile (const char *base, bool8 read_only, STREAM *file); void S9xCloseSnapshotFile (STREAM file); diff --git a/source/snes9x/dma.cpp b/source/snes9x/dma.cpp index c5df50f..92f502c 100644 --- a/source/snes9x/dma.cpp +++ b/source/snes9x/dma.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,12 +158,13 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifdef HAVE_CONFIG_H #include #endif #include "snes9x.h" - #include "memmap.h" #include "ppu.h" #include "cpuexec.h" @@ -156,1119 +174,1224 @@ #include "gfx.h" #include "sa1.h" #include "spc7110.h" - -#ifdef SDD1_DECOMP #include "sdd1emu.h" -#endif -#ifdef SDD1_DECOMP -uint8 buffer[0x10000]; -#endif +extern uint8 *HDMAMemPointers[8]; +extern int HDMA_ModeByteCounts[8]; +static uint8 sdd1_decode_buffer[0x10000]; -extern int HDMA_ModeByteCounts [8]; -extern uint8 *HDMAMemPointers [8]; -#if defined(__linux__) || defined(__WIN32__) || defined(__MACOSX__) static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) { return (*(uint32 *) p1 - *(uint32 *) p2); } -#endif -static inline void S9xTrySyncAPUInDMA (void) +// Add 8 cycles per byte, sync APU, and do HC related events. +// If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. +static inline bool8 addCyclesInDMA (uint8 dma_channel) { -#ifdef SPC700_C - S9xUpdateAPUTimer(); - APU_EXECUTE(); -#endif + CPU.Cycles += SLOW_ONE_CYCLE; + S9xAPUExecute(); + while (CPU.Cycles >= CPU.NextEvent) + S9xDoHEventProcessing(); + + if (CPU.HDMARanInDMA & (1 << dma_channel)) + { + CPU.HDMARanInDMA = 0; + #if 1 + printf("HDMA and DMA use the same channel %d!\n", dma_channel); + #endif + // If HDMA triggers in the middle of DMA transfer and it uses the same channel, + // it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. + return FALSE; + } + + CPU.HDMARanInDMA = 0; + return TRUE; } -/**********************************************************************************************/ -/* S9xDoDMA() */ -/* This function preforms the general dma transfer */ -/**********************************************************************************************/ - -void S9xDoDMA (uint8 Channel) +bool8 S9xDoDMA (uint8 Channel) { - uint8 Work; + CPU.InDMA = TRUE; + CPU.InDMAorHDMA = TRUE; - if (Channel > 7 || CPU.InDMA) - return; + SDMA *d = &DMA[Channel]; - CPU.InDMA = TRUE; - bool8 in_sa1_dma = FALSE; - uint8 *in_sdd1_dma = NULL; - uint8 *spc7110_dma=NULL; - bool s7_wrap=false; - SDMA *d = &DMA[Channel]; + // Check invalid DMA first + if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) + { + // Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written. + // Attempting a DMA from $2180 to WRAM will similarly not work, + // the value written is (initially) the OpenBus value. + // In either case, the address in $2181-3 is not incremented. + // Does an invalid DMA actually take time? + // I'd say yes, since 'invalid' is probably just the WRAM chip + // not being able to read and write itself at the same time + // And no, PPU.WRAM should not be updated. - int32 count = d->TransferBytes; + int32 c = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (c == 0) + c = 0x10000; - if (count == 0) - count = 0x10000; + // 8 cycles per channel + CPU.Cycles += SLOW_ONE_CYCLE; + // 8 cycles per byte + while (c) + { + d->TransferBytes--; + d->AAddress++; + c--; + if (!addCyclesInDMA(Channel)) + { + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + return FALSE; + } + } - int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + #ifdef DEBUGGER + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif - if((d->ABank==0x7E || d->ABank==0x7F) && d->BAddress==0x80 && !d->TransferDirection) - { - d->AAddress+= d->TransferBytes; - //does an invalid DMA actually take time? - // I'd say yes, since 'invalid' is probably just the WRAM chip - // not being able to read and write itself at the same time - // And no, PPU.WRAM should not be updated. - CPU.Cycles+=(d->TransferBytes+1)*SLOW_ONE_CYCLE; - S9xTrySyncAPUInDMA(); + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + return TRUE; + } + + // Prepare for accessing $2118-2119 + switch (d->BAddress) + { + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) + FLUSH_REDRAW(); + break; + } + + int32 inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + int32 count = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (count == 0) + count = 0x10000; + + // Prepare for custom chip DMA + + // S-DD1 + + uint8 *in_sdd1_dma = NULL; + + if (Settings.SDD1) + { + if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0) + { + // XXX: Should probably verify that we're DMAing from ROM? + // And somewhere we should make sure we're not running across a mapping boundary too. + // Hacky support for pre-decompressed S-DD1 data + inc = !d->AAddressDecrement ? 1 : -1; + + if (Settings.SDD1Pack) // XXX: Settings.SDD1Pack == true -> on-the-fly decoding. Weird. + { + // on-the-fly S-DD1 decoding + uint8 *in_ptr = GetBasePointer(((d->ABank << 16) | d->AAddress)); + if (in_ptr) + { + in_ptr += d->AAddress; + SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); + } + #ifdef DEBUGGER + else + { + sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + } + #endif + + in_sdd1_dma = sdd1_decode_buffer; + } + else + { + // S-DD1 graphics pack support + // XXX: Who still uses the graphics pack? + uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; + address |= Memory.FillRAM[0x4804 + ((d->ABank - 0xc0) >> 4)]; + + void *ptr = bsearch(&address, Memory.SDD1Index, Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); + if (ptr) + in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; + + if (!in_sdd1_dma) + { + // No matching decompressed data found. Must be some new graphics not encountered before. + // Log it if it hasn't been already. + uint8 *p = Memory.SDD1LoggedData; + bool8 found = FALSE; + uint8 SDD1Bank = Memory.FillRAM[0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; + + for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) + { + if (*(p + 0) == d->ABank || + *(p + 1) == (d->AAddress >> 8) && + *(p + 2) == (d->AAddress & 0xff) && + *(p + 3) == (count >> 8) && + *(p + 4) == (count & 0xff) && + *(p + 7) == SDD1Bank) + { + found = TRUE; + break; + } + } + + if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) + { + *(p + 0) = d->ABank; + *(p + 1) = d->AAddress >> 8; + *(p + 2) = d->AAddress & 0xff; + *(p + 3) = count >> 8; + *(p + 4) = count & 0xff; + *(p + 7) = SDD1Bank; + Memory.SDD1LoggedDataCount += 1; + } + } + } + } + + Memory.FillRAM[0x4801] = 0; + } + + // SPC7110 + + uint8 *spc7110_dma = NULL; + bool8 s7_wrap = FALSE; + + if (Settings.SPC7110) + { + if (d->AAddress == 0x4800 || d->ABank == 0x50) + { + uint32 i, j; + + i = (s7r.reg4805 | (s7r.reg4806 << 8)); + + #ifdef SPC7110_DEBUG + printf("SPC7110: DMA Transfer of %04X bytes from %02X%02X%02X:%02X, offset of %04X, internal bank of %04X, multiplier %02X\n", + d->TransferBytes, s7r.reg4803, s7r.reg4802, s7r.reg4801, s7r.reg4804, i, s7r.bank50Internal, s7r.AlignBy); + #endif + + i *= s7r.AlignBy; + i += s7r.bank50Internal; + i %= DECOMP_BUFFER_SIZE; + j = 0; + + if ((i + d->TransferBytes) < DECOMP_BUFFER_SIZE) + spc7110_dma = &s7r.bank50[i]; + else + { + spc7110_dma = new uint8[d->TransferBytes]; + j = DECOMP_BUFFER_SIZE - i; + memcpy(spc7110_dma, &s7r.bank50[i], j); + memcpy(&spc7110_dma[j], s7r.bank50, d->TransferBytes - j); + s7_wrap = TRUE; + } + + int32 icount = s7r.reg4809 | (s7r.reg480A << 8); + icount -= d->TransferBytes; + s7r.reg4809 = 0x00ff & icount; + s7r.reg480A = (0xff00 & icount) >> 8; + + s7r.bank50Internal += d->TransferBytes; + s7r.bank50Internal %= DECOMP_BUFFER_SIZE; + + inc = 1; + d->AAddress -= count; + } + } + + // SA-1 + + bool8 in_sa1_dma = FALSE; + + if (Settings.SA1) + { + if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) + { + // Perform packed bitmap to PPU character format conversion on the data + // before transmitting it to V-RAM via-DMA. + int32 num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7); + int32 depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; + int32 bytes_per_char = 8 * depth; + int32 bytes_per_line = depth * num_chars; + int32 char_line_bytes = bytes_per_char * num_chars; + uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; + + uint8 *base = GetBasePointer((d->ABank << 16) + addr); + if (!base) + { + sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + base = Memory.ROM; + } + + base += addr; + + uint8 *buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + uint8 *p = buffer; + uint32 inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes); + uint32 char_count = inc_sa1 / bytes_per_char; + + in_sa1_dma = TRUE; + + #if 0 + printf("SA-1 DMA: %08x,", base); + printf("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", + depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); + #endif + + switch (depth) + { + case 2: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 2) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 2; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + } + } + + break; + + case 4: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 4; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 4) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 4; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 32 - 16; + } + } + + break; + + case 8: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 8; + for (uint32 j = 0; j < char_count && p - buffer < count; j++, line += 8) + { + uint8 *q = line; + for (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + + p += 2; + } + + p += 64 - 16; + } + + break; + } + } + } + } #ifdef DEBUGGER - if (Settings.TraceDMA) - { - sprintf (String, "DMA[%d]: %s Mode: %d 0x%02X%04X->0x21%02X Bytes: %d (%s) V-Line:%ld -- ABORT WRAM Bank%02X->$2180", - Channel, d->TransferDirection ? "read" : "write", - d->TransferMode, d->ABank, d->AAddress, - d->BAddress, d->TransferBytes, - d->AAddressFixed ? "fixed" : - (d->AAddressDecrement ? "dec" : "inc"), - CPU.V_Counter, d->ABank); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d", + Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress, + d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter); + + if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) + sprintf(String, "%s VRAM: %04X (%d,%d) %s", String, + PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte"); + else + if (d->BAddress == 0x22 || d->BAddress == 0x3b) + sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP); + else + if (d->BAddress == 0x04 || d->BAddress == 0x38) + sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr); + + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } #endif - goto update_address; - } - switch (d->BAddress) + + // Do Transfer + + uint8 Work; + + // 8 cycles per channel + CPU.Cycles += SLOW_ONE_CYCLE; + + if (!d->ReverseTransfer) { - case 0x18: - case 0x19: - if (IPPU.RenderThisFrame) - FLUSH_REDRAW (); - break; - } - if (Settings.SDD1) - { - if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) - { - // XXX: Should probably verify that we're DMAing from ROM? And - // somewhere we should make sure we're not running across a mapping - // boundary too. - // Hacky support for pre-decompressed S-DD1 data - inc = !d->AAddressDecrement ? 1 : -1; - uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; + // CPU -> PPU + int32 b = 0; + uint16 p = d->AAddress; + uint8 *base = GetBasePointer((d->ABank << 16) + d->AAddress); + bool8 inWRAM_DMA; - address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; + int32 rem = count; + // Transfer per block if d->AAdressFixed is FALSE + count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK))); -#ifdef SDD1_DECOMP - if(Settings.SDD1Pack) - { - uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); - if(in_ptr){ - in_ptr+=d->AAddress; - SDD1_decompress(buffer,in_ptr,d->TransferBytes); - } else { - sprintf(String, "S-DD1 DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); - S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); - } - in_sdd1_dma=buffer; -#ifdef SDD1_VERIFY - void *ptr = bsearch (&address, Memory.SDD1Index, - Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); - if(memcmp(buffer, ptr, d->TransferBytes)) - { - uint8 *p = Memory.SDD1LoggedData; - bool8 found = FALSE; - uint8 SDD1Bank = Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; + // Settings for custom chip DMA + if (in_sa1_dma) + { + base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + p = 0; + count = rem; + } + else + if (in_sdd1_dma) + { + base = in_sdd1_dma; + p = 0; + count = rem; + } + else + if (spc7110_dma) + { + base = spc7110_dma; + p = 0; + count = rem; + } - for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) - { - if (*p == d->ABank || - *(p + 1) == (d->AAddress >> 8) && - *(p + 2) == (d->AAddress & 0xff) && - *(p + 3) == (count >> 8) && - *(p + 4) == (count & 0xff) && - *(p + 7) == SDD1Bank) - { - found = TRUE; - } - } - if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) - { - int j=0; - while(ptr[j]==buffer[j]) - j++; - - *p = d->ABank; - *(p + 1) = d->AAddress >> 8; - *(p + 2) = d->AAddress & 0xff; - *(p + 3) = j&0xFF; - *(p + 4) = (j>>8)&0xFF; - *(p + 7) = SDD1Bank; - Memory.SDD1LoggedDataCount += 1; - } - } -#endif - } - - else - { -#endif -#if defined(__linux__) || defined(__WIN32__) || defined(__MACOSX__) - void *ptr = bsearch (&address, Memory.SDD1Index, - Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); - if (ptr) - in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; -#else - uint8 *ptr = Memory.SDD1Index; - - for (uint32 e = 0; e < Memory.SDD1Entries; e++, ptr += 12) - { - if (address == *(uint32 *) ptr) - { - in_sdd1_dma = *(uint32 *) (ptr + 4) + Memory.SDD1Data; - break; - } - } -#endif - - if (!in_sdd1_dma) - { - // No matching decompressed data found. Must be some new - // graphics not encountered before. Log it if it hasn't been - // already. - uint8 *p = Memory.SDD1LoggedData; - bool8 found = FALSE; - uint8 SDD1Bank = Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; - - for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) - { - if (*p == d->ABank || - *(p + 1) == (d->AAddress >> 8) && - *(p + 2) == (d->AAddress & 0xff) && - *(p + 3) == (count >> 8) && - *(p + 4) == (count & 0xff) && - *(p + 7) == SDD1Bank) - { - found = TRUE; - break; - } - } - if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) - { - *p = d->ABank; - *(p + 1) = d->AAddress >> 8; - *(p + 2) = d->AAddress & 0xff; - *(p + 3) = count >> 8; - *(p + 4) = count & 0xff; - *(p + 7) = SDD1Bank; - Memory.SDD1LoggedDataCount += 1; - } - } - } -#ifdef SDD1_DECOMP - } -#endif - - Memory.FillRAM [0x4801] = 0; - } - if(Settings.SPC7110&&(d->AAddress==0x4800||d->ABank==0x50)) - { - uint32 i,j; - i=(s7r.reg4805|(s7r.reg4806<<8)); -#ifdef SPC7110_DEBUG - printf("DMA Transfer of %04X bytes from %02X%02X%02X:%02X, offset of %04X, internal bank of %04X, multiplier %02X\n",d->TransferBytes,s7r.reg4803,s7r.reg4802,s7r.reg4801, s7r.reg4804,i, s7r.bank50Internal, s7r.AlignBy); -#endif - i*=s7r.AlignBy; - i+=s7r.bank50Internal; - i%=DECOMP_BUFFER_SIZE; - j=0; - if((i+d->TransferBytes)TransferBytes]; - j=DECOMP_BUFFER_SIZE-i; - memcpy(spc7110_dma, &s7r.bank50[i], j); - memcpy(&spc7110_dma[j],s7r.bank50,d->TransferBytes-j); - s7_wrap=true; - } - int icount=s7r.reg4809|(s7r.reg480A<<8); - icount-=d->TransferBytes; - s7r.reg4809=0x00ff&icount; - s7r.reg480A=(0xff00&icount)>>8; - - s7r.bank50Internal+=d->TransferBytes; - s7r.bank50Internal%=DECOMP_BUFFER_SIZE; - inc=1; - d->AAddress-=count; - } - if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40) - { - // Perform packed bitmap to PPU character format conversion on the - // data before transmitting it to V-RAM via-DMA. - int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); - int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - - int bytes_per_char = 8 * depth; - int bytes_per_line = depth * num_chars; - int char_line_bytes = bytes_per_char * num_chars; - uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; - uint8 *base = GetBasePointer ((d->ABank << 16) + addr); - if(!base){ - sprintf(String, "SA-1 DMA from non-block address $%02X:%04X", d->ABank, addr); - S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); - base=Memory.ROM; - } - base+=addr; - uint8 *buffer = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - uint8 *p = buffer; - uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes); - uint32 char_count = inc / bytes_per_char; - - in_sa1_dma = TRUE; - - //printf ("%08x,", base); fflush (stdout); - //printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", - //depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); - int i; - - switch (depth) - { - case 2: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 2; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 2) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 2; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); - } - p += 2; - } - } - } - break; - case 4: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 4; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 4) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 4; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); - } - p += 2; - } - p += 32 - 16; - } - } - break; - case 8: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 8; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 8) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - p += 2; - } - p += 64 - 16; - } - } - break; - } - } - -#ifdef DEBUGGER - if (Settings.TraceDMA) - { - sprintf (String, "DMA[%d]: %s Mode: %d 0x%02X%04X->0x21%02X Bytes: %d (%s) V-Line:%ld", - Channel, d->TransferDirection ? "read" : "write", - d->TransferMode, d->ABank, d->AAddress, - d->BAddress, d->TransferBytes, - d->AAddressFixed ? "fixed" : - (d->AAddressDecrement ? "dec" : "inc"), - CPU.V_Counter); - if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) - sprintf (String, "%s VRAM: %04X (%d,%d) %s", String, - PPU.VMA.Address, - PPU.VMA.Increment, PPU.VMA.FullGraphicCount, - PPU.VMA.High ? "word" : "byte"); - - else - if (d->BAddress == 0x22 || d->BAddress == 0x3b) - - sprintf (String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, - PPU.CGFLIP); - else - if (d->BAddress == 0x04 || d->BAddress == 0x38) - sprintf (String, "%s OBJADDR: %04X", String, PPU.OAMAddr); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } -#endif - - if (!d->TransferDirection) - { - //reflects extra cycle used by DMA - CPU.Cycles += SLOW_ONE_CYCLE * (count+1); - S9xTrySyncAPUInDMA(); - - uint8 *base = GetBasePointer((d->ABank << 16) + d->AAddress); - uint16 p = d->AAddress; - int rem = count; - int b = 0; - count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p&MEMMAP_MASK)+1) : (MEMMAP_BLOCK_SIZE-(p&MEMMAP_MASK))); - bool8 inWRAM_DMA = FALSE; - - if (in_sa1_dma) - { - base = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - p = 0; - count = rem; - } - - if (in_sdd1_dma) - { - base = in_sdd1_dma; - p = 0; - count = rem; - } - - if (spc7110_dma) - { - base = spc7110_dma; - p = 0; - count = rem; - } - inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && - (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); - while(1){ - if(count>rem) count=rem; - rem -= count; - if (inc > 0) - d->AAddress += count; - else if (inc < 0) - d->AAddress -= count; - //CPU.InWRAM_DMA = (base>=Memory.RAM && baseTransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) - { - do - { - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else if (d->TransferMode == 1 || d->TransferMode == 5) - { - // This is a variation on Duff's Device. It is legal C/C++, - // see http://www.lysator.liu.se/c/duffs-device.html - switch(b){ - default: - while (count > 1) - { - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - count--; + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + p += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + return FALSE; \ + } - case 1: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count --; - } - } - if (count == 1) - { - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - b = 1; - } else { - b = 0; - } - } - else if (d->TransferMode == 3 || d->TransferMode == 7) - { - switch(b){ - default: - do - { - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 1; - break; - } + while (1) + { + if (count > rem) + count = rem; + rem -= count; - case 1: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 2; - break; - } + CPU.InWRAMDMAorHDMA = inWRAM_DMA; - case 2: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 3; - break; - } + if (!base) + { + // DMA SLOW PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + // This is a variation on Duff's Device. It is legal C/C++. + switch (b) + { + default: + while (count > 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; - case 3: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - if(--count<=0){ - b = 0; - break; - } - } while (1); - } - } - else if (d->TransferMode == 4) - { - switch(b){ - default: - do - { - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 1; - break; - } + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + count--; + } + } - case 1: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 2; - break; - } + if (count == 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } - case 2: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2102 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 3; - break; - } + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } - case 3: - Work = S9xGetByte((d->ABank << 16) + p); - S9xSetPPU (Work, 0x2103 + d->BAddress); - p += inc; - CHECK_SOUND(); - if (--count <= 0){ - b = 0; - break; - } - } while (1); - } - } - else - { -#ifdef DEBUGGER - // if (Settings.TraceDMA) - { - sprintf (String, "Unknown DMA transfer mode: %d on channel %d\n", - d->TransferMode, Channel); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } -#endif - } - } else { - // DMA FAST PATH - if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) - { - switch (d->BAddress) - { - case 0x04: - do - { - Work = *(base + p); - REGISTER_2104(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x18: -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x19: -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x22: - do - { - Work = *(base + p); - REGISTER_2122(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x80: - if(!CPU.InWRAM_DMA){ - do - { - Work = *(base + p); - REGISTER_2180(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } else { - count=0; - } - break; - default: - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - } - } - else if (d->TransferMode == 1 || d->TransferMode == 5) - { - if (d->BAddress == 0x18) - { - // Write to V-RAM -#ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = TRUE; -#endif - if (!PPU.VMA.FullGraphicCount) - { - switch(b){ - default: - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - count--; + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } - case 1: - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - count--; - } - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - b = 1; - } else { - b = 0; - } - } - else - { - switch(b){ - default: - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - count--; + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } - case 1: - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - count--; - } - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - b = 1; - } else { - b = 0; - } - } - } - else - { - // DMA mode 1 general case - switch(b){ - default: - while (count > 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - count--; + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } - case 1: - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count --; - } - } - if (count == 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - b = 1; - } else { - b = 0; - } - } - } - else if (d->TransferMode == 3 || d->TransferMode == 7) - { - switch(b){ - default: - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 1; - break; - } + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } - case 1: - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 2; - break; - } + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + else + { + // DMA FAST PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + switch (d->BAddress) + { + case 0x04: // OAMDATA + do + { + Work = *(base + p); + REGISTER_2104(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); - case 2: - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 3; - break; - } + break; - case 3: - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - if(--count<=0){ - b = 0; - break; - } - } while (1); - } - } - else if (d->TransferMode == 4) - { - switch(b){ - default: - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 1; - break; - } + case 0x18: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } - case 1: - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 2; - break; - } + break; - case 2: - Work = *(base + p); - S9xSetPPU (Work, 0x2102 + d->BAddress); - p += inc; - if (--count <= 0){ - b = 3; - break; - } + case 0x19: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } - case 3: - Work = *(base + p); - S9xSetPPU (Work, 0x2103 + d->BAddress); - p += inc; - CHECK_SOUND(); - if (--count <= 0){ - b = 0; - break; - } - } while (1); - } - } - else - { -#ifdef DEBUGGER - // if (Settings.TraceDMA) - { - sprintf (String, "Unknown DMA transfer mode: %d on channel %d\n", - d->TransferMode, Channel); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } -#endif - } - } - if(rem<=0) break; - base = GetBasePointer((d->ABank << 16) + d->AAddress); - count=MEMMAP_BLOCK_SIZE; + break; + + case 0x22: // CGDATA + do + { + Work = *(base + p); + REGISTER_2122(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + + break; + + case 0x80: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + do + { + Work = *(base + p); + REGISTER_2180(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + } + + break; + + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + } while (--count > 0); + + break; + } + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + if (d->BAddress == 0x18) + { + // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + CHECK_SOUND(); + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + { + // DMA mode 1 general case + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + CHECK_SOUND(); + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + + if (rem <= 0) + break; + + base = GetBasePointer((d->ABank << 16) + d->AAddress); + count = MEMMAP_BLOCK_SIZE; inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && - (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); - } - } + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + } + + #undef UPDATE_COUNTERS + } else { - if(d->BAddress>0x80-4 && d->BAddress<=0x83 && !(d->ABank&0x40)){ - // REVERSE-DMA REALLY-SLOW PATH - do - { - switch (d->TransferMode) - { - case 0: - case 2: - case 6: - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - --count; - break; + // PPU -> CPU - case 1: - case 5: - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + return FALSE; \ + } - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) + { + // REVERSE-DMA REALLY-SLOW PATH + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - case 3: - case 7: - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + break; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + case 1: + case 5: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + break; - case 4: - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + case 3: + case 7: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2102 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - CPU.InWRAM_DMA = (d->AAddress<0x2000); - Work = S9xGetPPU (0x2103 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - default: -#ifdef DEBUGGER - if (1) //Settings.TraceDMA) - { - sprintf (String, "Unknown DMA transfer mode: %d on channel %d\n", - d->TransferMode, Channel); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } -#endif - count = 0; - break; - } - CHECK_SOUND(); - } while (count); - } else { - // REVERSE-DMA FASTER PATH - CPU.InWRAM_DMA = (d->ABank==0x7e || d->ABank==0x7f); - do - { - switch (d->TransferMode) - { - case 0: - case 2: - case 6: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - --count; - break; + break; - case 1: - case 5: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + case 4: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - case 3: - case 7: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + break; - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } - case 4: - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + break; + } - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + CHECK_SOUND(); + } while (count); + } + else + { + // REVERSE-DMA FASTER PATH + CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f); + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - Work = S9xGetPPU (0x2102 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; + break; - Work = S9xGetPPU (0x2103 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; + case 1: + case 5: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; - default: -#ifdef DEBUGGER - if (1) //Settings.TraceDMA) - { - sprintf (String, "Unknown DMA transfer mode: %d on channel %d\n", - d->TransferMode, Channel); - S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String); - } -#endif - count = 0; - break; - } - CHECK_SOUND(); - } while(count); - } - } + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; - while (CPU.Cycles >= CPU.NextEvent) - S9xDoHEventProcessing (); - if ((CPU.Cycles >= Timings.WRAMRefreshPos) && (CPU.Cycles < (Timings.WRAMRefreshPos + SNES_WRAM_REFRESH_CYCLES))) - { - int32 mc = Timings.WRAMRefreshPos + SNES_WRAM_REFRESH_CYCLES - CPU.Cycles; - S9xCheckMissingHTimerPositionRange(CPU.Cycles, mc); - CPU.Cycles += mc; + break; + + case 3: + case 7: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } + + break; + } + + CHECK_SOUND(); + } while (count); + } } - - S9xTrySyncAPUInDMA(); - - if(Settings.SPC7110&&spc7110_dma) + + // If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger + // after the DMA completes (even if /NMI goes high again before the DMA + // completes). In this case, there is a 24-30 cycle delay between the end of DMA + // and the NMI handler, time enough for an instruction or two. + if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff)) + { + Timings.NMITriggerPos = CPU.Cycles + 30; + if (Timings.NMITriggerPos >= Timings.H_Max) + Timings.NMITriggerPos -= Timings.H_Max; + } + + // Release the memory used in SPC7110 DMA + if (Settings.SPC7110) { - if(spc7110_dma&&s7_wrap) + if (spc7110_dma && s7_wrap) delete [] spc7110_dma; } -update_address: - d->TransferBytes = 0; +#if 1 + // sanity check + if (d->TransferBytes != 0) + fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); +#endif - CPU.InDMA = CPU.InWRAM_DMA = FALSE; + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + + return TRUE; } static inline bool8 HDMAReadLineCount(int d){ @@ -1280,7 +1403,12 @@ static inline bool8 HDMAReadLineCount(int d){ DMA[d].Repeat = FALSE; DMA[d].LineCount = 128; if(DMA[d].HDMAIndirectAddressing){ - CPU.Cycles+=SLOW_ONE_CYCLE; + if(IPPU.HDMA&(0xfe<HDMAIndirectAddressing) { ShiftedIBank = (p->IndirectBank << 16); IAddr = p->IndirectAddress; @@ -1390,13 +1521,13 @@ uint8 S9xDoHDMA (uint8 byte) } #ifdef DEBUGGER - if (Settings.TraceSoundDSP && p->DoTransfer && + if (Settings.TraceSoundDSP && p->DoTransfer && p->BAddress >= 0x40 && p->BAddress <= 0x43) S9xTraceSoundDSP ("Spooling data!!!\n"); if (Settings.TraceHDMA && p->DoTransfer) { sprintf (String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", - p-DMA, p->TransferDirection? "read" : "write", + p-DMA, p->ReverseTransfer? "read" : "write", p->TransferMode, ShiftedIBank+IAddr, p->BAddress, p->HDMAIndirectAddressing ? "ind" : "abs", p->LineCount, @@ -1406,12 +1537,12 @@ uint8 S9xDoHDMA (uint8 byte) } #endif - if (!p->TransferDirection) { + if (!p->ReverseTransfer) { if((IAddr&MEMMAP_MASK)+HDMA_ModeByteCounts[p->TransferMode]>=MEMMAP_BLOCK_SIZE){ // HDMA REALLY-SLOW PATH HDMAMemPointers[d]=NULL; #define DOBYTE(Addr, RegOff) \ - CPU.InWRAM_DMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ S9xSetPPU (S9xGetByte(ShiftedIBank + ((uint16)(Addr))), 0x2100 + p->BAddress + RegOff); switch (p->TransferMode) { case 0: @@ -1454,7 +1585,7 @@ uint8 S9xDoHDMA (uint8 byte) } #undef DOBYTE } else { - CPU.InWRAM_DMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && IAddr<0x2000)); + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && IAddr<0x2000)); if(!HDMAMemPointers[d]){ // HDMA SLOW PATH uint32 Addr = ShiftedIBank + IAddr; @@ -1549,7 +1680,7 @@ uint8 S9xDoHDMA (uint8 byte) // bother with faster paths. HDMAMemPointers[d]=NULL; #define DOBYTE(Addr, RegOff) \ - CPU.InWRAM_DMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank==0x7e0000 || ShiftedIBank==0x7f0000 || (!(ShiftedIBank&0x400000) && ((uint16)(Addr))<0x2000)); \ S9xSetByte (S9xGetPPU(0x2100 + p->BAddress + RegOff), ShiftedIBank + ((uint16)(Addr))); switch (p->TransferMode) { case 0: @@ -1610,22 +1741,25 @@ uint8 S9xDoHDMA (uint8 byte) } else { CPU.Cycles += SLOW_ONE_CYCLE; } - - S9xTrySyncAPUInDMA(); } } - CPU.InDMA=CPU.InWRAM_DMA=FALSE; - + + S9xAPUExecute(); + + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InDMA; + CPU.InWRAMDMAorHDMA = temp; + return (byte); } void S9xResetDMA () { int d; for (d = 0; d < 8; d++) { - DMA[d].TransferDirection = FALSE; - DMA[d].HDMAIndirectAddressing = FALSE; + DMA[d].ReverseTransfer = TRUE; + DMA[d].HDMAIndirectAddressing = TRUE; DMA[d].AAddressFixed = TRUE; - DMA[d].AAddressDecrement = FALSE; + DMA[d].AAddressDecrement = TRUE; DMA[d].TransferMode = 7; DMA[d].BAddress = 0xff; DMA[d].AAddress = 0xffff; @@ -1637,5 +1771,6 @@ void S9xResetDMA () { DMA[d].LineCount = 0x7f; DMA[d].UnknownByte = 0xff; DMA[d].DoTransfer = FALSE; + DMA[d].UnusedBit43x0 = 1; } } diff --git a/source/snes9x/dma.h b/source/snes9x/dma.h index 147a5ad..38c5666 100644 --- a/source/snes9x/dma.h +++ b/source/snes9x/dma.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _DMA_H_ #define _DMA_H_ @@ -149,7 +168,7 @@ START_EXTERN_C void S9xResetDMA (); uint8 S9xDoHDMA (uint8); void S9xStartHDMA (); -void S9xDoDMA (uint8); +bool8 S9xDoDMA (uint8); END_EXTERN_C #endif diff --git a/source/snes9x/dsp1.cpp b/source/snes9x/dsp1.cpp index 8a840f0..2ce54c9 100644 --- a/source/snes9x/dsp1.cpp +++ b/source/snes9x/dsp1.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,11 +158,14 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "snes9x.h" #include "dsp1.h" #include "missing.h" #include "memmap.h" #include +#include #include "dsp1emu.c.inc" #include "dsp2emu.c.inc" @@ -158,7 +178,7 @@ uint8 (*GetDSP)(uint16)=&DSP1GetByte; void S9xInitDSP1 () { static bool8 init = FALSE; - + if (!init) { InitDSP (); @@ -169,14 +189,14 @@ void S9xInitDSP1 () void S9xResetDSP1 () { S9xInitDSP1 (); - + DSP1.waiting4command = TRUE; DSP1.in_count = 0; DSP1.out_count = 0; DSP1.in_index = 0; DSP1.out_index = 0; DSP1.first_parameter = TRUE; - + DSP4.waiting4command = TRUE; //printf("DSP-4 Reset\n"); } @@ -184,7 +204,7 @@ void S9xResetDSP1 () uint8 S9xGetDSP (uint16 address) { uint8 t; - + #ifdef DEBUGGER if (Settings.TraceDSP) { @@ -192,7 +212,7 @@ uint8 S9xGetDSP (uint16 address) S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); } #endif - + t=(*GetDSP)(address); //DSP1GetByte(address); return (t); @@ -214,14 +234,14 @@ void S9xSetDSP (uint8 byte, uint16 address) void DSP1SetByte(uint8 byte, uint16 address) { - if( (address & 0xf000) == 0x6000 || (address & 0x7fff) < 0x4000 ) + if (address < DSP1.boundary) { // if ((address & 1) == 0) // { if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) { DSP1.out_count--; - DSP1.out_index++; + DSP1.out_index++; return; } else if (DSP1.waiting4command) @@ -255,7 +275,7 @@ void DSP1SetByte(uint8 byte, uint16 address) case 0x0a: DSP1.in_count = 1; break; case 0x3a: case 0x2a: - case 0x1a: + case 0x1a: DSP1. command =0x1a; DSP1.in_count = 1; break; case 0x16: @@ -318,7 +338,7 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.first_parameter = FALSE; DSP1.in_index++; } - + if (DSP1.waiting4command || (DSP1.first_parameter && byte == 0x80)) { @@ -349,9 +369,9 @@ void DSP1SetByte(uint8 byte, uint16 address) case 0x00: // Multiple Op00Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op00Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - + DSPOp00 (); - + DSP1.out_count = 2; DSP1.output [0] = Op00Result&0xFF; DSP1.output [1] = (Op00Result>>8)&0xFF; @@ -360,111 +380,111 @@ void DSP1SetByte(uint8 byte, uint16 address) case 0x20: // Multiple Op20Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op20Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - + DSPOp20 (); - + DSP1.out_count = 2; DSP1.output [0] = Op20Result&0xFF; DSP1.output [1] = (Op20Result>>8)&0xFF; break; - + case 0x30: case 0x10: // Inverse Op10Coefficient = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op10Exponent = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - + DSPOp10 (); - + DSP1.out_count = 4; DSP1.output [0] = (uint8) (((int16) Op10CoefficientR)&0xFF); DSP1.output [1] = (uint8) ((((int16) Op10CoefficientR)>>8)&0xFF); DSP1.output [2] = (uint8) (((int16) Op10ExponentR)&0xff); DSP1.output [3] = (uint8) ((((int16) Op10ExponentR)>>8)&0xff); break; - + case 0x24: case 0x04: // Sin and Cos of angle Op04Angle = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op04Radius = (uint16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - + DSPOp04 (); - + DSP1.out_count = 4; DSP1.output [0] = (uint8) (Op04Sin&0xFF); DSP1.output [1] = (uint8) ((Op04Sin>>8)&0xFF); DSP1.output [2] = (uint8) (Op04Cos&0xFF); DSP1.output [3] = (uint8) ((Op04Cos>>8)&0xFF); break; - + case 0x08: // Radius Op08X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op08Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op08Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp08 (); - + DSP1.out_count = 4; - DSP1.output [0] = (uint8) (((int16) Op08Ll)&0xFF); - DSP1.output [1] = (uint8) ((((int16) Op08Ll)>>8)&0xFF); + DSP1.output [0] = (uint8) (((int16) Op08Ll)&0xFF); + DSP1.output [1] = (uint8) ((((int16) Op08Ll)>>8)&0xFF); DSP1.output [2] = (uint8) (((int16) Op08Lh)&0xFF); DSP1.output [3] = (uint8) ((((int16) Op08Lh)>>8)&0xFF); break; - + case 0x18: // Range - + Op18X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op18Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op18Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op18R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - + DSPOp18 (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op18D&0xFF); DSP1.output [1] = (uint8) ((Op18D>>8)&0xFF); break; case 0x38: // Range - + Op38X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op38Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op38Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op38R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - + DSPOp38 (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op38D&0xFF); DSP1.output [1] = (uint8) ((Op38D>>8)&0xFF); break; - + case 0x28: // Distance (vector length) Op28X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op28Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op28Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp28 (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op28R&0xFF); DSP1.output [1] = (uint8) ((Op28R>>8)&0xFF); break; - + case 0x2c: case 0x0c: // Rotate (2D rotate) Op0CA = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op0CX1 = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op0CY1 = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp0C (); - + DSP1.out_count = 4; DSP1.output [0] = (uint8) (Op0CX2&0xFF); DSP1.output [1] = (uint8) ((Op0CX2>>8)&0xFF); DSP1.output [2] = (uint8) (Op0CY2&0xFF); DSP1.output [3] = (uint8) ((Op0CY2>>8)&0xFF); break; - + case 0x3c: case 0x1c: // Polar (3D rotate) Op1CZ = (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); @@ -474,9 +494,9 @@ void DSP1SetByte(uint8 byte, uint16 address) Op1CXBR = (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); Op1CYBR = (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); Op1CZBR = (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - + DSPOp1C (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op1CXAR&0xFF); DSP1.output [1] = (uint8) ((Op1CXAR>>8)&0xFF); @@ -485,7 +505,7 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op1CZAR&0xFF); DSP1.output [5] = (uint8) ((Op1CZAR>>8)&0xFF); break; - + case 0x32: case 0x22: case 0x12: @@ -497,9 +517,9 @@ void DSP1SetByte(uint8 byte, uint16 address) Op02LES = (short)(DSP1.parameters [8]|(DSP1.parameters[9]<<8)); Op02AAS = (unsigned short)(DSP1.parameters [10]|(DSP1.parameters[11]<<8)); Op02AZS = (unsigned short)(DSP1.parameters [12]|(DSP1.parameters[13]<<8)); - + DSPOp02 (); - + DSP1.out_count = 8; DSP1.output [0] = (uint8) (Op02VOF&0xFF); DSP1.output [1] = (uint8) ((Op02VOF>>8)&0xFF); @@ -510,15 +530,15 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [6] = (uint8) (Op02CY&0xFF); DSP1.output [7] = (uint8) ((Op02CY>>8)&0xFF); break; - + case 0x3a: //1a Mirror case 0x2a: //1a Mirror case 0x1a: // Raster mode 7 matrix data case 0x0a: Op0AVS = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - + DSPOp0A (); - + DSP1.out_count = 8; DSP1.output [0] = (uint8) (Op0AA&0xFF); DSP1.output [2] = (uint8) (Op0AB&0xFF); @@ -530,7 +550,7 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [7] = (uint8) ((Op0AD>>8)&0xFF); DSP1.in_index=0; break; - + case 0x16: case 0x26: case 0x36: @@ -538,9 +558,9 @@ void DSP1SetByte(uint8 byte, uint16 address) Op06X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op06Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op06Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp06 (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op06H&0xff); DSP1.output [1] = (uint8) ((Op06H>>8)&0xFF); @@ -549,23 +569,23 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op06M&0xFF); DSP1.output [5] = (uint8) ((Op06M>>8)&0xFF); break; - + case 0x1e: case 0x2e: case 0x3e: case 0x0e: // Target Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - + DSPOp0E (); - + DSP1.out_count = 4; DSP1.output [0] = (uint8) (Op0EX&0xFF); DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); DSP1.output [2] = (uint8) (Op0EY&0xFF); DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); break; - + // Extra commands used by Pilot Wings case 0x05: case 0x35: @@ -575,30 +595,30 @@ void DSP1SetByte(uint8 byte, uint16 address) Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - + DSPOp01 (); break; - - case 0x15: + + case 0x15: case 0x11: // Set attitude matrix B Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); - + DSPOp11 (); break; - + case 0x25: case 0x21: // Set attitude matrix C Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - + DSPOp21 (); break; - + case 0x09: case 0x39: case 0x3d: @@ -606,9 +626,9 @@ void DSP1SetByte(uint8 byte, uint16 address) Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp0D (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op0DF&0xFF); DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); @@ -617,15 +637,15 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op0DU&0xFF); DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); break; - + case 0x19: case 0x1d: // Objective matrix B Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp1D (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op1DF&0xFF); DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); @@ -634,15 +654,15 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op1DU&0xFF); DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); break; - + case 0x29: case 0x2d: // Objective matrix C Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp2D (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op2DF&0xFF); DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); @@ -651,15 +671,15 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op2DU&0xFF); DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); break; - + case 0x33: case 0x03: // Subjective matrix A Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp03 (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op03X&0xFF); DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); @@ -668,14 +688,14 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op03Z&0xFF); DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); break; - + case 0x13: // Subjective matrix B Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp13 (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op13X&0xFF); DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); @@ -684,14 +704,14 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op13Z&0xFF); DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); break; - + case 0x23: // Subjective matrix C Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp23 (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op23X&0xFF); DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); @@ -700,55 +720,55 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op23Z&0xFF); DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); break; - + case 0x3b: case 0x0b: Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp0B (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op0BS&0xFF); DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); break; - + case 0x1b: Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp1B (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op1BS&0xFF); DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); break; - + case 0x2b: Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - + DSPOp2B (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8) (Op2BS&0xFF); DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); break; - + case 0x34: - case 0x14: + case 0x14: Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - + DSPOp14 (); - + DSP1.out_count = 6; DSP1.output [0] = (uint8) (Op14Zrr&0xFF); DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); @@ -757,30 +777,30 @@ void DSP1SetByte(uint8 byte, uint16 address) DSP1.output [4] = (uint8) (Op14Yrr&0xFF); DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); break; - + case 0x27: case 0x2F: Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - + DSPOp2F (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8)(Op2FSize&0xFF); DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); break; - - + + case 0x07: case 0x0F: Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - + DSPOp0F (); - + DSP1.out_count = 2; DSP1.output [0] = (uint8)(Op0FPass&0xFF); DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); break; - + default: break; } @@ -793,9 +813,7 @@ void DSP1SetByte(uint8 byte, uint16 address) uint8 DSP1GetByte(uint16 address) { uint8 t; - if ((address & 0xf000) == 0x6000 || -// (address >= 0x8000 && address < 0xc000)) - (address&0x7fff) < 0x4000) + if (address < DSP1.boundary) { if (DSP1.out_count) { @@ -880,7 +898,7 @@ void DSP2SetByte(uint8 byte, uint16 address) // DSP1.first_parameter = FALSE; DSP1.in_index++; } - + if (DSP1.in_count==DSP1.in_index) { //DSP1.parameters [DSP1.in_index] |= (byte << 8); @@ -1016,7 +1034,7 @@ void DSP4SetByte(uint8 byte, uint16 address) InitDSP4(); DSP4_init=TRUE; } - if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + if (address < DSP1.boundary) { dsp4_byte=byte; dsp4_address=address; @@ -1026,7 +1044,7 @@ void DSP4SetByte(uint8 byte, uint16 address) uint8 DSP4GetByte(uint16 address) { - if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + if (address < DSP1.boundary) { dsp4_address=address; DSP4_GetByte(); diff --git a/source/snes9x/dsp1.h b/source/snes9x/dsp1.h index 9d04f0f..8a1074b 100644 --- a/source/snes9x/dsp1.h +++ b/source/snes9x/dsp1.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _DSP1_H_ #define _DSP1_H_ @@ -161,6 +180,16 @@ void DSP3_Reset(); void DSP4SetByte(uint8 byte, uint16 address); uint8 DSP4GetByte(uint16 address); +enum +{ + M_DSP1_LOROM_S, + M_DSP1_LOROM_L, + M_DSP1_HIROM, + M_DSP2_LOROM, + M_DSP3_LOROM, + M_DSP4_LOROM +}; + struct SDSP1 { uint8 version; bool8 waiting4command; @@ -172,14 +201,22 @@ struct SDSP1 { uint32 out_index; uint8 parameters [512]; uint8 output [512]; + + uint8 temp_save_data [406]; + uint32 maptype; + uint32 boundary; }; START_EXTERN_C void S9xResetDSP1 (); uint8 S9xGetDSP (uint16 Address); void S9xSetDSP (uint8 Byte, uint16 Address); -END_EXTERN_C +void S9xPreSaveDSP1(); +void S9xPostLoadDSP1(); extern struct SDSP1 DSP1; +END_EXTERN_C + + #endif diff --git a/source/snes9x/dsp1emu.c.inc b/source/snes9x/dsp1emu.c.inc index d8377aa..cf44240 100644 --- a/source/snes9x/dsp1emu.c.inc +++ b/source/snes9x/dsp1emu.c.inc @@ -1213,3 +1213,182 @@ void DSPOp2F() { Op2FSize=0x100; } + + + +// FIXME: many of these are unnecessary to save. But some of them are necessary, like Matrix* and maybe VPlane_* +// TODO: move the necessary ones into a global structure so it's not as ugly to save +#define SAVE_OR_LOAD_THE_VARIABLES() \ +S(Op00Multiplicand); \ +S(Op00Multiplier); \ +S(Op00Result); \ +S(Op20Multiplicand); \ +S(Op20Multiplier); \ +S(Op20Result); \ +S(Op10Coefficient); \ +S(Op10Exponent); \ +S(Op10CoefficientR); \ +S(Op10ExponentR); \ +S(Op04Angle); \ +S(Op04Radius); \ +S(Op04Sin); \ +S(Op04Cos); \ +S(Op0CA); \ +S(Op0CX1); \ +S(Op0CY1); \ +S(Op0CX2); \ +S(Op0CY2); \ +S(CentreX); \ +S(CentreY); \ +S(VOffset); \ +S(VPlane_C); \ +S(VPlane_E); \ +S(SinAas); \ +S(CosAas); \ +S(SinAzs); \ +S(CosAzs); \ +S(SinAZS); \ +S(CosAZS); \ +S(SecAZS_C1); \ +S(SecAZS_E1); \ +S(SecAZS_C2); \ +S(SecAZS_E2); \ +S(Nx); S(Ny); S(Nz); \ +S(Gx); S(Gy); S(Gz); \ +S(C_Les); S(E_Les); S(G_Les); \ +S(Op02FX); \ +S(Op02FY); \ +S(Op02FZ); \ +S(Op02LFE); \ +S(Op02LES); \ +S(Op02AAS); \ +S(Op02AZS); \ +S(Op02VOF); \ +S(Op02VVA); \ +S(Op02CX); \ +S(Op02CY); \ +S(Op0AVS); \ +S(Op0AA); \ +S(Op0AB); \ +S(Op0AC); \ +S(Op0AD); \ +S(Op06X); \ +S(Op06Y); \ +S(Op06Z); \ +S(Op06H); \ +S(Op06V); \ +S(Op06M); \ +S(matrixC); \ +S(matrixB); \ +S(matrixA); \ +S(Op01m); \ +S(Op01Zr); \ +S(Op01Xr); \ +S(Op01Yr); \ +S(Op11m); \ +S(Op11Zr); \ +S(Op11Xr); \ +S(Op11Yr); \ +S(Op21m); \ +S(Op21Zr); \ +S(Op21Xr); \ +S(Op21Yr); \ +S(Op0DX); \ +S(Op0DY); \ +S(Op0DZ); \ +S(Op0DF); \ +S(Op0DL); \ +S(Op0DU); \ +S(Op1DX); \ +S(Op1DY); \ +S(Op1DZ); \ +S(Op1DF); \ +S(Op1DL); \ +S(Op1DU); \ +S(Op2DX); \ +S(Op2DY); \ +S(Op2DZ); \ +S(Op2DF); \ +S(Op2DL); \ +S(Op2DU); \ +S(Op03F); \ +S(Op03L); \ +S(Op03U); \ +S(Op03X); \ +S(Op03Y); \ +S(Op03Z); \ +S(Op13F); \ +S(Op13L); \ +S(Op13U); \ +S(Op13X); \ +S(Op13Y); \ +S(Op13Z); \ +S(Op23F); \ +S(Op23L); \ +S(Op23U); \ +S(Op23X); \ +S(Op23Y); \ +S(Op23Z); \ +S(Op14Zr); \ +S(Op14Xr); \ +S(Op14Yr); \ +S(Op14U); \ +S(Op14F); \ +S(Op14L); \ +S(Op14Zrr); \ +S(Op14Xrr); \ +S(Op14Yrr); \ +S(Op0EH); \ +S(Op0EV); \ +S(Op0EX); \ +S(Op0EY); \ +S(Op0BX); \ +S(Op0BY); \ +S(Op0BZ); \ +S(Op0BS); \ +S(Op1BX); \ +S(Op1BY); \ +S(Op1BZ); \ +S(Op1BS); \ +S(Op2BX); \ +S(Op2BY); \ +S(Op2BZ); \ +S(Op2BS); \ +S(Op08X); S(Op08Y); S(Op08Z); S(Op08Ll); S(Op08Lh); \ +S(Op18X); S(Op18Y); S(Op18Z); S(Op18R); S(Op18D); \ +S(Op38X); S(Op38Y); S(Op38Z); S(Op38R); S(Op38D); \ +S(Op28X); \ +S(Op28Y); \ +S(Op28Z); \ +S(Op28R); \ +S(Op1CX); S(Op1CY); S(Op1CZ); \ +S(Op1CXBR); S(Op1CYBR); S(Op1CZBR); S(Op1CXAR); S(Op1CYAR); S(Op1CZAR); \ +S(Op1CX1); \ +S(Op1CY1); \ +S(Op1CZ1); \ +S(Op1CX2); \ +S(Op1CY2); \ +S(Op1CZ2); \ +S(Op0FRamsize); \ +S(Op0FPass); \ +S(Op2FUnknown); \ +S(Op2FSize); \ +// end + +void S9xPreSaveDSP1() +{ + int i = 0; +#define S(x) {memcpy(DSP1.temp_save_data + i, &(x), sizeof(x)); i += sizeof(x);} + SAVE_OR_LOAD_THE_VARIABLES(); +#undef S + assert(i == sizeof(DSP1.temp_save_data)); +} + +void S9xPostLoadDSP1() +{ + int i = 0; +#define S(x) {memcpy(&(x), DSP1.temp_save_data + i, sizeof(x)); i += sizeof(x);} + SAVE_OR_LOAD_THE_VARIABLES(); +#undef S + assert(i == sizeof(DSP1.temp_save_data)); +} diff --git a/source/snes9x/dsp2emu.c.inc b/source/snes9x/dsp2emu.c.inc index 869ed81..7512b2d 100644 --- a/source/snes9x/dsp2emu.c.inc +++ b/source/snes9x/dsp2emu.c.inc @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -143,6 +160,8 @@ + + uint16 DSP2Op09Word1=0; uint16 DSP2Op09Word2=0; bool DSP2Op05HasLen=false; @@ -201,7 +220,7 @@ void DSP2_Op01 () { // Op01 size is always 32 bytes input and output. // The hardware does strange things if you vary the size. - + int j; unsigned char c0, c1, c2, c3; unsigned char *p1 = DSP1.parameters; @@ -299,7 +318,7 @@ void DSP2_Op0D() if ( (pixel_offset&1) == 0 ) pixelarray[i] = DSP1.parameters[pixel_offset>>1] >> 4; else - pixelarray[i] = DSP1.parameters[pixel_offset>>1] & 0x0f; + pixelarray[i] = DSP1.parameters[pixel_offset>>1] & 0x0f; } for ( i=0; i < DSP2Op0DOutLen; i++ ) diff --git a/source/snes9x/dsp3emu.c.inc b/source/snes9x/dsp3emu.c.inc index 7b120b9..06b91c8 100644 --- a/source/snes9x/dsp3emu.c.inc +++ b/source/snes9x/dsp3emu.c.inc @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef __cplusplus //C++ in C typedef unsigned char bool; @@ -1106,9 +1125,7 @@ void DSP3_OP1E_D( int16 move, int16 *lo, int16 *hi ) void DSP3_OP1E_D1( int16 move, int16 *lo, int16 *hi ) { -#ifndef NGC - uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; -#endif + //uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; int16 Lo; int16 Hi; @@ -1232,7 +1249,7 @@ void DSP3_Command() void DSP3SetByte(uint8 byte, uint16 address) { - if ((address & 0xC000) == 0x8000) + if (address < DSP1.boundary) { if (DSP3_SR & 0x04) { @@ -1243,20 +1260,20 @@ void DSP3SetByte(uint8 byte, uint16 address) { DSP3_SR ^= 0x10; - if (DSP3_SR & 0x10) + if (DSP3_SR & 0x10) DSP3_DR = (DSP3_DR & 0xff00) + byte; else { DSP3_DR = (DSP3_DR & 0x00ff) + (byte << 8); (*SetDSP3)(); - } + } } } } uint8 DSP3GetByte(uint16 address) { - if ((address & 0xC000) == 0x8000) + if (address < DSP1.boundary) { uint8 byte; @@ -1269,7 +1286,7 @@ uint8 DSP3GetByte(uint16 address) { DSP3_SR ^= 0x10; - if (DSP3_SR & 0x10) + if (DSP3_SR & 0x10) byte = (uint8) (DSP3_DR); else { diff --git a/source/snes9x/dsp4emu.c.inc b/source/snes9x/dsp4emu.c.inc index 29a1696..2a65842 100644 --- a/source/snes9x/dsp4emu.c.inc +++ b/source/snes9x/dsp4emu.c.inc @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include diff --git a/source/snes9x/font.h b/source/snes9x/font.h index ad54c3f..1b126cc 100644 --- a/source/snes9x/font.h +++ b/source/snes9x/font.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + static char *font[] = { " . . . . .. . . ", " .#. .#.#. . . ... .#. . . .##. .#. .#. . . . . ", @@ -227,7 +246,7 @@ static char *font[] = { " .#.#. .##. .#. .###. .#. .#. .#. .###. .#. .#. .####. .##. .##. ", " .#. .. .#. ... . . . ... . . .... .. .. ", " . . ", -//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 " .... . . ... . . . .... . . . .. . ..... . . . ", " .####. .#. ..#.. .###. ...#. ..#.. ..#.. .####. .#... .... .#.#. .##..#. .#####. .#... .#. .#. ", " .... ...#. .#. .#####. .#. .#####. .#####. .#####. .#..#. .####. .####. .#####. .. .#. ....#. .#####. .#. .#. ", @@ -237,24 +256,24 @@ static char *font[] = { " .#. .#. .##. .#####. .#..#. .#..#. .#. .#. .#. .####. .#. .###. .#. .#. .###. .###. ", " . . .. ..... . . . . . . . .... . ... . . ... ... ", " ", -//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 " .... .. . . . ... . . ... .... . . . ..... . . ", " .####. ..##. .#.#.#. .###. .#. ..#.. .###. .####. ..#.. .#. . . .#. .. .#####. .#. ..#.. ..... ", " .#..#. .###. .#.#.#. ..... .#. .#####. ... ...#. .#####. .#. .#.#. .#..##. ....#. .#.#. .#####. .#####. ", -" .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", +" .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", ".#...#. .####. . ..#. ..#.. .#.#. .#. .#. .###. .#. .#. .#. .#.. .#. . .#. .#.#.#. .#.#. ", " . .#. ..#. ...#. .#. .#.. ..#. ..... .#.#. .#.#.#. .#. .#. .#. .#.... ..#. .#. .#.#.#. .#. ", " .#. .##. .###. .#. .#. .##. .#####. .#. .#. ..#.. .#. .#. .#. .####. .##. .#. ..#.. .#. ", " . .. ... . . .. ..... . . . . . . .... .. . . . ", " ", -//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 +//2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 " .. . . ... . .... .... . . . . . ..... . . . . ", " .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", " ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", -" .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", +" .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", " ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", " .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", -" ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", +" ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", " . . .. ... . ..... .... .. ... . .. .. . . .. ... ", " ", @@ -279,6 +298,3 @@ static char *font[] = { " " }; -static int font_width = 8; -static int font_height = 9; - diff --git a/source/snes9x/fxdbg.cpp b/source/snes9x/fxdbg.cpp index d7b0d4c..f51c94d 100644 --- a/source/snes9x/fxdbg.cpp +++ b/source/snes9x/fxdbg.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "fxemu.h" #include "fxinst.h" #include @@ -173,7 +192,7 @@ extern struct FxRegs_s GSU; in this debug function. (See the diffrence of how the values vPipe1 and vPipe2 are read, compared to the values vByte1 and vByte2) - + */ void FxPipeString(char * pvString) { @@ -182,11 +201,11 @@ void FxPipeString(char * pvString) const char *m = fx_apvMnemonicTable[vOpcode]; uint8 vPipe1,vPipe2,vByte1,vByte2; uint8 vPipeBank = GSU.vPipeAdr >> 16; - + /* The next two bytes after the pipe's address */ vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+1)]; vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr+2)]; - + /* The actual next two bytes to be read */ vByte1 = PRGBANK(USEX16(R15)); vByte2 = PRGBANK(USEX16(R15+1)); @@ -195,7 +214,7 @@ void FxPipeString(char * pvString) sprintf(pvString, "%02x:%04x %02x ", USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); p = &pvString[strlen(pvString)]; - + /* Check if it's a branch instruction */ if( PIPE >= 0x05 && PIPE <= 0x0f ) { @@ -244,7 +263,7 @@ const char *fx_apvMnemonicTable[] = "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", /* 30 - 3f */ "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", @@ -301,7 +320,7 @@ const char *fx_apvMnemonicTable[] = "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", /* 30 - 3f */ "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", @@ -358,7 +377,7 @@ const char *fx_apvMnemonicTable[] = "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", /* 30 - 3f */ "stw (r0)","stw (r1)","stw (r2)", "stw (r3)", "stw (r4)", "stw (r5)", "stw (r6)", "stw (r7)", @@ -415,7 +434,7 @@ const char *fx_apvMnemonicTable[] = "to r0", "to r1", "to r2", "to r3", "to r4", "to r5", "to r6", "to r7", "to r8", "to r9", "to r10", "to r11", "to r12", "to r13", "to r14", "to r15", /* 20 - 2f */ - "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", + "with r0", "with r1", "with r2", "with r3", "with r4", "with r5", "with r6", "with r7", "with r8", "with r9", "with r10", "with r11", "with r12", "with r13", "with r14", "with r15", /* 30 - 3f */ "stb (r0)","stb (r1)","stb (r2)", "stb (r3)", "stb (r4)", "stb (r5)", "stb (r6)", "stb (r7)", diff --git a/source/snes9x/fxemu.cpp b/source/snes9x/fxemu.cpp index d2b15d1..2b7e660 100644 --- a/source/snes9x/fxemu.cpp +++ b/source/snes9x/fxemu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "fxemu.h" #include "fxinst.h" #include @@ -234,7 +253,7 @@ static void fx_backupCache() memcpy(t1,&GSU.pvCache[i<<4],a); memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); - } + } } c = USEX16(c+16); v >>= 1; @@ -270,7 +289,7 @@ static void fx_restoreCache() memcpy(&GSU.pvCache[i<<4],t1,a); memcpy(t2,&GSU.avCacheBackup[(i<<4)+a],16-a); memcpy(&GSU.pvCache[(i<<4)+a],t2,16-a); - } + } } c = USEX16(c+16); v >>= 1; @@ -326,7 +345,7 @@ static void fx_readRegisterSpace() GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; - + /* Set bank pointers */ GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; @@ -378,7 +397,7 @@ void fx_dirtySCBR() void fx_computeScreenPointers () { - if (GSU.vMode != GSU.vPrevMode || + if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) { @@ -476,7 +495,7 @@ void fx_computeScreenPointers () case 0: for (i = 0; i < 32; i++) { - GSU.apvScreen[i] = GSU.pvScreenBase + + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 9) + ((i & 0xf) << 8); GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); } @@ -484,7 +503,7 @@ void fx_computeScreenPointers () case 1: for (i = 0; i < 32; i++) { - GSU.apvScreen[i] = GSU.pvScreenBase + + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 10) + ((i & 0xf) << 9); GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); } @@ -493,7 +512,7 @@ void fx_computeScreenPointers () case 3: for (i = 0; i < 32; i++) { - GSU.apvScreen[i] = GSU.pvScreenBase + + GSU.apvScreen[i] = GSU.pvScreenBase + ((i & 0x10) << 11) + ((i & 0xf) << 10); GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); } @@ -510,7 +529,7 @@ static void fx_writeRegisterSpace() { int i; uint8 *p; - + p = GSU.pvRegisters; for(i=0; i<16; i++) { @@ -527,7 +546,7 @@ static void fx_writeRegisterSpace() else CF(OV); if(GSU.vCarry) SF(CY); else CF(CY); - + p = GSU.pvRegisters; p[GSU_SFR] = (uint8)GSU.vStatusReg; p[GSU_SFR+1] = (uint8)(GSU.vStatusReg>>8); @@ -536,7 +555,7 @@ static void fx_writeRegisterSpace() p[GSU_RAMBR] = (uint8)GSU.vRamBankReg; p[GSU_CBR] = (uint8)GSU.vCacheBaseReg; p[GSU_CBR+1] = (uint8)(GSU.vCacheBaseReg>>8); - + fx_restoreCache(); } @@ -550,7 +569,7 @@ void FxReset(struct FxInit_s *psFxInfo) &fx_a_apfFunctionTable[0], &fx_r_apfFunctionTable[0], &fx_ar_apfFunctionTable[0], -#endif +#endif }; static void (**appfPlot[])() = { &fx_apfPlotTable[0], @@ -558,22 +577,22 @@ void FxReset(struct FxInit_s *psFxInfo) &fx_a_apfPlotTable[0], &fx_r_apfPlotTable[0], &fx_ar_apfPlotTable[0], -#endif +#endif }; static void (**appfOpcode[])() = { &fx_apfOpcodeTable[0], -#if 0 +#if 0 &fx_a_apfOpcodeTable[0], &fx_r_apfOpcodeTable[0], &fx_ar_apfOpcodeTable[0], -#endif +#endif }; /* Get function pointers for the current emulation mode */ fx_ppfFunctionTable = appfFunction[psFxInfo->vFlags & 0x3]; fx_ppfPlotTable = appfPlot[psFxInfo->vFlags & 0x3]; fx_ppfOpcodeTable = appfOpcode[psFxInfo->vFlags & 0x3]; - + /* Clear all internal variables */ memset((uint8*)&GSU,0,sizeof(struct FxRegs_s)); @@ -592,7 +611,7 @@ void FxReset(struct FxInit_s *psFxInfo) /* The GSU can't access more than 2mb (16mbits) */ if(GSU.nRomBanks > 0x20) GSU.nRomBanks = 0x20; - + /* Clear FxChip register space */ memset(GSU.pvRegisters,0,0x300); @@ -625,7 +644,7 @@ void FxReset(struct FxInit_s *psFxInfo) GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; } - + /* Start with a nop in the pipe */ GSU.vPipe = 0x01; @@ -640,7 +659,7 @@ static uint8 fx_checkStartAddress() /* Check if we start inside the cache */ if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) return TRUE; - + /* Check if we're in an unused area */ #if 0 if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) @@ -658,7 +677,7 @@ static uint8 fx_checkStartAddress() /* If not, we're in ROM, so check if the RON flag is set */ if(!(SCMR&(1<<4))) return FALSE; - + return TRUE; } @@ -729,7 +748,7 @@ int FxStepOver(uint32 nInstructions) return 0; #endif } - + if( PIPE >= 0xf0 ) GSU.vStepPoint = USEX16(R15+3); else if( (PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf) ) diff --git a/source/snes9x/fxemu.h b/source/snes9x/fxemu.h index 22f8d5a..a9e1ee4 100644 --- a/source/snes9x/fxemu.h +++ b/source/snes9x/fxemu.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _FXEMU_H_ #define _FXEMU_H_ 1 diff --git a/source/snes9x/fxinst.cpp b/source/snes9x/fxinst.cpp index 76ee3e8..9f45bcc 100644 --- a/source/snes9x/fxinst.cpp +++ b/source/snes9x/fxinst.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #define FX_DO_ROMBUFFER #include "fxemu.h" @@ -213,7 +232,7 @@ static void fx_cache() memcpy(GSU.pvCache,t1,i); memcpy(&GSU.pvCache[i],t2,512-i); } -#endif +#endif } R15++; CLRFLAGS; @@ -389,7 +408,7 @@ static void fx_alt2() { SF(ALT2); CF(B); R15++; } /* 3f - alt3 - set alt3 mode */ static void fx_alt3() { SF(ALT1); SF(ALT2); CF(B); R15++; } - + /* 40-4b - ldw (rn) - load word from RAM */ #define FX_LDW(reg) uint32 v; \ GSU.vLastRamAdr = GSU.avReg[reg]; \ @@ -450,7 +469,7 @@ static void fx_plot_2bit() c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; else c = (uint8)GSU.vColorReg; - + if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); v = 128 >> (x&7); @@ -495,7 +514,7 @@ static void fx_plot_4bit() R15++; CLRFLAGS; R1++; - + #ifdef CHECK_LIMITS if(y >= GSU.vScreenHeight) return; #endif @@ -556,7 +575,7 @@ static void fx_plot_8bit() R15++; CLRFLAGS; R1++; - + #ifdef CHECK_LIMITS if(y >= GSU.vScreenHeight) return; #endif @@ -1063,7 +1082,7 @@ static void fx_umult_r12() { FX_UMULT(12); } static void fx_umult_r13() { FX_UMULT(13); } static void fx_umult_r14() { FX_UMULT(14); } static void fx_umult_r15() { FX_UMULT(15); } - + /* 80-8f(ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate */ #define FX_MULT_I(imm) \ uint32 v = (uint32) (SEX8(SREG) * ((int32)imm)); \ @@ -1088,7 +1107,7 @@ static void fx_mult_i12() { FX_MULT_I(12); } static void fx_mult_i13() { FX_MULT_I(13); } static void fx_mult_i14() { FX_MULT_I(14); } static void fx_mult_i15() { FX_MULT_I(15); } - + /* 80-8f(ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate */ #define FX_UMULT_I(imm) \ uint32 v = USEX8(SREG) * ((uint32)imm); \ @@ -1113,7 +1132,7 @@ static void fx_umult_i12() { FX_UMULT_I(12); } static void fx_umult_i13() { FX_UMULT_I(13); } static void fx_umult_i14() { FX_UMULT_I(14); } static void fx_umult_i15() { FX_UMULT_I(15); } - + /* 90 - sbk - store word to last accessed RAM address */ static void fx_sbk() { @@ -1767,7 +1786,7 @@ void (*fx_apfOpcodeTable[])() = &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, /* 30 - 3f */ &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, @@ -1820,7 +1839,7 @@ void (*fx_apfOpcodeTable[])() = &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, /* 30 - 3f */ &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, @@ -1873,7 +1892,7 @@ void (*fx_apfOpcodeTable[])() = &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, /* 30 - 3f */ &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, @@ -1926,7 +1945,7 @@ void (*fx_apfOpcodeTable[])() = &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, /* 30 - 3f */ &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, diff --git a/source/snes9x/fxinst.h b/source/snes9x/fxinst.h index a95c552..e78e682 100644 --- a/source/snes9x/fxinst.h +++ b/source/snes9x/fxinst.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _FXINST_H_ #define _FXINST_H_ 1 @@ -155,20 +174,20 @@ * 3004 - R2 pixel plot Y position register * 3006 - R3 * 3008 - R4 lower 16 bit result of lmult - * 300a - R5 + * 300a - R5 * 300c - R6 multiplier for fmult and lmult * 300e - R7 fixed point texel X position for merge * 3010 - R8 fixed point texel Y position for merge - * 3012 - R9 - * 3014 - R10 + * 3012 - R9 + * 3014 - R10 * 3016 - R11 return address set by link * 3018 - R12 loop counter * 301a - R13 loop point address * 301c - R14 rom address for getb, getbh, getbl, getbs - * 301e - R15 program counter + * 301e - R15 program counter * * 3020-302f - unused - * + * * Other internal registers * 3030 - SFR status flag register (16bit) * 3032 - unused @@ -190,21 +209,21 @@ * 3100-32ff - CACHERAM 512 bytes of GSU cache memory * * SFR status flag register bits: - * 0 - + * 0 - * 1 Z Zero flag * 2 CY Carry flag * 3 S Sign flag * 4 OV Overflow flag * 5 G Go flag (set to 1 when the GSU is running) * 6 R Set to 1 when reading ROM using R14 address - * 7 - + * 7 - * 8 ALT1 Mode set-up flag for the next instruction * 9 ALT2 Mode set-up flag for the next instruction * 10 IL Immediate lower 8-bit flag * 11 IH Immediate higher 8-bit flag * 12 B Set to 1 when the WITH instruction is executed - * 13 - - * 14 - + * 13 - + * 14 - * 15 IRQ Set to 1 when GSU caused an interrupt * Set to 0 when read by 658c16 * @@ -212,13 +231,13 @@ * BRAMR = 1, BackupRAM is enabled * * CFGR control flags register bits: - * 0 - - * 1 - - * 2 - - * 3 - - * 4 - + * 0 - + * 1 - + * 2 - + * 3 - + * 4 - * 5 MS0 Multiplier speed, 0=standard, 1=high speed - * 6 - + * 6 - * 7 IRQ Set to 1 when GSU interrupt request is masked * * CLSR clock speed register bits: @@ -231,8 +250,8 @@ * 3 RAN RAM access control * 4 RON ROM access control * 5 HT1 screen height bit 2 - * 6 - - * 7 - + * 6 - + * 7 - * * RON = 0 SNES CPU has ROM access * RON = 1 GSU has ROM access @@ -295,16 +314,16 @@ struct FxRegs_s uint32 vZero; /* v == 0 */ uint32 vCarry; /* a value of 1 or 0 */ int32 vOverflow; /* (v >= 0x8000 || v < -0x8000) */ - + /* Other emulator variables */ - + int32 vErrorCode; uint32 vIllegalAddress; - + uint8 bBreakPoint; uint32 vBreakPoint; uint32 vStepPoint; - + uint8 * pvRegisters; /* 768 bytes located in the memory at address 0x3000 */ uint32 nRamBanks; /* Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) */ uint8 * pvRam; /* Pointer to FxRam */ @@ -315,14 +334,14 @@ struct FxRegs_s uint32 vPrevMode; /* Previous depth */ uint8 * pvScreenBase; uint8 * apvScreen[32]; /* Pointer to each of the 32 screen colums */ - int x[32]; + int32 x[32]; uint32 vScreenHeight; /* 128, 160, 192 or 256 (could be overriden by cmode) */ uint32 vScreenRealHeight; /* 128, 160, 192 or 256 */ uint32 vPrevScreenHeight; uint32 vScreenSize; void (*pfPlot)(); void (*pfRpix)(); - + uint8 * pvRamBank; /* Pointer to current RAM-bank */ uint8 * pvRomBank; /* Pointer to current ROM-bank */ uint8 * pvPrgBank; /* Pointer to current program ROM-bank */ diff --git a/source/snes9x/getset.h b/source/snes9x/getset.h index 219ff6f..aa61a78 100644 --- a/source/snes9x/getset.h +++ b/source/snes9x/getset.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _GETSET_H_ #define _GETSET_H_ @@ -164,7 +183,7 @@ INLINE uint8 S9xGetByte (uint32 Address) int block; uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - if(!CPU.InDMA) + if(!CPU.InDMAorHDMA) CPU.Cycles += Memory.MemorySpeed [block]; if (GetAddress >= (uint8 *) CMemory::MAP_LAST) @@ -175,11 +194,11 @@ INLINE uint8 S9xGetByte (uint32 Address) #endif return (*(GetAddress + (Address & 0xffff))); } - + switch ((pint) GetAddress) { case CMemory::MAP_PPU: - if(CPU.InDMA && (Address&0xff00)==0x2100) return OpenBus; + if(CPU.InDMAorHDMA && (Address&0xff00)==0x2100) return OpenBus; return (S9xGetPPU (Address & 0xffff)); case CMemory::MAP_CPU: return (S9xGetCPU (Address & 0xffff)); @@ -193,6 +212,9 @@ INLINE uint8 S9xGetByte (uint32 Address) //unbound & SRAMMask = Sram offset return (*(Memory.SRAM + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Memory.SRAMMask))); + case CMemory::MAP_LOROM_SRAM_B: + return (*(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB))); + case CMemory::MAP_RONLY_SRAM: case CMemory::MAP_HIROM_SRAM: return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + @@ -271,10 +293,10 @@ INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE) int block; uint8 *GetAddress = Memory.Map [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - if(!CPU.InDMA) + if(!CPU.InDMAorHDMA) CPU.Cycles += (Memory.MemorySpeed [block]<<1); - + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) { #ifdef CPU_SHUTDOWN @@ -287,7 +309,7 @@ INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE) switch ((pint) GetAddress) { case CMemory::MAP_PPU: - if(CPU.InDMA){ + if(CPU.InDMAorHDMA){ OpenBus=S9xGetByte (Address); return (OpenBus | (S9xGetByte (Address + 1) << 8)); } @@ -313,11 +335,20 @@ INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE) } else { /* no READ_WORD here, since if Memory.SRAMMask=0x7ff * then the high byte doesn't follow the low byte. */ - return + return (*(Memory.SRAM + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Memory.SRAMMask)))| ((*(Memory.SRAM + (((((Address+1)&0xFF0000)>>1) |((Address+1)&0x7FFF)) &Memory.SRAMMask)))<<8); } + case CMemory::MAP_LOROM_SRAM_B: + if(Multi.sramMaskB>=MEMMAP_MASK){ + return READ_WORD(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB)); + } else { + return + (*(Multi.sramB + ((((Address&0xFF0000)>>1) |(Address&0x7FFF)) &Multi.sramMaskB)))| + ((*(Multi.sramB + (((((Address+1)&0xFF0000)>>1) |((Address+1)&0x7FFF)) &Multi.sramMaskB)))<<8); + } + case CMemory::MAP_RONLY_SRAM: case CMemory::MAP_HIROM_SRAM: if(Memory.SRAMMask>=MEMMAP_MASK){ @@ -347,7 +378,7 @@ INLINE uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE) printf("reading spc7110 ROM (word) at %06X\n", Address); #endif return (S9xGetSPC7110Byte(Address)| - (S9xGetSPC7110Byte (Address+1))<<8); + (S9xGetSPC7110Byte (Address+1))<<8); case CMemory::MAP_SPC7110_DRAM: #ifdef SPC7110_DEBUG printf("reading Bank 50 (word)\n"); @@ -384,10 +415,10 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) int block; uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - if (!CPU.InDMA) + if (!CPU.InDMAorHDMA) CPU.Cycles += Memory.MemorySpeed [block]; - + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) { #ifdef CPU_SHUTDOWN @@ -404,11 +435,11 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) #endif return; } - + switch ((pint) SetAddress) { case CMemory::MAP_PPU: - if(CPU.InDMA && (Address&0xff00)==0x2100) return; + if(CPU.InDMAorHDMA && (Address&0xff00)==0x2100) return; S9xSetPPU (Byte, Address & 0xffff); return; @@ -431,7 +462,15 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) } return; - case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + *(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Multi.sramMaskB))=Byte; + CPU.SRAMModified = TRUE; + } + return; + + case CMemory::MAP_HIROM_SRAM: if (Memory.SRAMMask) { *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + @@ -526,7 +565,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w=WRAP_NONE, int block; uint8 *SetAddress = Memory.WriteMap [block = ((Address&0xffffff) >> MEMMAP_SHIFT)]; - if (!CPU.InDMA) + if (!CPU.InDMAorHDMA) CPU.Cycles += Memory.MemorySpeed [block] << 1; @@ -550,7 +589,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w=WRAP_NONE, switch ((pint) SetAddress) { case CMemory::MAP_PPU: - if(CPU.InDMA){ + if(CPU.InDMAorHDMA){ if((Address&0xff00)!=0x2100) S9xSetPPU((uint8)Word, Address&0xffff); if(((Address+1)&0xff00)!=0x2100) S9xSetPPU(Word>>8, (Address+1)&0xffff); return; @@ -602,19 +641,32 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w=WRAP_NONE, } return; + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) { + if(Multi.sramMaskB>=MEMMAP_MASK){ + WRITE_WORD(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))&Multi.sramMaskB), Word); + } else { + *(Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF))& Multi.sramMaskB)) = (uint8) Word; + *(Multi.sramB + (((((Address+1)&0xFF0000)>>1)|((Address+1)&0x7FFF))& Multi.sramMaskB)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + return; + case CMemory::MAP_HIROM_SRAM: if (Memory.SRAMMask) { if(Memory.SRAMMask>=MEMMAP_MASK){ - WRITE_WORD(Memory.SRAM + + WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3) & Memory.SRAMMask)), Word); } else { /* no WRITE_WORD here, since if Memory.SRAMMask=0x7ff * then the high byte doesn't follow the low byte. */ - *(Memory.SRAM + + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3) & Memory.SRAMMask))) = (uint8) Word; - *(Memory.SRAM + + *(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3) & Memory.SRAMMask))) = (uint8) (Word >> 8); } @@ -714,7 +766,7 @@ INLINE uint8 *GetBasePointer (uint32 Address) // { // return s7r.bank50; // } - + case CMemory::MAP_SPC7110_ROM: #ifdef SPC7110_DEBUG printf("Getting Base pointer to SPC7110ROM\n"); @@ -728,6 +780,10 @@ INLINE uint8 *GetBasePointer (uint32 Address) if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; return (Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Memory.SRAMMask) - (Address&0xffff)); + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB) - (Address&0xffff)); + case CMemory::MAP_BWRAM: return (Memory.BWRAM - 0x6000 - (Address&0x8000)); @@ -766,7 +822,7 @@ INLINE uint8 *S9xGetMemPointer (uint32 Address) // { // return s7r.bank50 + (Address&0xffff); // } - + case CMemory::MAP_SPC7110_ROM: #ifdef SPC7110_DEBUG printf("Getting Mem pointer to SPC7110ROM\n"); @@ -780,6 +836,10 @@ INLINE uint8 *S9xGetMemPointer (uint32 Address) if((Memory.SRAMMask&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; return (Memory.SRAM + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Memory.SRAMMask)); + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK) return NULL; + return (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB)); + case CMemory::MAP_BWRAM: return (Memory.BWRAM - 0x6000 + (Address&0x7fff)); @@ -829,7 +889,7 @@ INLINE void S9xSetPCBase (uint32 Address) // CPU.PCBase = s7r.bank50; // return; // } - + case CMemory::MAP_SPC7110_ROM: #ifdef SPC7110_DEBUG printf("Getting Base pointer to SPC7110ROM\n"); @@ -849,6 +909,14 @@ INLINE void S9xSetPCBase (uint32 Address) } return; + case CMemory::MAP_LOROM_SRAM_B: + if((Multi.sramMaskB&MEMMAP_MASK)!=MEMMAP_MASK){ + CPU.PCBase = NULL; + } else { + CPU.PCBase = (Multi.sramB + ((((Address&0xFF0000)>>1)|(Address&0x7FFF)) & Multi.sramMaskB)) - (Address&0xffff); + } + return; + case CMemory::MAP_BWRAM: CPU.PCBase = (Memory.BWRAM - 0x6000 - (Address&0x8000)); return; @@ -868,9 +936,9 @@ INLINE void S9xSetPCBase (uint32 Address) case CMemory::MAP_OBC_RAM: CPU.PCBase = GetBasePointerOBC1(Address); return; - + case CMemory::MAP_BSX: - CPU.PCBase = S9xGetPasePointerBSX(Address); + CPU.PCBase = S9xGetBasePointerBSX(Address); return; case CMemory::MAP_DEBUG: diff --git a/source/snes9x/gfx.cpp b/source/snes9x/gfx.cpp index 321d1d2..027d193 100644 --- a/source/snes9x/gfx.cpp +++ b/source/snes9x/gfx.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,12 +114,25 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "cpuexec.h" #include "gfx.h" @@ -153,9 +172,29 @@ #include "cheats.h" -static void S9xDisplayString(const char *string); -static void S9xDisplayFrameRate(); -void ComputeClipWindows(); +#ifndef NGC +#include "movie.h" +#endif + +#include "font.h" +static int font_width = 8; +static int font_height = 9; + +// private text-displaying functions +static void S9xDisplayPressedKeys (); +static void S9xDisplayFrameRate (); +static void S9xDisplayString (const char *string, int linesFromBottom=5, int pixelsFromLeft=1, bool allowWrap=true); +#ifndef NGC +static void S9xDisplayWatchedAddresses (); +#endif +// shared params for the above functions and DisplayChar +uint16* display_screen = NULL; +int display_ppl, display_width, display_height; +int display_fontwidth = font_width, display_fontheight = font_height, display_hfontaccessscale = 1, display_vfontaccessscale = 1; +bool8 display_paramsinited = FALSE; +#define DisplayString (S9xCustomDisplayString ? S9xCustomDisplayString : S9xDisplayString) + +void ComputeClipWindows (); extern struct SLineData LineData[240]; extern struct SLineMatrixData LineMatrixData [240]; @@ -170,7 +209,7 @@ bool8 S9xGraphicsInit(){ GFX.DoInterlace=0; GFX.InterlaceFrame=0; - PPU.BG_Forced=0; + Settings.BG_Forced=0; IPPU.OBJChanged=TRUE; IPPU.DirectColourMapsNeedRebuild=TRUE; GFX.RealPPL=GFX.Pitch>>1; @@ -241,6 +280,8 @@ bool8 S9xGraphicsInit(){ } } + GFX.Repainting = FALSE; + return TRUE; FAIL: @@ -341,6 +382,7 @@ void S9xStartScreenRefresh(){ IPPU.RenderedFramesCount = 0; IPPU.FrameCount = 0; } + ++IPPU.TotalEmulatedFrames; } void RenderLine(uint8 C) { @@ -375,12 +417,71 @@ void RenderLine(uint8 C) { } } +bool watchesCleared=false; +#ifndef NGC +void S9xDisplayWatchedAddresses () +{ + if(!watchesCleared) + { + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + watches[i].on = false; + watchesCleared = true; + } + + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + { + if(!watches[i].on) + break; + + int32 displayNumber = 0; + + extern struct SCheatData Cheat; + for(int r=0;r= 8388608) + displayNumber -= 16777216; + + sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int)displayNumber); + } + + + DisplayString(buf, 6+i, 1, false); + } +} +#endif + +void S9xReRefresh () +{ + if(Settings.StopEmulation) + return; + + GFX.Repainting = TRUE; + S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight/*, Settings.SixteenBit*/); + GFX.Repainting = FALSE; +} + + void S9xEndScreenRefresh() { if(IPPU.RenderThisFrame) { FLUSH_REDRAW(); if(GFX.DoInterlace && GFX.InterlaceFrame==0){ S9xControlEOF(); - // XXX: Invent S9xContinueUpdate()? + S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); } else { if(IPPU.ColorsChanged) { uint32 saved = PPU.CGDATA[0]; @@ -389,15 +490,15 @@ void S9xEndScreenRefresh() { PPU.CGDATA[0] = saved; } -#ifndef NGC +#ifndef NGC if(Settings.TakeScreenshot) S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); -#endif +#endif S9xControlEOF(); - if (Settings.DisplayFrameRate) - S9xDisplayFrameRate(); - if (GFX.InfoString) - S9xDisplayString(GFX.InfoString); + + if(Settings.AutoDisplayMessages || Settings.OpenGLEnable || Settings.GlideEnable) + S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); } } else { @@ -497,13 +598,13 @@ void S9xSetupOBJ() { } else { GFX.OBJWidths[S]=SmallWidth; Height=SmallHeight; } - int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=256; + int HPos=PPU.OBJ[S].HPos; if(HPos==-256) HPos=0; if(HPos>-GFX.OBJWidths[S] && HPos<=256) { if(HPos<0){ GFX.OBJVisibleTiles[S]=(GFX.OBJWidths[S]+HPos+7)>>3; - } else if(HPos+GFX.OBJWidths[S]>=257){ - GFX.OBJVisibleTiles[S]=(257-HPos+7)>>3; + } else if(HPos+GFX.OBJWidths[S]>255){ + GFX.OBJVisibleTiles[S]=(256-HPos+7)>>3; } else { GFX.OBJVisibleTiles[S]=GFX.OBJWidths[S]>>3; } @@ -905,7 +1006,7 @@ static void DrawBackgroundMosaic(int bg, uint8 Zh, uint8 Zl){ } uint32 Width = Right-Left; - uint32 f = 0; + HPos&=7; while(LeftWidth) w=Width; @@ -923,9 +1024,8 @@ static void DrawBackgroundMosaic(int bg, uint8 Zh, uint8 Zl){ } } HPos+=PPU.Mosaic; - f+=PPU.Mosaic; - while(f>=8){ - f-=8; + while(HPos>=8){ + HPos-=8; if(BG.TileSizeH==8){ t++; if(HTile==31) t=b2; @@ -1328,14 +1428,14 @@ static inline void RenderScreen(bool8 sub){ GFX.S = GFX.Screen; GFX.DB = GFX.ZBuffer; GFX.Clip = IPPU.Clip[0]; - BGActive=Memory.FillRAM[0x212c] & ~PPU.BG_Forced; + BGActive=Memory.FillRAM[0x212c] & ~Settings.BG_Forced; if(GFX.DoInterlace && GFX.InterlaceFrame) GFX.S+=GFX.RealPPL; D=32; } else { GFX.S = GFX.SubScreen; GFX.DB = GFX.SubZBuffer; GFX.Clip = IPPU.Clip[1]; - BGActive=Memory.FillRAM[0x212d] & ~PPU.BG_Forced; + BGActive=Memory.FillRAM[0x212d] & ~Settings.BG_Forced; D=(Memory.FillRAM[0x2130]&2)<<4; // 'do math' depth flag } @@ -1519,76 +1619,291 @@ void S9xUpdateScreen() { IPPU.PreviousLine = IPPU.CurrentLine; } +extern bool unfreezing_from_stream; void S9xSetInfoString (const char *string) { - GFX.InfoString = string; - GFX.InfoStringTimeout = 120; + if(Settings.InitialInfoStringTimeout > 0) + { + GFX.InfoString = string; + GFX.InfoStringTimeout = Settings.InitialInfoStringTimeout; + + if (Settings.Paused && !unfreezing_from_stream) + { + //refresh screen to show new message immediately + S9xReRefresh(); + } + } } -#include "font.h" +static inline void FontPixToScreen(char p, uint16 *s) +{ + if(p == '#') + { + *s = Settings.DisplayColor; + } + else if(p == '.') + { + static const uint16 black = BUILD_PIXEL(0,0,0); + *s = black; + } +} void DisplayChar(uint16 *s, uint8 c) { - int line = ((c - 32) >> 4) * font_height; - int offset = ((c - 32) & 15) * font_width; - int h, w, rws; - rws = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; - for(h=0; h= max_chars || (unsigned char) string [i] < 32) { - Screen -= (font_width - 1) * max_chars; - Screen += font_height * GFX.RealPPL; - if(Screen >= GFX.Screen+GFX.RealPPL*IPPU.RenderedScreenHeight) - break; - char_count -= max_chars; + int line = ((c - 32) >> 4) * display_fontheight; + int offset = ((c - 32) & 15) * display_fontwidth; + int h, w; + if(!display_paramsinited) display_ppl = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; + if(display_hfontaccessscale == 1 && display_vfontaccessscale == 1) { + for(h=0; h max_chars && !allowWrap && display_hfontaccessscale > 1) + { + display_fontwidth /= display_hfontaccessscale; + display_hfontaccessscale--; + display_fontwidth *= display_hfontaccessscale; + + max_chars = display_width / (display_fontwidth-display_hfontaccessscale); + } + + // loop through and draw the characters + for(int i = 0 ; i < len ; i++, char_count++) + { + if(char_count >= max_chars || (unsigned char)string[i] < 32) + { + if(!allowWrap) + break; + + Screen -= /*Settings.SixteenBit ? (display_fontwidth-display_hfontaccessscale)*sizeof(uint16)*max_chars :*/ (display_fontwidth-display_hfontaccessscale)*max_chars; + Screen += display_fontheight * display_ppl; + if(Screen >= display_screen + display_ppl * display_height) + break; + + char_count -= max_chars; + } + if((unsigned char) string[i]<32) continue; + + DisplayChar(Screen, string[i]); + Screen += /*Settings.SixteenBit ? (display_fontwidth-display_hfontaccessscale)*sizeof(uint16) :*/ (display_fontwidth-display_hfontaccessscale); + } + + // revert temporary change to font scale, if any + if(display_hfontaccessscale != prev_hfont_access_scale) + { + display_hfontaccessscale = prev_hfont_access_scale; + display_fontwidth *= display_hfontaccessscale; + } +} + +// input display +static void S9xDisplayPressedKeys () +{ +#ifndef NGC + uint16 MovieGetJoypad(int i); + bool MovieGetMouse(int i, uint8 out [5]); + bool MovieGetScope(int i, uint8 out [6]); + bool MovieGetJustifier(int i, uint8 out [11]); +#endif + + enum controllers controller; + int8 ids[4]; + + int line = 1; +#ifndef NGC + const static char KeyMap[]= {'0','1','2','R','L','X','A','>','<','v','^','S','s','Y','B'}; + const static int KeyOrder[]={8,10,7,9, 0, 6,14,13,5, 1, 4,3, 2, 11,12}; // < ^ > v A B Y X L R S s +#endif + char string[255]; + int len; + + S9xGetController(1, &controller, &ids[0],&ids[1],&ids[2],&ids[3]); +#ifndef NGC + bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD && !(MovieGetJoypad(1) & 0xffff))); +#else + bool singlePlayer = (controller == CTL_NONE || (controller == CTL_JOYPAD)); +#endif + for(int port = 0; port < 2; port++) + { + S9xGetController(port, &controller, &ids[0],&ids[1],&ids[2],&ids[3]); + for(int idid = 0; idid < 4; idid++) + { + const int id = ids[idid]; + if(id == -1) + continue; + + bool skip = false; + switch(controller) + { + default: { + skip = true; + } break; + + case CTL_MP5: + singlePlayer = false; + // no break: + case CTL_JOYPAD: { + if(line < id+1) + line = id+1; +#ifndef NGC + uint16 tempJoypad = MovieGetJoypad(id); + if(!(tempJoypad & 0xffff) && id > 0) + skip = true; + else + { + sprintf(string, !singlePlayer?"P%d: ":" ",id+1); + + for (int i=0; i < 15; i++) + { + int j = KeyOrder[i]; + int mask = (1 << (j+1)); + string[strlen("P?: ")+i]= ((tempJoypad & mask)!=0) ? KeyMap[j] : ' '; + } + } +#endif + } break; + + case CTL_MOUSE: { +#ifndef NGC + uint8 buf [5] = {0}; + MovieGetMouse(id, buf); + int16 x = ((uint16*)buf)[0]; + int16 y = ((uint16*)buf)[1]; + uint8 buttons = buf[4]; + //if(delta_x < 0) delta_x = 128|-delta_x; + //if(delta_y < 0) delta_y = 128|-delta_y; + sprintf(string, "(%4d,%4d) %c%c", x, y, (buttons&0x40)?'L':' ', (buttons&0x80)?'R':' '); +#endif + } break; + + case CTL_SUPERSCOPE: { +#ifndef NGC + uint8 buf [6] = {0}; + MovieGetScope(id, buf); + int16 x = ((uint16*)buf)[0]; + int16 y = ((uint16*)buf)[1]; + uint8 buttons = buf[4]; + sprintf(string, "(%3d,%3d) %c%c%c%c", x, y, (buttons&0x80)?'F':' ', (buttons&0x40)?'C':' ', (buttons&0x20)?'T':' ', (buttons&0x10)?'P':' '); +#endif + } break; + + case CTL_JUSTIFIER: { +#ifndef NGC + uint8 buf [11] = {0}; + MovieGetJustifier(port, buf); + int16 x1 = ((uint16*)buf)[0]; + int16 x2 = ((uint16*)buf)[1]; + int16 y1 = ((uint16*)buf)[2]; + int16 y2 = ((uint16*)buf)[3]; + uint8 buttons = buf[8]; + bool8 offscreen1 = buf[9]; + bool8 offscreen2 = buf[10]; + if(id == 1) + sprintf(string, "(%3d,%3d) %c%c%c / (%3d,%3d) %c%c%c", x1, y1, (buttons&0x80)?'T':' ', (buttons&0x20)?'S':' ', offscreen1?'O':' ', x2, y2, (buttons&0x40)?'T':' ', (buttons&0x10)?'S':' ', offscreen2?'O':' '); + else + sprintf(string, "(%3d,%3d) %c%c%c", x1, y1, (buttons&0x80)?'T':' ', (buttons&0x20)?'S':' ', offscreen1?'O':' '); +#endif + } break; + } + + if(skip) + continue; + + len=strlen(string); + + DisplayString(string, line, 1, false); + + line++; + } + } +} + +void S9xDisplayMessages(uint16 *screen, int ppl, int width, int height, int scale) +{ + display_screen = screen; + display_ppl = ppl; + display_width = width; + display_height = height; + display_fontwidth = font_width * scale; + display_fontheight = font_height * scale; + display_hfontaccessscale = scale; + display_vfontaccessscale = scale; + display_paramsinited = TRUE; + + if (Settings.DisplayFrameRate) + S9xDisplayFrameRate(); + + if (Settings.DisplayPressedKeys==2) + S9xDisplayPressedKeys(); + + if (GFX.FrameDisplay +#ifndef NGC + && S9xMovieActive() +#endif +#ifdef NETPLAY_SUPPORT + || Settings.NetPlay +#endif + ) + DisplayString(GFX.FrameDisplayString, 4, 1, false); + + if (GFX.InfoString && *GFX.InfoString) + DisplayString(GFX.InfoString, 5, 1, !GFX.FrameDisplay +#ifndef NGC +|| (!S9xMovieActive() +#ifdef NETPLAY_SUPPORT + && !Settings.NetPlay +#endif + ) +#endif + ); + +#ifndef NGC + if (Settings.DisplayWatchedAddresses) + S9xDisplayWatchedAddresses(); +#endif + display_paramsinited = FALSE; + display_fontwidth = font_width; + display_fontheight = font_height; + display_hfontaccessscale = 1; + display_vfontaccessscale = 1; } #include "crosshairs.h" @@ -1609,7 +1924,7 @@ static uint16 get_crosshair_color(uint8 color){ case 11: return BUILD_PIXEL(0,23,31); // Sky case 12: return BUILD_PIXEL(0,0,31); // Blue case 13: return BUILD_PIXEL(23,0,31); // Violet - case 14: return BUILD_PIXEL(31,0,31); // MagicPink + case 14: return BUILD_PIXEL(31,0,31); // Magenta case 15: return BUILD_PIXEL(31,0,16); // Purple } return 0; // stupid compiler warning @@ -1623,26 +1938,33 @@ void S9xDrawCrosshair(const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 if(IPPU.DoubleWidthPixels){ cx=2; x*=2; W*=2; } if(IPPU.DoubleHeightPixels){ rx=2; y*=2; H*=2; } if(crosshair==NULL) return; + if(GFX.Screen==NULL) return; + if(Settings.StopEmulation) return; uint16 fg, bg; fg=get_crosshair_color(fgcolor); bg=get_crosshair_color(bgcolor); - uint16 *s = GFX.Screen + y * GFX.RealPPL + x; - rws = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; - for(r=0; r<15*rx; r++, s+=rws-15*cx) { - if(y+r<0){ s+=15*cx; continue; } - if(y+r>=H) break; - for(c=0; c<15*cx; c++, s++) { - if(x+c<0) continue; - if(x+c>=W){ s+=15*cx-c; break; } - uint8 p = crosshair[(r/rx)*15+(c/cx)]; +#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... + if(x >= 0 && y >= 0) +#endif + { + uint16 *s = GFX.Screen + y * GFX.RealPPL + x; + rws = Settings.OpenGLEnable ? IPPU.RenderedScreenWidth : GFX.RealPPL; + for(r=0; r<15*rx; r++, s+=rws-15*cx) { + if(y+r<0){ s+=15*cx; continue; } // if y is negative, skip line + if(y+r>=H) break; // if y is past bottom, stop + for(c=0; c<15*cx; c++, s++) { + if(x+c<0 || s=W){ s+=15*cx-c; break; } // if x is past right, go to next line + uint8 p = crosshair[(r/rx)*15+(c/cx)]; - if(p == '#' && fgcolor) { - *s=(fgcolor&0x10)?COLOR_ADD1_2(fg,*s):fg; - } else if(p == '.' && bgcolor) { - *s=(bgcolor&0x10)?COLOR_ADD1_2(*s,bg):bg; - } - } - } + if(p == '#' && fgcolor) { + *s=(fgcolor&0x10)?COLOR_ADD1_2(fg,*s):fg; + } else if(p == '.' && bgcolor) { + *s=(bgcolor&0x10)?COLOR_ADD1_2(*s,bg):bg; + } + } + } + } } @@ -1740,3 +2062,4 @@ bool8 S9xSetRenderPixelFormat (int format) } #endif +void (*S9xCustomDisplayString) (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) = NULL; diff --git a/source/snes9x/gfx.h b/source/snes9x/gfx.h index 980ecd6..248885e 100644 --- a/source/snes9x/gfx.h +++ b/source/snes9x/gfx.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _GFX_H_ #define _GFX_H_ @@ -175,6 +194,9 @@ struct SGFX{ uint32 FixedColour; const char *InfoString; uint32 InfoStringTimeout; + char FrameDisplayString[256]; + bool8 FrameDisplay; + bool8 Repainting; // True if the frame is being re-drawn uint8 DoInterlace; uint8 InterlaceFrame; uint32 StartY; @@ -242,7 +264,7 @@ struct SBG { uint32 PaletteMask; uint8 EnableMath; uint8 InterlaceLine; - + uint8 *Buffer, *BufferFlip; uint8 *Buffered, *BufferedFlip; bool8 DirectColourMode; @@ -287,7 +309,7 @@ GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ (GFX.X2 [((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \ - (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) + (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) #endif #define COLOR_ADD1_2(C1, C2) \ @@ -314,7 +336,7 @@ inline uint16 COLOR_SUB(uint16 C1, uint16 C2) mC1 = C1 & FIRST_COLOR_MASK; mC2 = C2 & FIRST_COLOR_MASK; if (mC1 > mC2) v += (mC1 - mC2); - + mC1 = C1 & SECOND_COLOR_MASK; mC2 = C2 & SECOND_COLOR_MASK; if (mC1 > mC2) v += (mC1 - mC2); @@ -322,7 +344,7 @@ inline uint16 COLOR_SUB(uint16 C1, uint16 C2) mC1 = C1 & THIRD_COLOR_MASK; mC2 = C2 & THIRD_COLOR_MASK; if (mC1 > mC2) v += (mC1 - mC2); - + return v; } #endif @@ -340,17 +362,22 @@ void S9xUpdateScreen (); void RenderLine (uint8 line); void S9xBuildDirectColourMaps (); -// External port interface which must be implemented or initialised for each -// port. +void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale); // called automatically unless Settings.AutoDisplayMessages is false + extern struct SGFX GFX; +// External port interface which must be implemented or initialised for each +// port. bool8 S9xGraphicsInit (); void S9xGraphicsDeinit(); bool8 S9xInitUpdate (void); bool8 S9xDeinitUpdate (int Width, int Height); +bool8 S9xContinueUpdate (int Width, int Height); void S9xSetPalette (); void S9xSyncSpeed (); +extern void (*S9xCustomDisplayString) (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); // called instead of S9xDisplayString if set to non-NULL + #ifdef GFX_MULTI_FORMAT bool8 S9xSetRenderPixelFormat (int format); #endif diff --git a/source/snes9x/globals.cpp b/source/snes9x/globals.cpp index ab6e6ca..e031e81 100644 --- a/source/snes9x/globals.cpp +++ b/source/snes9x/globals.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,12 +114,25 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary @@ -141,7 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ -#define _GLOBALS_CPP + + #include "snes9x.h" #include "memmap.h" @@ -160,14 +178,12 @@ #include "sa1.h" #include "bsx.h" - +#include "spc7110.h" #ifdef NETPLAY_SUPPORT #include "netplay.h" #endif -#include "spc7110.h" - -//START_EXTERN_C +START_EXTERN_C char String[513]; struct Missing missing; @@ -196,25 +212,28 @@ struct SSA1 SA1; struct SBSX BSX; +struct SMulti Multi; + SSoundData SoundData; SnesModel M1SNES={1,3,2}; SnesModel M2SNES={2,4,3}; SnesModel* Model=&M1SNES; - -uint8 *SRAM = NULL; +#if defined(ZSNES_FX) || defined(ZSNES_C4) uint8 *ROM = NULL; +uint8 *SRAM = NULL; uint8 *RegRAM = NULL; +#endif CMemory Memory; -SSNESGameFixes SNESGameFixes; +struct SSNESGameFixes SNESGameFixes; unsigned char OpenBus = 0; -//END_EXTERN_C +END_EXTERN_C #ifndef ZSNES_FX struct FxInit_s SuperFX; diff --git a/source/snes9x/language.h b/source/snes9x/language.h index 91aa32f..3bf22f9 100644 --- a/source/snes9x/language.h +++ b/source/snes9x/language.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,22 +159,30 @@ **********************************************************************************/ + + /* This file is for core emulator messages. Use a port-specific file for * * GUI strings and the like. Thank you. */ /* Movie Messages */ +#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" +#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" #define MOVIE_INFO_REPLAY "Movie replay" #define MOVIE_INFO_RECORD "Movie record" #define MOVIE_INFO_RERECORD "Movie re-record" #define MOVIE_INFO_REWIND "Movie rewind" #define MOVIE_INFO_STOP "Movie stop" #define MOVIE_INFO_END "Movie end" -#define MOVIE_INFO_RECORDING_ENABLED "Recording enabled" -#define MOVIE_INFO_RECORDING_DISABLED "Recording disabled" -#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" -#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" -#define MOVIE_ERR_COULD_NOT_OPEN "Could not open movie file." -#define MOVIE_ERR_NOT_FOUND "File not found." -#define MOVIE_ERR_WRONG_FORMAT "File is wrong format." -#define MOVIE_ERR_WRONG_VERSION "File is wrong version." +#define MOVIE_INFO_SNAPSHOT "Movie snapshot" +#define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" + +/* Snapshot Messages */ + +#define SAVE_INFO_SNAPSHOT "Saved" +#define SAVE_INFO_LOAD "Loaded" +#define SAVE_ERR_WRONG_FORMAT "File not in Snes9x freeze format" +#define SAVE_ERR_WRONG_VERSION "Incompatable Snes9x freeze file format version" +#define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for freeze file not found" +#define SAVE_ERR_SAVE_NOT_FOUND "Save file %s does not exist." + diff --git a/source/snes9x/memmap.cpp b/source/snes9x/memmap.cpp index f115e47..5293709 100644 --- a/source/snes9x/memmap.cpp +++ b/source/snes9x/memmap.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,12 +114,25 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary @@ -142,6 +159,9 @@ **********************************************************************************/ + +#include + #include #ifdef HAVE_STRINGS_H #include @@ -153,29 +173,27 @@ #include #endif -#ifdef JMA_SUPPORT -#include "jma/s9x-jma.h" +#ifdef __W32_HEAP +#include #endif -#include "snes9x.h" #include "memmap.h" +#include "display.h" #include "cpuexec.h" #include "ppu.h" -#include "display.h" - -#include "cheats.h" - #include "apu.h" -#include "sa1.h" #include "dsp1.h" -#include "srtc.h" +#include "sa1.h" #include "sdd1.h" #include "spc7110.h" #include "seta.h" +#include "srtc.h" #include "bsx.h" + #ifndef NGC #include "reader.h" +#include "cheats.h" #else #include #include "aram.h" /*** Nintendo GameCube ARAM loader. @@ -186,750 +204,767 @@ extern int hasloaded; #endif #include "controls.h" +//#include "movie.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +#endif #ifdef UNZIP_SUPPORT #include "unzip.h" #endif -#ifdef __W32_HEAP -#include +#ifdef JMA_SUPPORT +#include "jma/s9x-jma.h" #endif -#ifndef ZSNES_FX -#include "fxemu.h" -extern struct FxInit_s SuperFX; -#else -START_EXTERN_C -extern uint8 *SFXPlotTable; -END_EXTERN_C +#ifdef __WIN32__ +#ifndef _XBOX +#include "win32/wsnes9x.h" // FIXME: shouldn't be necessary +#endif +#endif + +#ifdef __WIN32__ +#define snprintf _snprintf // needs ANSI compliant name #endif #ifndef SET_UI_COLOR #define SET_UI_COLOR(r,g,b) ; #endif -//you would think everyone would have these -//since they're so useful. #ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) #endif -static int retry_count=0; -void S9xDeinterleaveType2 (bool8 reset=TRUE); -inline uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32 = 0xFFFFFFFF); +#ifndef ZSNES_FX +extern struct FxInit_s SuperFX; +#else +EXTERN_C uint8 *SFXPlotTable; +#endif -extern char *rom_filename; +static bool8 stopMovie = TRUE; +static char LastRomFilename[_MAX_PATH + 1] = ""; -const uint32 crc32Table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +static const uint32 crc32Table[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; +static void S9xDeinterleaveType1 (int, uint8 *); +static void S9xDeinterleaveType2 (int, uint8 *); +static void S9xDeinterleaveGD24 (int, uint8 *); +static bool8 allASCII (uint8 *, int); +static bool8 is_SufamiTurbo_BIOS (uint8 *, uint32); +static bool8 is_SufamiTurbo_Cart (uint8 *, uint32); +static bool8 is_SameGame_BIOS (uint8 *, uint32); +static bool8 is_SameGame_Add_On (uint8 *, uint32); +static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); +#ifndef NGC +static long ReadInt (Reader *, unsigned); +static bool8 ReadIPSPatch (Reader *, long, int32 &); +static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE); +#endif +// deinterleave - -void S9xDeinterleaveType1(int TotalFileSize, uint8 * base) +static void S9xDeinterleaveType1 (int size, uint8 *base) { - if(Settings.DisplayColor==0xffff) + if (Settings.DisplayColor == 0xffff) { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); } - int i; - int nblocks = TotalFileSize >> 16; - uint8 blocks [256]; - for (i = 0; i < nblocks; i++) + uint8 blocks[256]; + int nblocks = size >> 16; + + for (int i = 0; i < nblocks; i++) { - blocks [i * 2] = i + nblocks; - blocks [i * 2 + 1] = i; + blocks[i * 2] = i + nblocks; + blocks[i * 2 + 1] = i; } - uint8 *tmp = (uint8 *) malloc (0x8000); + + uint8 *tmp = (uint8 *) malloc(0x8000); if (tmp) { - for (i = 0; i < nblocks * 2; i++) + for (int i = 0; i < nblocks * 2; i++) { for (int j = i; j < nblocks * 2; j++) { - if (blocks [j] == i) + if (blocks[j] == i) { - memmove (tmp, &base [blocks [j] * 0x8000], 0x8000); - memmove (&base [blocks [j] * 0x8000], - &base [blocks [i] * 0x8000], 0x8000); - memmove (&base [blocks [i] * 0x8000], tmp, 0x8000); - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; + memmove(tmp, &base[blocks[j] * 0x8000], 0x8000); + memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000); + memmove(&base[blocks[i] * 0x8000], tmp, 0x8000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; break; } } } - free ((char *) tmp); + + free(tmp); } } -void S9xDeinterleaveGD24(int TotalFileSize, uint8 * base) +static void S9xDeinterleaveType2 (int size, uint8 *base) { - - if(TotalFileSize!=0x300000) - return; - - if(Settings.DisplayColor==0xffff) + // for odd Super FX images + if (Settings.DisplayColor == 0xffff || Settings.DisplayColor == BUILD_PIXEL(0, 31, 0)) { - Settings.DisplayColor=BUILD_PIXEL(0,31,31); - SET_UI_COLOR(0,255,255); + Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); + SET_UI_COLOR(255, 119, 25); } - uint8 *tmp = (uint8 *) malloc (0x80000); + uint8 blocks[256]; + int nblocks = size >> 16; + int step = 64; + + while (nblocks <= step) + step >>= 1; + nblocks = step; + + for (int i = 0; i < nblocks * 2; i++) + blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2); + + uint8 *tmp = (uint8 *) malloc(0x10000); + if (tmp) + { + for (int i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks[j] == i) + { + memmove(tmp, &base[blocks[j] * 0x10000], 0x10000); + memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000); + memmove(&base[blocks[i] * 0x10000], tmp, 0x10000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; + break; + } + } + } + + free(tmp); + } +} + +static void S9xDeinterleaveGD24 (int size, uint8 *base) +{ + // for 24Mb images dumped with Game Doctor + if (size != 0x300000) + return; + + if (Settings.DisplayColor == 0xffff) + { + Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); + SET_UI_COLOR(0, 255, 255); + } + + uint8 *tmp = (uint8 *) malloc(0x80000); if (tmp) { memmove(tmp, &base[0x180000], 0x80000); memmove(&base[0x180000], &base[0x200000], 0x80000); memmove(&base[0x200000], &base[0x280000], 0x80000); memmove(&base[0x280000], tmp, 0x80000); - free ((char *) tmp); - S9xDeinterleaveType1(TotalFileSize, base); + free(tmp); + + S9xDeinterleaveType1(size, base); } } -bool8 CMemory::AllASCII (uint8 *b, int size) +// allocation and deallocation + +bool8 CMemory::Init (void) { - for (int i = 0; i < size; i++) + RAM = (uint8 *) malloc(0x20000); + SRAM = (uint8 *) malloc(0x20000); + VRAM = (uint8 *) malloc(0x10000); + ROM = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000); + + IPPU.TileCache[TILE_2BIT] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_8BIT] = (uint8 *) malloc(MAX_8BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + + IPPU.TileCached[TILE_2BIT] = (uint8 *) malloc(MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT] = (uint8 *) malloc(MAX_4BIT_TILES); + IPPU.TileCached[TILE_8BIT] = (uint8 *) malloc(MAX_8BIT_TILES); + IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES); + IPPU.TileCached[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES); + IPPU.TileCached[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES); + + if (!RAM || !SRAM || !VRAM || !ROM || + !IPPU.TileCache[TILE_2BIT] || + !IPPU.TileCache[TILE_4BIT] || + !IPPU.TileCache[TILE_8BIT] || + !IPPU.TileCache[TILE_2BIT_EVEN] || + !IPPU.TileCache[TILE_2BIT_ODD] || + !IPPU.TileCache[TILE_4BIT_EVEN] || + !IPPU.TileCache[TILE_4BIT_ODD] || + !IPPU.TileCached[TILE_2BIT] || + !IPPU.TileCached[TILE_4BIT] || + !IPPU.TileCached[TILE_8BIT] || + !IPPU.TileCached[TILE_2BIT_EVEN] || + !IPPU.TileCached[TILE_2BIT_ODD] || + !IPPU.TileCached[TILE_4BIT_EVEN] || + !IPPU.TileCached[TILE_4BIT_ODD]) { - if (b[i] < 32 || b[i] > 126) - return (FALSE); - } - return (TRUE); -} - -int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) -{ - int score = 0; - int o = skip_header ? 0xff00 + 0x200 : 0xff00; - - o+=romoff; - - if(Memory.ROM [o + 0xd5] & 0x1) - score+=2; - - //Mode23 is SA-1 - if(Memory.ROM [o + 0xd5] == 0x23) - score-=2; - - if(Memory.ROM [o+0xd4] == 0x20) - score +=2; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - { - score += 2; - if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) - score++; - } - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 6; - if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) - score -= 2; //reduced after looking at a scan by Cowering - if (CalculatedSize > 1024 * 1024 * 3) - score += 4; - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) -{ - int score = 0; - int o = skip_header ? 0x7f00 + 0x200 : 0x7f00; - - o+=romoff; - - if(!(Memory.ROM [o + 0xd5] & 0x1)) - score+=3; - - //Mode23 is SA-1 - if(Memory.ROM [o + 0xd5] == 0x23) - score+=2; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - { - score += 2; - if(0!=(Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8))) - score++; - } - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (CalculatedSize <= 1024 * 1024 * 16) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 6; - if ((Memory.ROM [o + 0xfc]|(Memory.ROM [o + 0xfd]<<8))>0xFFB0) - score -= 2;//reduced per Cowering suggestion - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -char *CMemory::Safe (const char *s) -{ - static char *safe; - static int safe_len = 0; - - if(s==NULL) - { - if(safe!=NULL) - { - free((char*)safe); - safe = NULL; - } - return NULL; - } - int len = strlen (s); - if (!safe || len + 1 > safe_len) - { - if (safe) - free ((char *) safe); - safe = (char *) malloc (safe_len = len + 1); - } - - for (int i = 0; i < len; i++) - { - if (s [i] >= 32 && s [i] < 127) - safe [i] = s[i]; - else - safe [i] = '?'; - } - safe [len] = 0; - return (safe); -} - -char *CMemory::SafeANK (const char *s) -{ - static char *safe; - static int safe_len = 0; - - if(s==NULL) - { - if(safe!=NULL) - { - free((char*)safe); - safe = NULL; - } - return NULL; - } - int len = strlen (s); - if (!safe || len + 1 > safe_len) - { - if (safe) - free ((char *) safe); - safe = (char *) malloc (safe_len = len + 1); - } - - for (int i = 0; i < len; i++) - { - if (s [i] >= 32 && s [i] < 127) // ASCII - safe [i] = s[i]; - else - if (Memory.ROMRegion == 0 && ((unsigned char) s[i] >= 0xa0 && (unsigned char) s[i] < 0xe0)) // JIS X 201 - safe [i] = s[i]; - else - safe [i] = '?'; - - } - safe [len] = 0; - return (safe); -} - -/**********************************************************************************************/ -/* Init() */ -/* This function allocates all the memory needed by the emulator */ -/**********************************************************************************************/ -bool8 CMemory::Init () -{ - RAM = (uint8 *) malloc (0x20000); - SRAM = (uint8 *) malloc (0x20000); - VRAM = (uint8 *) malloc (0x10000); - ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); - - memset (RAM, 0, 0x20000); - memset (SRAM, 0, 0x20000); - memset (VRAM, 0, 0x10000); - memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000); - - FillRAM = NULL; - - IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 64); - IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 64); - IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 64); - IPPU.TileCache [TILE_2BIT_EVEN] = (uint8 *) malloc (MAX_2BIT_TILES * 64); - IPPU.TileCache [TILE_2BIT_ODD] = (uint8 *) malloc (MAX_2BIT_TILES * 64); - IPPU.TileCache [TILE_4BIT_EVEN] = (uint8 *) malloc (MAX_4BIT_TILES * 64); - IPPU.TileCache [TILE_4BIT_ODD] = (uint8 *) malloc (MAX_4BIT_TILES * 64); - - IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES); - IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES); - IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES); - IPPU.TileCached [TILE_2BIT_EVEN] = (uint8 *) malloc (MAX_2BIT_TILES); - IPPU.TileCached [TILE_2BIT_ODD] = (uint8 *) malloc (MAX_2BIT_TILES); - IPPU.TileCached [TILE_4BIT_EVEN] = (uint8 *) malloc (MAX_4BIT_TILES); - IPPU.TileCached [TILE_4BIT_ODD] = (uint8 *) malloc (MAX_4BIT_TILES); - - if (!RAM || !SRAM || !VRAM || !ROM || - !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || - !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || - !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT] || - !IPPU.TileCache [TILE_2BIT_EVEN] || !IPPU.TileCache [TILE_2BIT_ODD] || - !IPPU.TileCache [TILE_4BIT_EVEN] || !IPPU.TileCache [TILE_4BIT_ODD] || - !IPPU.TileCached [TILE_2BIT_EVEN] || !IPPU.TileCached [TILE_2BIT_ODD] || - !IPPU.TileCached [TILE_4BIT_EVEN] || !IPPU.TileCached [TILE_4BIT_ODD]) - { - Deinit (); + Deinit(); return (FALSE); } - // FillRAM uses first 32K of ROM image area, otherwise space just - // wasted. Might be read by the SuperFX code. + ZeroMemory(RAM, 0x20000); + ZeroMemory(SRAM, 0x20000); + ZeroMemory(VRAM, 0x10000); + ZeroMemory(ROM, MAX_ROM_SIZE + 0x200 + 0x8000); - FillRAM = ROM; + ZeroMemory(IPPU.TileCache[TILE_2BIT], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_8BIT], MAX_8BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD], MAX_4BIT_TILES * 64); - // Add 0x8000 to ROM image pointer to stop SuperFX code accessing - // unallocated memory (can cause crash on some ports). - ROM += 0x8000; + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); - C4RAM = ROM + 0x400000 + 8192 * 8; + // FillRAM uses first 32K of ROM image area, otherwise space just + // wasted. Might be read by the SuperFX code. + + FillRAM = ROM; + + // Add 0x8000 to ROM image pointer to stop SuperFX code accessing + // unallocated memory (can cause crash on some ports). + + ROM += 0x8000; + + C4RAM = ROM + 0x400000 + 8192 * 8; // C4 + BIOSROM = ROM + 0x300000; // BS + BSRAM = ROM + 0x400000; // BS + +#if defined(ZSNES_FX) || defined(ZSNES_C4) ::ROM = ROM; ::SRAM = SRAM; ::RegRAM = FillRAM; - - // BS - BIOSROM = ROM + 0x300000; - BSRAM = ROM + 0x400000; - -#ifdef ZSNES_FX - SFXPlotTable = ROM + 0x400000; -#else - SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; - SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB, 2=128KB=1024Mb - SuperFX.pvRam = ::SRAM; - SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); - SuperFX.pvRom = (uint8 *) ROM; #endif - ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_2BIT_EVEN], MAX_2BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_2BIT_ODD], MAX_2BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_4BIT_EVEN], MAX_4BIT_TILES * 64); - ZeroMemory (IPPU.TileCache [TILE_4BIT_ODD], MAX_4BIT_TILES * 64); +#ifdef ZSNES_FX + SFXPlotTable = ROM + 0x400000; +#else + SuperFX.pvRegisters = FillRAM + 0x3000; + SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB=512Mb, 2=128KB=1024Mb + SuperFX.pvRam = SRAM; + SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); + SuperFX.pvRom = (uint8 *) ROM; +#endif - ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_2BIT_EVEN], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_2BIT_ODD], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT_EVEN], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT_ODD], MAX_4BIT_TILES); + SDD1Data = NULL; + SDD1Index = NULL; - SDD1Data = NULL; - SDD1Index = NULL; + PostRomInitFunc = NULL; - return (TRUE); + return (TRUE); } -void CMemory::Deinit () +void CMemory::Deinit (void) { + // XXX: Please remove port specific codes #ifdef __W32_HEAP - if(_HEAPOK!=_heapchk()) + if (_HEAPOK! = _heapchk()) MessageBox(GUI.hWnd, "CMemory::Deinit", "Heap Corrupt", MB_OK); #endif - if (RAM) - { - free ((char *) RAM); + if (RAM) + { + free(RAM); RAM = NULL; - } - if (SRAM) - { - free ((char *) SRAM); - SRAM = NULL; - } - if (VRAM) - { - free ((char *) VRAM); - VRAM = NULL; - } - if (ROM) - { - ROM -= 0x8000; - free ((char *) ROM); - ROM = NULL; - } + } - for(int t=0; t<7; t++){ - if(IPPU.TileCache[t]) { - free ((char *) IPPU.TileCache[t]); + if (SRAM) + { + free(SRAM); + SRAM = NULL; + } + + if (VRAM) + { + free(VRAM); + VRAM = NULL; + } + + if (ROM) + { + ROM -= 0x8000; + free(ROM); + ROM = NULL; + } + + for (int t = 0; t < 7; t++) + { + if (IPPU.TileCache[t]) + { + free(IPPU.TileCache[t]); IPPU.TileCache[t] = NULL; } - if(IPPU.TileCached[t]) { - free ((char *) IPPU.TileCached[t]); + + if (IPPU.TileCached[t]) + { + free(IPPU.TileCached[t]); IPPU.TileCached[t] = NULL; } } - FreeSDD1Data (); + FreeSDD1Data(); + Safe(NULL); SafeANK(NULL); } -void CMemory::FreeSDD1Data () +void CMemory::FreeSDD1Data (void) { - if (SDD1Index) - { - free ((char *) SDD1Index); + if (SDD1Index) + { + free(SDD1Index); SDD1Index = NULL; - } - if (SDD1Data) - { - free ((char *) SDD1Data); + } + + if (SDD1Data) + { + free(SDD1Data); SDD1Data = NULL; - } + } } -/**********************************************************************************************/ -/* LoadROM() */ -/* This function loads a Snes-Backup image */ -/**********************************************************************************************/ +// file management and ROM detection + +static bool8 allASCII (uint8 *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + return (FALSE); + } + + return (TRUE); +} + +static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x40000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) +{ + if (size >= 0x80000 && size <= 0x100000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) +{ + if (size == 0x80000) + return (TRUE); + else + return (FALSE); +} + +int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (buf[0xd5] & 0x1) + score += 2; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score -= 2; + + if (buf[0xd4] == 0x20) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced after looking at a scan by Cowering + + if (CalculatedSize > 1024 * 1024 * 3) + score += 4; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (!(buf[0xd5] & 0x1)) + score += 3; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced per Cowering suggestion + + if (CalculatedSize <= 1024 * 1024 * 16) + score += 2; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) +{ + uint32 calc_size = (size / 0x2000) * 0x2000; + + if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) + { + uint8 *NSRTHead = buf + 0x1D0; // NSRT Header Location + + // detect NSRT header + if (!strncmp("NSRT", (char *) &NSRTHead[24], 4)) + { + if (NSRTHead[28] == 22) + { + if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) && + (NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) && + (((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4)) + memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader)); + } + } + + memmove(buf, buf + 512, calc_size); + headerCount++; + size -= 512; + } + + return (size); +} + + bool8 CMemory::LoadROM (const char *filename) { - int32 TotalFileSize = 0; - bool8 Interleaved = FALSE; - bool8 Tales = FALSE; + int retry_count = 0; - uint8* RomHeader=ROM; - - ExtendedFormat=NOPE; - - - if(CleanUp7110!=NULL) - (*CleanUp7110)(); - - memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - - CPU.TriedInterleavedMode2 = FALSE; - - CalculatedSize = 0; - retry_count =0; - -again: - Settings.DisplayColor=0xffff; - SET_UI_COLOR(255,255,255); - - TotalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); - - if (!TotalFileSize) - return FALSE; // it ends here + if (!filename || !*filename) + return (FALSE); #ifndef NGC - else if(!Settings.NoPatch) - CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize); + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); +#endif /* you don't want to do that: ROM already loaded */ + +again: + Settings.DisplayColor = 0xffff; + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + int32 totalFileSize; + + totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); + if (!totalFileSize) + return (FALSE); +#ifndef NGC + if (!Settings.NoPatch) + CheckForIPSPatch(filename, HeaderCount != 0, totalFileSize); #endif + int hi_score, lo_score; - //fix hacked games here. - if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0x7FC0],19)==0)&&(ROM[0x7FD5]!=0x31)) + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + + if (HeaderCount == 0 && !Settings.ForceNoHeader && + ((hi_score > lo_score && ScoreHiROM(TRUE) > hi_score) || + (hi_score <= lo_score && ScoreLoROM(TRUE) > lo_score))) { - ROM[0x7FD5]=0x31; - ROM[0x7FD6]=0x02; - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); + memmove(ROM, ROM + 512, totalFileSize - 512); + totalFileSize -= 512; + S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work"); + // modifying ROM, so we need to rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); } - if((strncmp("HONKAKUHA IGO GOSEI", (char*)&ROM[0xFFC0],19)==0)&&(ROM[0xFFD5]!=0x31)) + CalculatedSize = (totalFileSize / 0x2000) * 0x2000; + + if (CalculatedSize > 0x400000 && + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1 + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 && + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110 + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a) + ExtendedFormat = YEAH; + + // if both vectors are invalid, it's type 1 LoROM + if (ExtendedFormat == NOPE && + ((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) && + ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) { - ROM[0xFFD5]=0x31; - ROM[0xFFD6]=0x02; - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); - } - - if((ROM[0x7FD5]==0x42)&&(ROM[0x7FD6]==0x13)&&(strncmp("METAL COMBAT",(char*)&ROM[0x7FC0],12)==0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - S9xMessage(S9X_ERROR,S9X_ROM_CONFUSING_FORMAT_INFO, "Warning! Hacked Dump!"); - } - - int orig_hi_score, orig_lo_score; - int hi_score, lo_score; - - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - - if (HeaderCount == 0 && !Settings.ForceNoHeader && - ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || - (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) - { - memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); - TotalFileSize -= 512; - S9xMessage (S9X_INFO, S9X_HEADER_WARNING, - "Try specifying the -nhd command line option if the game doesn't work\n"); - //modifying ROM, so we need to rescore - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - } - - CalculatedSize = (TotalFileSize / 0x2000) * 0x2000; - ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); - - if(CalculatedSize >0x400000&& - !(ROM[0x7FD5]==0x32&&((ROM[0x7FD6]&0xF0)==0x40)) && //exclude S-DD1 - !(ROM[0xFFD5]==0x3A&&((ROM[0xFFD6]&0xF0)==0xF0))) //exclude SPC7110 - { - //you might be a Jumbo! - ExtendedFormat=YEAH; - } - - //If both vectors are invalid, it's type 1 LoROM - - if(ExtendedFormat==NOPE&&((ROM[0x7FFC]|(ROM[0x7FFD]<<8))<0x8000)&&((ROM[0xFFFC]|(ROM[0xFFFD]<<8)) <0x8000)) - { - if(Settings.DisplayColor==0xffff) + if (Settings.DisplayColor == 0xffff) { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); } - if(!Settings.ForceInterleaved) - S9xDeinterleaveType1(TotalFileSize, ROM); + + if (!Settings.ForceInterleaved) + S9xDeinterleaveType1(totalFileSize, ROM); } - //CalculatedSize is now set, so rescore - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); + // CalculatedSize is now set, so rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); - if(NOPE!=ExtendedFormat) + uint8 *RomHeader = ROM; + + if (ExtendedFormat != NOPE) { - int loromscore, hiromscore, swappedlorom, swappedhirom; - loromscore=ScoreLoROM(FALSE); - hiromscore=ScoreHiROM(FALSE); - swappedlorom=ScoreLoROM(FALSE, 0x400000); - swappedhirom=ScoreHiROM(FALSE, 0x400000); + int swappedhirom, swappedlorom; - //set swapped here. + swappedhirom = ScoreHiROM(FALSE, 0x400000); + swappedlorom = ScoreLoROM(FALSE, 0x400000); - if(max(swappedlorom, swappedhirom) >= max(loromscore, hiromscore)) + // set swapped here + if (max(swappedlorom, swappedhirom) >= max(lo_score, hi_score)) { ExtendedFormat = BIGFIRST; - hi_score=swappedhirom; - lo_score=swappedlorom; - RomHeader=ROM+0x400000; + hi_score = swappedhirom; + lo_score = swappedlorom; + RomHeader += 0x400000; } else - { ExtendedFormat = SMALLFIRST; - lo_score=loromscore; - hi_score=hiromscore; - RomHeader=ROM; - } - - } - Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; - if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) - { + bool8 interleaved, tales = FALSE; + + interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; + + if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) + { LoROM = TRUE; HiROM = FALSE; - // Ignore map type byte if not 0x2x or 0x3x - if ((RomHeader [0x7fd5] & 0xf0) == 0x20 || (RomHeader [0x7fd5] & 0xf0) == 0x30) + // ignore map type byte if not 0x2x or 0x3x + if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30) { - switch (RomHeader [0x7fd5] & 0xf) + switch (RomHeader[0x7fd5] & 0xf) { - case 1: - Interleaved = TRUE; - break; - case 5: - Interleaved = TRUE; - Tales = TRUE; - break; - } - } - } - else - { - if ((RomHeader [0xffd5] & 0xf0) == 0x20 || (RomHeader [0xffd5] & 0xf0) == 0x30) - { - switch (RomHeader [0xffd5] & 0xf) - { - case 0: - case 3: - Interleaved = TRUE; - break; + case 1: + interleaved = TRUE; + break; + + case 5: + interleaved = TRUE; + tales = TRUE; + break; } } + } + else + { LoROM = FALSE; HiROM = TRUE; - } - // More - if (!Settings.ForceHiROM && !Settings.ForceLoROM && - !Settings.ForceInterleaved && !Settings.ForceInterleaved2 && - !Settings.ForceNotInterleaved && !Settings.ForcePAL && - !Settings.ForceSuperFX && !Settings.ForceDSP1 && - !Settings.ForceSA1 && !Settings.ForceC4 && - !Settings.ForceSDD1) - { - - -#ifdef DETECT_NASTY_FX_INTERLEAVE -//MK: Damn. YI trips a BRK currently. Maybe even on a real cart. - - if(strncmp((char *)&ROM[0x7fc0], "YOSHI'S ISLAND", 14) == 0 && READ_WORD(ROM+0x7FDE)==57611 && ROM[0x10002]==0xA9) + if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30) { - Interleaved=true; - Settings.ForceInterleaved2=true; + switch (RomHeader[0xffd5] & 0xf) + { + case 0: + case 3: + interleaved = TRUE; + break; + } } -#endif - if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0) + } + + // this two games fail to be detected + if (!Settings.ForceHiROM && !Settings.ForceLoROM) + { + if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || + (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER", 21) == 0)) { LoROM = TRUE; HiROM = FALSE; - Interleaved = FALSE; + interleaved = FALSE; + tales = FALSE; } - } + } - if (!Settings.ForceNotInterleaved && Interleaved) - { - CPU.TriedInterleavedMode2 = TRUE; - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); + if (!Settings.ForceNotInterleaved && interleaved) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting..."); - if (Tales) + if (tales) { - if(Memory.ExtendedFormat==BIGFIRST) + if (ExtendedFormat == BIGFIRST) { S9xDeinterleaveType1(0x400000, ROM); - S9xDeinterleaveType1(CalculatedSize-0x400000, ROM+0x400000); + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000); } else { - S9xDeinterleaveType1(CalculatedSize-0x400000, ROM); - S9xDeinterleaveType1(0x400000, ROM+CalculatedSize-0x400000); - + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM); + S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000); } LoROM = FALSE; HiROM = TRUE; - - } - else if (Settings.ForceInterleaved2) + else + if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000) { - S9xDeinterleaveType2(FALSE); - } - else if (Settings.ForceInterleaveGD24 && CalculatedSize ==0x300000) - { - bool8 t = LoROM; - + bool8 t = LoROM; LoROM = HiROM; HiROM = t; S9xDeinterleaveGD24(CalculatedSize, ROM); } else + if (Settings.ForceInterleaved2) + S9xDeinterleaveType2(CalculatedSize, ROM); + else { - if(Settings.DisplayColor==0xffff) - { - Settings.DisplayColor=BUILD_PIXEL(0,31,0); - SET_UI_COLOR(0,255,0); - } - bool8 t = LoROM; - + bool8 t = LoROM; LoROM = HiROM; HiROM = t; - S9xDeinterleaveType1(CalculatedSize, ROM); } - hi_score = ScoreHiROM (FALSE); - lo_score = ScoreLoROM (FALSE); + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); - if ((HiROM && - (lo_score >= hi_score || hi_score < 0)) || - (LoROM && - (hi_score > lo_score || lo_score < 0))) + if ((HiROM && (lo_score >= hi_score || hi_score < 0)) || + (LoROM && (hi_score > lo_score || lo_score < 0))) { if (retry_count == 0) { - S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, - "ROM lied about its type! Trying again."); + S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again."); Settings.ForceNotInterleaved = TRUE; Settings.ForceInterleaved = FALSE; retry_count++; @@ -938,206 +973,174 @@ again: } } - if(ExtendedFormat==SMALLFIRST) - Tales=true; + if (ExtendedFormat == SMALLFIRST) + tales = TRUE; - FreeSDD1Data (); - InitROM (Tales); + if (tales) + { + uint8 *tmp = (uint8 *) malloc(CalculatedSize - 0x400000); + if (tmp) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM..."); + memmove(tmp, ROM, CalculatedSize - 0x400000); + memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000); + memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000); + free(tmp); + } + } + + if (strncmp(LastRomFilename, filename, _MAX_PATH)) + { + strncpy(LastRomFilename, filename, _MAX_PATH); + LastRomFilename[_MAX_PATH] = 0; + } + + FreeSDD1Data(); + if (CleanUp7110) + (*CleanUp7110)(); + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; #ifndef NGC - S9xLoadCheatFile (S9xGetFilename(".cht", PATCH_DIR)); - S9xInitCheatData (); - S9xApplyCheats (); + S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); #endif - S9xReset (); + InitROM(); + +#ifndef NGC + S9xInitCheatData(); + S9xApplyCheats(); +#endif + + S9xReset(); return (TRUE); } -uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) +uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) { + // <- ROM size without header + // ** Memory.HeaderCount + // ** Memory.ROMFilename - + int32 totalSize = 0; #ifndef NGC - STREAM ROMFile; - int len = 0; - int nFormat=FILE_DEFAULT; -#endif - - int32 TotalFileSize = 0; - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; - - unsigned long FileSize = 0; - -#ifdef UNZIP_SUPPORT - unzFile file=NULL; -#endif - - _splitpath (filename, drive, dir, name, ext); - _makepath (fname, drive, dir, name, ext); + char fname[_MAX_PATH + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; + char *ext; #if defined(__WIN32__) || defined(__MACOSX__) - memmove (&ext [0], &ext[1], 4); + ext = &exts[1]; +#else + ext = &exts[0]; +#endif #endif + memset(NSRTHeader, 0, sizeof(NSRTHeader)); + HeaderCount = 0; #ifndef NGC - if (strcasecmp (ext, "zip") == 0) + _splitpath(filename, drive, dir, name, exts); + _makepath(fname, drive, dir, name, exts); + int nFormat = FILE_DEFAULT; + if (strcasecmp(ext, "zip") == 0) nFormat = FILE_ZIP; - else if (strcasecmp (ext, "rar") == 0) - nFormat = FILE_RAR; - else if (strcasecmp (ext, "jma") == 0) - nFormat = FILE_JMA; else - nFormat = FILE_DEFAULT; + if (strcasecmp(ext, "jma") == 0) + nFormat = FILE_JMA; - switch( nFormat ) + switch (nFormat) { - case FILE_ZIP: - -#ifdef UNZIP_SUPPORT - - file = unzOpen(fname); - - if(file != NULL) + case FILE_ZIP: { +#ifdef UNZIP_SUPPORT + if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); + return (0); + } - // its a valid ZIP, close it and let LoadZIP handle it. + strcpy(ROMFilename, fname); +#else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); + return (0); +#endif + break; + } - unzClose(file); + case FILE_JMA: + { +#ifdef JMA_SUPPORT + size_t size = load_jma_file(fname, buffer); + if (!size) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive."); + return (0); + } - if (!LoadZip (fname, &TotalFileSize, &HeaderCount, ROM)) + totalSize = HeaderRemove(size, HeaderCount, buffer); + + strcpy(ROMFilename, fname); +#else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); + return (0); +#endif + break; + } + + case FILE_DEFAULT: + default: + { + STREAM fp = OPEN_STREAM(fname, "rb"); + if (!fp) return (0); - strcpy (ROMFilename, fname); + strcpy(ROMFilename, fname); - } - else - { - // its a bad zip file. Walk away + int len = 0; + uint32 size = 0; + bool8 more = FALSE; + uint8 *ptr = buffer; - S9xMessage (S9X_ERROR, S9X_ROM_INFO, "Invalid Zip Archive."); - return (0); - } -#else - S9xMessage (S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); - return (0); -#endif - break; - - case FILE_JMA: - { -#ifdef JMA_SUPPORT - size_t FileSize = load_jma_file(fname, ROM); - - if (!FileSize) - { - S9xMessage (S9X_ERROR, S9X_ROM_INFO, "Invalid JMA."); - return (0); - } - - TotalFileSize = FileSize; - HeaderCount = 0; - - size_t calc_size = (FileSize / 0x2000) * 0x2000; - - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) - { - memmove (ROM, ROM + 512, calc_size); - HeaderCount = 1; - FileSize -= 512; - } - - strcpy (ROMFilename, fname); -#else - S9xMessage (S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); - return (0); -#endif - break; - } - - case FILE_RAR: - // non existant rar loading - S9xMessage (S9X_ERROR, S9X_ROM_INFO, "Rar Archives are not currently supported."); - return (0); - break; - - case FILE_DEFAULT: - default: - // any other roms go here - - if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL) - return (0); - - strcpy (ROMFilename, fname); - - HeaderCount = 0; - uint8 *ptr = buffer; - bool8 more = FALSE; - - do - { - FileSize = READ_STREAM (ptr, maxsize + 0x200 - (ptr - ROM), ROMFile); - CLOSE_STREAM (ROMFile); - - int calc_size = (FileSize / 0x2000) * 0x2000; - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) + do { - memmove (ptr, ptr + 512, calc_size); - HeaderCount++; - FileSize -= 512; - } + size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); + CLOSE_STREAM(fp); - ptr += FileSize; - TotalFileSize += FileSize; + size = HeaderRemove(size, HeaderCount, ptr); + totalSize += size; + ptr += size; + // check for multi file roms + if (ptr - buffer < maxsize + 0x200 && + (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) + { + more = TRUE; + ext[0]++; + _makepath(fname, drive, dir, name, exts); + } + else + if (ptr - buffer < maxsize + 0x200 && + (((len = strlen(name)) == 7 || len == 8) && + strncasecmp(name, "sf", 2) == 0 && + isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) && + isalpha(name[len - 1]))) + { + more = TRUE; + name[len - 1]++; + _makepath(fname, drive, dir, name, exts); + } + else + more = FALSE; - // check for multi file roms + } while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL); - if (ptr - ROM < maxsize + 0x200 && - (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9')) - { - more = TRUE; - ext [0]++; -#if defined(__WIN32__) || defined(__MACOSX__) - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else if (ptr - ROM < maxsize + 0x200 && - (((len = strlen (name)) == 7 || len == 8) && - strncasecmp (name, "sf", 2) == 0 && - isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) && - isdigit (name [5]) && isalpha (name [len - 1]))) - { - more = TRUE; - name [len - 1]++; -#if defined(__WIN32__) || defined(__MACOSX__) - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else - more = FALSE; - - } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL); - - break; - } + break; + } #else - - /*** Nintendo Gamecube ARAM ROM File Loader +//#include "ftfont.h" +/*** Nintendo Gamecube ARAM ROM File Loader This is simply a modified version of FILE_DEFAULT, which uses the ARAM as temporary ROM storage. @@ -1146,662 +1149,311 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize) HeaderCount = 0; uint8 *ptr = buffer; - unsigned long ARAM_max = maxsize + 0x200 - (ptr - ROM); - FileSize = ARAM_ROMSIZE; + long unsigned int size = 0; + uint32 ARAM_max = maxsize + 0x200 - (ptr - buffer); + size = ARAM_ROMSIZE; - if ( FileSize > ARAM_max ) - FileSize = ARAM_max; + if ( size > ARAM_max ) + size = ARAM_max; if ( hasloaded == 0 ) - ARAMFetchSlow( (char *)ptr, (char *)AR_SNESROM, FileSize ); + ARAMFetchSlow( (char *)ptr, (char *)AR_SNESROM, size ); - int calc_size = (FileSize / 0x2000) * 0x2000; - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) - { - memmove (ptr, ptr + 512, calc_size); - HeaderCount++; - FileSize -= 512; - } - - ptr += FileSize; - TotalFileSize += FileSize; + size = HeaderRemove(size, HeaderCount, ptr); + ptr += size; + totalSize += size; #endif - if (HeaderCount == 0) - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); else - { - if (HeaderCount == 1) - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, - "Found ROM file header (and ignored it)."); + if (HeaderCount == 1) + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it)."); + else + S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them)."); + + return ((uint32) totalSize); +} +bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) +{ + bool8 r = TRUE; + + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + + Settings.DisplayColor = 0xffff; + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + if (cartA && cartA[0]) + Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE); + + if (Multi.cartSizeA == 0) + { + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + } + + if (Multi.cartSizeA) + { + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA)) + Multi.cartType = 4; else - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, - "Found multiple ROM file headers (and ignored them)."); - } - - - return TotalFileSize; - -} - -#if 0 -/**********************************************************************************************/ -/* LoadMulti() */ -/* This function loads a Slotted SNES-Backup image and fills the slot. */ -/**********************************************************************************************/ - -bool8 CMemory::LoadMulti (const char *basename, const char *slot1name, const char *slot2name) -{ - unsigned long FileSize = 0; - - if(*basename=='\0') - return FALSE; - - SufamiTurbo=TRUE; - - int32 offset; - - memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - - CalculatedSize = 0; - - Settings.DisplayColor=0xffff; - SET_UI_COLOR(255,255,255); - - int32 TotalFileSize = FileLoader(ROM, basename, MAX_ROM_SIZE); - - if(0== TotalFileSize) return FALSE; - -#ifndef NGC - CheckForIPSPatch (basename, HeaderCount != 0, TotalFileSize); -#endif - - CalculatedSize=TotalFileSize; - - for(offset=0; offset0x100000||size <0x80000) - return FALSE; - //probably a minicart - return TRUE; - } - return FALSE; -} - -bool8 SameGameSig(uint8* file, int32 size) -{ - //preheader sig - if(strcmp((char*)(file+0xFFA0),"1995/12/16 10:2018ZS5J")) - return FALSE; - if(size!=0x100000) - return FALSE; - if(0x133E1C5B==caCRC32(file, size)) - return TRUE; - return FALSE; -} -bool8 GNextSig(uint8* file, int32 size) -{ - //preheader sig - if(strcmp((char*)(file+0xFFAA),"GNEXT B2ZX3J")) - return FALSE; - if(size!=0x180000) - return FALSE; - if(0x845E420D==caCRC32(file, size)) - return TRUE; - return FALSE; -} -int MultiType(uint8* file, int32 size) -{ - //check for ST signiture - if(SufamiTurboBIOSSig(file, size)) - return 1; - //check for Same Game signiture - if(SameGameSig(file, size)) - return 2; - //check for G-Next signiture - if(GNextSig(file, size)) - return 3; - return 0; -} - -#endif - -//compatibility wrapper -void S9xDeinterleaveMode2 () -{ - S9xDeinterleaveType2(); -} - -void S9xDeinterleaveType2 (bool8 reset) -{ - if(Settings.DisplayColor==0xffff||Settings.DisplayColor==BUILD_PIXEL(0,31,0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,14,6); - SET_UI_COLOR(255,119,25); - - } - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); - - int nblocks = Memory.CalculatedSize >> 16; - int step = 64; - - while (nblocks <= step) - step >>= 1; - - nblocks = step; - uint8 blocks [256]; - int i; - - for (i = 0; i < nblocks * 2; i++) - { - blocks [i] = (i & ~0xF) | ((i & 3) << 2) | - ((i & 12) >> 2); - } - - uint8 *tmp = (uint8 *) malloc (0x10000); - - if (tmp) - { - for (i = 0; i < nblocks * 2; i++) - { - for (int j = i; j < nblocks * 2; j++) - { - if (blocks [j] == i) - { - memmove (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000); - memmove (&Memory.ROM [blocks [j] * 0x10000], - &Memory.ROM [blocks [i] * 0x10000], 0x10000); - memmove (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000); - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; - break; - } - } - } - free ((char *) tmp); - tmp=NULL; - } - if(reset) - { - Memory.InitROM (FALSE); - S9xReset (); - } -} - -//CRC32 for char arrays -inline uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32) -{ - for (register uint32 i = 0; i < size; i++) - { - crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; - } - return ~crc32; -} - -void CMemory::InitROM (bool8 Interleaved) -{ -#ifndef ZSNES_FX - SuperFX.nRomBanks = CalculatedSize >> 15; -#endif - Settings.DSP1Master = Settings.ForceDSP1; - Settings.SuperFX = FALSE; - Settings.SA1 = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - Settings.SRTC = FALSE; - Settings.SPC7110=FALSE; - Settings.SPC7110RTC=FALSE; - Settings.BS=FALSE; - Settings.OBC1=FALSE; - Settings.SETA=FALSE; - s7r.DataRomSize = 0; - CalculatedChecksum=0; - - uint8* RomHeader; - - RomHeader=ROM+0x7FB0; - - if(ExtendedFormat==BIGFIRST) - RomHeader+=0x400000; - - if(HiROM) - RomHeader+=0x8000; - - for (int i = 0; i < MEMMAP_NUM_BLOCKS; i++) - { - Map [MEMMAP_NUM_BLOCKS] = (uint8 *) MAP_NONE; - BlockIsRAM [MEMMAP_NUM_BLOCKS] = FALSE; - BlockIsROM [MEMMAP_NUM_BLOCKS] = FALSE; - } - - S9xInitBSX(); - - ::SRAM = SRAM; - memset (ROMId, 0, 5); - memset (CompanyId, 0, 3); - - ParseSNESHeader(RomHeader); - - // Try to auto-detect the DSP1 chip - if (!Settings.ForceNoDSP1 && - (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0) - Settings.DSP1Master = TRUE; - - if (Memory.HiROM) - { - // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2 - Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5; - - if(((ROMSpeed&0x0F)==0x0A)&&((ROMType&0xF0)==0xF0)) - { - Settings.SPC7110=true; - if((ROMType&0x0F)==0x09) - Settings.SPC7110RTC=true; - } - - if (Settings.BS) - /* Do nothing */; - else if(Settings.SPC7110) - { - SPC7110HiROMMap(); - } - else if ((ROMSpeed & ~0x10) == 0x25) - { - TalesROMMap (Interleaved); - } - else HiROMMap (); - } - else - { - Settings.SuperFX = Settings.ForceSuperFX; - - if(ROMType==0x25) - { - Settings.OBC1=TRUE; - } - - if ((ROMType & 0xf0) == 0x10) - Settings.SuperFX = !Settings.ForceNoSuperFX; - - Settings.SDD1 = Settings.ForceSDD1; - if ((ROMType & 0xf0) == 0x40) - Settings.SDD1 = !Settings.ForceNoSDD1; - - if (Settings.SDD1) - S9xLoadSDD1Data (); - - if(((ROMType &0xF0) == 0xF0)&((ROMSpeed&0x0F)!=5)) - { - SRAMSize=2; - SNESGameFixes.SRAMInitialValue = 0x00; - if((ROMType &0x0F)==6) - { - if(ROM[0x7FD7]==0x09) - { - Settings.SETA=ST_011; - SetSETA=&S9xSetST011; - GetSETA=&S9xGetST011; - } - else - { - Settings.SETA=ST_010; - SetSETA=&S9xSetST010; - GetSETA=&S9xGetST010; - } - } - else - { - Settings.SETA=ST_018; - SRAMSize=2; - } - } - - Settings.C4 = Settings.ForceC4; - if ((ROMType & 0xf0) == 0xf0 && - (strncmp (ROMName, "MEGAMAN X", 9) == 0 || - strncmp (ROMName, "ROCKMAN X", 9) == 0)) - { - Settings.C4 = !Settings.ForceNoC4; - } - - if(Settings.SETA&&Settings.SETA!=ST_018) - { - SetaDSPMap(); - } - else if (Settings.SuperFX) - { - //::SRAM = ROM + 1024 * 1024 * 4; - SuperFXROMMap (); - Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.SA1 = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - } - else if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && - (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) - { - Settings.SA1 = TRUE; -// Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - SA1ROMMap (); - } - else if ((ROMSpeed & ~0x10) == 0x25) - TalesROMMap (Interleaved); - else if(ExtendedFormat!=NOPE) - JumboLoROMMap(Interleaved); - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) - { - LoROM24MBSMap (); - Settings.DSP1Master = FALSE; - } - - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) - { - SRAM512KLoROMMap (); - Settings.DSP1Master = FALSE; - } - else if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0) - { - Settings.MultiPlayer5Master = FALSE; - Settings.MouseMaster = FALSE; - Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - SufamiTurboLoROMMap(); - Memory.SRAMSize = 3; - } - else if ((ROMSpeed & ~0x10) == 0x22 && - strncmp (ROMName, "Super Street Fighter", 20) != 0) - { - AlphaROMMap (); - } - else if (Settings.BS) - /* Do nothing */; - else LoROMMap (); - } - - uint32 sum1 = 0; - uint32 sum2 = 0; - if(0==CalculatedChecksum) - { - int power2 = 0; - int size = CalculatedSize; - - while (size >>= 1) - power2++; - - size = 1 << power2; - uint32 remainder = CalculatedSize - size; - - - int i; - - for (i = 0; i < size; i++) - sum1 += ROM [i]; - - for (i = 0; i < (int) remainder; i++) - sum2 += ROM [size + i]; - - int sub = 0; - if (Settings.BS && !Settings.BSXItself) - { - if (Memory.HiROM) - { - for (i = 0; i < 48; i++) - sub += ROM[0xffb0 + i]; - } - else if (Memory.LoROM) - { - for (i = 0; i < 48; i++) - sub += ROM[0x7fb0 + i]; - } - sum1 -= sub; - } - - - if (remainder) - { - sum1 += sum2 * (size / remainder); - } - - - sum1 &= 0xffff; - Memory.CalculatedChecksum=sum1; - } - //now take a CRC32 - ROMCRC32 = caCRC32(ROM, CalculatedSize); - - if (Settings.ForceNTSC) - Settings.PAL = FALSE; - else if (Settings.ForcePAL) - Settings.PAL = TRUE; - else - { - //Korea refers to South Korea, which uses NTSC - switch(ROMRegion) - { - case 13: - case 1: - case 0: - Settings.PAL=FALSE; - break; - default: Settings.PAL=TRUE; - break; - } - } - - Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE; - Timings.H_Max = Timings.H_Max_Master; - Timings.HBlankStart = SNES_HBLANK_START_HC; - Timings.HBlankEnd = SNES_HBLANK_END_HC; - Timings.HDMAInit = SNES_HDMA_INIT_HC; - Timings.HDMAStart = SNES_HDMA_START_HC; - Timings.RenderPos = SNES_RENDER_START_HC; - Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER; - Timings.V_Max = Timings.V_Max_Master; - - if (Settings.PAL) - { - Settings.FrameTime = Settings.FrameTimePAL; - Memory.ROMFramesPerSecond = 50; + if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) + Multi.cartType = 3; } else + if (Multi.cartSizeB) { - Settings.FrameTime = Settings.FrameTimeNTSC; - Memory.ROMFramesPerSecond = 60; + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartType = 4; + } + else + Multi.cartType = 4; // assuming BIOS only + + switch (Multi.cartType) + { + case 4: + r = LoadSufamiTurbo(cartA, cartB); + break; + + case 3: + r = LoadSameGame(cartA, cartB); + break; + + default: + r = FALSE; } - ROMName[ROM_NAME_LEN - 1] = 0; - if (strlen (ROMName)) + if (!r) { - char *p = ROMName + strlen (ROMName); - if(p>ROMName+21 && ROMName[20]==' ') p=ROMName+21; - - while (p > ROMName && *(p - 1) == ' ') - p--; - *p = 0; + ZeroMemory(&Multi, sizeof(Multi)); + return (FALSE); } + FreeSDD1Data(); + if (CleanUp7110) + (*CleanUp7110)(); + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + +#ifndef NGC + S9xLoadCheatFile(S9xGetFilename(".cht", PATCH_DIR)); +#endif + + InitROM(); + +#ifndef NGC + S9xInitCheatData(); + S9xApplyCheats(); +#endif + + S9xReset(); + + return (TRUE); +} + +bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0x100000; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = SRAM + 0x10000; + + if (Multi.cartSizeA) { - SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; + Multi.sramSizeA = 4; // ROM[0x37]? + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + +#ifndef NGC + if (!Settings.NoPatch) + CheckForIPSPatch(cartA, HeaderCount != 0, Multi.cartSizeA); +#endif + strcpy(Multi.fileNameA, cartA); + memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); } - if((ROMChecksum + ROMComplementChecksum != 0xffff) || ROMChecksum != CalculatedChecksum || ((uint32)CalculatedSize > (uint32)(((1<<(ROMSize-7))*128)*1024))) + + if (Multi.cartSizeA && !Multi.cartSizeB) { - if(Settings.DisplayColor==0xffff || Settings.DisplayColor!=BUILD_PIXEL(31,0,0)) + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + + if (Multi.cartSizeB) { - Settings.DisplayColor=BUILD_PIXEL(31,31,0); - SET_UI_COLOR(255,255,0); + if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartSizeB = 0; } } - IAPU.OneCycle = ONE_APU_CYCLE; - Settings.Shutdown = Settings.ShutdownMaster; + if (Multi.cartSizeB) + { + Multi.sramSizeB = 4; // ROM[0x37]? + Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; - SetDSP=&DSP1SetByte; - GetDSP=&DSP1GetByte; - - CPU.FastROMSpeed = 0; - ResetSpeedMap(); - ApplyROMFixes (); - - char displayName[ROM_NAME_LEN]; - strcpy (RawROMName, ROMName); - sprintf (displayName, "%s", SafeANK (ROMName)); - sprintf (ROMName, "%s", Safe (ROMName)); - sprintf (ROMId, "%s", Safe (ROMId)); - sprintf (CompanyId, "%s", Safe (CompanyId)); - - sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s CRC32: %08X", - displayName, - (ROMChecksum + ROMComplementChecksum != 0xffff || - ROMChecksum != CalculatedChecksum) ? "bad checksum" : "checksum ok", - MapType (), - Size (), - KartContents (), - MapMode (), - TVStandard (), - StaticRAMSize (), - ROMId, - CompanyId, - ROMCRC32); - - S9xMessage (S9X_INFO, S9X_ROM_INFO, String); -#ifdef __WIN32__ - #ifndef _XBOX - EnableMenuItem(GUI.hMenu, IDM_ROM_INFO, MF_ENABLED); - #endif - #ifdef RTC_DEBUGGER - if(Settings.SPC7110RTC) - EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_ENABLED); - else EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_GRAYED); - #endif +#ifndef NGC + if (!Settings.NoPatch) + CheckForIPSPatch(cartB, HeaderCount != 0, Multi.cartSizeB); #endif - Settings.ForceHeader = Settings.ForceHiROM = Settings.ForceLoROM = - Settings.ForceInterleaved = Settings.ForceNoHeader = Settings.ForceNotInterleaved = - Settings.ForceInterleaved2=false; + strcpy(Multi.fileNameB, cartB); + memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); + } - S9xVerifyControllers(); + FILE *fp; + size_t size; + char path[_MAX_PATH + 1]; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcat(path, "STBIOS.bin"); + + fp = fopen(path, "rb"); + if (fp) + { + size = fread((void *) ROM, 1, 0x40000, fp); + fclose(fp); + if (!is_SufamiTurbo_BIOS(ROM, size)) + return (FALSE); + } + else + return (FALSE); + + if (Multi.cartSizeA) + strcpy(ROMFilename, Multi.fileNameA); + else + if (Multi.cartSizeB) + strcpy(ROMFilename, Multi.fileNameB); + else + strcpy(ROMFilename, path); + + LoROM = TRUE; + HiROM = FALSE; + CalculatedSize = 0x40000; + + return (TRUE); +} + +bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = NULL; + + Multi.sramSizeA = ROM[0xffd8]; + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + Multi.sramSizeB = 0; + Multi.sramMaskB = 0; + +#ifndef NGC + if (!Settings.NoPatch) + CheckForIPSPatch(cartA, HeaderCount != 0, Multi.cartSizeA); +#endif + strcpy(Multi.fileNameA, cartA); + + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB); + + if (Multi.cartSizeB) + { + if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; + else + strcpy(Multi.fileNameB, cartB); + } + + strcpy(ROMFilename, Multi.fileNameA); + + LoROM = FALSE; + HiROM = TRUE; + CalculatedSize = Multi.cartSizeA; + + return (TRUE); +} + +bool8 CMemory::LoadLastROM (void) +{ + if (Multi.cartType) + return (FALSE); + + bool8 r; + + stopMovie = FALSE; + r = LoadROM(LastRomFilename); + stopMovie = TRUE; + + return (r); +} + +void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) +{ + if(onlyNonSavedSRAM) + if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM + return; + + memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); } bool8 CMemory::LoadSRAM (const char *filename) { - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; + ClearSRAM(); - memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); - - if (size > 0x20000) - size = 0x20000; #ifndef NGC - if (size) - { - FILE *file; - if ((file = fopen (filename, "rb"))) + FILE *file; + int size, len; + char sramName[_MAX_PATH + 1]; + strcpy(sramName, filename); + + + if (Multi.cartType && Multi.sramSizeB) + { + char temp[_MAX_PATH + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb"); + if (file) { - int len = fread ((char*) ::SRAM, 1, 0x20000, file); - fclose (file); + len = fread((char *) Multi.sramB, 1, 0x10000, file); + fclose(file); if (len - size == 512) - { - // S-RAM file has a header - remove it - memmove (::SRAM, ::SRAM + 512, size); - } + memmove(Multi.sramB, Multi.sramB + 512, size); + } + + strcpy(ROMFilename, temp); + } + + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + if (size > 0x20000) + size = 0x20000; + + if (size) + { + file = fopen(sramName, "rb"); + if (file) + { + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + if (len == size + SRTC_SRAM_PAD) { - S9xSRTCPostLoadState (); - S9xResetSRTC (); + S9xSRTCPostLoadState(); + S9xResetSRTC(); rtc.index = -1; rtc.mode = MODE_READ; } else - S9xHardResetSRTC (); + S9xHardResetSRTC(); - if(Settings.SPC7110RTC) - { - S9xLoadSPC7110RTC (&rtc_f9); - } + if (Settings.SPC7110RTC) + S9xLoadSPC7110RTC(&rtc_f9); return (TRUE); } @@ -1810,17 +1462,20 @@ bool8 CMemory::LoadSRAM (const char *filename) { // The BS game's SRAM was not found // Try to read BS-X.srm instead - char path[_MAX_PATH + 1]; strcpy(path, S9xGetDirectory(SRAM_DIR)); strcat(path, SLASH_STR); strcat(path, "BS-X.srm"); - if ((file = fopen(path, "rb"))) + file = fopen(path, "rb"); + if (file) { - fread((char *) ::SRAM, 1, 0x20000, file); - fclose (file); + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead."); S9xHardResetSRTC(); return (TRUE); @@ -1833,2325 +1488,1845 @@ bool8 CMemory::LoadSRAM (const char *filename) } } - S9xHardResetSRTC (); + S9xHardResetSRTC(); return (FALSE); - } - if (Settings.SDD1) - S9xSDD1LoadLoggedData (); + } + if (Settings.SDD1) + S9xSDD1LoadLoggedData(); #endif - return (TRUE); + return (TRUE); } bool8 CMemory::SaveSRAM (const char *filename) { - if(Settings.SuperFX && Memory.ROMType < 0x15) - return TRUE; - if(Settings.SA1 && Memory.ROMType == 0x34) - return TRUE; + if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM + return (TRUE); - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (Settings.SRTC) - { - size += SRTC_SRAM_PAD; - S9xSRTCPreSaveState (); + if (Settings.SA1 && ROMType == 0x34) // doesn't have SRAM + return (TRUE); + + FILE *file; + int size; + char sramName[_MAX_PATH + 1]; + + strcpy(sramName, filename); + + if (Multi.cartType && Multi.sramSizeB) + { + char name[_MAX_PATH + 1], temp[_MAX_PATH + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + strcpy(name, S9xGetFilename(".srm", SRAM_DIR)); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(name, "wb"); + if (file) + { + fwrite((char *) Multi.sramB, size, 1, file); + fclose(file); +#ifdef __linux + chown(name, getuid(), getgid()); +#endif + } + + strcpy(ROMFilename, temp); } - if (Settings.SDD1) - S9xSDD1SaveLoggedData (); + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; - if (size > 0x20000) + if (Settings.SRTC) + { + size += SRTC_SRAM_PAD; + S9xSRTCPreSaveState(); + } + + if (Settings.SDD1) + S9xSDD1SaveLoggedData(); + + if (size > 0x20000) size = 0x20000; - if (size && *Memory.ROMFilename) - { - FILE *file; - if ((file = fopen (filename, "wb"))) + if (size) + { + file = fopen(sramName, "wb"); + if (file) { - fwrite ((char *) ::SRAM, size, 1, file); - fclose (file); -#if defined(__linux) - chown (filename, getuid (), getgid ()); + fwrite((char *) SRAM, size, 1, file); + fclose(file); +#ifdef __linux + chown(sramName, getuid(), getgid()); #endif - if(Settings.SPC7110RTC) - { - S9xSaveSPC7110RTC (&rtc_f9); - } + if (Settings.SPC7110RTC) + S9xSaveSPC7110RTC(&rtc_f9); + return (TRUE); } - } - return (FALSE); -} - -void CMemory::FixROMSpeed () -{ - int c; - - if(CPU.FastROMSpeed==0) - CPU.FastROMSpeed=SLOW_ONE_CYCLE; - - - for (c = 0x800; c < 0x1000; c++) - { - if (c&0x8 || c&0x400) - MemorySpeed [c] = (uint8) CPU.FastROMSpeed; - } -} - - -void CMemory::ResetSpeedMap() -{ - int i; - memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); - for(i=0;i<0x400;i+=0x10) - { - MemorySpeed[i+2]=MemorySpeed[0x800+i+2]= ONE_CYCLE; - MemorySpeed[i+3]=MemorySpeed[0x800+i+3]= ONE_CYCLE; - MemorySpeed[i+4]=MemorySpeed[0x800+i+4]= ONE_CYCLE; - MemorySpeed[i+5]=MemorySpeed[0x800+i+5]= ONE_CYCLE; } - CMemory::FixROMSpeed (); + + return (FALSE); } -void CMemory::WriteProtectROM () +// initialization + +static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32) { - memmove ((void *) WriteMap, (void *) Map, sizeof (Map)); - for (int c = 0; c < 0x1000; c++) - { - if (BlockIsROM [c]) - WriteMap [c] = (uint8 *) MAP_NONE; - } + for (uint32 i = 0; i < size; i++) + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; + + return (~crc32); } -void CMemory::MapRAM () +char * CMemory::Safe (const char *s) { - int c; + static char *safe = NULL; + static int safe_len = 0; - if(Memory.LoROM&&!Settings.SDD1) + if (s == NULL) { - // Banks 70->77, S-RAM - for (c = 0; c < 0x0f; c++) + if (safe) { - for(int i=0;i<8;i++) - { - Map [(c<<4) + 0xF00+i]=Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [(c<<4) + 0xF00+i] =BlockIsRAM [(c<<4) + 0x700+i] = TRUE; - BlockIsROM [(c<<4) + 0xF00+i] =BlockIsROM [(c<<4) + 0x700+i] = FALSE; - } + free(safe); + safe = NULL; } + + return (NULL); } - else if(Memory.LoROM&&Settings.SDD1) + + int len = strlen(s); + if (!safe || len + 1 > safe_len) { - // Banks 70->77, S-RAM - for (c = 0; c < 0x0f; c++) + if (safe) + free(safe); + + safe_len = len + 1; + safe = (char *) malloc(safe_len); + } + + for (int i = 0; i < len; i++) + { + if (s[i] >= 32 && s[i] < 127) + safe[i] = s[i]; + else + safe[i] = '_'; + } + + safe[len] = 0; + + return (safe); +} + +char * CMemory::SafeANK (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + if (s == NULL) + { + if (safe) { - for(int i=0;i<8;i++) - { - Map [(c<<4) + 0x700+i] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [(c<<4) + 0x700+i] = TRUE; - BlockIsROM [(c<<4) + 0x700+i] = FALSE; - } + free(safe); + safe = NULL; } + + return (NULL); } - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); -} -void CMemory::MapExtraRAM () -{ - int c; - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->73, S-RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x700] = ::SRAM; - Map [c + 0x710] = ::SRAM + 0x8000; - Map [c + 0x720] = ::SRAM + 0x10000; - Map [c + 0x730] = ::SRAM + 0x18000; - - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - BlockIsRAM [c + 0x710] = TRUE; - BlockIsROM [c + 0x710] = FALSE; - BlockIsRAM [c + 0x720] = TRUE; - BlockIsROM [c + 0x720] = FALSE; - BlockIsRAM [c + 0x730] = TRUE; - BlockIsROM [c + 0x730] = FALSE; - } -} - -void CMemory::LoROMMap () -{ - int c; - int i; - int j; - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; - - mask[0]=(CalculatedSize/0x8000)-1; - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) + int len = strlen(s); + if (!safe || len + 1 > safe_len) { - x=1; - foundZeros=false; - pastZeros=false; + if (safe) + free(safe); - mask[j+1]=mask[j]; + safe_len = len + 1; + safe = (char *) malloc(safe_len); + } - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) + for (int i = 0; i < len; i++) + { + if (s[i] >= 32 && s[i] < 127) // ASCII + safe [i] = s[i]; + else + if (ROMRegion == 0 && ((uint8) s[i] >= 0xa0 && (uint8) s[i] < 0xe0)) // JIS X 201 - Katakana + safe [i] = s[i]; + else + safe [i] = '_'; + } + + safe [len] = 0; + + return (safe); +} + +void CMemory::ParseSNESHeader (uint8 *RomHeader) +{ + bool8 bs = Settings.BS & !Settings.BSXItself; + + strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); + if (bs) + memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17); + + if (bs) + { + if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || + (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000))) + printf("BS: Size mismatch\n"); + + // FIXME + int p = 0; + while ((1 << p) < (int) CalculatedSize) + p++; + ROMSize = p - 10; + } + else + ROMSize = RomHeader[0x27]; + + SRAMSize = bs ? 5 /* BS-X */ : RomHeader[0x28]; + ROMSpeed = bs ? RomHeader[0x28] : RomHeader[0x25]; + ROMType = bs ? 0xE5 /* BS-X */ : RomHeader[0x26]; + ROMRegion = bs ? 0 : RomHeader[0x29]; + + ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8); + ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8); + + memmove(ROMId, &RomHeader[0x02], 4); + + if (RomHeader[0x2A] == 0x33) + memmove(CompanyId, &RomHeader[0x00], 2); + else + sprintf(CompanyId, "%02X", RomHeader[0x2A]); +} + +void CMemory::InitROM (void) +{ + Settings.DSP1Master = FALSE; + Settings.SuperFX = FALSE; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + Settings.SRTC = FALSE; + Settings.SPC7110 = FALSE; + Settings.SPC7110RTC = FALSE; + Settings.BS = FALSE; + Settings.OBC1 = FALSE; + Settings.SETA = FALSE; +#ifndef ZSNES_FX + SuperFX.nRomBanks = CalculatedSize >> 15; +#endif + s7r.DataRomSize = 0; + + //// Parse ROM header and read ROM informatoin + + memset(ROMId, 0, 5); + memset(CompanyId, 0, 3); + + uint8 *RomHeader = ROM + 0x7FB0; + if (ExtendedFormat == BIGFIRST) + RomHeader += 0x400000; + if (HiROM) + RomHeader += 0x8000; + + S9xInitBSX(); // Set BS header before parsing + + ParseSNESHeader(RomHeader); + + //// Detect and initialize chips + //// detection codes are compatible with NSRT + + // DSP1/2/3/4 + Settings.DSP1Master = Settings.ForceDSP1; + DSP1.version = 0xff; + + if (ROMType == 0x03) + { + if (ROMSpeed == 0x30) + DSP1.version = 3; // DSP4 + else + DSP1.version = 0; // DSP1 + } + else + if (ROMType == 0x05) + { + if (ROMSpeed == 0x20) + DSP1.version = 1; // DSP2 + else + if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2) + DSP1.version = 2; // DSP3 + else + DSP1.version = 0; // DSP1 + } + + if (DSP1.version != 0xff) + Settings.DSP1Master = !Settings.ForceNoDSP1; + + switch (DSP1.version) + { + case 0: // DSP1 + if (HiROM) { - x<<=1; - if(foundZeros) - pastZeros=true; + DSP1.boundary = 0x7000; + DSP1.maptype = M_DSP1_HIROM; + } + else + if (CalculatedSize > 0x100000) + { + DSP1.boundary = 0x4000; + DSP1.maptype = M_DSP1_LOROM_L; } else { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP1_LOROM_S; } - } + + SetDSP = &DSP1SetByte; + GetDSP = &DSP1GetByte; + break; + + case 1: // DSP2 + DSP1.boundary = 0x10000; + DSP1.maptype = M_DSP2_LOROM; + SetDSP = &DSP2SetByte; + GetDSP = &DSP2GetByte; + break; + + case 2: // DSP3 + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP3_LOROM; + SetDSP = &DSP3SetByte; + GetDSP = &DSP3GetByte; + DSP3_Reset(); + break; + + case 3: // DSP4 + DSP1.boundary = 0xc000; + DSP1.maptype = M_DSP4_LOROM; + SetDSP = &DSP4SetByte; + GetDSP = &DSP4GetByte; + break; + + default: + SetDSP = NULL; + GetDSP = NULL; + break; } + Settings.SA1 = Settings.ForceSA1; + Settings.SuperFX = Settings.ForceSuperFX; + Settings.SDD1 = Settings.ForceSDD1; + Settings.C4 = Settings.ForceC4; - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + uint32 identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff); - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - if(Settings.SETA==ST_018) - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_SETA_RISC; - else Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else if (Settings.C4) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; - } - else if(Settings.OBC1) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_OBC_RAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_OBC_RAM; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=(c+0x400)>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - - Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); - } - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - BlockIsROM [c + 0xe00] = FALSE; - } - } - - int sum=0, k,l, bankcount; - bankcount=1<<(ROMSize-7);//Mbits - - //safety for corrupt headers - if(bankcount > 128) - bankcount = (CalculatedSize/0x8000)/4; - bankcount*=4;//to banks - bankcount<<=4;//Map banks - bankcount+=0x800;//normalize - for(k=0x800;k<(bankcount);k+=16) + switch (identifier) { - uint8* bank=0x8000+Map[k+8]; - for(l=0;l<0x8000;l++) - sum+=bank[l]; - } - CalculatedChecksum=sum&0xFFFF; + // SRTC + case 0x5535: + Settings.SRTC = TRUE; + break; - MapRAM (); - WriteProtectROM (); -} + // SPC7110 + case 0xF93A: + Settings.SPC7110RTC = TRUE; + case 0xF53A: + Settings.SPC7110 = TRUE; + S9xSpc7110Init(); + break; -void CMemory::SetaDSPMap () -{ - int c; - int i; - int j; - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; + // OBC1 + case 0x2530: + Settings.OBC1 = TRUE; + break; - mask[0]=(CalculatedSize/0x8000)-1; + // SA1 + case 0x3423: + case 0x3523: + Settings.SA1 = !Settings.ForceNoSA1; + break; - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) + // SuperFX + case 0x1320: + case 0x1420: + case 0x1520: + case 0x1A20: + Settings.SuperFX = !Settings.ForceNoSuperFX; + if (Settings.SuperFX) { - x<<=1; - if(foundZeros) - pastZeros=true; + if (ROM[0x7FDA] == 0x33) + SRAMSize = ROM[0x7FBD]; + else + SRAMSize = 5; + } + + break; + + // SDD1 + case 0x4332: + case 0x4532: + Settings.SDD1 = !Settings.ForceNoSDD1; + if (Settings.SDD1) + S9xLoadSDD1Data(); + break; + + // ST018 + case 0xF530: + Settings.SETA = ST_018; + SetSETA = NULL; + GetSETA = NULL; + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // ST010/011 + case 0xF630: + if (ROM[0x7FD7] == 0x09) + { + Settings.SETA = ST_011; + SetSETA = &S9xSetST011; + GetSETA = &S9xGetST011; } else { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; + Settings.SETA = ST_010; + SetSETA = &S9xSetST010; + GetSETA = &S9xGetST010; } - } + + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // C4 + case 0xF320: + Settings.C4 = !Settings.ForceNoC4; + break; } + //// Map memory and calculate checksum - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) + Map_Initialize(); + CalculatedChecksum = 0; + + if (HiROM) { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (((d)-1)*0x8000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SPC7110) + Map_SPC7110HiROMMap(); + else + if (ExtendedFormat != NOPE) + Map_ExtendedHiROMMap(); + else + if (Multi.cartType == 3) + Map_SameGameHiROMMap(); + else + Map_HiROMMap(); } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) + else { - for (i = c + 8; i < c + 16; i++) + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SETA && Settings.SETA != ST_018) + Map_SetaDSPLoROMMap(); + else + if (Settings.SuperFX) + Map_SuperFXLoROMMap(); + else + if (Settings.SA1) + Map_SA1LoROMMap(); + else + if (Settings.SDD1) + Map_SDD1LoROMMap(); + else + if (ExtendedFormat != NOPE) + Map_JumboLoROMMap(); + else + if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0) + Map_NoMAD1LoROMMap(); + else + if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp(ROMName, "DERBY STALLION 96", 17) == 0) + Map_ROM24MBSLoROMMap(); + else + if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 || + strncmp(ROMName, "RPG-TCOOL 2", 11) == 0) + Map_SRAM512KLoROMMap(); + else + if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0) { - int e=3; - int d=(c+0x400)>>4; - while(d>mask[0]) + if (Multi.cartType == 4) { - d&=mask[e]; - e--; - } - - Map [i + 0x400] = Map [i + 0xc00] = ROM + (((d)-1)*0x8000); - } - - //only upper half is ROM - for (i = c+8; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - memset(SRAM, 0, 0x1000); - for (c=0x600;c<0x680;c+=0x10) - { - for(i=0;i<0x08;i++) - { - //where does the SETA chip access, anyway? - //please confirm this? - Map[c+0x80+i]=(uint8*)MAP_SETA_DSP; - BlockIsROM [c+0x80+i] = FALSE; - BlockIsRAM [c+0x80+i] = TRUE; - } - - for(i=0;i<0x04;i++) - { - //and this! - Map[c+i]=(uint8*)MAP_SETA_DSP; - BlockIsROM [c+i] = FALSE; - } - } - - int sum=0, k,l, bankcount; - bankcount=1<<(ROMSize-7);//Mbits - //safety for corrupt headers - if(bankcount > 128) - bankcount = (CalculatedSize/0x8000)/4; - bankcount*=4;//to banks - bankcount<<=4;//Map banks - bankcount+=0x800;//normalize - for(k=0x800;k<(bankcount);k+=16) - { - uint8* bank=0x8000+Map[k+8]; - for(l=0;l<0x8000;l++) - sum+=bank[l]; - } - CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::HiROMMap () -{ - int i; - int c; - int j; - - int mask[4]; - for (j=0; j<4; j++) - mask[j]=0x00ff; - - mask[0]=(CalculatedSize/0x10000)-1; - - if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && - (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) - { - x=1; - foundZeros=false; - pastZeros=false; - - mask[j+1]=mask[j]; - - while (x>0x100&&!pastZeros) - { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; + SRAMSize = Multi.sramSizeA; + Map_SufamiTurboLoROMMap(); } else { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; + SRAMSize = 5; + Map_SufamiTurboPseudoLoROMMap(); } } - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - for (i = c + 8; i < c + 16; i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i] = Map [i + 0x800] = ROM + (d*0x10000); - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } + Map_LoROMMap(); } - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } + Checksum_Calculate(); - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - int e=3; - int d=(c)>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } - Map [i + 0x400] = Map [i + 0xc00] = ROM + (d*0x10000); - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } + bool8 isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) & + (ROMChecksum == CalculatedChecksum); - int bankmax=0x40+ (1<<(ROMSize-6)); - //safety for corrupt headers - if(bankmax > 128) - bankmax = 0x80; - int sum=0; - for(i=0x40;i3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - //makes more sense to map the range here. - //ToP seems to use sram to skip intro??? - if(c>=0x300) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_HIROM_SRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [6 + c] = BlockIsRAM [7 + c] = - BlockIsRAM [0x806 + c]= BlockIsRAM [0x807 + c] = TRUE; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - } - for (i = c + 8; i < c + 16; i++) - { - Map [i] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET0]; - Map [i + 0x800] = &ROM [((c << 12) % 0x400000) + OFFSET2]; - BlockIsROM [i] = TRUE; - BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - { - Map [i + 0x400] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; - Map [i + 0x408] = &ROM [((c << 12) % (CalculatedSize-0x400000)) + OFFSET1]; - Map [i + 0xc00] = &ROM [((c << 12) %0x400000)+ OFFSET2]; - Map [i + 0xc08] = &ROM [((c << 12) % 0x400000) + OFFSET2]; - BlockIsROM [i + 0x400] = TRUE; - BlockIsROM [i + 0x408] = TRUE; - BlockIsROM [i + 0xc00] = TRUE; - BlockIsROM [i + 0xc08] = TRUE; - } - } - - if((strncmp("TALES",(char*)Map[8]+0xFFC0, 5)==0)) - { - if(((*(Map[8]+0xFFDE))==(*(Map[0x808]+0xFFDE)))) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } + int offset = HiROM ? 0xffc0 : 0x7fc0; + // Backup + uint8 BSMagic0 = ROM[offset + 22], + BSMagic1 = ROM[offset + 23]; + // uCONSRT standard + ROM[offset + 22] = 0x42; + ROM[offset + 23] = 0x00; + // Calc + ROMCRC32 = caCRC32(ROM, CalculatedSize); + // Convert back + ROM[offset + 22] = BSMagic0; + ROM[offset + 23] = BSMagic1; } - ROMChecksum = *(Map[8]+0xFFDE) + (*(Map[8]+0xFFDF) << 8); - ROMComplementChecksum = *(Map[8]+0xFFDC) + (*(Map[8]+0xFFDD) << 8); + // NTSC/PAL + if (Settings.ForceNTSC) + Settings.PAL = FALSE; + else + if (Settings.ForcePAL) + Settings.PAL = TRUE; + else + if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12)) + Settings.PAL = TRUE; + else + Settings.PAL = FALSE; -int sum=0; -for(i=0x40;i<0x80; i++) -{ - uint8 * bank_low=(uint8*)Map[i<<4]; - uint8 * bank_high=(uint8*)Map[(i<<4)+0x800]; - for (c=0;c<0x10000; c++) + + //// Initialize emulation + + Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE; + Timings.H_Max = Timings.H_Max_Master; + Timings.HBlankStart = SNES_HBLANK_START_HC; + Timings.HBlankEnd = SNES_HBLANK_END_HC; + Timings.HDMAInit = SNES_HDMA_INIT_HC; + Timings.HDMAStart = SNES_HDMA_START_HC; + Timings.RenderPos = SNES_RENDER_START_HC; + Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER; + Timings.V_Max = Timings.V_Max_Master; + /* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock), + and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles. + Possible delays: { 12, 14, 16, 18, 20, 22, 24 } + XXX: Snes9x can't emulate this timing :( so let's use the average value... */ + Timings.DMACPUSync = 18; + + + if (Settings.PAL) { - sum+=bank_low[c]; - sum+=bank_high[c]; - } -} - -CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::AlphaROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = TRUE; - } - } - - // Banks 40->7f and c0->ff - - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize]; - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapRAM (); - WriteProtectROM (); -} - -void DetectSuperFxRamSize() -{ - if(ROM[0x7FDA]==0x33) - { - Memory.SRAMSize=ROM[0x7FBD]; + Settings.FrameTime = Settings.FrameTimePAL; + ROMFramesPerSecond = 50; } else { - if(strncmp(Memory.ROMName, "STAR FOX 2", 10)==0) - { - Memory.SRAMSize=6; - } - else Memory.SRAMSize=5; + Settings.FrameTime = Settings.FrameTimeNTSC; + ROMFramesPerSecond = 60; } -} -void CMemory::SuperFXROMMap () -{ - int c; - int i; - - DetectSuperFxRamSize(); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [0x006 + c] = Map [0x806 + c] = (uint8 *) ::SRAM - 0x6000; - Map [0x007 + c] = Map [0x807 + c] = (uint8 *) ::SRAM - 0x6000; - BlockIsRAM [0x006 + c] = BlockIsRAM [0x007 + c] = BlockIsRAM [0x806 + c] = BlockIsRAM [0x807 + c] = TRUE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->71, S-RAM - for (c = 0; c < 32; c++) - { - Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16); - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - - // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K - // block is repeated twice in each 64K block. - for (c = 0; c < 64; c++) - { - memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - } - - WriteProtectROM (); -} - -void CMemory::SA1ROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = FALSE; - } - } - - // c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); - - // Now copy the map and correct it for the SA1 CPU. - memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - memmove ((void *) SA1.Map, (void *) Map, sizeof (Map)); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; - SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; - } - - // Banks 60->6f - for (c = 0; c < 0x100; c++) - SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; - - BWRAM = SRAM; -} - -void CMemory::LoROM24MBSMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x200; c += 16) - { - Map [c + 0x800] = RAM; - Map [c + 0x801] = RAM; - BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000; - BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::SufamiTurboLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - BlockIsROM [c + 0xe00] = FALSE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 60->67, S-RAM - for (c = 0; c < 0x80; c++) - { - Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0x600] = TRUE; - BlockIsROM [c + 0x600] = FALSE; - } - - WriteProtectROM (); -} - -#if 0 - -//untested!! -void CMemory::SameGameMap () -{ - int i; - int c; - int j; - - int mask[4]; - int mask2[4]; - for (j=0; j<4; j++) - mask[j]=mask2[j]=0x00ff; - - mask[0]=(CalculatedSize/0x10000)-1; - mask2[0]=(Slot1Size/0x10000)-1; - - int x; - bool foundZeros; - bool pastZeros; - - for(j=0;j<3;j++) + // truncate cart name + ROMName[ROM_NAME_LEN - 1] = 0; + if (strlen(ROMName)) { - x=1; - foundZeros=false; - pastZeros=false; + char *p = ROMName + strlen(ROMName); + if (p > ROMName + 21 && ROMName[20] == ' ') + p = ROMName + 21; + while (p > ROMName && *(p - 1) == ' ') + p--; + *p = 0; + } - mask[j+1]=mask[j]; + // SRAM size + SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0; - while (x>0x100&&!pastZeros) + // checksum + if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024))) + { + if (Settings.DisplayColor == 0xffff || Settings.DisplayColor != BUILD_PIXEL(31, 0, 0)) { - if(mask[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask[j+1]|=x; - x<<=1; - } + Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); + SET_UI_COLOR(255, 255, 0); } } - for(j=0;j<3;j++) + if (Multi.cartType == 4) { - x=1; - foundZeros=false; - pastZeros=false; - - mask2[j+1]=mask2[j]; - - while (x>0x100&&!pastZeros) - { - if(mask2[j]&x) - { - x<<=1; - if(foundZeros) - pastZeros=true; - } - else - { - foundZeros=true; - pastZeros=false; - mask2[j+1]|=x; - x<<=1; - } - } + Settings.DisplayColor = BUILD_PIXEL(0, 16, 31); + SET_UI_COLOR(0, 128, 255); } + IAPU.OneCycle = SNES_APU_ONE_CYCLE_SCALED; - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; + CPU.FastROMSpeed = 0; + ResetSpeedMap(); - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; + IPPU.TotalEmulatedFrames = 0; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } + Settings.Shutdown = Settings.ShutdownMaster; - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } + //// Hack games - for c=0; c<0x200; c+=16) - { - for(i=0;i<8;i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } + ApplyROMFixes(); - int f=3; - int g=c>>4; - while(g>mask2[0]) - { - g&=mask2[f]; - f--; - } + //// Show ROM information + char displayName[ROM_NAME_LEN]; - //stuff in HiROM areas - Map[c+0x400+i]=&ROM[d*0x10000]; - Map[c+0xC00+i]=&ROM[d*0x10000]; - //MINI - Map[c+0x600+i]=&ROMOffset1[g*0x10000]; - Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; + strcpy(RawROMName, ROMName); + sprintf(displayName, "%s", SafeANK(ROMName)); + sprintf(ROMName, "%s", Safe(ROMName)); + sprintf(ROMId, "%s", Safe(ROMId)); + sprintf(CompanyId, "%s", Safe(CompanyId)); - } - for(i=8;i<16;i++) - { - int e=3; - int d=c>>4; - while(d>mask[0]) - { - d&=mask[e]; - e--; - } + sprintf(String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s CRC32: %08X", + displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"), + MapType(), Size(), KartContents(), MapMode(), TVStandard(), StaticRAMSize(), ROMId, CompanyId, ROMCRC32); + S9xMessage(S9X_INFO, S9X_ROM_INFO, String); - int f=3; - int g=c>>4; - while(g>mask2[0]) - { - g&=mask2[f]; - f--; - } - - - //all stuff - //BASE - Map[c+i]=&ROM[d*0x10000]; - Map[c+0x800+i]=&ROM[d*0x10000]; - Map[c+0x400+i]=&ROM[d*0x10000]; - Map[c+0xC00+i]=&ROM[d*0x10000]; - //MINI - Map[c+0x200+i]=&ROMOffset1[g*0x10000]; - Map[c+0xA00+i]=&ROMOffset1[g*0x10000]; - Map[c+0x600+i]=&ROMOffset1[g*0x10000]; - Map[c+0xE00+i]=&ROMOffset1[g*0x10000]; - } - - } - - int bankmax=0x40+ (1<<(ROMSize-6)); - //safety for corrupt headers - if(bankmax > 128) - bankmax = 0x80; - int sum=0; - for(i=0x40;i3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - - // Banks 40->4f (was 7f, but SNES docs and GNext overdumping shows nothing here.) - for (c = 0; c < 0x100; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = FALSE; - } - } - - for (c = 0; c < 0x100; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x700] = (uint8 *) &ROMOffset1 [(c << 12) & (Slot1Size-1)]; - } - - // c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); - - // Now copy the map and correct it for the SA1 CPU. - memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap)); - memmove ((void *) SA1.Map, (void *) Map, sizeof (Map)); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - SA1.Map [c + 0] = SA1.Map [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.Map [c + 1] = SA1.Map [c + 0x801] = (uint8 *) MAP_NONE; - SA1.WriteMap [c + 0] = SA1.WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1.WriteMap [c + 1] = SA1.WriteMap [c + 0x801] = (uint8 *) MAP_NONE; - } - - // Banks 60->6f - for (c = 0; c < 0x100; c++) - SA1.Map [c + 0x600] = SA1.WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; - - BWRAM = SRAM; -} - -void CMemory::SufamiTurboAltROMMap () -{ - int c; - int i; - - if(Slot1Size!=0) - Slot1SRAMSize=(1<<((uint8)ROMOffset1[0x32]))*1024; - else Slot1Size=0x8000; - if(Slot2Size!=0) - Slot2SRAMSize=(1<<((uint8)ROMOffset2[0x32]))*1024; -else Slot2Size=0x8000; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - -// for (i = c + 8; i < c + 16; i++) -// { -// Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; -// BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; -// } - - } - - //Map Bios - - for (c=0; c<0x200; c+=16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [((c>>4)*0x8000)%CalculatedSize] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - } - - - for (c=0x200; c<0x400; c+=16) - { - for (i = c + 8; i < c + 16; i++) - { - if(Slot1Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset1 [(((c>>4)*0x8000)%Slot1Size)] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - } - - } - - for (c=0x400; c<0x600; c+=16) - { - for (i = c; i < c + 8; i++) - { - if(Slot2Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - - } - for (i = c + 8; i < c + 16; i++) - { - if(Slot2Size!=0) - { - Map [i] = Map [i + 0x800] = &ROMOffset2[(((c>>4)*0x8000)%Slot2Size)] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - else Map [i] = Map [i + 0x800] = (uint8*)MAP_NONE; - - } - - } - - // Banks 60->67 (7F?), S-RAM - if(Slot1SRAMSize!=0) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xE00] = Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0xE00] = BlockIsRAM [c + 0x600] = TRUE; - BlockIsROM [c + 0xE00] = BlockIsROM [c + 0x600] = FALSE; - } - } - if(Slot2SRAMSize!=0) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xF00] = Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0xF00] = BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0xF00] = BlockIsROM [c + 0x700] = FALSE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - WriteProtectROM (); -} + // XXX: Please remove port specific codes +#ifdef __WIN32__ +#ifndef _XBOX + EnableMenuItem(GUI.hMenu, IDM_ROM_INFO, MF_ENABLED); +#endif +#ifdef RTC_DEBUGGER + if (Settings.SPC7110RTC) + EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_ENABLED); + else + EnableMenuItem(GUI.hMenu, IDM_7110_RTC, MF_GRAYED); +#endif #endif + Settings.ForceHiROM = Settings.ForceLoROM = FALSE; + Settings.ForceHeader = Settings.ForceNoHeader = FALSE; + Settings.ForceInterleaved = Settings.ForceNotInterleaved = Settings.ForceInterleaved2 = FALSE; -void CMemory::SRAM512KLoROMMap () -{ - int c; - int i; +#ifndef NGC + if (stopMovie) + S9xMovieStop(TRUE); +#endif + if (PostRomInitFunc) + PostRomInitFunc(); - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapExtraRAM (); - WriteProtectROM (); + S9xVerifyControllers(); } -void CMemory::JumboLoROMMap (bool8 Interleaved) +void CMemory::FixROMSpeed (void) { - int c; - int i; + if (CPU.FastROMSpeed == 0) + CPU.FastROMSpeed = SLOW_ONE_CYCLE; - uint32 OFFSET0 = 0x400000; - uint32 OFFSET1 = 0x400000; - uint32 OFFSET2 = 0x000000; - - if (Interleaved) - { - OFFSET0 = 0x000000; - OFFSET1 = 0x000000; - OFFSET2 = CalculatedSize-0x400000; //changed to work with interleaved DKJM2. - } - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else if (Settings.C4) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; - Map [i + 0x800] = &ROM [((c << 11) % (0x400000)) + OFFSET2] - 0x8000; - BlockIsROM [i + 0x800] = BlockIsROM [i] = TRUE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0x400; c < 0x800; c += 16) - { - //updated mappings to correct A15 mirroring - for (i = c; i < c + 8; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0]; - Map [i + 0x800] = &ROM [((c << 11) % 0x400000) +OFFSET2]; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i]= &ROM [((c << 11) % (CalculatedSize - 0x400000)) + OFFSET0] - 0x8000; - Map [i + 0x800] = &ROM [((c << 11) % 0x400000) + OFFSET2 ] - 0x8000; - } - - for (i = c; i < c + 16; i++) - { - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - //ROM type has to be 64 Mbit header! - int sum=0, k,l; - for(k=0;k<256;k++) + // [80-bf]:[8000-ffff], [c0-ff]:[0000-ffff] + for (int c = 0x800; c < 0x1000; c++) { - uint8* bank=0x8000+Map[8+(k<<4)];//use upper half of the banks, and adjust for LoROM. - for(l=0;l<0x8000;l++) - sum+=bank[l]; + if (c & 0x8 || c & 0x400) + MemorySpeed[c] = (uint8) CPU.FastROMSpeed; } - CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); } -void CMemory::SPC7110HiROMMap () +void CMemory::ResetSpeedMap (void) { - int c; - int i; + memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - - Map [c + 6] /*= Map [c + 0x806]*/ = (uint8 *) MAP_HIROM_SRAM; - Map [c + 7] /*= Map [c + 0x807]*/ = (uint8 *) MAP_HIROM_SRAM; - Map [c + 0x806]=Map [c + 0x807]= (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - } - - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_NONE; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_NONE; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - // BlockIsRAM [0xb06 + (c << 4)] = TRUE; - // BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c=0;c<0x10;c++) + // Fast - [00-3f|80-bf]:[2000-3fff|4200-5fff] + // XSlow - [00-3f|80-bf]:[4000-41ff] see also S9xGet/SetCPU() + for (int i = 0; i < 0x400; i += 0x10) { - Map [0x500+c]=(uint8 *)MAP_SPC7110_DRAM; - BlockIsROM [0x500+c]=TRUE; + MemorySpeed[i + 2] = MemorySpeed[0x800 + i + 2] = ONE_CYCLE; + MemorySpeed[i + 3] = MemorySpeed[0x800 + i + 3] = ONE_CYCLE; + MemorySpeed[i + 4] = MemorySpeed[0x800 + i + 4] = ONE_CYCLE; + MemorySpeed[i + 5] = MemorySpeed[0x800 + i + 5] = ONE_CYCLE; } - for (c=0;c<0x100;c++) - { - Map [0xD00+c] = (uint8 *) MAP_SPC7110_ROM; - Map [0xE00+c] = (uint8 *) MAP_SPC7110_ROM; - Map [0xF00+c] = (uint8 *) MAP_SPC7110_ROM; - BlockIsROM [0xD00+c] = BlockIsROM [0xE00+c] = BlockIsROM [0xF00+c] = TRUE; + FixROMSpeed(); +} +// memory map + +uint32 CMemory::map_mirror (uint32 size, uint32 pos) +{ + // from bsnes + if (size == 0) + return (0); + if (pos < size) + return (pos); + + uint32 mask = 1 << 31; + while (!(pos & mask)) + mask >>= 1; + + if (size <= (pos & mask)) + return (map_mirror(size, pos - mask)); + else + return (mask + map_mirror(size - mask, pos - mask)); +} + +void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c & 0x7f) * 0x8000; + Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } } - S9xSpc7110Init(); - -int sum=0; -for(i=0;i<(int)CalculatedSize; i++) -{ - sum+=ROM[i]; } -if(CalculatedSize==0x300000) - sum<<=1; -CalculatedChecksum=sum&0xFFFF; - - MapRAM (); - WriteProtectROM (); -} -void CMemory::SPC7110Sram(uint8 newstate) +void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) { - if(newstate&0x80) + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) { - Memory.Map[6]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[7]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[0x306]=(uint8 *)MAP_HIROM_SRAM; - Memory.Map[0x307]=(uint8 *)MAP_HIROM_SRAM; + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = c << 16; + Map[p] = ROM + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} +void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = ((c - bank_s) & 0x7f) * 0x8000; + Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c - bank_s) << 16; + Map[p] = ROM + offset + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data) +{ + uint32 c, i, p; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = data; + BlockIsROM[p] = FALSE; + BlockIsRAM[p] = TRUE; + } + } +} + +void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type) +{ + uint32 c, i, p; + bool8 isROM, isRAM; + + isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? FALSE : TRUE; + isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? FALSE : TRUE; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = (uint8 *) index; + BlockIsROM[p] = isROM; + BlockIsRAM[p] = isRAM; + } + } +} + +void CMemory::map_System (void) +{ + // will be overwritten + map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM); + map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); + map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM); + map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); +} + +void CMemory::map_WRAM (void) +{ + // will overwrite others + map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM); + map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000); +} + +void CMemory::map_LoROMSRAM (void) +{ + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_HiROMSRAM (void) +{ + map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_DSP (void) +{ + switch (DSP1.maptype) + { + case M_DSP1_LOROM_S: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_LOROM_L: + map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_HIROM: + map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP2_LOROM: + map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP3_LOROM: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP4_LOROM: + map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + } +} + +void CMemory::map_C4 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); +} + +void CMemory::map_OBC1 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); +} + +void CMemory::map_SetaRISC (void) +{ + map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); +} + +void CMemory::map_SetaDSP (void) +{ + // where does the SETA chip access, anyway? + // please confirm this? + map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM); + // and this! + map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O); + + // ST-0010: + // map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?); +} + +void CMemory::map_WriteProtectROM (void) +{ + memmove((void *) WriteMap, (void *) Map, sizeof(Map)); + + for (int c = 0; c < 0x1000; c++) + { + if (BlockIsROM[c]) + WriteMap[c] = (uint8 *) MAP_NONE; + } +} + +void CMemory::Map_Initialize (void) +{ + for (int c = 0; c < 0x1000; c++) + { + Map[c] = (uint8 *) MAP_NONE; + WriteMap[c] = (uint8 *) MAP_NONE; + BlockIsROM[c] = FALSE; + BlockIsRAM[c] = FALSE; + } +} + +void CMemory::Map_LoROMMap (void) +{ + printf("Map_LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP1Master) + map_DSP(); + else + if (Settings.C4) + map_C4(); + else + if (Settings.OBC1) + map_OBC1(); + else + if (Settings.SETA == ST_018) + map_SetaRISC(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_NoMAD1LoROMMap (void) +{ + printf("Map_NoMAD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_JumboLoROMMap (void) +{ + // XXX: Which game uses this? + printf("Map_JumboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ROM24MBSLoROMMap (void) +{ + // PCB: BSC-1A5M-01, BSC-1A7M-10 + printf("Map_ROM24MBSLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SRAM512KLoROMMap (void) +{ + printf("Map_SRAM512KLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000); + map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000); + map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboLoROMMap (void) +{ + printf("Map_SufamiTurboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + if (Multi.sramSizeA) + { + map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + } + + if (Multi.sramSizeB) + { + map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + } + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboPseudoLoROMMap (void) +{ + // for combined images + printf("Map_SufamiTurboPseudoLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000); + + // I don't care :P + map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SuperFXLoROMMap (void) +{ + printf("Map_SuperFXLoROMMap\n"); + map_System(); + + // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K + // block is repeated twice in each 64K block. + for (int c = 0; c < 64; c++) + { + memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + } + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SetaDSPLoROMMap (void) +{ + printf("Map_SetaDSPLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize); + + map_SetaDSP(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SDD1LoROMMap (void) +{ + printf("Map_SDD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically + + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SA1LoROMMap (void) +{ + printf("Map_SA1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM); + map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM); + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + + for (int c = 0x40; c < 0x80; c++) + map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); + + // Now copy the map and correct it for the SA1 CPU. + memmove((void *) SA1.Map, (void *) Map, sizeof(Map)); + memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap)); + + // SA-1 Banks 00->3f and 80->bf + for (int c = 0x000; c < 0x400; c += 0x10) + { + SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000; + SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8 *) MAP_NONE; + SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000; + SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8 *) MAP_NONE; + } + + // SA-1 Banks 60->6f + for (int c = 0x600; c < 0x700; c++) + SA1.Map[c] = SA1.WriteMap[c] = (uint8 *) MAP_BWRAM_BITMAP; + + BWRAM = SRAM; +} + +void CMemory::Map_HiROMMap (void) +{ + printf("Map_HiROMMap\n"); + map_System(); + + map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP1Master) + map_DSP(); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ExtendedHiROMMap (void) +{ + printf("Map_ExtendedHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SameGameHiROMMap (void) +{ + printf("Map_SameGameHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SPC7110HiROMMap (void) +{ + printf("Map_SPC7110HiROMMap\n"); + map_System(); + + map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); + map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM, MAP_TYPE_ROM); + + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +// checksum + +uint16 CMemory::checksum_calc_sum (uint8 *data, uint32 length) +{ + uint16 sum = 0; + + for (uint32 i = 0; i < length; i++) + sum += data[i]; + + return (sum); +} + +uint16 CMemory::checksum_mirror_sum (uint8 *start, uint32 &length, uint32 mask) +{ + // from NSRT + while (!(length & mask)) + mask >>= 1; + + uint16 part1 = checksum_calc_sum(start, mask); + uint16 part2 = 0; + + uint32 next_length = length - mask; + if (next_length) + { + part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1); + + while (next_length < mask) + { + next_length += next_length; + part2 += part2; + } + + length = mask + mask; + } + + return (part1 + part2); +} + +void CMemory::Checksum_Calculate (void) +{ + // from NSRT + uint16 sum = 0; + + if (Settings.BS && !Settings.BSXItself) + sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48); + else + if (Settings.SPC7110) + { + sum = checksum_calc_sum(ROM, CalculatedSize); + if (CalculatedSize == 0x300000) + sum += sum; } else { - Memory.Map[6]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[7]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[0x306]=(uint8 *)MAP_RONLY_SRAM; - Memory.Map[0x307]=(uint8 *)MAP_RONLY_SRAM; - } -} -const char *CMemory::TVStandard () -{ - return (Settings.PAL ? "PAL" : "NTSC"); -} - -const char *CMemory::Speed () -{ - return (ROMSpeed & 0x10 ? "120ns" : "200ns"); -} - -const char *CMemory::MapType () -{ - return (HiROM ? "HiROM" : "LoROM"); -} - -const char *CMemory::StaticRAMSize () -{ - static char tmp [20]; - - if (Memory.SRAMSize > 16) - return ("Corrupt"); - sprintf (tmp, "%dKB", (SRAMMask + 1) / 1024); - return (tmp); -} - -const char *CMemory::Size () -{ - static char tmp [20]; - - if (ROMSize < 7 || ROMSize - 7 > 23) - return ("Corrupt"); - sprintf (tmp, "%dMbits", 1 << (ROMSize - 7)); - return (tmp); -} - -const char *CMemory::KartContents () -{ - static char tmp [30]; - static const char *CoPro [16] = { - "DSP", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6", - "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12", - "CoPro#13", "CoPro#14", "CoPro-Custom" - }; - static const char *Contents [3] = { - "ROM", "ROM+RAM", "ROM+RAM+BAT" - }; - static const char *DSPSel [4] = { - "DSP1", "DSP2", "DSP3", "DSP4" - }; - if (ROMType == 0&&!Settings.BS) - return ("ROM only"); - - sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]); - - if(Settings.BS) - sprintf (tmp, "%s+%s", tmp, "BSX"); - else if(Settings.SPC7110&&Settings.SPC7110RTC) - sprintf (tmp, "%s+%s", tmp, "SPC7110+RTC"); - else if(Settings.SPC7110) - sprintf (tmp, "%s+%s", tmp, "SPC7110"); - else if(Settings.C4) - sprintf (tmp, "%s+%s", tmp, "C4"); - else if(Settings.SETA!=0) - { - switch(Settings.SETA) + if (CalculatedSize & 0x7fff) + sum = checksum_calc_sum(ROM, CalculatedSize); + else { - case ST_010: - sprintf (tmp, "%s+%s", tmp, "ST-010"); - break; - case ST_011: - sprintf (tmp, "%s+%s", tmp, "ST-011"); - break; - - case ST_018: - sprintf (tmp, "%s+%s", tmp, "ST-018"); - break; - + uint32 length = CalculatedSize; + sum = checksum_mirror_sum(ROM, length); } } - else if ((ROMType & 0xf) >= 3) - { - if (ROMType & 0xf0) - sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]); - else - sprintf (tmp, "%s+%s", tmp, DSPSel [DSP1.version]); - } - return (tmp); + CalculatedChecksum = sum; } -const char *CMemory::MapMode () +// information + +const char * CMemory::TVStandard (void) { - static char tmp [4]; - sprintf (tmp, "%02x", ROMSpeed & ~0x10); - return (tmp); + return (Settings.PAL ? "PAL" : "NTSC"); } -const char *CMemory::ROMID () +const char * CMemory::MapType (void) { - return (ROMId); + return (HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM"); } -void CMemory::ApplyROMFixes () +const char * CMemory::MapMode (void) +{ + static char str[4]; + + sprintf(str, "%02x", ROMSpeed & ~0x10); + + return (str); +} + +const char * CMemory::StaticRAMSize (void) +{ + static char str[20]; + + if (SRAMSize > 16) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dKB", (SRAMMask + 1) / 1024); + + return (str); +} + +const char * CMemory::Size (void) +{ + static char str[20]; + + if (Multi.cartType == 4) + strcpy(str, "N/A"); + else + if (ROMSize < 7 || ROMSize - 7 > 23) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dMbits", 1 << (ROMSize - 7)); + + return (str); +} + +const char * CMemory::Revision (void) +{ + static char str[20]; + + sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]); + + return (str); +} + +const char * CMemory::KartContents (void) +{ + static char str[30]; + static char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; + + char chip[16]; + + if (ROMType == 0 && !Settings.BS) + return ("ROM"); + + if (Settings.BS) + strcpy(chip, "+BSX"); + else + if (Settings.SuperFX) + strcpy(chip, "+SuperFX"); + else + if (Settings.SDD1) + strcpy(chip, "+S-DD1"); + else + if (Settings.OBC1) + strcpy(chip, "+OBC1"); + else + if (Settings.SA1) + strcpy(chip, "+SA-1"); + else + if (Settings.SPC7110RTC) + strcpy(chip, "+SPC7110+RTC"); + else + if (Settings.SPC7110) + strcpy(chip, "+SPC7110"); + else + if (Settings.SRTC) + strcpy(chip, "+S-RTC"); + else + if (Settings.C4) + strcpy(chip, "+C4"); + else + if (Settings.SETA == ST_010) + strcpy(chip, "+ST-010"); + else + if (Settings.SETA == ST_011) + strcpy(chip, "+ST-011"); + else + if (Settings.SETA == ST_018) + strcpy(chip, "+ST-018"); + else + if (Settings.DSP1Master) + sprintf(chip, "+DSP%d", DSP1.version + 1); + else + strcpy(chip, ""); + + sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip); + + return (str); +} + +// hack + +bool8 CMemory::match_na (const char *str) +{ + return (strcmp(ROMName, str) == 0); +} + +bool8 CMemory::match_nn (const char *str) +{ + return (strncmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_nc (const char *str) +{ + return (strncasecmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_id (const char *str) +{ + return (strncmp(ROMId, str, strlen(str)) == 0); +} + +void CMemory::ApplyROMFixes (void) { #ifdef __W32_HEAP - if(_HEAPOK!=_heapchk()) + if (_HEAPOK != _heapchk()) MessageBox(GUI.hWnd, "CMemory::ApplyROMFixes", "Heap Corrupt", MB_OK); #endif - //don't steal my work! -MK - if(ROMCRC32 == 0x1B4A5616 && strncmp(ROMName, "RUDORA NO HIHOU", 15)==0) + //// Warnings + + // Don't steal my work! -MK + if ((ROMCRC32 == 0x1B4A5616) && match_nn("RUDORA NO HIHOU")) { strncpy(ROMName, "THIS SCRIPT WAS STOLEN", 22); - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); + Settings.DisplayColor = BUILD_PIXEL(31, 0, 0); + SET_UI_COLOR(255, 0, 0); + } + + // Reject strange hacked games + if ((ROMCRC32 == 0x6810aa95) || + (ROMCRC32 == 0x340f23e5) || + (ROMCRC32 == 0x77fd806a) || + (match_nn("HIGHWAY BATTLE 2")) || + (match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) || + (match_nn("HONKAKUHA IGO GOSEI") && (ROM[0xffd5] != 0x31))) + { + Settings.DisplayColor = BUILD_PIXEL(31, 0, 0); + SET_UI_COLOR(255, 0, 0); + } + + //// APU timing hacks :( + + // This game cannot work well anyway + if (match_id("AVCJ")) // Rendering Ranger R2 + { + IAPU.OneCycle = (int32) (15.7 * (1 << SNES_APU_ACCURACY)); + printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + } + + // XXX: All Quintet games? + if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki + match_id("JG ") || // Illusion of Gaia + match_id("CQ ")) // Stunt Race FX + { + IAPU.OneCycle = (int32) (13.0 * (1 << SNES_APU_ACCURACY)); + printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + } + + if (match_na("SOULBLADER - 1") || // Soul Blader + match_na("SOULBLAZER - 1 USA") || // Soul Blazer + match_na("SLAP STICK 1 JPN") || // Slap Stick + match_id("E9 ") || // Robotrek + match_nn("ACTRAISER") || // Actraiser + match_nn("ActRaiser-2") || // Actraiser 2 + match_id("AQT") || // Tenchi Souzou, Terranigma + match_id("ATV") || // Tales of Phantasia + match_id("ARF") || // Star Ocean + match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan + match_id("A4B") || // Super Bomberman 4 + match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban + match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban + match_id("APB") || // Super Bomberman - Panic Bomber W + match_na("DARK KINGDOM") || // Dark Kingdom + match_na("ZAN3 SFC") || // Zan III Spirits + match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai + match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta + match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase + match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing + match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen + match_na("MASTERS") || // Harukanaru Augusta 2 - Masters + match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider + match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou + match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7 + match_nn("SWORD WORLD SFC") || // Sword World SFC/2 + match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4 + match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master + match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 + match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 + match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! + { + IAPU.OneCycle = (int32) (15.0 * (1 << SNES_APU_ACCURACY)); + printf("APU OneCycle hack: %d\n", IAPU.OneCycle); + } + + //// DMA/HDMA timing hacks :( + + Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; + Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; + + // The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536) + // while preparing to jump to the IRQ vector address. + // That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ(). + // Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground. + // IRQ timing is bad? HDMA timing is bad? else? + if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel + { + Timings.HDMAStart -= 10; + Timings.HBlankStart -= 10; + printf("HDMA timing hack: %d\n", Timings.HDMAStart); + } + + // The delay to sync CPU and DMA which Snes9x cannot emulate. + // Some games need really severe delay timing... + if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix + { + Timings.DMACPUSync = 20; + printf("DMA sync: %d\n", Timings.DMACPUSync); + } + + //// CPU speed-ups (CPU_Shutdown()) + + // Force disabling a speed-up hack + // Games which spool sound samples between the SNES and sound CPU using + // H-DMA as the sample is playing. + if (match_na("EARTHWORM JIM 2") || // Earth Worm Jim 2 + match_na("PRIMAL RAGE") || // Primal Rage + match_na("CLAY FIGHTER") || // Clay Fighter + match_na("ClayFighter 2") || // Clay Fighter 2 + match_na("WeaponLord") || // Weapon Lord + match_nn("WAR 2410") || // War 2410 + match_id("ARF") || // Star Ocean + match_id("A4WJ") || // Mini Yonku Shining Scorpion - Let's & Go!! + match_nn("NHL") || + match_nc("MADDEN")) + { + if (Settings.Shutdown) + printf("Disabled CPU shutdown hack.\n"); + Settings.Shutdown = FALSE; + } + + // SA-1 + SA1.WaitAddress = 0xffffffff; + SA1.WaitByteAddress1 = NULL; + SA1.WaitByteAddress2 = NULL; + + if (Settings.SA1) + { + // Itoi Shigesato no Bass Tsuri No.1 (J) + if (match_id("ZBPJ")) + { + SA1.WaitAddress = 0x0093f1; + SA1.WaitByteAddress1 = FillRAM + 0x304a; + } + + // Daisenryaku Expert WWII (J) + if (match_id("AEVJ")) + { + SA1.WaitAddress = 0x0ed18d; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Derby Jockey 2 (J) + if (match_id("A2DJ")) + { + SA1.WaitAddress = 0x008b62; + } + + // Dragon Ball Z - Hyper Dimension (J) + if (match_id("AZIJ")) + { + SA1.WaitAddress = 0x008083; + SA1.WaitByteAddress1 = FillRAM + 0x3020; + } + + // SD Gundam G NEXT (J) + if (match_id("ZX3J")) + { + SA1.WaitAddress = 0x0087f2; + SA1.WaitByteAddress1 = FillRAM + 0x30c4; + } + + // Shougi no Hanamichi (J) + if (match_id("AARJ")) + { + SA1.WaitAddress = 0xc1f85a; + SA1.WaitByteAddress1 = SRAM + 0x0c64; + SA1.WaitByteAddress2 = SRAM + 0x0c66; + } + + // Asahi Shinbun Rensai Katou Hifumi Kudan Shougi Shingiryu (J) + if (match_id("A23J")) + { + SA1.WaitAddress = 0xc25037; + SA1.WaitByteAddress1 = SRAM + 0x0c06; + SA1.WaitByteAddress2 = SRAM + 0x0c08; + } + + // Taikyoku Igo - Idaten (J) + if (match_id("AIIJ")) + { + SA1.WaitAddress = 0xc100be; + SA1.WaitByteAddress1 = SRAM + 0x1002; + SA1.WaitByteAddress2 = SRAM + 0x1004; + } + + // Takemiya Masaki Kudan no Igo Taishou (J) + if (match_id("AITJ")) + { + SA1.WaitAddress = 0x0080b7; + } + + // J. League '96 Dream Stadium (J) + if (match_id("AJ6J")) + { + SA1.WaitAddress = 0xc0f74a; + } + + // Jumpin' Derby (J) + if (match_id("AJUJ")) + { + SA1.WaitAddress = 0x00d926; + } + + // Kakinoki Shougi (J) + if (match_id("AKAJ")) + { + SA1.WaitAddress = 0x00f070; + } + + // Hoshi no Kirby 3 (J), Kirby's Dream Land 3 (U) + if (match_id("AFJJ") || match_id("AFJE")) + { + SA1.WaitAddress = 0x0082d4; + SA1.WaitByteAddress1 = SRAM + 0x72a4; + } + + // Hoshi no Kirby - Super Deluxe (J) + if (match_id("AKFJ")) + { + SA1.WaitAddress = 0x008c93; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Kirby Super Star (U) + if (match_id("AKFE")) + { + SA1.WaitAddress = 0x008cb8; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Super Mario RPG (J), (U) + if (match_id("ARWJ") || match_id("ARWE")) + { + SA1.WaitAddress = 0xc0816f; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Marvelous (J) + if (match_id("AVRJ")) + { + SA1.WaitAddress = 0x0085f2; + SA1.WaitByteAddress1 = FillRAM + 0x3024; + } + + // Harukanaru Augusta 3 - Masters New (J) + if (match_id("AO3J")) + { + SA1.WaitAddress = 0x00dddb; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // Jikkyou Oshaberi Parodius (J) + if (match_id("AJOJ")) + { + SA1.WaitAddress = 0x8084e5; + } + + // Super Bomberman - Panic Bomber W (J) + if (match_id("APBJ")) + { + SA1.WaitAddress = 0x00857a; + } + + // Pebble Beach no Hatou New - Tournament Edition (J) + if (match_id("AONJ")) + { + SA1.WaitAddress = 0x00df33; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // PGA European Tour (U) + if (match_id("AEPE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // PGA Tour 96 (U) + if (match_id("A3GE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // Power Rangers Zeo - Battle Racers (U) + if (match_id("A4RE")) + { + SA1.WaitAddress = 0x009899; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // SD F-1 Grand Prix (J) + if (match_id("AGFJ")) + { + SA1.WaitAddress = 0x0181bc; + } + + // Saikousoku Shikou Shougi Mahjong (J) + if (match_id("ASYJ")) + { + SA1.WaitAddress = 0x00f2cc; + SA1.WaitByteAddress1 = SRAM + 0x7ffe; + SA1.WaitByteAddress2 = SRAM + 0x7ffc; + } + + // Shougi Saikyou II (J) + if (match_id("AX2J")) + { + SA1.WaitAddress = 0x00d675; + } + + // Mini Yonku Shining Scorpion - Let's & Go!! (J) + if (match_id("A4WJ")) + { + SA1.WaitAddress = 0xc048be; + } + + // Shin Shougi Club (J) + if (match_id("AHJJ")) + { + SA1.WaitAddress = 0xc1002a; + SA1.WaitByteAddress1 = SRAM + 0x0806; + SA1.WaitByteAddress2 = SRAM + 0x0808; + } + + // rest games: + // Habu Meijin no Omoshiro Shougi (J) + // Hayashi Kaihou Kudan no Igo Taidou (J) + // Shougi Saikyou (J) + // Super Robot Wars Gaiden (J) + // Super Shougi 3 - Kitaihei (J) + } + + //// SRAM fixes + + if (match_na("HITOMI3")) + { + SRAMSize = 1; + SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; + } + + // SRAM value fixes + if (match_na("SUPER DRIFT OUT") || // Super Drift Out + match_na("SATAN IS OUR FATHER!") || + match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu + SNESGameFixes.SRAMInitialValue = 0x00; + + // Additional game fixes by sanmaiwashi ... + // XXX: unnecessary? + if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari + SNESGameFixes.SRAMInitialValue = 0x6b; + + // others: BS and ST-01x games are 0x00. + + //// Specific game fixes + + // for ZSNES SuperFX: is it still necessary? + Settings.WinterGold = match_na("FX SKIING NINTENDO 96") || match_na("DIRT RACER"); + + // OAM hacks because we don't fully understand the behavior of the SNES. + // Totally wacky display in 2P mode... + // seems to need a disproven behavior, so we're definitely overlooking some other bug? + if (match_nn("UNIRACERS")) // Uniracers + { + SNESGameFixes.Uniracers = TRUE; + printf("Applied Uniracers hack.\n"); } /* - HACKS NSRT can fix that we hadn't detected before. -[14:25:13] <@Nach> case 0x0c572ef0: //So called Hook (US)(2648) -[14:25:13] <@Nach> case 0x6810aa95: //Bazooka Blitzkreig swapped sizes hack -handled -[14:25:17] <@Nach> case 0x61E29C06: //The Tick region hack -[14:25:19] <@Nach> case 0x1EF90F74: //Jikkyou Keiba Simulation Stable Star PAL hack -[14:25:23] <@Nach> case 0x4ab225b5: //So called Krusty's Super Fun House (E) -[14:25:25] <@Nach> case 0x77fd806a: //Donkey Kong Country 2 (E) v1.1 bad dump -handled -[14:25:27] <@Nach> case 0x340f23e5: //Donkey Kong Country 3 (U) copier hack - handled - */ - - if(ROMCRC32==0x6810aa95 || ROMCRC32==0x340f23e5 || ROMCRC32==0x77fd806a || - strncmp (ROMName, "HIGHWAY BATTLE 2", 16)==0 || - (strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 && ROM[0x7FDA]==0)) - { - Settings.DisplayColor=BUILD_PIXEL(31,0,0); - SET_UI_COLOR(255,0,0); - } - - //Ambiguous chip function pointer assignments - DSP1.version=0; - - //DSP switching: - if(strncmp(ROMName, "DUNGEON MASTER", 14)==0) - { - //Set DSP-2 - DSP1.version=1; - SetDSP=&DSP2SetByte; - GetDSP=&DSP2GetByte; - } - - if(strncmp(ROMName, "SD\x0b6\x0de\x0dd\x0c0\x0de\x0d1GX", 10)==0) // SD Gundam GX - { - //Set DSP-3 - DSP1.version=2; - SetDSP = &DSP3SetByte; - GetDSP = &DSP3GetByte; - DSP3_Reset(); - } - - if(strncmp(ROMName, "TOP GEAR 3000", 13)==0 - ||strncmp(ROMName, "PLANETS CHAMP TG3000", 20)==0) - { - //Set DSP-4 - DSP1.version=3; - SetDSP=&DSP4SetByte; - GetDSP=&DSP4GetByte; - // FIXME: memory map correction - for (int c = 0; c < 0x400; c += 16) - { - Map[c + 6] = Map[c + 0x806] = (uint8 *) MAP_NONE; - Map[c + 7] = Map[c + 0x807] = (uint8 *) MAP_NONE; - } - WriteProtectROM(); - } - - //memory map corrections - if(strncmp(ROMName, "XBAND",5)==0) - { - for (int c=0xE00;c<0xE10;c++) - { - Map [c] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c] = TRUE; - BlockIsROM [c] = FALSE; - } - WriteProtectROM (); - } - - //not MAD-1 compliant - if(strcmp (ROMName, "WANDERERS FROM YS") == 0) - { - for(int c=0;c<0xE0;c++) - { - Map[c+0x700]=(uint8*)MAP_LOROM_SRAM; - BlockIsROM[c+0x700]=FALSE; - BlockIsRAM[c+0x700]=TRUE; - } - WriteProtectROM(); - } - -#if 0 -// These two games don't have SRAM. Sounds like OpenBus issue... - if (strcmp (ROMName, "GOGO ACKMAN3") == 0 || - strcmp (ROMName, "HOME ALONE") == 0) - { - // Banks 00->3f and 80->bf - for (int c = 0; c < 0x400; c += 16) - { - Map [c + 6] = Map [c + 0x806] = SRAM; - Map [c + 7] = Map [c + 0x807] = SRAM; - BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE; - BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE; - BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; - BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; - } - WriteProtectROM (); - } -#endif - - if (strncmp (ROMName, "BATMAN--REVENGE JOKER", 21) == 0) - { - Memory.HiROM = FALSE; - Memory.LoROM = TRUE; - LoROMMap (); - } - - // Force Disabling a speed-up hack (CPU_Shutdown()) - // Games which spool sound samples between the SNES and sound CPU using - // H-DMA as the sample is playing. - if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 || - strcmp (ROMName, "PRIMAL RAGE") == 0 || - strcmp (ROMName, "CLAY FIGHTER") == 0 || - strcmp (ROMName, "ClayFighter 2") == 0 || - strncasecmp (ROMName, "MADDEN", 6) == 0 || - strncmp (ROMName, "NHL", 3) == 0 || - strcmp (ROMName, "WeaponLord") == 0 || - strncmp(ROMName, "WAR 2410", 8) == 0 || - strncmp (ROMId, "ARF", 3) == 0) // Star Ocean - { - Settings.Shutdown = FALSE; - } - - //APU timing hacks - - // Stunt Racer FX - if (strcmp (ROMId, "CQ ") == 0 || - // Illusion of Gaia - strncmp (ROMId, "JG", 2) == 0 || - strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0) - { - IAPU.OneCycle = 13; - } - - // RENDERING RANGER R2 - if (strcmp (ROMId, "AVCJ") == 0 || - //Mark Davis - strncmp(ROMName, "THE FISHING MASTER", 18)==0 || //needs >= actual APU timing. (21 is .002 Mhz slower) - // Star Ocean - strncmp (ROMId, "ARF", 3) == 0 || - // Tales of Phantasia - strncmp (ROMId, "ATV", 3) == 0 || - // Act Raiser 1 & 2 - strncasecmp (ROMName, "ActRaiser", 9) == 0 || - // Soulblazer - strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 || - strcmp (ROMName, "SOULBLADER - 1") == 0 || - - // Terranigma - strncmp (ROMId, "AQT", 3) == 0 || - // Robotrek - strncmp (ROMId, "E9 ", 3) == 0 || - strcmp (ROMName, "SLAP STICK 1 JPN") == 0 || - // ZENNIHON PURORESU2 - strncmp (ROMId, "APR", 3) == 0 || - // Bomberman 4 - strncmp (ROMId, "A4B", 3) == 0 || - // UFO KAMEN YAKISOBAN - strncmp (ROMId, "Y7 ", 3) == 0 || - strncmp (ROMId, "Y9 ", 3) == 0 || - // Panic Bomber World - strncmp (ROMId, "APB", 3) == 0 || - ((strncmp (ROMName, "Parlor", 6) == 0 || - strcmp (ROMName, "HEIWA Parlor!Mini8") == 0 || - strncmp (ROMName, "SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!", 21) == 0) && //SANKYO Fever! Fever! - strcmp (CompanyId, "A0") == 0) || - strcmp (ROMName, "DARK KINGDOM") == 0 || - strcmp (ROMName, "ZAN3 SFC") == 0 || - strcmp (ROMName, "HIOUDEN") == 0 || - strcmp (ROMName, "\xC3\xDD\xBC\xC9\xB3\xC0") == 0 || //Tenshi no Uta - strcmp (ROMName, "FORTUNE QUEST") == 0 || - strcmp (ROMName, "FISHING TO BASSING") == 0 || - strncmp (ROMName, "TokyoDome '95Battle 7", 21) == 0 || - strcmp (ROMName, "OHMONO BLACKBASS") == 0 || - strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 || - strcmp (ROMName, "MASTERS") ==0 || //Augusta 2 J - strcmp (ROMName, "SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") == 0 || //Kamen Rider - strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 || - strncmp (ROMName, "LETs PACHINKO(", 14) == 0) //A set of BS games - { - IAPU.OneCycle = 15; - } - - //Specific game fixes - - // for ZSNES SuperFX: is it still necessary? - Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 || - strcmp (ROMName, "DIRT RACER") == 0; - - //OAM hacks because we don't fully understand the - //behavior of the SNES. - //Totally wacky display... - //seems to need a disproven behavior, so - //we're definitely overlooking some other bug? - if(strncmp(ROMName, "UNIRACERS", 9)==0) - SNESGameFixes.Uniracers=true; - -#if 0 - if (strcmp (ROMName, "\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0") == 0 || //Super Famista - strcmp (ROMName, "\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0 2") == 0 || //Super Famista 2 - strcmp (ROMName, "GANBA LEAGUE") == 0) - { + // XXX: What's this? + if (match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0") || // Super Famista + match_na("\xBD\xB0\xCA\xDF\xB0\xCC\xA7\xD0\xBD\xC0 2") || // Super Famista 2 + match_na("GANBA LEAGUE")) // Hakunetsu Pro Yakyuu - Ganba League SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; - } -#endif - - //CPU timing hacks - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * Settings.CyclesPercentage) / 100; - Timings.HBlankStart = SNES_HBLANK_START_HC; - Timings.HDMAStart = SNES_HDMA_START_HC; - Timings.RenderPos = SNES_RENDER_START_HC; - - //The first new hack since timings were changed :( - if (strncmp(ROMName, "SeikenDensetsu 2", 16) == 0 || - strncmp(ROMName, "Secret of MANA", 14) == 0) - { - Timings.HBlankStart -= 34; - Timings.HDMAStart -= 34; - } - -/* if(strcmp(ROMName, "HOME IMPROVEMENT")==0) - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 200) / 100; - - if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100) - // Street Racer - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100; - - // Power Rangers Fight - if (strncmp (ROMId, "A3R", 3) == 0 || - // Clock Tower - strncmp (ROMId, "AJE", 3) == 0) - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100; - - if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100) - // Mortal Kombat 3. Fixes cut off speech sample - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; - - //Darkness Beyond Twilight - //Crimson beyond blood that flows - //buried in the stream of time - //is where your power grows - //I pledge myself to conquer - //all the foes who stand - //before the might gift betsowed - //in my unworthy hand - if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 && - Settings.CyclesPercentage == 100) - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; - // Start Trek: Deep Sleep 9 - if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) - Timings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; -*/ - Timings.H_Max_Master = Timings.H_Max; - - //SA-1 Speedup settings - SA1.WaitAddress = 0xffffffff; - SA1.WaitByteAddress1 = NULL; - SA1.WaitByteAddress2 = NULL; - - /* Bass Fishing */ - if (strcmp (ROMId, "ZBPJ") == 0) - { - SA1.WaitAddress = 0x0093f1; - SA1.WaitByteAddress1 = FillRAM + 0x304a; - } - /* DAISENRYAKU EXPERTWW2 */ - if (strcmp (ROMId, "AEVJ") == 0) - { - SA1.WaitAddress = 0x0ed18d; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* debjk2 */ - if (strcmp (ROMId, "A2DJ") == 0) - { - SA1.WaitAddress = 0x008b62; - } - /* Dragon Ballz HD */ - if (strcmp (ROMId, "AZIJ") == 0) - { - SA1.WaitAddress = 0x008083; - SA1.WaitByteAddress1 = FillRAM + 0x3020; - } - /* SFC SDGUNDAMGNEXT */ - if (strcmp (ROMId, "ZX3J") == 0) - { - SA1.WaitAddress = 0x0087f2; - SA1.WaitByteAddress1 = FillRAM + 0x30c4; - } - /* ShougiNoHanamichi */ - if (strcmp (ROMId, "AARJ") == 0) - { - SA1.WaitAddress = 0xc1f85a; - SA1.WaitByteAddress1 = SRAM + 0x0c64; - SA1.WaitByteAddress2 = SRAM + 0x0c66; - } - /* KATO HIFUMI9DAN SYOGI */ - if (strcmp (ROMId, "A23J") == 0) - { - SA1.WaitAddress = 0xc25037; - SA1.WaitByteAddress1 = SRAM + 0x0c06; - SA1.WaitByteAddress2 = SRAM + 0x0c08; - } - /* idaten */ - if (strcmp (ROMId, "AIIJ") == 0) - { - SA1.WaitAddress = 0xc100be; - SA1.WaitByteAddress1 = SRAM + 0x1002; - SA1.WaitByteAddress2 = SRAM + 0x1004; - } - /* igotais */ - if (strcmp (ROMId, "AITJ") == 0) - { - SA1.WaitAddress = 0x0080b7; - } - /* J96 DREAM STADIUM */ - if (strcmp (ROMId, "AJ6J") == 0) - { - SA1.WaitAddress = 0xc0f74a; - } - /* JumpinDerby */ - if (strcmp (ROMId, "AJUJ") == 0) - { - SA1.WaitAddress = 0x00d926; - } - /* JKAKINOKI SHOUGI */ - if (strcmp (ROMId, "AKAJ") == 0) - { - SA1.WaitAddress = 0x00f070; - } - /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */ - if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0) - { - SA1.WaitAddress = 0x0082d4; - SA1.WaitByteAddress1 = SRAM + 0x72a4; - } - /* KIRBY SUPER DELUXE JAP */ - if (strcmp (ROMId, "AKFJ") == 0) - { - SA1.WaitAddress = 0x008c93; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* KIRBY SUPER DELUXE US */ - if (strcmp (ROMId, "AKFE") == 0) - { - SA1.WaitAddress = 0x008cb8; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* SUPER MARIO RPG JAP & US */ - if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0) - { - SA1.WaitAddress = 0xc0816f; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* marvelous.zip */ - if (strcmp (ROMId, "AVRJ") == 0) - { - SA1.WaitAddress = 0x0085f2; - SA1.WaitByteAddress1 = FillRAM + 0x3024; - } - /* AUGUSTA3 MASTERS NEW */ - if (strcmp (ROMId, "AO3J") == 0) - { - SA1.WaitAddress = 0x00dddb; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* OSHABERI PARODIUS */ - if (strcmp (ROMId, "AJOJ") == 0) - { - SA1.WaitAddress = 0x8084e5; - } - /* PANIC BOMBER WORLD */ - if (strcmp (ROMId, "APBJ") == 0) - { - SA1.WaitAddress = 0x00857a; - } - /* PEBBLE BEACH NEW */ - if (strcmp (ROMId, "AONJ") == 0) - { - SA1.WaitAddress = 0x00df33; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* PGA EUROPEAN TOUR */ - if (strcmp (ROMId, "AEPE") == 0) - { - SA1.WaitAddress = 0x003700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* PGA TOUR 96 */ - if (strcmp (ROMId, "A3GE") == 0) - { - SA1.WaitAddress = 0x003700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* POWER RANGERS 4 */ - if (strcmp (ROMId, "A4RE") == 0) - { - SA1.WaitAddress = 0x009899; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* PACHISURO PALUSUPE */ - if (strcmp (ROMId, "AGFJ") == 0) - { - // Never seems to turn on the SA-1! - } - /* SD F1 GRAND PRIX */ - if (strcmp (ROMId, "AGFJ") == 0) - { - SA1.WaitAddress = 0x0181bc; - } - /* SHOUGI MARJONG */ - if (strcmp (ROMId, "ASYJ") == 0) - { - SA1.WaitAddress = 0x00f2cc; - SA1.WaitByteAddress1 = SRAM + 0x7ffe; - SA1.WaitByteAddress2 = SRAM + 0x7ffc; - } - /* shogisai2 */ - if (strcmp (ROMId, "AX2J") == 0) - { - SA1.WaitAddress = 0x00d675; - } - - /* SHINING SCORPION */ - if (strcmp (ROMId, "A4WJ") == 0) - { - SA1.WaitAddress = 0xc048be; - } - /* SHIN SHOUGI CLUB */ - if (strcmp (ROMId, "AHJJ") == 0) - { - SA1.WaitAddress = 0xc1002a; - SA1.WaitByteAddress1 = SRAM + 0x0806; - SA1.WaitByteAddress2 = SRAM + 0x0808; - } - - - //Other - - // Additional game fixes by sanmaiwashi ... - if (strcmp (ROMName, "SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1") == 0) // Gundam Knight Story - { -// bytes0x2000 [0xb18] = 0x4c; -// bytes0x2000 [0xb19] = 0x4b; -// bytes0x2000 [0xb1a] = 0xea; - SNESGameFixes.SRAMInitialValue = 0x6b; - } - - - // HITOMI3 - if (strcmp (ROMName, "HITOMI3") == 0) - { - Memory.SRAMSize = 1; - SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; - } - - //sram value fixes - if (strcmp (Memory.ROMName, "SUPER DRIFT OUT") == 0 || - strcmp(Memory.ROMName, "SATAN IS OUR FATHER!") == 0 || - strcmp (ROMName, "goemon 4") == 0) - SNESGameFixes.SRAMInitialValue = 0x00; - -#if 0 - if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0) - { - for (c = 0x200; c < 0x400; c += 16) - { - for (int i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000]; - BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE; - } - } - WriteProtectROM (); - } -#endif - -#if 0 -// XXX: wait-and-see... -#define RomPatch(adr,ov,nv) \ - if (ROM [adr] == ov) \ - ROM [adr] = nv - - // Love Quest - if (strcmp (ROMName, "LOVE QUEST") == 0) - { - RomPatch (0x1385ec, 0xd0, 0xea); - RomPatch (0x1385ed, 0xb2, 0xea); - } - //BNE D0 into nops - - //this is a cmp on $00:2140 - // Super Batter Up - if (strcmp (ROMName, "Super Batter Up") == 0) - { - RomPatch (0x27ae0, 0xd0, 0xea); - RomPatch (0x27ae1, 0xfa, 0xea); - } - //BNE -#endif + */ } - #ifndef NGC +// IPS + // Read variable size MSB int from a file static long ReadInt (Reader *r, unsigned nbytes) { @@ -4170,7 +3345,7 @@ static long ReadInt (Reader *r, unsigned nbytes) #define IPS_EOF 0x00454F46l #ifndef NGC -static bool8 ReadIPSPatch(Reader *r, long offset, int32 &rom_size) +static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) { char fname[6]; for(int i=0; i<5; i++){ @@ -4216,7 +3391,7 @@ static bool8 ReadIPSPatch(Reader *r, long offset, int32 &rom_size) rchar = r->get_char(); if (rchar == EOF) goto err_eof; - ROM [ofs++] = (uint8) rchar; + Memory.ROM [ofs++] = (uint8) rchar; } if (ofs > rom_size) rom_size = ofs; @@ -4235,7 +3410,7 @@ static bool8 ReadIPSPatch(Reader *r, long offset, int32 &rom_size) goto err_eof; while (rlen--) - ROM [ofs++] = (uint8) rchar; + Memory.ROM [ofs++] = (uint8) rchar; if (ofs > rom_size) rom_size = ofs; @@ -4254,11 +3429,12 @@ static bool8 ReadIPSPatch(Reader *r, long offset, int32 &rom_size) err_eof: return 0; } - #endif #ifndef NGC -static int unzFindExtension(unzFile &file, const char *ext, bool restart=true, bool print=true){ + +static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) +{ int port; int l=strlen(ext); @@ -4281,12 +3457,11 @@ static int unzFindExtension(unzFile &file, const char *ext, bool restart=true, b } return port; } - #endif #ifndef NGC -void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, - int32 &rom_size) + +void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, int32 &rom_size) { if(Settings.NoPatch) return; @@ -4507,50 +3682,7 @@ void CMemory::CheckForIPSPatch (const char *rom_filename, bool8 header, if(flag) return; } } - #endif - -void CMemory::ParseSNESHeader(uint8 *RomHeader) -{ - bool8 bs = Settings.BS & !Settings.BSXItself; - - strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); - if (bs) - memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17); - - if (bs) - { - if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || - (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000))) - printf("BS: Size mismatch\n"); - - // FIXME - int p = 0; - while ((1 << p) < (int) CalculatedSize) - p++; - ROMSize = p - 10; - } - else - ROMSize = RomHeader[0x27]; - - Memory.SRAMSize = bs ? 5 /* BS-X */: RomHeader[0x28]; - - ROMSpeed = bs ? RomHeader[0x28] : RomHeader[0x25]; - ROMType = bs ? 0xE5 /* BS-X */ : RomHeader[0x26]; - ROMRegion = bs ? 0 : RomHeader[0x29]; - - ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8); - ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8); - - memmove(ROMId, &RomHeader[0x02], 4); - - if (RomHeader[0x2A] == 0x33) - memmove(CompanyId, &RomHeader[0x00], 2); - else - sprintf(CompanyId, "%02X", RomHeader[0x2A]); -} - #undef INLINE #define INLINE #include "getset.h" - diff --git a/source/snes9x/memmap.h b/source/snes9x/memmap.h index f4d3ddf..4eb8e67 100644 --- a/source/snes9x/memmap.h +++ b/source/snes9x/memmap.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,191 +159,242 @@ **********************************************************************************/ + #ifndef _memmap_h_ #define _memmap_h_ #include "snes9x.h" -#define MEMMAP_BLOCK_SIZE (0x1000) -#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) -#define MEMMAP_BLOCKS_PER_BANK (0x10000 / MEMMAP_BLOCK_SIZE) -#define MEMMAP_SHIFT 12 -#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) -#define MEMMAP_MAX_SDD1_LOGGED_ENTRIES (0x10000 / 8) +#define MEMMAP_BLOCK_SIZE (0x1000) +#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) +#define MEMMAP_SHIFT (12) +#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) +#define MEMMAP_MAX_SDD1_LOGGED_ENTRIES (0x10000 / 8) -//Extended ROM Formats -#define NOPE 0 -#define YEAH 1 -#define BIGFIRST 2 -#define SMALLFIRST 3 +struct CMemory +{ + enum + { MAX_ROM_SIZE = 0x800000 }; -//File Formats go here -enum file_formats { FILE_ZIP, FILE_RAR, FILE_JMA, FILE_DEFAULT }; + enum file_formats + { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; -class CMemory { -public: - bool8 LoadROM (const char *); - uint32 FileLoader (uint8* buffer, const char* filename, int32 maxsize); - void InitROM (bool8); - bool8 LoadSRAM (const char *); - bool8 SaveSRAM (const char *); - bool8 Init (); - void Deinit (); - void FreeSDD1Data (); - - void WriteProtectROM (); - void FixROMSpeed (); - void MapRAM (); - void MapExtraRAM (); - char *Safe (const char *); - char *SafeANK (const char *); - - void JumboLoROMMap (bool8); - void LoROMMap (); - void LoROM24MBSMap (); - void SRAM512KLoROMMap (); -// void SRAM1024KLoROMMap (); - void SufamiTurboLoROMMap (); - void HiROMMap (); - void SuperFXROMMap (); - void TalesROMMap (bool8); - void AlphaROMMap (); - void SA1ROMMap (); - void SPC7110HiROMMap(); - void SPC7110Sram(uint8); - void SetaDSPMap(); - bool8 AllASCII (uint8 *b, int size); - int ScoreHiROM (bool8 skip_header, int32 offset=0); - int ScoreLoROM (bool8 skip_header, int32 offset=0); -#if 0 - void SufamiTurboAltROMMap(); -#endif - void ApplyROMFixes (); - void CheckForIPSPatch (const char *rom_filename, bool8 header, - int32 &rom_size); - - const char *TVStandard (); - const char *Speed (); - const char *StaticRAMSize (); - const char *MapType (); - const char *MapMode (); - const char *KartContents (); - const char *Size (); - const char *Headers (); - const char *ROMID (); - const char *CompanyID (); - void ParseSNESHeader(uint8*); - enum { - MAP_PPU, MAP_CPU, MAP_DSP, MAP_LOROM_SRAM, MAP_HIROM_SRAM, - MAP_NONE, MAP_DEBUG, MAP_C4, MAP_BWRAM, MAP_BWRAM_BITMAP, - MAP_BWRAM_BITMAP2, MAP_SA1RAM, MAP_SPC7110_ROM, MAP_SPC7110_DRAM, - MAP_RONLY_SRAM, MAP_OBC_RAM, MAP_SETA_DSP, MAP_SETA_RISC, MAP_BSX, MAP_LAST - }; - enum { MAX_ROM_SIZE = 0x800000 }; - - uint8 *RAM; - uint8 *ROM; - uint8 *VRAM; - uint8 *SRAM; - uint8 *BWRAM; - uint8 *FillRAM; - uint8 *C4RAM; - bool8 HiROM; - bool8 LoROM; - uint32 SRAMMask; - uint8 SRAMSize; - uint8 *Map [MEMMAP_NUM_BLOCKS]; - uint8 *WriteMap [MEMMAP_NUM_BLOCKS]; - uint8 MemorySpeed [MEMMAP_NUM_BLOCKS]; - uint8 BlockIsRAM [MEMMAP_NUM_BLOCKS]; - uint8 BlockIsROM [MEMMAP_NUM_BLOCKS]; - char ROMName [ROM_NAME_LEN]; - char RawROMName [ROM_NAME_LEN]; - char ROMId [5]; - char CompanyId [3]; - uint8 ROMSpeed; - uint8 ROMType; - uint8 ROMSize; - int32 ROMFramesPerSecond; - int32 HeaderCount; - uint32 CalculatedSize; - uint32 CalculatedChecksum; - uint32 ROMChecksum; - uint32 ROMComplementChecksum; - uint8 *SDD1Index; - uint8 *SDD1Data; - uint32 SDD1Entries; - uint32 SDD1LoggedDataCountPrev; - uint32 SDD1LoggedDataCount; - uint8 SDD1LoggedData [MEMMAP_MAX_SDD1_LOGGED_ENTRIES]; - char ROMFilename [_MAX_PATH]; - uint8 ROMRegion; - uint32 ROMCRC32; - uint8 ExtendedFormat; -#if 0 - bool8 SufamiTurbo; - char Slot1Filename [_MAX_PATH]; - char Slot2Filename [_MAX_PATH]; - uint8* ROMOffset1; - uint8* ROMOffset2; - uint8* SRAMOffset1; - uint8* SRAMOffset2; - uint32 Slot1Size; - uint32 Slot2Size; - uint32 Slot1SRAMSize; - uint32 Slot2SRAMSize; - uint8 SlotContents; -#endif - uint8 *BSRAM; - uint8 *BIOSROM; - void ResetSpeedMap(); -#if 0 - bool8 LoadMulti (const char *,const char *,const char *); -#endif + enum + { NOPE, YEAH, BIGFIRST, SMALLFIRST }; + + enum + { MAP_TYPE_I_O, MAP_TYPE_ROM, MAP_TYPE_RAM }; + + enum + { + MAP_PPU, + MAP_CPU, + MAP_LOROM_SRAM, + MAP_LOROM_SRAM_B, + MAP_HIROM_SRAM, + MAP_DSP, + MAP_C4, + MAP_BWRAM, + MAP_BWRAM_BITMAP, + MAP_BWRAM_BITMAP2, + MAP_SA1RAM, + MAP_SPC7110_ROM, + MAP_SPC7110_DRAM, + MAP_RONLY_SRAM, + MAP_OBC_RAM, + MAP_SETA_DSP, + MAP_SETA_RISC, + MAP_BSX, + MAP_NONE, + MAP_DEBUG, + MAP_LAST + }; + + uint8 NSRTHeader[32]; + int32 HeaderCount; + + uint8 *RAM; + uint8 *ROM; + uint8 *SRAM; + uint8 *VRAM; + uint8 *FillRAM; + uint8 *BWRAM; + uint8 *C4RAM; + uint8 *BSRAM; + uint8 *BIOSROM; + + uint8 *Map[MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; + uint8 MemorySpeed[MEMMAP_NUM_BLOCKS]; + uint8 ExtendedFormat; + + char ROMFilename[_MAX_PATH + 1]; + char ROMName[ROM_NAME_LEN]; + char RawROMName[ROM_NAME_LEN]; + char ROMId[5]; + char CompanyId[3]; + uint8 ROMRegion; + uint8 ROMSpeed; + uint8 ROMType; + uint8 ROMSize; + uint32 ROMChecksum; + uint32 ROMComplementChecksum; + uint32 ROMCRC32; + int32 ROMFramesPerSecond; + + bool8 HiROM; + bool8 LoROM; + uint8 SRAMSize; + uint32 SRAMMask; + uint32 CalculatedSize; + uint32 CalculatedChecksum; + + uint8 *SDD1Index; + uint8 *SDD1Data; + uint32 SDD1Entries; + uint32 SDD1LoggedDataCountPrev; + uint32 SDD1LoggedDataCount; + uint8 SDD1LoggedData[MEMMAP_MAX_SDD1_LOGGED_ENTRIES]; + + // ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls) + void (*PostRomInitFunc) (); + + bool8 Init (void); + void Deinit (void); + void FreeSDD1Data (void); + + int ScoreHiROM (bool8, int32 romoff = 0); + int ScoreLoROM (bool8, int32 romoff = 0); + uint32 HeaderRemove (uint32, int32 &, uint8 *); + uint32 FileLoader (uint8 *, const char *, int32); + bool8 LoadROM (const char *); + bool8 LoadMultiCart (const char *, const char *); + bool8 LoadSufamiTurbo (const char *, const char *); + bool8 LoadSameGame (const char *, const char *); + bool8 LoadLastROM (void); + bool8 LoadSRAM (const char *); + bool8 SaveSRAM (const char *); + void ClearSRAM (bool8 onlyNonSavedSRAM = 0); + + char * Safe (const char *); + char * SafeANK (const char *); + void ParseSNESHeader (uint8 *); + void InitROM (void); + void FixROMSpeed (void); + void ResetSpeedMap (void); + + uint32 map_mirror (uint32, uint32); + void map_lorom (uint32, uint32, uint32, uint32, uint32); + void map_hirom (uint32, uint32, uint32, uint32, uint32); + void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_space (uint32, uint32, uint32, uint32, uint8 *); + void map_index (uint32, uint32, uint32, uint32, int, int); + void map_System (void); + void map_WRAM (void); + void map_LoROMSRAM (void); + void map_HiROMSRAM (void); + void map_DSP (void); + void map_C4 (void); + void map_OBC1 (void); + void map_SetaRISC (void); + void map_SetaDSP (void); + void map_WriteProtectROM (void); + void Map_Initialize (void); + void Map_LoROMMap (void); + void Map_NoMAD1LoROMMap (void); + void Map_JumboLoROMMap (void); + void Map_ROM24MBSLoROMMap (void); + void Map_SRAM512KLoROMMap (void); + void Map_SufamiTurboLoROMMap (void); + void Map_SufamiTurboPseudoLoROMMap (void); + void Map_SuperFXLoROMMap (void); + void Map_SetaDSPLoROMMap (void); + void Map_SDD1LoROMMap (void); + void Map_SA1LoROMMap (void); + void Map_HiROMMap (void); + void Map_ExtendedHiROMMap (void); + void Map_SameGameHiROMMap (void); + void Map_SPC7110HiROMMap (void); + + uint16 checksum_calc_sum (uint8 *, uint32); + uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000); + void Checksum_Calculate (void); + + bool8 match_na (const char *); + bool8 match_nn (const char *); + bool8 match_nc (const char *); + bool8 match_id (const char *); + void ApplyROMFixes (void); + void CheckForIPSPatch (const char *, bool8, int32 &); + + const char * TVStandard (void); + const char * MapType (void); + const char * MapMode (void); + const char * StaticRAMSize (void); + const char * Size (void); + const char * Revision (void); + const char * KartContents (void); +}; + +struct SMulti +{ + int cartType; + int32 cartSizeA, cartSizeB; + int32 sramSizeA, sramSizeB; + uint32 sramMaskA, sramMaskB; + uint32 cartOffsetA, cartOffsetB; + uint8 *sramA, *sramB; + char fileNameA[_MAX_PATH + 1], fileNameB[_MAX_PATH + 1]; }; START_EXTERN_C -extern CMemory Memory; -extern uint8 *SRAM; -extern uint8 *ROM; -extern uint8 *RegRAM; -void S9xDeinterleaveMode2 (); -bool8 LoadZip(const char* zipname, - int32 *TotalFileSize, - int32 *headers, - uint8 *buffer); +extern CMemory Memory; +extern SMulti Multi; +#if defined(ZSNES_FX) || defined(ZSNES_C4) +extern uint8 *ROM; +extern uint8 *SRAM; +extern uint8 *RegRAM; +#endif +bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); END_EXTERN_C -void S9xAutoSaveSRAM (); +void S9xAutoSaveSRAM (void); - -enum s9xwrap_t { - WRAP_NONE, - WRAP_BANK, - WRAP_PAGE +enum s9xwrap_t +{ + WRAP_NONE, + WRAP_BANK, + WRAP_PAGE }; -enum s9xwriteorder_t { - WRITE_01, - WRITE_10 +enum s9xwriteorder_t +{ + WRITE_01, + WRITE_10 }; #ifdef NO_INLINE_SET_GET -uint8 S9xGetByte (uint32 Address); -uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w=WRAP_NONE); -void S9xSetByte (uint8 Byte, uint32 Address); -void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w=WRAP_NONE, enum s9xwriteorder_t o=WRITE_01); -void S9xSetPCBase (uint32 Address); -uint8 *S9xGetMemPointer (uint32 Address); -uint8 *GetBasePointer (uint32 Address); + +uint8 S9xGetByte (uint32); +uint16 S9xGetWord (uint32, enum s9xwrap_t w = WRAP_NONE); +void S9xSetByte (uint8, uint32); +void S9xSetWord (uint16, uint32, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01); +void S9xSetPCBase (uint32); +uint8 * S9xGetMemPointer (uint32); +uint8 * GetBasePointer (uint32); START_EXTERN_C -extern uint8 OpenBus; +extern uint8 OpenBus; END_EXTERN_C + #else + #define INLINE inline #include "getset.h" + #endif // NO_INLINE_SET_GET #endif // _memmap_h_ - diff --git a/source/snes9x/messages.h b/source/snes9x/messages.h index b2230e1..eb55261 100644 --- a/source/snes9x/messages.h +++ b/source/snes9x/messages.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _messages_h_ #define _messages_h_ @@ -186,6 +205,7 @@ enum { S9X_MOVIE_INFO, S9X_WRONG_MOVIE_SNAPSHOT, S9X_NOT_A_MOVIE_SNAPSHOT, + S9X_SNAPSHOT_INCONSISTENT, S9X_AVI_INFO }; diff --git a/source/snes9x/missing.h b/source/snes9x/missing.h index 98dc6a4..ef7c8d8 100644 --- a/source/snes9x/missing.h +++ b/source/snes9x/missing.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _MISSING_H_ #define _MISSING_H_ diff --git a/source/snes9x/obc1.cpp b/source/snes9x/obc1.cpp index 06da2f5..9f4cee8 100644 --- a/source/snes9x/obc1.cpp +++ b/source/snes9x/obc1.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include "memmap.h" #include "obc1.h" @@ -158,18 +177,18 @@ uint8 GetOBC1 (uint16 Address) switch(Address) { case 0x7ff0: return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)]; - + case 0x7ff1: return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1]; - + case 0x7ff2: return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2]; - + case 0x7ff3: return OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3]; - + case 0x7ff4: - return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; + return OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; } return OBC1_RAM[Address & 0x1fff]; @@ -183,51 +202,51 @@ void SetOBC1 (uint8 Byte, uint16 Address) OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2)] = Byte; break; } - + case 0x7ff1: { OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 1] = Byte; break; } - + case 0x7ff2: { OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 2] = Byte; break; } - + case 0x7ff3: { OBC1_RAM[OBC1_BasePtr + (OBC1_Address << 2) + 3] = Byte; break; } - + case 0x7ff4: { unsigned char Temp; Temp = OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200]; - Temp = (Temp & ~(3 << OBC1_Shift)) | ((Byte & 3) << OBC1_Shift); + Temp = (Temp & ~(3 << OBC1_Shift)) | ((Byte & 3) << OBC1_Shift); OBC1_RAM[OBC1_BasePtr + (OBC1_Address >> 2) + 0x200] = Temp; break; } - + case 0x7ff5: { - if (Byte & 1) + if (Byte & 1) OBC1_BasePtr = 0x1800; else OBC1_BasePtr = 0x1c00; break; } - + case 0x7ff6: { - OBC1_Address = Byte & 0x7f; - OBC1_Shift = (Byte & 3) << 1; + OBC1_Address = Byte & 0x7f; + OBC1_Shift = (Byte & 3) << 1; break; - } + } } OBC1_RAM[Address & 0x1fff] = Byte; @@ -253,12 +272,12 @@ void ResetOBC1() { OBC1_RAM = &Memory.FillRAM[0x6000]; - if (OBC1_RAM[0x1ff5] & 1) + if (OBC1_RAM[0x1ff5] & 1) OBC1_BasePtr = 0x1800; else OBC1_BasePtr = 0x1c00; - OBC1_Address = OBC1_RAM[0x1ff6] & 0x7f; + OBC1_Address = OBC1_RAM[0x1ff6] & 0x7f; OBC1_Shift = (OBC1_RAM[0x1ff6] & 3) << 1; } diff --git a/source/snes9x/obc1.h b/source/snes9x/obc1.h index 2b4c5c4..c9ddc66 100644 --- a/source/snes9x/obc1.h +++ b/source/snes9x/obc1.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _OBC1_H_ #define _OBC1_H_ @@ -151,7 +170,7 @@ void SetOBC1 (uint8 Byte, uint16 Address); uint8 *GetBasePointerOBC1(uint32 Address); uint8 *GetMemPointerOBC1(uint32 Address); void ResetOBC1();//bool8 full); -END_EXTERN_C +END_EXTERN_C #endif diff --git a/source/snes9x/pixform.h b/source/snes9x/pixform.h index 5f42ad2..bdda64c 100644 --- a/source/snes9x/pixform.h +++ b/source/snes9x/pixform.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _PIXFORM_H_ #define _PIXFORM_H_ @@ -196,7 +215,7 @@ extern uint32 HIGH_BITS_SHIFTED_TWO_MASK; #define FIRST_COLOR_MASK_RGB565 0xF800 #define SECOND_COLOR_MASK_RGB565 0x07E0 #define THIRD_COLOR_MASK_RGB565 0x001F -#define ALPHA_BITS_MASK_RGB565 0x0000 +#define ALPHA_BITS_MASK_RGB565 0x0000 /* RGB555 format */ #define BUILD_PIXEL_RGB555(R,G,B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) diff --git a/source/snes9x/port.h b/source/snes9x/port.h index c5b204c..a98409a 100644 --- a/source/snes9x/port.h +++ b/source/snes9x/port.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _PORT_H_ #define _PORT_H_ @@ -177,17 +196,17 @@ #ifdef _C #undef _C #endif - + #ifdef _D #undef _D #endif - + #define CHECK_SOUND() #define PIXEL_FORMAT RGB555 #undef GFX_MULTI_FORMAT #undef USE_X86_ASM #undef _MAX_PATH - + #define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); @@ -234,10 +253,16 @@ typedef long long int64; typedef unsigned long long uint64; #else /* __WIN32__ */ +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + # ifdef __BORLANDC__ # include # else +#define SNES_JOY_READ_CALLBACKS + typedef unsigned char uint8; typedef unsigned short uint16; typedef signed char int8; @@ -345,16 +370,12 @@ EXTERN_C void MixSound(void); #if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ defined(__x86_64__) || defined(__WIN32__) || defined(__alpha__) -//#define LSB_FIRST -//#define FAST_LSB_WORD_ACCESS +#define LSB_FIRST +#define FAST_LSB_WORD_ACCESS #else #define MSB_FIRST #endif -#ifndef MSB_FIRST -#define MSB_FIRST -#endif - #ifdef __sun #define TITLE "Snes9X: Solaris" #endif diff --git a/source/snes9x/ppu.cpp b/source/snes9x/ppu.cpp index 20684e5..600732e 100644 --- a/source/snes9x/ppu.cpp +++ b/source/snes9x/ppu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "ppu.h" @@ -152,17 +171,15 @@ #include "gfx.h" #include "display.h" #include "sa1.h" - -#ifndef NGC -#include "netplay.h" -#endif - #include "sdd1.h" #include "srtc.h" #include "spc7110.h" #include "bsx.h" -#include "movie.h" +//#include "movie.h" #include "controls.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif #ifndef ZSNES_FX #include "fxemu.h" @@ -193,23 +210,23 @@ static inline void S9xLatchCounters (bool force) #endif PPU.HVBeamCounterLatched = 1; PPU.VBeamPosLatched = (uint16) CPU.V_Counter; - + // From byuu: - // All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long. + // All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long. // This holds true for all scanlines except scanline 240 on non-interlace odd frames. // The reason for this is because this scanline is only 1360 cycles long, // instead of 1364 like all other scanlines. // This makes the effective range of hscan_pos 0-339 at all times. int32 hc = CPU.Cycles; - + if (Timings.H_Max == Timings.H_Max_Master) // 1364 - { + { if (hc >= 1292) hc -= (ONE_DOT_CYCLE / 2); if (hc >= 1308) hc -= (ONE_DOT_CYCLE / 2); } - + PPU.HBeamPosLatched = (uint16) (hc / ONE_DOT_CYCLE); // Causes screen flicker for Yoshi's Island if uncommented @@ -218,7 +235,7 @@ static inline void S9xLatchCounters (bool force) Memory.FillRAM [0x213F] |= 0x40; } - + if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) { @@ -250,7 +267,7 @@ static inline void S9xTryGunLatch (bool force) Memory.FillRAM [0x213F] |= 0x40; } - + PPU.GunVLatch = 1000; } } @@ -267,8 +284,20 @@ void S9xCheckMissingHTimerPosition (int32 hc) } } -void S9xCheckMissingHTimerPositionRange (int32 hc_from, int32 range) -{ +void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range) +{ + if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + CPU.IRQPending = 1; + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + CPU.IRQPending = 1; + } +} + +void S9xCheckMissingHTimerRange (int32 hc_from, int32 range) +{ if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) { if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) @@ -279,12 +308,6 @@ void S9xCheckMissingHTimerPositionRange (int32 hc_from, int32 range) } } -void S9xCheckMissingVTimerPosition (void) -{ - if (PPU.VTimerEnabled && !PPU.HTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition) && (CPU.Cycles >= PPU.HTimerPosition)) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); -} - void S9xUpdateHVTimerPosition (void) { if (PPU.HTimerEnabled) @@ -297,7 +320,7 @@ void S9xUpdateHVTimerPosition (void) // IRQ_read PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE; if (Timings.H_Max == Timings.H_Max_Master) // 1364 - { + { if (PPU.IRQHBeamPos > 322) PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); if (PPU.IRQHBeamPos > 326) @@ -319,7 +342,7 @@ void S9xUpdateHVTimerPosition (void) if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340)) { - PPU.HTimerPosition -= Timings.H_Max; + PPU.HTimerPosition -= Timings.H_Max; PPU.VTimerPosition++; // FIXME if (PPU.VTimerPosition >= Timings.V_Max) @@ -334,27 +357,27 @@ void S9xUpdateHVTimerPosition (void) CPU.WhichEvent = HC_HDMA_START_EVENT; CPU.NextEvent = Timings.HDMAStart; break; - + case HC_IRQ_3_5_EVENT: CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; CPU.NextEvent = Timings.H_Max; break; - + case HC_IRQ_5_7_EVENT: CPU.WhichEvent = HC_HDMA_INIT_EVENT; CPU.NextEvent = Timings.HDMAInit; break; - + case HC_IRQ_7_9_EVENT: CPU.WhichEvent = HC_RENDER_EVENT; CPU.NextEvent = Timings.RenderPos; break; - + case HC_IRQ_9_A_EVENT: CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; CPU.NextEvent = Timings.WRAMRefreshPos; break; - + case HC_IRQ_A_1_EVENT: CPU.WhichEvent = HC_HBLANK_START_EVENT; CPU.NextEvent = Timings.HBlankStart; @@ -362,32 +385,32 @@ void S9xUpdateHVTimerPosition (void) } } else - if (PPU.HTimerPosition < CPU.NextEvent) + if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent))) { CPU.NextEvent = PPU.HTimerPosition; - + switch (CPU.WhichEvent) { case HC_HDMA_START_EVENT: CPU.WhichEvent = HC_IRQ_1_3_EVENT; break; - + case HC_HCOUNTER_MAX_EVENT: CPU.WhichEvent = HC_IRQ_3_5_EVENT; break; - + case HC_HDMA_INIT_EVENT: CPU.WhichEvent = HC_IRQ_5_7_EVENT; break; - + case HC_RENDER_EVENT: CPU.WhichEvent = HC_IRQ_7_9_EVENT; break; - + case HC_WRAM_REFRESH_EVENT: CPU.WhichEvent = HC_IRQ_9_A_EVENT; break; - + case HC_HBLANK_START_EVENT: CPU.WhichEvent = HC_IRQ_A_1_EVENT; break; @@ -401,27 +424,27 @@ void S9xUpdateHVTimerPosition (void) CPU.WhichEvent = HC_HDMA_START_EVENT; CPU.NextEvent = Timings.HDMAStart; break; - + case HC_IRQ_3_5_EVENT: CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; CPU.NextEvent = Timings.H_Max; break; - + case HC_IRQ_5_7_EVENT: CPU.WhichEvent = HC_HDMA_INIT_EVENT; CPU.NextEvent = Timings.HDMAInit; break; - + case HC_IRQ_7_9_EVENT: CPU.WhichEvent = HC_RENDER_EVENT; CPU.NextEvent = Timings.RenderPos; break; - + case HC_IRQ_9_A_EVENT: CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; CPU.NextEvent = Timings.WRAMRefreshPos; break; - + case HC_IRQ_A_1_EVENT: CPU.WhichEvent = HC_HBLANK_START_EVENT; CPU.NextEvent = Timings.HBlankStart; @@ -452,7 +475,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) // fprintf(stderr, "%03d: %02x to %04x\n", CPU.V_Counter, Byte, Address); // Take care of DMA wrapping - if(CPU.InDMA && Address>0x21ff) Address=0x2100+(Address&0xff); + if(CPU.InDMAorHDMA && Address>0x21ff) Address=0x2100+(Address&0xff); if (Address <= 0x219F) { @@ -478,6 +501,17 @@ void S9xSetPPU (uint8 Byte, uint16 Address) PPU.ForcedBlanking = (Byte >> 7) & 1; } } + if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter==PPU.ScreenHeight+FIRST_VISIBLE_LINE){ + PPU.OAMAddr = PPU.SavedOAMAddr; + uint8 tmp = 0; + if(PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xFE) >> 1; + if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp){ + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + PPU.OAMFlip = 0; + } break; case 0x2101: @@ -650,7 +684,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) case 0x210E: // Yes, the two formulas are supposed to be different. - PPU.BG[0].VOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[0].VOffset>>8)&7); + PPU.BG[0].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; PPU.M7VOFS = (Byte<<8) | PPU.M7byte; PPU.BGnxOFSbyte = Byte; PPU.M7byte = Byte; @@ -662,7 +696,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) break; case 0x2110: - PPU.BG[1].VOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[1].VOffset>>8)&7); + PPU.BG[1].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; PPU.BGnxOFSbyte = Byte; break; @@ -672,7 +706,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) break; case 0x2112: - PPU.BG[2].VOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[2].VOffset>>8)&7); + PPU.BG[2].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; PPU.BGnxOFSbyte = Byte; break; @@ -682,7 +716,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address) break; case 0x2114: - PPU.BG[3].VOffset = (Byte<<8) | (PPU.BGnxOFSbyte&~7) | ((PPU.BG[3].VOffset>>8)&7); + PPU.BG[3].VOffset = (Byte<<8) | PPU.BGnxOFSbyte; PPU.BGnxOFSbyte = Byte; break; @@ -1157,37 +1191,33 @@ void S9xSetPPU (uint8 Byte, uint16 Address) case 0x2174: case 0x2175: case 0x2176: case 0x2177: case 0x2178: case 0x2179: case 0x217a: case 0x217b: case 0x217c: case 0x217d: case 0x217e: case 0x217f: -#ifdef SPCTOOL - _SPCInPB (Address & 3, Byte); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; - Memory.FillRAM [Address] = Byte; - IAPU.RAM [(Address & 3) + 0xf4] = Byte; #ifdef SPC700_SHUTDOWN IAPU.APUExecuting = Settings.APUEnabled; IAPU.WaitCounter++; #endif -#endif // SPCTOOL + S9xAPUExecute(); + Memory.FillRAM [Address] = Byte; + IAPU.RAM [(Address & 3) + 0xf4] = Byte; break; case 0x2180: - if(!CPU.InWRAM_DMA){ + if(!CPU.InWRAMDMAorHDMA){ REGISTER_2180(Byte); } break; case 0x2181: - if(!CPU.InWRAM_DMA){ + if(!CPU.InWRAMDMAorHDMA){ PPU.WRAM &= 0x1FF00; PPU.WRAM |= Byte; } break; case 0x2182: - if(!CPU.InWRAM_DMA){ + if(!CPU.InWRAMDMAorHDMA){ PPU.WRAM &= 0x100FF; PPU.WRAM |= Byte << 8; } break; case 0x2183: - if(!CPU.InWRAM_DMA){ + if(!CPU.InWRAMDMAorHDMA){ PPU.WRAM &= 0x0FFFF; PPU.WRAM |= Byte << 16; PPU.WRAM &= 0x1FFFF; @@ -1357,7 +1387,7 @@ uint8 S9xGetPPU (uint16 Address) return OpenBus; //treat as unmapped memory returning last byte on the bus // Take care of DMA wrapping - if(CPU.InDMA && Address>0x21ff) Address=0x2100+(Address&0xff); + if(CPU.InDMAorHDMA && Address>0x21ff) Address=0x2100+(Address&0xff); if (Address <= 0x219F) { @@ -1552,7 +1582,7 @@ uint8 S9xGetPPU (uint16 Address) } else byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; - + if (!PPU.VMA.High) { PPU.VMA.Address += PPU.VMA.Increment; @@ -1618,7 +1648,7 @@ uint8 S9xGetPPU (uint16 Address) PPU.CGFLIPRead ^= 1; return (PPU.OpenBus2 = byte); - + case 0x213C: // Horizontal counter value 0-339 #ifdef DEBUGGER @@ -1679,26 +1709,24 @@ uint8 S9xGetPPU (uint16 Address) case 0x2174: case 0x2175: case 0x2176: case 0x2177: case 0x2178: case 0x2179: case 0x217a: case 0x217b: case 0x217c: case 0x217d: case 0x217e: case 0x217f: -#ifdef SPCTOOL - return ((uint8) _SPCOutP [Address & 3]); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; -#ifdef SPC700_SHUTDOWN +#ifdef SPC700_SHUTDOWN IAPU.APUExecuting = Settings.APUEnabled; IAPU.WaitCounter++; #endif - if (Settings.APUEnabled) + S9xAPUExecute(); + if (Settings.APUEnabled) { #ifdef CPU_SHUTDOWN // CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif +#endif +#if 0 if (SNESGameFixes.APU_OutPorts_ReturnValueFix && Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) { - return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : + return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : (rand() & 0xff)); } - +#endif return (APU.OutPorts [Address & 3]); } @@ -1732,14 +1760,13 @@ uint8 S9xGetPPU (uint16 Address) return ((r >> 3) & 0xff); } return (Memory.FillRAM[Address]); -#endif // SPCTOOL case 0x2180: // Read WRAM #ifdef DEBUGGER missing.wram_read = 1; #endif - if(!CPU.InWRAM_DMA){ + if(!CPU.InWRAMDMAorHDMA){ byte = Memory.RAM [PPU.WRAM++]; PPU.WRAM &= 0x1FFFF; } else { @@ -1754,7 +1781,7 @@ uint8 S9xGetPPU (uint16 Address) case 0x2186: case 0x2187: return OpenBus; - + case 0x2188: case 0x2189: case 0x218a: @@ -1813,7 +1840,7 @@ uint8 S9xGetPPU (uint16 Address) if (Settings.SRTC) return (S9xGetSRTC (Address)); /*FALL*/ - + default: #ifdef DEBUGGER missing.unknownppu_read = Address; @@ -1826,7 +1853,7 @@ uint8 S9xGetPPU (uint16 Address) return OpenBus; } } - + if (!Settings.SuperFX) return OpenBus; #ifdef ZSNES_FX @@ -1838,7 +1865,7 @@ uint8 S9xGetPPU (uint16 Address) #ifdef CPU_SHUTDOWN if (Address == 0x3030) CPU.WaitAddress = CPU.PBPCAtOpcodeStart; -#endif +#endif if (Address == 0x3031) CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); #else @@ -1904,7 +1931,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4200: // NMI, V & H IRQ and joypad reading enable flags pV = PPU.VTimerEnabled; - + if (byte & 0x20) { PPU.VTimerEnabled = TRUE; @@ -1926,16 +1953,17 @@ void S9xSetCPU (uint8 byte, uint16 Address) } else PPU.HTimerEnabled = FALSE; - + S9xUpdateHVTimerPosition(); - // FIXME - if (pV != PPU.VTimerEnabled) - S9xCheckMissingVTimerPosition(); - + + // The case that IRQ will trigger in an instruction such as STA $4200 + // FIXME: not true but good enough for Snes9x, I think. + S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); + if (!(byte & 0x30)) CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - if ((byte & 0x80) && + if ((byte & 0x80) && !(Memory.FillRAM [0x4200] & 0x80) && // NMI can trigger during VBlank as long as NMI_read ($4210) wasn't cleard. // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling @@ -2011,12 +2039,8 @@ void S9xSetCPU (uint8 byte, uint16 Address) missing.virq_pos = PPU.IRQVBeamPos; #endif if (PPU.IRQVBeamPos != d) - { S9xUpdateHVTimerPosition(); - // FIXME - S9xCheckMissingVTimerPosition(); - } - + break; case 0x420A: @@ -2026,22 +2050,18 @@ void S9xSetCPU (uint8 byte, uint16 Address) missing.virq_pos = PPU.IRQVBeamPos; #endif if (PPU.IRQVBeamPos != d) - { S9xUpdateHVTimerPosition(); - // FIXME - S9xCheckMissingVTimerPosition(); - } - + break; case 0x420B: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; #ifdef DEBUGGER missing.dma_this_frame = byte; missing.dma_channels = byte; #endif // XXX: Not quite right... - if(byte) CPU.Cycles += 18; + if (byte) CPU.Cycles += Timings.DMACPUSync; if ((byte & 0x01) != 0) S9xDoDMA (0); if ((byte & 0x02) != 0) @@ -2060,10 +2080,10 @@ void S9xSetCPU (uint8 byte, uint16 Address) S9xDoDMA (7); break; case 0x420C: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; #ifdef DEBUGGER missing.hdma_this_frame |= byte; - missing.hdma_channels |= byte; + missing.hdma_channels |= byte; #endif if (Settings.DisableHDMA) byte = 0; @@ -2133,9 +2153,9 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4350: case 0x4360: case 0x4370: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; - DMA[d].TransferDirection = (byte&0x80)?1:0; + DMA[d].ReverseTransfer = (byte&0x80)?1:0; DMA[d].HDMAIndirectAddressing = (byte&0x40)?1:0; DMA[d].UnusedBit43x0 = (byte&0x20)?1:0; DMA[d].AAddressDecrement = (byte&0x10)?1:0; @@ -2151,7 +2171,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4351: case 0x4361: case 0x4371: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; DMA[((Address >> 4) & 0x7)].BAddress = byte; return; @@ -2163,7 +2183,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4352: case 0x4362: case 0x4372: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; DMA[d].AAddress &= 0xFF00; DMA[d].AAddress |= byte; @@ -2177,7 +2197,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4353: case 0x4363: case 0x4373: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; DMA[d].AAddress &= 0xFF; DMA[d].AAddress |= byte << 8; @@ -2191,7 +2211,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4354: case 0x4364: case 0x4374: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; DMA[d=((Address >> 4) & 0x7)].ABank = byte; HDMAMemPointers[d]=NULL; return; @@ -2204,7 +2224,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4355: case 0x4365: case 0x4375: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00; DMA[d].DMACount_Or_HDMAIndirectAddress |= byte; @@ -2219,7 +2239,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4356: case 0x4366: case 0x4376: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff; DMA[d].DMACount_Or_HDMAIndirectAddress |= byte << 8; @@ -2234,7 +2254,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4357: case 0x4367: case 0x4377: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; HDMAMemPointers[d]=NULL; return; @@ -2247,7 +2267,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4358: case 0x4368: case 0x4378: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 7; DMA[d].Address &= 0xff00; DMA[d].Address |= byte; @@ -2262,7 +2282,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x4359: case 0x4369: case 0x4379: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; DMA[d].Address &= 0xff; DMA[d].Address |= byte << 8; @@ -2277,7 +2297,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x435A: case 0x436A: case 0x437A: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; d = (Address >> 4) & 0x7; if(byte&0x7f){ DMA[d].LineCount = byte & 0x7f; @@ -2305,7 +2325,7 @@ void S9xSetCPU (uint8 byte, uint16 Address) case 0x435F: case 0x436F: case 0x437F: - if(CPU.InDMA) return; + if(CPU.InDMAorHDMA) return; DMA[((Address >> 4) & 0x7)].UnknownByte = byte; return; @@ -2402,6 +2422,12 @@ uint8 S9xGetCPU (uint16 Address) if (Address < 0x4200) { +#ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if(Address==0x4016 || Address==0x4017) + S9xOnSNESPadRead(), pad_read = true; +#endif + CPU.Cycles += ONE_CYCLE; switch (Address) { @@ -2446,7 +2472,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4210: #ifdef CPU_SHUTDOWN CPU.WaitAddress = CPU.PBPCAtOpcodeStart; -#endif +#endif byte = Memory.FillRAM[0x4210]; Memory.FillRAM[0x4210] = Model->_5A22; //SNEeSe returns 2 for 5A22 version. @@ -2490,6 +2516,13 @@ uint8 S9xGetCPU (uint16 Address) case 0x421d: case 0x421e: case 0x421f: +#ifdef SNES_JOY_READ_CALLBACKS + { + extern bool8 pad_read; + if(Memory.FillRAM[0x4200] & 1) + S9xOnSNESPadRead(), pad_read = true; + } +#endif // Joypads 1-4 button and direction state. return (Memory.FillRAM [Address]); @@ -2501,9 +2534,9 @@ uint8 S9xGetCPU (uint16 Address) case 0x4350: case 0x4360: case 0x4370: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; d = (Address >> 4) & 0x7; - return ((DMA[d].TransferDirection?0x80:0x00) | + return ((DMA[d].ReverseTransfer?0x80:0x00) | (DMA[d].HDMAIndirectAddressing?0x40:0x00) | (DMA[d].UnusedBit43x0?0x20:0x00) | (DMA[d].AAddressDecrement?0x10:0x00) | @@ -2518,7 +2551,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4351: case 0x4361: case 0x4371: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return DMA[((Address >> 4) & 0x7)].BAddress; case 0x4302: @@ -2529,7 +2562,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4352: case 0x4362: case 0x4372: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].AAddress & 0xFF); case 0x4303: @@ -2540,7 +2573,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4353: case 0x4363: case 0x4373: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].AAddress >> 8); case 0x4304: @@ -2551,7 +2584,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4354: case 0x4364: case 0x4374: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return DMA[((Address >> 4) & 0x7)].ABank; case 0x4305: @@ -2562,7 +2595,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4355: case 0x4365: case 0x4375: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].DMACount_Or_HDMAIndirectAddress & 0xff); case 0x4306: @@ -2573,7 +2606,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4356: case 0x4366: case 0x4376: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].DMACount_Or_HDMAIndirectAddress >> 8); case 0x4307: @@ -2584,7 +2617,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4357: case 0x4367: case 0x4377: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return DMA[((Address >> 4) & 0x7)].IndirectBank; case 0x4308: @@ -2595,7 +2628,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4358: case 0x4368: case 0x4378: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].Address & 0xFF); case 0x4309: @@ -2606,7 +2639,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x4359: case 0x4369: case 0x4379: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return (DMA[((Address >> 4) & 0x7)].Address >> 8); case 0x430A: @@ -2617,7 +2650,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x435A: case 0x436A: case 0x437A: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; d = (Address >> 4) & 0x7; return (DMA[d].LineCount ^ (DMA[d].Repeat?0x00:0x80)); @@ -2637,7 +2670,7 @@ uint8 S9xGetCPU (uint16 Address) case 0x435F: case 0x436F: case 0x437F: - if(CPU.InDMA) return OpenBus; + if(CPU.InDMAorHDMA) return OpenBus; return DMA[((Address >> 4) & 0x7)].UnknownByte; default: @@ -2648,7 +2681,7 @@ uint8 S9xGetCPU (uint16 Address) sprintf (String, "Unknown register read: $%04X\n", Address); S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); } - + #endif if(Address>= 0x4800&&Settings.SPC7110) @@ -2668,6 +2701,9 @@ void S9xResetPPU () S9xSoftResetPPU(); S9xControlsReset(); IPPU.PreviousLine = IPPU.CurrentLine = 0; + PPU.M7HOFS = 0; + PPU.M7VOFS = 0; + PPU.M7byte = 0; } void S9xSoftResetPPU () @@ -2740,8 +2776,8 @@ void S9xSoftResetPPU () PPU.OAMFlip = 0; PPU.OAMTileAddress = 0; PPU.OAMAddr = 0; - PPU.IRQVBeamPos = 0; - PPU.IRQHBeamPos = 0; + PPU.IRQVBeamPos = 0x1ff; + PPU.IRQHBeamPos = 0x1ff; PPU.VBeamPosLatched = 0; PPU.HBeamPosLatched = 0; @@ -2758,7 +2794,6 @@ void S9xSoftResetPPU () PPU.SavedOAMAddr = 0; PPU.ScreenHeight = SNES_HEIGHT; PPU.WRAM = 0; - PPU.BG_Forced = 0; PPU.ForcedBlanking = TRUE; PPU.OBJThroughMain = FALSE; PPU.OBJThroughSub = FALSE; diff --git a/source/snes9x/ppu.h b/source/snes9x/ppu.h index f7031d5..ced5d0b 100644 --- a/source/snes9x/ppu.h +++ b/source/snes9x/ppu.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _PPU_H_ #define _PPU_H_ @@ -187,6 +206,7 @@ struct InternalPPU { uint32 FrameCount; uint32 RenderedFramesCount; uint32 DisplayedRenderedFrameCount; + uint32 TotalEmulatedFrames; uint32 SkippedFrames; uint32 FrameSkip; uint8 *TileCache [7]; @@ -215,7 +235,7 @@ struct InternalPPU { struct SOBJ { - short HPos; + int16 HPos; uint16 VPos; uint16 Name; uint8 VFlip; @@ -249,7 +269,7 @@ struct SPPU { } BG [4]; bool8 CGFLIP; - uint16 CGDATA [256]; + uint16 CGDATA [256]; uint8 FirstSprite; uint8 LastSprite; struct SOBJ OBJ [128]; @@ -284,7 +304,6 @@ struct SPPU { uint16 SavedOAMAddr; uint16 ScreenHeight; uint32 WRAM; - uint8 BG_Forced; bool8 ForcedBlanking; bool8 OBJThroughMain; bool8 OBJThroughSub; @@ -334,7 +353,7 @@ struct SPPU { struct SDMA { /* $43x0 */ - bool8 TransferDirection; + bool8 ReverseTransfer; bool8 HDMAIndirectAddressing; bool8 UnusedBit43x0; bool8 AAddressFixed; @@ -392,8 +411,8 @@ uint8 *S9xGetBasePointerC4 (uint16 Address); void S9xUpdateHVTimerPosition (void); void S9xCheckMissingHTimerPosition (int32); -void S9xCheckMissingHTimerPositionRange (int32, int32); -void S9xCheckMissingVTimerPosition (void); +void S9xCheckMissingHTimerRange (int32, int32); +void S9xCheckMissingHTimerHalt (int32, int32); extern struct SPPU PPU; extern struct SDMA DMA [8]; @@ -409,11 +428,11 @@ typedef struct{ uint8 _5A22; } SnesModel; -#ifndef _GLOBALS_CPP +START_EXTERN_C extern SnesModel* Model; extern SnesModel M1SNES; extern SnesModel M2SNES; -#endif +END_EXTERN_C #define MAX_5C77_VERSION 0x01 #define MAX_5C78_VERSION 0x03 @@ -426,7 +445,7 @@ STATIC inline uint8 REGISTER_4212() CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3) GetBank = 1; - GetBank |= CPU.Cycles >= Timings.HBlankStart ? 0x40 : 0; + GetBank |= ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart)) ? 0x40 : 0; if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) GetBank |= 0x80; /* XXX: 0x80 or 0xc0 ? */ @@ -526,8 +545,19 @@ STATIC inline void REGISTER_2104 (uint8 byte) Memory.FillRAM [0x2104] = byte; } +// This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :( +#define CHECK_INBLANK \ +{ \ + if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + { \ + return; \ + } \ +} \ + STATIC inline void REGISTER_2118 (uint8 Byte) { + CHECK_INBLANK; + uint32 address; if (PPU.VMA.FullGraphicCount) { @@ -555,13 +585,13 @@ STATIC inline void REGISTER_2118 (uint8 Byte) if (!PPU.VMA.High) { #ifdef DEBUGGER - if (Settings.TraceVRAM && !CPU.InDMA) + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) { printf ("VRAM write byte: $%04X (%d,%d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM [0x2115] & 0x0c) >> 2); } -#endif +#endif PPU.VMA.Address += PPU.VMA.Increment; } // Memory.FillRAM [0x2118] = Byte; @@ -569,6 +599,8 @@ STATIC inline void REGISTER_2118 (uint8 Byte) STATIC inline void REGISTER_2118_tile (uint8 Byte) { + CHECK_INBLANK; + uint32 address; uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + @@ -593,6 +625,8 @@ STATIC inline void REGISTER_2118_tile (uint8 Byte) STATIC inline void REGISTER_2118_linear (uint8 Byte) { + CHECK_INBLANK; + uint32 address; Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xFFFF] = Byte; IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; @@ -613,6 +647,8 @@ STATIC inline void REGISTER_2118_linear (uint8 Byte) STATIC inline void REGISTER_2119 (uint8 Byte) { + CHECK_INBLANK; + uint32 address; if (PPU.VMA.FullGraphicCount) { @@ -640,13 +676,13 @@ STATIC inline void REGISTER_2119 (uint8 Byte) if (PPU.VMA.High) { #ifdef DEBUGGER - if (Settings.TraceVRAM && !CPU.InDMA) + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) { printf ("VRAM write word: $%04X (%d,%d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM [0x2115] & 0x0c) >> 2); } -#endif +#endif PPU.VMA.Address += PPU.VMA.Increment; } // Memory.FillRAM [0x2119] = Byte; @@ -654,6 +690,8 @@ STATIC inline void REGISTER_2119 (uint8 Byte) STATIC inline void REGISTER_2119_tile (uint8 Byte) { + CHECK_INBLANK; + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + @@ -677,6 +715,8 @@ STATIC inline void REGISTER_2119_tile (uint8 Byte) STATIC inline void REGISTER_2119_linear (uint8 Byte) { + CHECK_INBLANK; + uint32 address; Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xFFFF] = Byte; IPPU.TileCached [TILE_2BIT][address >> 4] = FALSE; diff --git a/source/snes9x/sa1.cpp b/source/snes9x/sa1.cpp index 7389f9e..81d4163 100644 --- a/source/snes9x/sa1.cpp +++ b/source/snes9x/sa1.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "ppu.h" #include "cpuexec.h" @@ -437,7 +456,7 @@ void S9xSA1SetPCBase (uint32 address) #ifdef DEBUGGER printf ("SBP %06x\n", address); #endif - + default: case CMemory::MAP_NONE: SA1.PCBase = NULL; @@ -476,7 +495,7 @@ void S9xSetSA1MemMap (uint32 which1, uint8 map) for (i = c; i < c + 16; i++) Memory.Map [start + i] = SA1.Map [start + i] = block; } - + for (c = 0; c < 0x200; c += 16) { uint8 *block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; @@ -493,7 +512,7 @@ uint8 S9xGetSA1 (uint32 address) switch (address) { case 0x2300: - return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | + return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); case 0x2301: return ((Memory.FillRAM [0x2200] & 0xf) | @@ -520,7 +539,7 @@ uint8 S9xGetSA1 (uint32 address) } return (byte); } - default: + default: printf ("R: %04x\n", address); break; } @@ -545,7 +564,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) Memory.FillRAM [0x2301] |= 0x80; if (Memory.FillRAM [0x220a] & 0x80) { - SA1.Flags |= IRQ_PENDING_FLAG; + SA1.Flags |= IRQ_FLAG; SA1.IRQActive |= SNES_IRQ_SOURCE; SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; } @@ -621,21 +640,21 @@ void S9xSetSA1 (uint8 byte, uint32 address) if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && (Memory.FillRAM [0x2301] & byte & 0x80)) { - SA1.Flags |= IRQ_PENDING_FLAG; + SA1.Flags |= IRQ_FLAG; SA1.IRQActive |= SNES_IRQ_SOURCE; // SA1.Executing = !SA1.Waiting; } if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && (Memory.FillRAM [0x2301] & byte & 0x40)) { - SA1.Flags |= IRQ_PENDING_FLAG; + SA1.Flags |= IRQ_FLAG; SA1.IRQActive |= TIMER_IRQ_SOURCE; // SA1.Executing = !SA1.Waiting; } if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && (Memory.FillRAM [0x2301] & byte & 0x20)) { - SA1.Flags |= IRQ_PENDING_FLAG; + SA1.Flags |= IRQ_FLAG; SA1.IRQActive |= DMA_IRQ_SOURCE; // SA1.Executing = !SA1.Waiting; } @@ -669,7 +688,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) Memory.FillRAM [0x2301] &= ~0x10; } if (!SA1.IRQActive) - SA1.Flags &= ~IRQ_PENDING_FLAG; + SA1.Flags &= ~IRQ_FLAG; break; case 0x220c: // printf ("SNES NMI vector: %04x\n", byte | (Memory.FillRAM [0x220d] << 8)); @@ -693,19 +712,19 @@ void S9xSetSA1 (uint8 byte, uint32 address) #endif break; case 0x2211: - printf ("Timer reset\n"); +// printf ("Timer reset\n"); break; case 0x2212: - printf ("H-Timer %04x\n", byte | (Memory.FillRAM [0x2213] << 8)); +// printf ("H-Timer %04x\n", byte | (Memory.FillRAM [0x2213] << 8)); break; case 0x2213: - printf ("H-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2212]); +// printf ("H-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2212]); break; case 0x2214: - printf ("V-Timer %04x\n", byte | (Memory.FillRAM [0x2215] << 8)); +// printf ("V-Timer %04x\n", byte | (Memory.FillRAM [0x2215] << 8)); break; case 0x2215: - printf ("V-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2214]); +// printf ("V-Timer %04x\n", (byte << 8) | Memory.FillRAM [0x2214]); break; case 0x2220: case 0x2221: @@ -763,7 +782,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) case 0x2234: Memory.FillRAM [address] = byte; #if 0 - printf ("DMA source start %06x\n", + printf ("DMA source start %06x\n", Memory.FillRAM [0x2232] | (Memory.FillRAM [0x2233] << 8) | (Memory.FillRAM [0x2234] << 16)); #endif @@ -795,7 +814,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) S9xSA1DMA (); } #if 0 - printf ("DMA dest address %06x\n", + printf ("DMA dest address %06x\n", Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8) | (Memory.FillRAM [0x2237] << 16)); #endif @@ -804,7 +823,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) case 0x2239: Memory.FillRAM [address] = byte; #if 0 - printf ("DMA length %04x\n", + printf ("DMA length %04x\n", Memory.FillRAM [0x2238] | (Memory.FillRAM [0x2239] << 8)); #endif break; @@ -846,7 +865,7 @@ void S9xSetSA1 (uint8 byte, uint32 address) SA1.sum = 0; SA1.arithmetic_op = byte & 3; break; - + case 0x2251: SA1.op1 = (SA1.op1 & 0xff00) | byte; break; @@ -987,10 +1006,10 @@ static void S9xSA1DMA () } memmove (d, s, len); Memory.FillRAM [0x2301] |= 0x20; - + if (Memory.FillRAM [0x220a] & 0x20) { - SA1.Flags |= IRQ_PENDING_FLAG; + SA1.Flags |= IRQ_FLAG; SA1.IRQActive |= DMA_IRQ_SOURCE; // SA1.Executing = !SA1.Waiting; } diff --git a/source/snes9x/sa1.h b/source/snes9x/sa1.h index ae19900..96e1194 100644 --- a/source/snes9x/sa1.h +++ b/source/snes9x/sa1.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _sa1_h_ #define _sa1_h_ diff --git a/source/snes9x/sa1cpu.cpp b/source/snes9x/sa1cpu.cpp index 5341411..0183c2e 100644 --- a/source/snes9x/sa1cpu.cpp +++ b/source/snes9x/sa1cpu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "ppu.h" @@ -213,7 +232,7 @@ void S9xSA1MainLoop () S9xSA1Opcode_NMI (); } #endif - if (SA1.Flags & IRQ_PENDING_FLAG) + if (SA1.Flags & IRQ_FLAG) { if (SA1.IRQActive) { @@ -226,7 +245,7 @@ void S9xSA1MainLoop () S9xSA1Opcode_IRQ (); } else - SA1.Flags &= ~IRQ_PENDING_FLAG; + SA1.Flags &= ~IRQ_FLAG; } for (i = 0; i < 3 && SA1.Executing; i++) { diff --git a/source/snes9x/sar.h b/source/snes9x/sar.h index 9562fda..140dfeb 100644 --- a/source/snes9x/sar.h +++ b/source/snes9x/sar.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _SAR_H_ #define _SAR_H_ diff --git a/source/snes9x/screenshot.h b/source/snes9x/screenshot.h index 4afdfe9..1665a3c 100644 --- a/source/snes9x/screenshot.h +++ b/source/snes9x/screenshot.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef SCREENSHOT_H #define SCREENSHOT_H diff --git a/source/snes9x/sdd1.cpp b/source/snes9x/sdd1.cpp index fa5caf1..ae5206f 100644 --- a/source/snes9x/sdd1.cpp +++ b/source/snes9x/sdd1.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #include "snes9x.h" #include "memmap.h" #include "ppu.h" @@ -225,7 +244,7 @@ void S9xSDD1LoadLoggedData () if (fs) { - int c = fread (Memory.SDD1LoggedData, 8, + int c = fread (Memory.SDD1LoggedData, 8, MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); if (c != EOF) diff --git a/source/snes9x/sdd1.h b/source/snes9x/sdd1.h index 0cc17a8..c03c343 100644 --- a/source/snes9x/sdd1.h +++ b/source/snes9x/sdd1.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _SDD1_H_ #define _SDD1_H_ void S9xSetSDD1MemoryMap (uint32 bank, uint32 value); diff --git a/source/snes9x/sdd1emu.cpp b/source/snes9x/sdd1emu.cpp index 9e6a5a1..4104137 100644 --- a/source/snes9x/sdd1emu.cpp +++ b/source/snes9x/sdd1emu.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,14 +158,16 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + /* S-DD1 decompressor * * Based on code and documentation by Andreas Naive, who deserves a great deal * of thanks and credit for figuring this out. * * Andreas says: - * The author is greatly indebted with The Dumper, without whose help and - * patience providing him with real S-DD1 data the research had never been + * The author is greatly indebted with The Dumper, without whose help and + * patience providing him with real S-DD1 data the research had never been * possible. He also wish to note that in the very beggining of his research, * Neviksti had done some steps in the right direction. By last, the author is * indirectly indebted to all the people that worked and contributed in the @@ -274,7 +293,7 @@ static inline uint8 ProbGetBit(uint8 context){ static inline uint8 GetBit(uint8 cur_bitplane){ uint8 bit; - + bit=ProbGetBit(((cur_bitplane&1)<<4) | ((prev_bits[cur_bitplane]&high_context_bits)>>5) | (prev_bits[cur_bitplane]&low_context_bits)); @@ -289,7 +308,7 @@ void SDD1_decompress(uint8 *out, uint8 *in, int len){ uint8 byte1, byte2; if(len==0) len=0x10000; - + bitplane_type=in[0]>>6; switch(in[0]&0x30){ @@ -412,7 +431,7 @@ void SDD1_init(uint8 *in){ uint8 SDD1_get_byte(void){ uint8 bit; uint8 byte=0; - + switch(bitplane_type){ case 0: num_bits+=16; diff --git a/source/snes9x/sdd1emu.h b/source/snes9x/sdd1emu.h index 1a15296..86c03e9 100644 --- a/source/snes9x/sdd1emu.h +++ b/source/snes9x/sdd1emu.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef SDD1EMU_H #define SDD1EMU_H diff --git a/source/snes9x/seta.cpp b/source/snes9x/seta.cpp index 364e9b7..ca3bfba 100644 --- a/source/snes9x/seta.cpp +++ b/source/snes9x/seta.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "seta.h" void (*SetSETA)(uint32, uint8)=&S9xSetST010; diff --git a/source/snes9x/seta.h b/source/snes9x/seta.h index 89ba983..0c49170 100644 --- a/source/snes9x/seta.h +++ b/source/snes9x/seta.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef NO_SETA #ifndef _seta_h #define _seta_h diff --git a/source/snes9x/seta010.cpp b/source/snes9x/seta010.cpp index 8987851..e0a84f1 100644 --- a/source/snes9x/seta010.cpp +++ b/source/snes9x/seta010.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "seta.h" #include "memmap.h" @@ -307,7 +326,7 @@ short ST010_Cos(short Theta) void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) { if ((x0 < 0) && (y0 < 0)) - { + { x1 = -x0; y1 = -y0; Quadrant = -0x8000; @@ -327,7 +346,7 @@ void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short else { x1 = x0; - y1 = y0; + y1 = y0; Quadrant = 0x0000; } @@ -366,7 +385,7 @@ void SETA_Distance(short Y0, short X0, short &Distance) Distance = ((X0 * 0x7af0) + 0x4000) >> 15; } -void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) { bool Sorted; uint16 Temp; @@ -375,7 +394,7 @@ void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) do { Sorted = true; for (int i = 0; i < Positions - 1; i++) - if (Places[i] < Places[i + 1]) + if (Places[i] < Places[i + 1]) { Temp = Places[i + 1]; Places[i + 1] = Places[i]; @@ -425,7 +444,7 @@ void S9xSetST010(uint32 Address, uint8 Byte) case 0x02: { #ifdef FAST_LSB_WORD_ACCESS - ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080)); + ST010_SortDrivers(*(uint16*)(Memory.SRAM + 0x0024), (uint16*) (Memory.SRAM + 0x0040), (uint16*) (Memory.SRAM + 0x0080)); #else uint16 Places[32]; uint16 Positions = ST010_WORD(0x0024); @@ -433,25 +452,25 @@ void S9xSetST010(uint32 Address, uint8 Byte) Offset = 0; - for (Pos = 0; Pos < Positions; Pos++) + for (Pos = 0; Pos < Positions; Pos++) { Places[Pos] = ST010_WORD(0x0040 + Offset); Offset += 2; } - ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080)); + ST010_SortDrivers(Positions, Places, (uint16*) (Memory.SRAM + 0x0080)); Offset = 0; for (Pos = 0; Pos < Positions; Pos++) { - SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); - SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); + Memory.SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); + Memory.SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); Offset += 2; } -#endif +#endif break; - + } // Two Dimensional Coordinate Scale @@ -531,23 +550,23 @@ void S9xSetST010(uint32 Address, uint8 Byte) { // Calculate Mode 7 Matrix A/D data data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15; - + Memory.SRAM[0x00f0 + offset]=(uint8)(data); Memory.SRAM[0x00f1 + offset]=(uint8)(data >> 8); Memory.SRAM[0x0510 + offset]=(uint8)(data); - Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); + Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); // Calculate Mode 7 Matrix B/C data - data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; + data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; Memory.SRAM[0x0250 + offset]=(uint8)(data); Memory.SRAM[0x0251 + offset]=(uint8)(data >> 8); - + if (data) data = ~data; - + Memory.SRAM[0x03b0 + offset]=(uint8)(data); Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); - + offset += 2; } @@ -655,9 +674,9 @@ void S9xSetST010(uint32 Address, uint8 Byte) int16 xpos_max = ST010_WORD(0x00C2); // current coordinates and direction - int32 ypos = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24); - int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24); - uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8); + int32 ypos = Memory.SRAM[0xC4]|(Memory.SRAM[0xC5]<<8)|(Memory.SRAM[0xC6]<<16)|(Memory.SRAM[0xC7]<<24); + int32 xpos = Memory.SRAM[0xC8]|(Memory.SRAM[0xC9]<<8)|(Memory.SRAM[0xCA]<<16)|(Memory.SRAM[0xCB]<<24); + uint16 rot = Memory.SRAM[0xCC]|(Memory.SRAM[0xCD]<<8); // physics uint16 speed = ST010_WORD(0x00D4); @@ -680,10 +699,10 @@ void S9xSetST010(uint32 Address, uint8 Byte) dy = ypos_max-(ypos>>16); // quirk: clear and move in9 - SRAM[0xD2]=0xFF; - SRAM[0xD3]=0xFF; - SRAM[0xDA]=0; - SRAM[0xDB]=0; + Memory.SRAM[0xD2]=0xFF; + Memory.SRAM[0xD3]=0xFF; + Memory.SRAM[0xDA]=0; + Memory.SRAM[0xDB]=0; // grab the target angle ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); @@ -770,24 +789,24 @@ void S9xSetST010(uint32 Address, uint8 Byte) xpos &= 0x1FFFFFFF; ypos &= 0x1FFFFFFF; - SRAM[0x00C0]=(uint8)(ypos_max); - SRAM[0x00C1]=(uint8)(ypos_max >> 8); - SRAM[0x00C2]=(uint8)(xpos_max); - SRAM[0x00C3]=(uint8)(xpos_max >> 8); - SRAM[0x00C4]=(uint8)(ypos); - SRAM[0x00C5]=(uint8)(ypos >> 8); - SRAM[0x00C6]=(uint8)(ypos >> 16); - SRAM[0x00C7]=(uint8)(ypos >> 24); - SRAM[0x00C8]=(uint8)(xpos); - SRAM[0x00C9]=(uint8)(xpos >> 8); - SRAM[0x00CA]=(uint8)(xpos >> 16); - SRAM[0x00CB]=(uint8)(xpos >> 24); - SRAM[0x00CC]=(uint8)(rot); - SRAM[0x00CD]=(uint8)(rot >> 8); - SRAM[0x00D4]=(uint8)(speed); - SRAM[0x00D5]=(uint8)(speed >> 8); - SRAM[0x00DC]=(uint8)(flags); - SRAM[0x00DD]=(uint8)(flags >> 8); + Memory.SRAM[0x00C0]=(uint8)(ypos_max); + Memory.SRAM[0x00C1]=(uint8)(ypos_max >> 8); + Memory.SRAM[0x00C2]=(uint8)(xpos_max); + Memory.SRAM[0x00C3]=(uint8)(xpos_max >> 8); + Memory.SRAM[0x00C4]=(uint8)(ypos); + Memory.SRAM[0x00C5]=(uint8)(ypos >> 8); + Memory.SRAM[0x00C6]=(uint8)(ypos >> 16); + Memory.SRAM[0x00C7]=(uint8)(ypos >> 24); + Memory.SRAM[0x00C8]=(uint8)(xpos); + Memory.SRAM[0x00C9]=(uint8)(xpos >> 8); + Memory.SRAM[0x00CA]=(uint8)(xpos >> 16); + Memory.SRAM[0x00CB]=(uint8)(xpos >> 24); + Memory.SRAM[0x00CC]=(uint8)(rot); + Memory.SRAM[0x00CD]=(uint8)(rot >> 8); + Memory.SRAM[0x00D4]=(uint8)(speed); + Memory.SRAM[0x00D5]=(uint8)(speed >> 8); + Memory.SRAM[0x00DC]=(uint8)(flags); + Memory.SRAM[0x00DD]=(uint8)(flags >> 8); break; } diff --git a/source/snes9x/seta011.cpp b/source/snes9x/seta011.cpp index aff5429..9995283 100644 --- a/source/snes9x/seta011.cpp +++ b/source/snes9x/seta011.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include "seta.h" #include "memmap.h" @@ -171,7 +190,7 @@ uint8 S9xGetST011(uint32 Address) { t = Memory.SRAM[address]; } - + // debug // if(address<0x150) // printf( "ST011 R: %06X %02X\n", Address, t); @@ -260,7 +279,7 @@ void S9xSetST011(uint32 Address, uint8 Byte) break; // unknown - case 0x05: + case 0x05: { // outputs Memory.SRAM[0x12C] = 0x00; diff --git a/source/snes9x/seta018.cpp b/source/snes9x/seta018.cpp index 505c17e..6ce9e9e 100644 --- a/source/snes9x/seta018.cpp +++ b/source/snes9x/seta018.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "seta.h" #include "memmap.h" @@ -173,7 +192,7 @@ uint8 S9xGetST018(uint32 Address) // status register else if (address == 0x3800) t = ST018.status; - + printf( "ST018 R: %06X %02X\n", Address, t); return t; diff --git a/source/snes9x/snapshot.cpp b/source/snes9x/snapshot.cpp index c8ff5b7..f60ab8a 100644 --- a/source/snes9x/snapshot.cpp +++ b/source/snes9x/snapshot.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,12 +114,25 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #ifdef HAVE_STRINGS_H #include @@ -148,6 +167,7 @@ #include #include #include +#include #if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) #include @@ -156,11 +176,9 @@ #endif #include "snapshot.h" - #ifndef NGC #include "snaporig.h" #endif - #include "memmap.h" #include "snes9x.h" #include "65c816.h" @@ -174,11 +192,30 @@ #include "srtc.h" #include "sdd1.h" #include "spc7110.h" -#include "movie.h" +//#include "movie.h" #include "controls.h" +#include "dsp1.h" +#include "c4.h" +#ifndef ZSNES_FX + #include "fxinst.h" +#endif +#include "language.h" + +#ifdef NGC #include "freeze.h" #include "gccore.h" #include "menudraw.h" +#endif + +//you would think everyone would have these +//since they're so useful. +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif extern uint8 *SRAM; @@ -194,8 +231,8 @@ void S9xResetSaveTimer(bool8 dontsave){ static time_t t=-1; if(!dontsave && t!=-1 && time(NULL)-t>300){{ -#ifndef NGC - char def [PATH_MAX]; +#ifndef NGC + char def [PATH_MAX]; char filename [PATH_MAX]; char drive [_MAX_DRIVE]; char dir [_MAX_DIR]; @@ -207,7 +244,7 @@ void S9xResetSaveTimer(bool8 dontsave){ S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, "Auto-saving 'oops' savestate"); Snapshot(filename); #endif - }} + }} t=time(NULL); } @@ -215,13 +252,15 @@ bool8 S9xUnfreezeZSNES (const char *filename); typedef struct { int offset; + int offset2; int size; int type; uint16 debuted_in, deleted_in; + const char* name; } FreezeData; enum { - INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V + INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V, uint8_INDIR_ARRAY_V, uint16_INDIR_ARRAY_V, uint32_INDIR_ARRAY_V, POINTER_V }; static struct Obsolete { @@ -232,113 +271,141 @@ static struct Obsolete { uint8 SAPU_Flags; } Obsolete; +#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) +#define SIZE_TO_ARRAY_TYPE(s) ((s)==1 ? uint8_ARRAY_V : ((s)==2 ? uint16_ARRAY_V : uint32_ARRAY_V)) + #define Offset(field,structure) \ ((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) #define DUMMY(f) Offset(f,struct Obsolete *) #define DELETED(f) (-1) - -#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) +#define OFFSET(f) Offset(f, STRUCT *) +//#define ARRAY_ENTRY(save_version_introduced, field) {OFFSET(field), COUNT(((STRUCT*)NULL)->field), SIZE_TO_ARRAY_TYPE(sizeof(((STRUCT*)NULL)->field)), save_version_introduced, 9999} +#define INT_ENTRY(save_version_introduced, field) {OFFSET(field),0, sizeof(((STRUCT*)NULL)->field), INT_V, save_version_introduced, 9999, #field} +#define ARRAY_ENTRY(save_version_introduced, field, count, elemType) {OFFSET(field),0, count, elemType, save_version_introduced, 9999, #field} +#define POINTER_ENTRY(save_version_introduced, field, relativeToField) {OFFSET(field),OFFSET(relativeToField), 4, POINTER_V, save_version_introduced, 9999, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes +#define OBSOLETE_INT_ENTRY(save_version_introduced, save_version_removed, field) {DUMMY(field),0, sizeof(((struct Obsolete*)NULL)->field), INT_V, save_version_introduced, save_version_removed, #field} +#define OBSOLETE_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) {DUMMY(field),0, count, elemType, save_version_introduced, save_version_removed, #field} +#define OBSOLETE_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) {DUMMY(field),DUMMY(relativeToField), 4, POINTER_V, save_version_introduced, save_version_removed, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes +#define DELETED_INT_ENTRY(save_version_introduced, save_version_removed, field, size) {DELETED(field),0, size, INT_V, save_version_introduced, save_version_removed, #field} +#define DELETED_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) {DELETED(field),0, count, elemType, save_version_introduced, save_version_removed, #field} +#define DELETED_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) {DELETED(field),DELETED(relativeToField), 4, POINTER_V, save_version_introduced, save_version_removed, #field} // size=4 -> (field - relativeToField) must fit in 4 bytes struct SnapshotMovieInfo { uint32 MovieInputDataSize; }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SnapshotMovieInfo *) +#undef STRUCT +#define STRUCT struct SnapshotMovieInfo -#ifndef NGC -static FreezeData SnapMovie [] = { - {OFFSET (MovieInputDataSize), 4, INT_V, 1, 9999}, +#ifndef NGC + static FreezeData SnapMovie [] = { + INT_ENTRY(1, MovieInputDataSize), }; #endif -#undef OFFSET -#define OFFSET(f) Offset(f,struct SCPUState *) +#undef STRUCT +#define STRUCT struct SCPUState static FreezeData SnapCPU [] = { - {OFFSET (Flags), 4, INT_V, 1, 9999}, - {OFFSET (BranchSkip), 1, INT_V, 1, 9999}, - {OFFSET (NMIActive), 1, INT_V, 1, 9999}, - {OFFSET (IRQActive), 1, INT_V, 1, 9999}, - {OFFSET (WaitingForInterrupt), 1, INT_V, 1, 9999}, - {OFFSET (WhichEvent), 1, INT_V, 1, 9999}, - {OFFSET (Cycles), 4, INT_V, 1, 9999}, - {OFFSET (NextEvent), 4, INT_V, 1, 9999}, - {OFFSET (V_Counter), 4, INT_V, 1, 9999}, - {OFFSET (MemSpeed), 4, INT_V, 1, 9999}, - {OFFSET (MemSpeedx2), 4, INT_V, 1, 9999}, - {OFFSET (FastROMSpeed), 4, INT_V, 1, 9999} + INT_ENTRY(1, Flags), + INT_ENTRY(1, BranchSkip), + DELETED_INT_ENTRY(1,4, NMIActive,1), + INT_ENTRY(1, IRQActive), + INT_ENTRY(1, WaitingForInterrupt), + INT_ENTRY(1, WhichEvent), + INT_ENTRY(1, Cycles), + INT_ENTRY(1, NextEvent), + INT_ENTRY(1, V_Counter), + INT_ENTRY(1, MemSpeed), + INT_ENTRY(1, MemSpeedx2), + INT_ENTRY(1, FastROMSpeed), + // not sure if the following are necessary + INT_ENTRY(3, InDMAorHDMA), + INT_ENTRY(3, InWRAMDMAorHDMA), + INT_ENTRY(3, PBPCAtOpcodeStart), + INT_ENTRY(3, WaitAddress), + INT_ENTRY(3, WaitCounter), + DELETED_INT_ENTRY(3,4, AutoSaveTimer,4), + DELETED_INT_ENTRY(3,4, SRAMModified,1), + DELETED_INT_ENTRY(3,4, BRKTriggered,1), + INT_ENTRY(3, TriedInterleavedMode2), // deprecated + INT_ENTRY(4, IRQPending), // essential + INT_ENTRY(4, InDMA), + INT_ENTRY(4, InHDMA), + INT_ENTRY(4, HDMARanInDMA), + INT_ENTRY(4, PrevCycles), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SRegisters *) +#undef STRUCT +#define STRUCT struct SRegisters static FreezeData SnapRegisters [] = { - {OFFSET (PB), 1, INT_V, 1, 9999}, - {OFFSET (DB), 1, INT_V, 1, 9999}, - {OFFSET (P.W), 2, INT_V, 1, 9999}, - {OFFSET (A.W), 2, INT_V, 1, 9999}, - {OFFSET (D.W), 2, INT_V, 1, 9999}, - {OFFSET (S.W), 2, INT_V, 1, 9999}, - {OFFSET (X.W), 2, INT_V, 1, 9999}, - {OFFSET (Y.W), 2, INT_V, 1, 9999}, - {OFFSET (PCw), 2, INT_V, 1, 9999} + INT_ENTRY(1, PB), + INT_ENTRY(1, DB), + INT_ENTRY(1, P.W), + INT_ENTRY(1, A.W), + INT_ENTRY(1, D.W), + INT_ENTRY(1, S.W), + INT_ENTRY(1, X.W), + INT_ENTRY(1, Y.W), + INT_ENTRY(1, PCw), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPPU *) +#undef STRUCT +#define STRUCT struct SPPU static FreezeData SnapPPU [] = { - {OFFSET (BGMode), 1, INT_V, 1, 9999}, - {OFFSET (BG3Priority), 1, INT_V, 1, 9999}, - {OFFSET (Brightness), 1, INT_V, 1, 9999}, - {OFFSET (VMA.High), 1, INT_V, 1, 9999}, - {OFFSET (VMA.Increment), 1, INT_V, 1, 9999}, - {OFFSET (VMA.Address), 2, INT_V, 1, 9999}, - {OFFSET (VMA.Mask1), 2, INT_V, 1, 9999}, - {OFFSET (VMA.FullGraphicCount), 2, INT_V, 1, 9999}, - {OFFSET (VMA.Shift), 2, INT_V, 1, 9999}, - {OFFSET (BG[0].SCBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[0].VOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[0].HOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[0].BGSize), 1, INT_V, 1, 9999}, - {OFFSET (BG[0].NameBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[0].SCSize), 2, INT_V, 1, 9999}, + INT_ENTRY(1, BGMode), + INT_ENTRY(1, BG3Priority), + INT_ENTRY(1, Brightness), + INT_ENTRY(1, VMA.High), + INT_ENTRY(1, VMA.Increment), + INT_ENTRY(1, VMA.Address), + INT_ENTRY(1, VMA.Mask1), + INT_ENTRY(1, VMA.FullGraphicCount), + INT_ENTRY(1, VMA.Shift), + INT_ENTRY(1, BG[0].SCBase), + INT_ENTRY(1, BG[0].VOffset), + INT_ENTRY(1, BG[0].HOffset), + INT_ENTRY(1, BG[0].BGSize), + INT_ENTRY(1, BG[0].NameBase), + INT_ENTRY(1, BG[0].SCSize), - {OFFSET (BG[1].SCBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[1].VOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[1].HOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[1].BGSize), 1, INT_V, 1, 9999}, - {OFFSET (BG[1].NameBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[1].SCSize), 2, INT_V, 1, 9999}, + INT_ENTRY(1, BG[1].SCBase), + INT_ENTRY(1, BG[1].VOffset), + INT_ENTRY(1, BG[1].HOffset), + INT_ENTRY(1, BG[1].BGSize), + INT_ENTRY(1, BG[1].NameBase), + INT_ENTRY(1, BG[1].SCSize), - {OFFSET (BG[2].SCBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[2].VOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[2].HOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[2].BGSize), 1, INT_V, 1, 9999}, - {OFFSET (BG[2].NameBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[2].SCSize), 2, INT_V, 1, 9999}, + INT_ENTRY(1, BG[2].SCBase), + INT_ENTRY(1, BG[2].VOffset), + INT_ENTRY(1, BG[2].HOffset), + INT_ENTRY(1, BG[2].BGSize), + INT_ENTRY(1, BG[2].NameBase), + INT_ENTRY(1, BG[2].SCSize), - {OFFSET (BG[3].SCBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[3].VOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[3].HOffset), 2, INT_V, 1, 9999}, - {OFFSET (BG[3].BGSize), 1, INT_V, 1, 9999}, - {OFFSET (BG[3].NameBase), 2, INT_V, 1, 9999}, - {OFFSET (BG[3].SCSize), 2, INT_V, 1, 9999}, + INT_ENTRY(1, BG[3].SCBase), + INT_ENTRY(1, BG[3].VOffset), + INT_ENTRY(1, BG[3].HOffset), + INT_ENTRY(1, BG[3].BGSize), + INT_ENTRY(1, BG[3].NameBase), + INT_ENTRY(1, BG[3].SCSize), - {OFFSET (CGFLIP), 1, INT_V, 1, 9999}, - {OFFSET (CGDATA), 256, uint16_ARRAY_V, 1, 9999}, - {OFFSET (FirstSprite), 1, INT_V, 1, 9999}, + INT_ENTRY(1, CGFLIP), + ARRAY_ENTRY(1, CGDATA, 256, uint16_ARRAY_V), + INT_ENTRY(1, FirstSprite), + INT_ENTRY(3, LastSprite), #define O(N) \ - {OFFSET (OBJ[N].HPos), 2, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].VPos), 2, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].Name), 2, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].VFlip), 1, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].HFlip), 1, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].Priority), 1, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].Palette), 1, INT_V, 1, 9999}, \ - {OFFSET (OBJ[N].Size), 1, INT_V, 1, 9999} + INT_ENTRY(1, OBJ[N].HPos), \ + INT_ENTRY(1, OBJ[N].VPos), \ + INT_ENTRY(1, OBJ[N].Name), \ + INT_ENTRY(1, OBJ[N].VFlip), \ + INT_ENTRY(1, OBJ[N].HFlip), \ + INT_ENTRY(1, OBJ[N].Priority), \ + INT_ENTRY(1, OBJ[N].Palette), \ + INT_ENTRY(1, OBJ[N].Size) O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), @@ -357,355 +424,502 @@ static FreezeData SnapPPU [] = { O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), #undef O - {OFFSET (OAMPriorityRotation), 1, INT_V, 1, 9999}, - {OFFSET (OAMAddr), 2, INT_V, 1, 9999}, - {OFFSET (OAMFlip), 1, INT_V, 1, 9999}, - {OFFSET (OAMTileAddress), 2, INT_V, 1, 9999}, - {OFFSET (IRQVBeamPos), 2, INT_V, 1, 9999}, - {OFFSET (IRQHBeamPos), 2, INT_V, 1, 9999}, - {OFFSET (VBeamPosLatched), 2, INT_V, 1, 9999}, - {OFFSET (HBeamPosLatched), 2, INT_V, 1, 9999}, - {OFFSET (HBeamFlip), 1, INT_V, 1, 9999}, - {OFFSET (VBeamFlip), 1, INT_V, 1, 9999}, - {OFFSET (HVBeamCounterLatched), 1, INT_V, 1, 9999}, - {OFFSET (MatrixA), 2, INT_V, 1, 9999}, - {OFFSET (MatrixB), 2, INT_V, 1, 9999}, - {OFFSET (MatrixC), 2, INT_V, 1, 9999}, - {OFFSET (MatrixD), 2, INT_V, 1, 9999}, - {OFFSET (CentreX), 2, INT_V, 1, 9999}, - {OFFSET (CentreY), 2, INT_V, 1, 9999}, - {OFFSET (M7HOFS), 2, INT_V, 2, 9999}, - {OFFSET (M7VOFS), 2, INT_V, 2, 9999}, - {DUMMY (SPPU_Joypad1ButtonReadPos), 1, INT_V, 1, 2}, - {DUMMY (SPPU_Joypad2ButtonReadPos), 1, INT_V, 1, 2}, - {DUMMY (SPPU_Joypad3ButtonReadPos), 1, INT_V, 1, 2}, - {OFFSET (CGADD), 1, INT_V, 1, 9999}, - {OFFSET (FixedColourRed), 1, INT_V, 1, 9999}, - {OFFSET (FixedColourGreen), 1, INT_V, 1, 9999}, - {OFFSET (FixedColourBlue), 1, INT_V, 1, 9999}, - {OFFSET (SavedOAMAddr), 2, INT_V, 1, 9999}, - {OFFSET (ScreenHeight), 2, INT_V, 1, 9999}, - {OFFSET (WRAM), 4, INT_V, 1, 9999}, - {OFFSET (ForcedBlanking), 1, INT_V, 1, 9999}, - {OFFSET (OBJNameSelect), 2, INT_V, 1, 9999}, - {OFFSET (OBJSizeSelect), 1, INT_V, 1, 9999}, - {OFFSET (OBJNameBase), 2, INT_V, 1, 9999}, - {OFFSET (OAMReadFlip), 1, INT_V, 1, 9999}, - {OFFSET (VTimerEnabled), 1, INT_V, 1, 9999}, - {OFFSET (HTimerEnabled), 1, INT_V, 1, 9999}, - {OFFSET (HTimerPosition), 2, INT_V, 1, 9999}, - {OFFSET (Mosaic), 1, INT_V, 1, 9999}, - {OFFSET (Mode7HFlip), 1, INT_V, 1, 9999}, - {OFFSET (Mode7VFlip), 1, INT_V, 1, 9999}, - {OFFSET (Mode7Repeat), 1, INT_V, 1, 9999}, - {OFFSET (Window1Left), 1, INT_V, 1, 9999}, - {OFFSET (Window1Right), 1, INT_V, 1, 9999}, - {OFFSET (Window2Left), 1, INT_V, 1, 9999}, - {OFFSET (Window2Right), 1, INT_V, 1, 9999}, + INT_ENTRY(1, OAMPriorityRotation), + INT_ENTRY(1, OAMAddr), + INT_ENTRY(1, OAMFlip), + INT_ENTRY(1, OAMTileAddress), + INT_ENTRY(1, IRQVBeamPos), + INT_ENTRY(1, IRQHBeamPos), + INT_ENTRY(1, VBeamPosLatched), + INT_ENTRY(1, HBeamPosLatched), + INT_ENTRY(1, HBeamFlip), + INT_ENTRY(1, VBeamFlip), + INT_ENTRY(1, HVBeamCounterLatched), + INT_ENTRY(1, MatrixA), + INT_ENTRY(1, MatrixB), + INT_ENTRY(1, MatrixC), + INT_ENTRY(1, MatrixD), + INT_ENTRY(1, CentreX), + INT_ENTRY(1, CentreY), + INT_ENTRY(2, M7HOFS), + INT_ENTRY(2, M7VOFS), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad1ButtonReadPos), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad2ButtonReadPos), + OBSOLETE_INT_ENTRY(1,2, SPPU_Joypad3ButtonReadPos), + INT_ENTRY(1, CGADD), + INT_ENTRY(1, FixedColourRed), + INT_ENTRY(1, FixedColourGreen), + INT_ENTRY(1, FixedColourBlue), + INT_ENTRY(1, SavedOAMAddr), + INT_ENTRY(1, ScreenHeight), + INT_ENTRY(1, WRAM), + DELETED_INT_ENTRY(3,3, BG_Forced,1), + INT_ENTRY(1, ForcedBlanking), + INT_ENTRY(3, OBJThroughMain), + INT_ENTRY(3, OBJThroughSub), + INT_ENTRY(1, OBJNameSelect), + INT_ENTRY(1, OBJSizeSelect), + INT_ENTRY(1, OBJNameBase), + INT_ENTRY(3, OBJAddition), + INT_ENTRY(1, OAMReadFlip), + INT_ENTRY(1, VTimerEnabled), + INT_ENTRY(1, HTimerEnabled), + INT_ENTRY(1, HTimerPosition), + INT_ENTRY(1, Mosaic), + INT_ENTRY(3, MosaicStart), + INT_ENTRY(1, Mode7HFlip), + INT_ENTRY(1, Mode7VFlip), + INT_ENTRY(1, Mode7Repeat), + INT_ENTRY(1, Window1Left), + INT_ENTRY(1, Window1Right), + INT_ENTRY(1, Window2Left), + INT_ENTRY(1, Window2Right), #define O(N) \ - {OFFSET (ClipWindowOverlapLogic[N]), 1, INT_V, 1, 9999}, \ - {OFFSET (ClipWindow1Enable[N]), 1, INT_V, 1, 9999}, \ - {OFFSET (ClipWindow2Enable[N]), 1, INT_V, 1, 9999}, \ - {OFFSET (ClipWindow1Inside[N]), 1, INT_V, 1, 9999}, \ - {OFFSET (ClipWindow2Inside[N]), 1, INT_V, 1, 9999} + INT_ENTRY(3, ClipCounts[N]), \ + INT_ENTRY(1, ClipWindowOverlapLogic[N]), \ + INT_ENTRY(1, ClipWindow1Enable[N]), \ + INT_ENTRY(1, ClipWindow2Enable[N]), \ + INT_ENTRY(1, ClipWindow1Inside[N]), \ + INT_ENTRY(1, ClipWindow2Inside[N]) O(0), O(1), O(2), O(3), O(4), O(5), - #undef O - - {OFFSET (CGFLIPRead), 1, INT_V, 1, 9999}, - {OFFSET (Need16x8Mulitply), 1, INT_V, 1, 9999}, - {OFFSET (BGMosaic), 4, uint8_ARRAY_V, 1, 9999}, - {OFFSET (OAMData), 512 + 32, uint8_ARRAY_V, 1, 9999}, - {OFFSET (Need16x8Mulitply), 1, INT_V, 1, 9999}, - {DUMMY (SPPU_MouseSpeed), 2, uint8_ARRAY_V, 1, 2}, - {OFFSET (OAMWriteRegister), 2, INT_V, 2, 9999}, - {OFFSET (BGnxOFSbyte), 1, INT_V, 2, 9999}, - {OFFSET (M7byte), 1, INT_V, 2, 9999}, - {OFFSET (OpenBus1), 1, INT_V, 2, 9999}, - {OFFSET (OpenBus2), 1, INT_V, 2, 9999}, - {OFFSET (VTimerPosition), 2, INT_V, 2, 9999}, + INT_ENTRY(3, RecomputeClipWindows), + INT_ENTRY(1, CGFLIPRead), + INT_ENTRY(1, Need16x8Mulitply), + ARRAY_ENTRY(1, BGMosaic, 4, uint8_ARRAY_V), + ARRAY_ENTRY(1, OAMData, 512 + 32, uint8_ARRAY_V), + INT_ENTRY(1, Need16x8Mulitply), + OBSOLETE_ARRAY_ENTRY(1,2, SPPU_MouseSpeed, 2, uint8_ARRAY_V), + INT_ENTRY(2, OAMWriteRegister), + INT_ENTRY(2, BGnxOFSbyte), + INT_ENTRY(2, M7byte), + INT_ENTRY(2, OpenBus1), + INT_ENTRY(2, OpenBus2), + INT_ENTRY(3, GunVLatch), + INT_ENTRY(3, GunHLatch), + INT_ENTRY(2, VTimerPosition), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SDMA *) +#undef STRUCT +#define STRUCT struct SDMA static FreezeData SnapDMA [] = { #define O(N) \ - {OFFSET (TransferDirection) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (AAddressFixed) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (TransferMode) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (ABank) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (AAddress) + N * sizeof (struct SDMA), 2, INT_V, 1, 9999}, \ - {OFFSET (Address) + N * sizeof (struct SDMA), 2, INT_V, 1, 9999}, \ - {OFFSET (BAddress) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {DELETED (TransferBytes), 2, INT_V, 1, 2}, \ - {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (DMACount_Or_HDMAIndirectAddress) + N * sizeof (struct SDMA), 2, INT_V, 1, 9999}, \ - {OFFSET (IndirectBank) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (Repeat) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (LineCount) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (DoTransfer) + N * sizeof (struct SDMA), 1, INT_V, 1, 9999}, \ - {OFFSET (UnknownByte) + N * sizeof (struct SDMA), 1, INT_V, 2, 9999}, \ - {OFFSET (UnusedBit43x0) + N * sizeof (struct SDMA), 1, INT_V, 2, 9999} + {OFFSET (ReverseTransfer) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "ReverseTransfer"}, \ + {OFFSET (AAddressFixed) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "AAddressFixed"}, \ + {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "AAddressDecrement"}, \ + {OFFSET (TransferMode) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "TransferMode"}, \ + {OFFSET (ABank) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "ABank"}, \ + {OFFSET (AAddress) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "AAddress"}, \ + {OFFSET (Address) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "Address"}, \ + {OFFSET (BAddress) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "BAddress"}, \ + {DELETED (TransferBytes),0, 2, INT_V, 1, 2, "TransferBytes"}, \ + {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "HDMAIndirectAddressing"}, \ + {OFFSET (DMACount_Or_HDMAIndirectAddress) + N * sizeof (struct SDMA),0, 2, INT_V, 1, 9999, "DMACount_Or_HDMAIndirectAddress"}, \ + {OFFSET (IndirectBank) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "IndirectBank"}, \ + {OFFSET (Repeat) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "Repeat"}, \ + {OFFSET (LineCount) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "LineCount"}, \ + {OFFSET (DoTransfer) + N * sizeof (struct SDMA),0, 1, INT_V, 1, 9999, "DoTransfer"}, \ + {OFFSET (UnknownByte) + N * sizeof (struct SDMA),0, 1, INT_V, 2, 9999, "UnknownByte"}, \ + {OFFSET (UnusedBit43x0) + N * sizeof (struct SDMA),0, 1, INT_V, 2, 9999, "UnusedBit43x0"} O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) #undef O }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPU *) +#undef STRUCT +#define STRUCT struct SAPU static FreezeData SnapAPU [] = { - {OFFSET (Cycles), 4, INT_V, 1, 9999}, - {OFFSET (ShowROM), 1, INT_V, 1, 9999}, - {DUMMY (SAPU_Flags), 1, INT_V, 1, 2}, - {OFFSET (Flags), 4, INT_V, 2, 9999}, - {OFFSET (KeyedChannels), 1, INT_V, 1, 9999}, - {OFFSET (OutPorts), 4, uint8_ARRAY_V, 1, 9999}, - {OFFSET (DSP), 0x80, uint8_ARRAY_V, 1, 9999}, - {OFFSET (ExtraRAM), 64, uint8_ARRAY_V, 1, 9999}, - {OFFSET (Timer), 3, uint16_ARRAY_V, 1, 9999}, - {OFFSET (TimerTarget), 3, uint16_ARRAY_V, 1, 9999}, - {OFFSET (TimerEnabled), 3, uint8_ARRAY_V, 1, 9999}, - {OFFSET (TimerValueWritten), 3, uint8_ARRAY_V, 1, 9999} + INT_ENTRY(1, OldCycles), + INT_ENTRY(1, ShowROM), + OBSOLETE_INT_ENTRY(1,2, SAPU_Flags), + INT_ENTRY(2, Flags), + INT_ENTRY(1, KeyedChannels), + ARRAY_ENTRY(1, OutPorts, 4, uint8_ARRAY_V), + ARRAY_ENTRY(1, DSP, 0x80, uint8_ARRAY_V), + ARRAY_ENTRY(1, ExtraRAM, 64, uint8_ARRAY_V), + ARRAY_ENTRY(1, Timer, 3, uint16_ARRAY_V), + ARRAY_ENTRY(1, TimerTarget, 3, uint16_ARRAY_V), + ARRAY_ENTRY(1, TimerEnabled, 3, uint8_ARRAY_V), + ARRAY_ENTRY(1, TimerValueWritten, 3, uint8_ARRAY_V), + INT_ENTRY(4, Cycles), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPURegisters *) +#undef STRUCT +#define STRUCT struct SAPURegisters static FreezeData SnapAPURegisters [] = { - {OFFSET (P), 1, INT_V, 1, 9999}, - {OFFSET (YA.W), 2, INT_V, 1, 9999}, - {OFFSET (X), 1, INT_V, 1, 9999}, - {OFFSET (S), 1, INT_V, 1, 9999}, - {OFFSET (PC), 2, INT_V, 1, 9999}, + INT_ENTRY(1, P), + INT_ENTRY(1, YA.W), + INT_ENTRY(1, X), + INT_ENTRY(1, S), + INT_ENTRY(1, PC), }; -#undef OFFSET -#define OFFSET(f) Offset(f,SSoundData *) +#undef STRUCT +#define STRUCT SSoundData static FreezeData SnapSoundData [] = { - {OFFSET (master_volume_left), 2, INT_V, 1, 9999}, - {OFFSET (master_volume_right), 2, INT_V, 1, 9999}, - {OFFSET (echo_volume_left), 2, INT_V, 1, 9999}, - {OFFSET (echo_volume_right), 2, INT_V, 1, 9999}, - {OFFSET (echo_enable), 4, INT_V, 1, 9999}, - {OFFSET (echo_feedback), 4, INT_V, 1, 9999}, - {OFFSET (echo_ptr), 4, INT_V, 1, 9999}, - {OFFSET (echo_buffer_size), 4, INT_V, 1, 9999}, - {OFFSET (echo_write_enabled), 4, INT_V, 1, 9999}, - {OFFSET (echo_channel_enable), 4, INT_V, 1, 9999}, - {OFFSET (pitch_mod), 4, INT_V, 1, 9999}, - {OFFSET (dummy), 3, uint32_ARRAY_V, 1, 9999}, + INT_ENTRY(1, master_volume_left), + INT_ENTRY(1, master_volume_right), + INT_ENTRY(1, echo_volume_left), + INT_ENTRY(1, echo_volume_right), + INT_ENTRY(1, echo_enable), + INT_ENTRY(1, echo_feedback), + INT_ENTRY(1, echo_ptr), + INT_ENTRY(1, echo_buffer_size), + INT_ENTRY(1, echo_write_enabled), + INT_ENTRY(1, echo_channel_enable), + INT_ENTRY(1, pitch_mod), + ARRAY_ENTRY(1, dummy, 3, uint32_ARRAY_V), #define O(N) \ - {OFFSET (channels [N].state), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].type), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].volume_left), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].volume_right), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].hertz), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].count), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].loop), 1, INT_V, 1, 9999}, \ - {OFFSET (channels [N].envx), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].left_vol_level), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].right_vol_level), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].envx_target), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].env_error), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].erate), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].direction), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].attack_rate), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].decay_rate), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].sustain_rate), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].release_rate), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].sustain_level), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].sample), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].decoded), 16, uint16_ARRAY_V, 1, 9999}, \ - {OFFSET (channels [N].previous16), 2, uint16_ARRAY_V, 1, 9999}, \ - {OFFSET (channels [N].sample_number), 2, INT_V, 1, 9999}, \ - {OFFSET (channels [N].last_block), 1, INT_V, 1, 9999}, \ - {OFFSET (channels [N].needs_decode), 1, INT_V, 1, 9999}, \ - {OFFSET (channels [N].block_pointer), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].sample_pointer), 4, INT_V, 1, 9999}, \ - {OFFSET (channels [N].mode), 4, INT_V, 1, 9999} + INT_ENTRY(1, channels [N].state), \ + INT_ENTRY(1, channels [N].type), \ + INT_ENTRY(1, channels [N].volume_left), \ + INT_ENTRY(1, channels [N].volume_right), \ + INT_ENTRY(1, channels [N].hertz), \ + INT_ENTRY(1, channels [N].count), \ + INT_ENTRY(1, channels [N].loop), \ + INT_ENTRY(1, channels [N].envx), \ + INT_ENTRY(1, channels [N].left_vol_level), \ + INT_ENTRY(1, channels [N].right_vol_level), \ + INT_ENTRY(1, channels [N].envx_target), \ + INT_ENTRY(1, channels [N].env_error), \ + INT_ENTRY(1, channels [N].erate), \ + INT_ENTRY(1, channels [N].direction), \ + INT_ENTRY(1, channels [N].attack_rate), \ + INT_ENTRY(1, channels [N].decay_rate), \ + INT_ENTRY(1, channels [N].sustain_rate), \ + INT_ENTRY(1, channels [N].release_rate), \ + INT_ENTRY(1, channels [N].sustain_level), \ + INT_ENTRY(1, channels [N].sample), \ + ARRAY_ENTRY(1, channels [N].decoded, 16, uint16_ARRAY_V), \ + ARRAY_ENTRY(1, channels [N].previous16, 2, uint16_ARRAY_V), \ + INT_ENTRY(1, channels [N].sample_number), \ + INT_ENTRY(1, channels [N].last_block), \ + INT_ENTRY(1, channels [N].needs_decode), \ + INT_ENTRY(1, channels [N].block_pointer), \ + INT_ENTRY(1, channels [N].sample_pointer), \ + INT_ENTRY(1, channels [N].mode) O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7), #undef O - {OFFSET (noise_rate), 4, INT_V, 2, 9999}, + INT_ENTRY(2, noise_rate), #define O(N) \ - {OFFSET (channels [N].out_sample), 2, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xenvx), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xenvx_target), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xenv_count), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xenv_rate), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xattack_rate), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xdecay_rate), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xsustain_rate), 4, INT_V, 2, 9999}, \ - {OFFSET (channels [N].xsustain_level), 4, INT_V, 2, 9999} + INT_ENTRY(2, channels [N].out_sample), \ + INT_ENTRY(2, channels [N].xenvx), \ + INT_ENTRY(2, channels [N].xenvx_target), \ + INT_ENTRY(2, channels [N].xenv_count), \ + INT_ENTRY(2, channels [N].xenv_rate), \ + INT_ENTRY(2, channels [N].xattack_rate), \ + INT_ENTRY(2, channels [N].xdecay_rate), \ + INT_ENTRY(2, channels [N].xsustain_rate), \ + INT_ENTRY(2, channels [N].xsustain_level) - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7), #undef O + INT_ENTRY(4, noise_count), + INT_ENTRY(4, no_filter), + INT_ENTRY(4, echo_volume[0]), + INT_ENTRY(4, echo_volume[1]), + INT_ENTRY(4, master_volume[0]), + INT_ENTRY(4, master_volume[1]), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1Registers *) +#undef STRUCT +#define STRUCT struct SSA1Registers static FreezeData SnapSA1Registers [] = { - {OFFSET (PB), 1, INT_V, 1, 9999}, - {OFFSET (DB), 1, INT_V, 1, 9999}, - {OFFSET (P.W), 2, INT_V, 1, 9999}, - {OFFSET (A.W), 2, INT_V, 1, 9999}, - {OFFSET (D.W), 2, INT_V, 1, 9999}, - {OFFSET (S.W), 2, INT_V, 1, 9999}, - {OFFSET (X.W), 2, INT_V, 1, 9999}, - {OFFSET (Y.W), 2, INT_V, 1, 9999}, - {OFFSET (PCw), 2, INT_V, 1, 9999} + INT_ENTRY(1, PB), + INT_ENTRY(1, DB), + INT_ENTRY(1, P.W), + INT_ENTRY(1, A.W), + INT_ENTRY(1, D.W), + INT_ENTRY(1, S.W), + INT_ENTRY(1, X.W), + INT_ENTRY(1, Y.W), + INT_ENTRY(1, PCw), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1 *) +#undef STRUCT +#define STRUCT struct SSA1 static FreezeData SnapSA1 [] = { - {OFFSET (Flags), 4, INT_V, 1, 9999}, - {OFFSET (NMIActive), 1, INT_V, 1, 9999}, - {OFFSET (IRQActive), 1, INT_V, 1, 9999}, - {OFFSET (WaitingForInterrupt), 1, INT_V, 1, 9999}, - {OFFSET (op1), 2, INT_V, 1, 9999}, - {OFFSET (op2), 2, INT_V, 1, 9999}, - {OFFSET (arithmetic_op), 4, INT_V, 1, 9999}, - {OFFSET (sum), 8, INT_V, 1, 9999}, - {OFFSET (overflow), 1, INT_V, 1, 9999} + INT_ENTRY(1, Flags), + INT_ENTRY(1, NMIActive), + INT_ENTRY(1, IRQActive), + INT_ENTRY(1, WaitingForInterrupt), + INT_ENTRY(1, op1), + INT_ENTRY(1, op2), + INT_ENTRY(1, arithmetic_op), + INT_ENTRY(1, sum), + INT_ENTRY(1, overflow), + // not sure if the following are necessary, but better safe than sorry + INT_ENTRY(3, CPUExecuting), + INT_ENTRY(3, ShiftedPB), + INT_ENTRY(3, ShiftedDB), + INT_ENTRY(3, Executing), + INT_ENTRY(3, Waiting), + INT_ENTRY(3, PBPCAtOpcodeStart), + INT_ENTRY(3, WaitAddress), + INT_ENTRY(3, WaitCounter), + INT_ENTRY(3, VirtualBitmapFormat), + INT_ENTRY(3, in_char_dma), + INT_ENTRY(3, variable_bit_pos), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPC7110EmuVars *) +#undef STRUCT +#define STRUCT struct SDSP1 + +static FreezeData SnapDSP1 [] = { + INT_ENTRY(3, version), + INT_ENTRY(3, waiting4command), + INT_ENTRY(3, first_parameter), + INT_ENTRY(3, command), + INT_ENTRY(3, in_count), + INT_ENTRY(3, in_index), + INT_ENTRY(3, out_count), + INT_ENTRY(3, out_index), + ARRAY_ENTRY(3, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(3, output, 512, uint8_ARRAY_V), + ARRAY_ENTRY(4, temp_save_data, sizeof(DSP1.temp_save_data), uint8_ARRAY_V), +}; + +#undef STRUCT +#define STRUCT struct SPC7110EmuVars static FreezeData SnapSPC7110 [] = { - {OFFSET (reg4800), 1, INT_V, 1, 9999}, - {OFFSET (reg4801), 1, INT_V, 1, 9999}, - {OFFSET (reg4802), 1, INT_V, 1, 9999}, - {OFFSET (reg4803), 1, INT_V, 1, 9999}, - {OFFSET (reg4804), 1, INT_V, 1, 9999}, - {OFFSET (reg4805), 1, INT_V, 1, 9999}, - {OFFSET (reg4806), 1, INT_V, 1, 9999}, - {OFFSET (reg4807), 1, INT_V, 1, 9999}, - {OFFSET (reg4808), 1, INT_V, 1, 9999}, - {OFFSET (reg4809), 1, INT_V, 1, 9999}, - {OFFSET (reg480A), 1, INT_V, 1, 9999}, - {OFFSET (reg480B), 1, INT_V, 1, 9999}, - {OFFSET (reg480C), 1, INT_V, 1, 9999}, - {OFFSET (reg4811), 1, INT_V, 1, 9999}, - {OFFSET (reg4812), 1, INT_V, 1, 9999}, - {OFFSET (reg4813), 1, INT_V, 1, 9999}, - {OFFSET (reg4814), 1, INT_V, 1, 9999}, - {OFFSET (reg4815), 1, INT_V, 1, 9999}, - {OFFSET (reg4816), 1, INT_V, 1, 9999}, - {OFFSET (reg4817), 1, INT_V, 1, 9999}, - {OFFSET (reg4818), 1, INT_V, 1, 9999}, - {OFFSET (reg4820), 1, INT_V, 1, 9999}, - {OFFSET (reg4821), 1, INT_V, 1, 9999}, - {OFFSET (reg4822), 1, INT_V, 1, 9999}, - {OFFSET (reg4823), 1, INT_V, 1, 9999}, - {OFFSET (reg4824), 1, INT_V, 1, 9999}, - {OFFSET (reg4825), 1, INT_V, 1, 9999}, - {OFFSET (reg4826), 1, INT_V, 1, 9999}, - {OFFSET (reg4827), 1, INT_V, 1, 9999}, - {OFFSET (reg4828), 1, INT_V, 1, 9999}, - {OFFSET (reg4829), 1, INT_V, 1, 9999}, - {OFFSET (reg482A), 1, INT_V, 1, 9999}, - {OFFSET (reg482B), 1, INT_V, 1, 9999}, - {OFFSET (reg482C), 1, INT_V, 1, 9999}, - {OFFSET (reg482D), 1, INT_V, 1, 9999}, - {OFFSET (reg482E), 1, INT_V, 1, 9999}, - {OFFSET (reg482F), 1, INT_V, 1, 9999}, - {OFFSET (reg4830), 1, INT_V, 1, 9999}, - {OFFSET (reg4831), 1, INT_V, 1, 9999}, - {OFFSET (reg4832), 1, INT_V, 1, 9999}, - {OFFSET (reg4833), 1, INT_V, 1, 9999}, - {OFFSET (reg4834), 1, INT_V, 1, 9999}, - {OFFSET (reg4840), 1, INT_V, 1, 9999}, - {OFFSET (reg4841), 1, INT_V, 1, 9999}, - {OFFSET (reg4842), 1, INT_V, 1, 9999}, - {OFFSET (AlignBy), 1, INT_V, 1, 9999}, - {OFFSET (written), 1, INT_V, 1, 9999}, - {OFFSET (offset_add), 1, INT_V, 1, 9999}, - {OFFSET (DataRomOffset), 4, INT_V, 1, 9999}, - {OFFSET (DataRomSize), 4, INT_V, 1, 9999}, - {OFFSET (bank50Internal), 4, INT_V, 1, 9999}, - {OFFSET (bank50), 0x10000, uint8_ARRAY_V, 1, 9999} + INT_ENTRY(1, reg4800), + INT_ENTRY(1, reg4801), + INT_ENTRY(1, reg4802), + INT_ENTRY(1, reg4803), + INT_ENTRY(1, reg4804), + INT_ENTRY(1, reg4805), + INT_ENTRY(1, reg4806), + INT_ENTRY(1, reg4807), + INT_ENTRY(1, reg4808), + INT_ENTRY(1, reg4809), + INT_ENTRY(1, reg480A), + INT_ENTRY(1, reg480B), + INT_ENTRY(1, reg480C), + INT_ENTRY(1, reg4811), + INT_ENTRY(1, reg4812), + INT_ENTRY(1, reg4813), + INT_ENTRY(1, reg4814), + INT_ENTRY(1, reg4815), + INT_ENTRY(1, reg4816), + INT_ENTRY(1, reg4817), + INT_ENTRY(1, reg4818), + INT_ENTRY(1, reg4820), + INT_ENTRY(1, reg4821), + INT_ENTRY(1, reg4822), + INT_ENTRY(1, reg4823), + INT_ENTRY(1, reg4824), + INT_ENTRY(1, reg4825), + INT_ENTRY(1, reg4826), + INT_ENTRY(1, reg4827), + INT_ENTRY(1, reg4828), + INT_ENTRY(1, reg4829), + INT_ENTRY(1, reg482A), + INT_ENTRY(1, reg482B), + INT_ENTRY(1, reg482C), + INT_ENTRY(1, reg482D), + INT_ENTRY(1, reg482E), + INT_ENTRY(1, reg482F), + INT_ENTRY(1, reg4830), + INT_ENTRY(1, reg4831), + INT_ENTRY(1, reg4832), + INT_ENTRY(1, reg4833), + INT_ENTRY(1, reg4834), + INT_ENTRY(1, reg4840), + INT_ENTRY(1, reg4841), + INT_ENTRY(1, reg4842), + INT_ENTRY(1, AlignBy), + INT_ENTRY(1, written), + INT_ENTRY(1, offset_add), + INT_ENTRY(1, DataRomOffset), + INT_ENTRY(1, DataRomSize), + INT_ENTRY(1, bank50Internal), + ARRAY_ENTRY(1, bank50, 0x10000, uint8_ARRAY_V), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPC7110RTC *) +#undef STRUCT +#define STRUCT struct SPC7110RTC static FreezeData SnapS7RTC [] = { - {OFFSET (reg), 16, uint8_ARRAY_V, 1, 9999}, - {OFFSET (index), 2, INT_V, 1, 9999}, - {OFFSET (control), 1, INT_V, 1, 9999}, - {OFFSET (init), 1, INT_V, 1, 9999}, - {OFFSET (last_used), 4, INT_V, 1, 9999} + ARRAY_ENTRY(1, reg, 16, uint8_ARRAY_V), + INT_ENTRY(1, index), + INT_ENTRY(1, control), + INT_ENTRY(1, init), + INT_ENTRY(1, last_used), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SControlSnapshot *) +#undef STRUCT +#define STRUCT struct SControlSnapshot static FreezeData SnapControls [] = { - {OFFSET (ver), 1, INT_V, 2, 9999}, - {OFFSET (port1_read_idx), 2, uint8_ARRAY_V, 2, 9999}, - {OFFSET (dummy1), 4, uint8_ARRAY_V, 2, 9999}, - {OFFSET (port2_read_idx), 2, uint8_ARRAY_V, 2, 9999}, - {OFFSET (dummy2), 4, uint8_ARRAY_V, 2, 9999}, - {OFFSET (mouse_speed), 2, uint8_ARRAY_V, 2, 9999}, - {OFFSET (justifier_select), 1, INT_V, 2, 9999}, - {OFFSET (dummy3), 10, uint8_ARRAY_V, 2, 9999} + INT_ENTRY(2, ver), + ARRAY_ENTRY(2, port1_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(2, dummy1, 4, uint8_ARRAY_V), + ARRAY_ENTRY(2, port2_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(2, dummy2, 4, uint8_ARRAY_V), + ARRAY_ENTRY(2, mouse_speed, 2, uint8_ARRAY_V), + INT_ENTRY(2, justifier_select), + ARRAY_ENTRY(2, dummy3, 8, uint8_ARRAY_V), + INT_ENTRY(4, pad_read), + INT_ENTRY(4, pad_read_last), + ARRAY_ENTRY(3, internal, 60, uint8_ARRAY_V), // yes, we need to save this! }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct STimings *) +#undef STRUCT +#define STRUCT struct STimings static FreezeData SnapTimings [] = { - {OFFSET (H_Max_Master), 4, INT_V, 2, 9999}, - {OFFSET (H_Max), 4, INT_V, 2, 9999}, - {OFFSET (V_Max_Master), 4, INT_V, 2, 9999}, - {OFFSET (V_Max), 4, INT_V, 2, 9999}, - {OFFSET (HBlankStart), 4, INT_V, 2, 9999}, - {OFFSET (HBlankEnd), 4, INT_V, 2, 9999}, - {OFFSET (HDMAInit), 4, INT_V, 2, 9999}, - {OFFSET (HDMAStart), 4, INT_V, 2, 9999}, - {OFFSET (NMITriggerPos), 4, INT_V, 2, 9999}, - {OFFSET (WRAMRefreshPos), 4, INT_V, 2, 9999}, - {OFFSET (RenderPos), 4, INT_V, 2, 9999}, - {OFFSET (InterlaceField), 1, INT_V, 2, 9999} + INT_ENTRY(2, H_Max_Master), + INT_ENTRY(2, H_Max), + INT_ENTRY(2, V_Max_Master), + INT_ENTRY(2, V_Max), + INT_ENTRY(2, HBlankStart), + INT_ENTRY(2, HBlankEnd), + INT_ENTRY(2, HDMAInit), + INT_ENTRY(2, HDMAStart), + INT_ENTRY(2, NMITriggerPos), + INT_ENTRY(2, WRAMRefreshPos), + INT_ENTRY(2, RenderPos), + INT_ENTRY(2, InterlaceField), + INT_ENTRY(4, DMACPUSync), }; -#undef OFFSET -#define OFFSET(f) Offset(f,struct SBSX *) +#undef STRUCT +#define STRUCT struct SBSX static FreezeData SnapBSX [] = { - {OFFSET (dirty), 1, INT_V, 2, 9999}, - {OFFSET (dirty2), 1, INT_V, 2, 9999}, - {OFFSET (bootup), 1, INT_V, 2, 9999}, - {OFFSET (flash_enable), 1, INT_V, 2, 9999}, - {OFFSET (write_enable), 1, INT_V, 2, 9999}, - {OFFSET (read_enable), 1, INT_V, 2, 9999}, - {OFFSET (flash_command), 4, INT_V, 2, 9999}, - {OFFSET (old_write), 4, INT_V, 2, 9999}, - {OFFSET (new_write), 4, INT_V, 2, 9999}, - {OFFSET (out_index), 1, INT_V, 2, 9999}, - {OFFSET (output), 32, uint8_ARRAY_V, 2, 9999}, - {OFFSET (PPU), 32, uint8_ARRAY_V, 2, 9999}, - {OFFSET (MMC), 16, uint8_ARRAY_V, 2, 9999}, - {OFFSET (prevMMC), 16, uint8_ARRAY_V, 2, 9999}, - {OFFSET (test2192), 32, uint8_ARRAY_V, 2, 9999} + INT_ENTRY(2, dirty), + INT_ENTRY(2, dirty2), + INT_ENTRY(2, bootup), + INT_ENTRY(2, flash_enable), + INT_ENTRY(2, write_enable), + INT_ENTRY(2, read_enable), + INT_ENTRY(2, flash_command), + INT_ENTRY(2, old_write), + INT_ENTRY(2, new_write), + INT_ENTRY(2, out_index), + ARRAY_ENTRY(2, output, 32, uint8_ARRAY_V), + ARRAY_ENTRY(2, PPU, 32, uint8_ARRAY_V), + ARRAY_ENTRY(2, MMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(2, prevMMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(2, test2192, 32, uint8_ARRAY_V), }; +// deleted blocks +static FreezeData SnapIPPU [] = { + DELETED_ARRAY_ENTRY(3,4, Junk, 2, uint32_ARRAY_V), +}; +static FreezeData SnapGFX [] = { + DELETED_ARRAY_ENTRY(3,4, Junk, 22+256+MAX_SNES_WIDTH*MAX_SNES_HEIGHT*2, uint8_ARRAY_V), +}; + + +#ifndef NGC +struct SnapshotScreenshotInfo +{ + uint16 Width; + uint16 Height; + uint8 Data [MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; + uint8 Interlaced; +}; + +#undef STRUCT +#define STRUCT struct SnapshotScreenshotInfo + +static FreezeData SnapScreenshot [] = { + INT_ENTRY(4, Width), + INT_ENTRY(4, Height), + ARRAY_ENTRY(4, Data, MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3, uint8_ARRAY_V), + INT_ENTRY(4, Interlaced), // needed in case interlacing was on before loading a state where it is off +}; +#endif + +#ifndef ZSNES_FX + extern struct FxRegs_s GSU; + + #undef STRUCT + #define STRUCT struct FxRegs_s + + // TODO: figure out which of these are completely unnecessary. Many of them are necessary. + static FreezeData SnapFX [] = { + INT_ENTRY(4, vColorReg), + INT_ENTRY(4, vPlotOptionReg), + INT_ENTRY(4, vStatusReg), + INT_ENTRY(4, vPrgBankReg), + INT_ENTRY(4, vRomBankReg), + INT_ENTRY(4, vRamBankReg), + INT_ENTRY(4, vCacheBaseReg), + INT_ENTRY(4, vCacheFlags), + INT_ENTRY(4, vLastRamAdr), + INT_ENTRY(4, vPipeAdr), + INT_ENTRY(4, vSign), + INT_ENTRY(4, vZero), + INT_ENTRY(4, vCarry), + INT_ENTRY(4, vOverflow), + INT_ENTRY(4, vErrorCode), + INT_ENTRY(4, vIllegalAddress), + INT_ENTRY(4, vBreakPoint), + INT_ENTRY(4, vStepPoint), + INT_ENTRY(4, nRamBanks), + INT_ENTRY(4, nRomBanks), + INT_ENTRY(4, vMode), + INT_ENTRY(4, vPrevMode), + INT_ENTRY(4, vScreenHeight), + INT_ENTRY(4, vScreenRealHeight), + INT_ENTRY(4, vPrevScreenHeight), + INT_ENTRY(4, vScreenSize), + INT_ENTRY(4, vCounter), + INT_ENTRY(4, vInstCount), + INT_ENTRY(4, vSCBRDirty), + INT_ENTRY(4, vRomBuffer), + INT_ENTRY(4, vPipe), + INT_ENTRY(4, bCacheActive), + INT_ENTRY(4, bBreakPoint), + ARRAY_ENTRY(4, avCacheBackup, 512, uint8_ARRAY_V), + ARRAY_ENTRY(4, avReg, 16, uint32_ARRAY_V), + ARRAY_ENTRY(4, x, 32, uint32_ARRAY_V), + POINTER_ENTRY(4, pvScreenBase, pvRam), + POINTER_ENTRY(4, pvPrgBank, apvRomBank), + POINTER_ENTRY(4, pvDreg, avReg), + POINTER_ENTRY(4, pvSreg, avReg), +#define O(N) POINTER_ENTRY(4, apvScreen[N], pvRam) + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), +#undef O + POINTER_ENTRY(4, pvRamBank, apvRamBank), + POINTER_ENTRY(4, pvRomBank, apvRomBank), + POINTER_ENTRY(4, pvCache, pvRegisters), + POINTER_ENTRY(4, apvRamBank[0], pvRam), + POINTER_ENTRY(4, apvRamBank[1], pvRam), + POINTER_ENTRY(4, apvRamBank[2], pvRam), + POINTER_ENTRY(4, apvRamBank[3], pvRam), +// uint8 * apvRomBank[256]; // probably OK to not save it, because it only changes in FxReset +// uint8 * pvRegisters; // can't save, but no need +// uint8 * pvRam; // can't save, but no need +// uint8 * pvRom; // can't save, but no need +// void (*pfPlot)(); // can't save, so we set it after loading +// void (*pfRpix)(); // can't save, so we set it after loading + }; +#endif + + static char ROMFilename [_MAX_PATH]; //static char SnapshotFilename [_MAX_PATH]; void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, int num_fields); - void FreezeBlock (STREAM stream, char *name, uint8 *block, int size); + #ifdef NGC extern void NGCFreezeBlock (char *name, uint8 *block, int size); extern int NGCUnFreezeBlock( char *name, uint8 *block, int size ); @@ -726,7 +940,6 @@ void S9xCloseSnapshotFile (FILE *stream) { fclose(stream); } - bool8 Snapshot (const char *filename) { return (S9xFreezeGame (filename)); @@ -739,7 +952,7 @@ bool8 S9xFreezeGame (const char *filename) #ifndef NGC if (S9xOpenSnapshotFile (filename, FALSE, &stream)) #endif - { + { S9xPrepareSoundForSnapshotSave (FALSE); S9xFreezeToStream (stream); @@ -752,12 +965,18 @@ bool8 S9xFreezeGame (const char *filename) #ifndef NGC if(S9xMovieActive()) { - sprintf(String, "Movie snapshot %s", S9xBasename (filename)); + const char * name = S9xBasename (filename); + if(name && strlen(name) > 3) + name += strlen(name) - 3; + else + name = filename; + sprintf(String, MOVIE_INFO_SNAPSHOT " %s", name); S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + GFX.InfoStringTimeout /= 4; } else { - sprintf(String, "Saved %s", S9xBasename (filename)); + sprintf(String, SAVE_INFO_SNAPSHOT " %s", S9xBasename (filename)); S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); } #endif @@ -773,10 +992,10 @@ bool8 S9xLoadSnapshot (const char *filename) bool8 S9xUnfreezeGame (const char *filename) { - char def [PATH_MAX]; - char drive [_MAX_DRIVE]; - char dir [_MAX_DIR]; - char ext [_MAX_EXT]; + char def [PATH_MAX + 1 ]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1 ]; + char ext [_MAX_EXT + 1 ] ; _splitpath (filename, drive, dir, def, ext); S9xResetSaveTimer (!strcmp(ext, "oops") || !strcmp(ext, "oop")); @@ -789,32 +1008,25 @@ bool8 S9xUnfreezeGame (const char *filename) if (S9xLoadOrigSnapshot (filename)) return (TRUE); - if (S9xUnfreezeZSNES (filename)) return (TRUE); - #endif STREAM snapshot = NULL; - #ifndef NGC - if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) + if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) #endif - { + { int result; if ((result = S9xUnfreezeFromStream (snapshot)) != SUCCESS) { switch (result) { case WRONG_FORMAT: - S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, - "File not in Snes9x freeze format"); - WaitPrompt("File not in Snes9x freeze format"); + S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); break; case WRONG_VERSION: - S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, - "Incompatable Snes9x freeze file format version"); - WaitPrompt("Incompatable Snes9x freeze file format version"); + S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); break; case WRONG_MOVIE_SNAPSHOT: S9xMessage (S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); @@ -822,12 +1034,13 @@ bool8 S9xUnfreezeGame (const char *filename) case NOT_A_MOVIE_SNAPSHOT: S9xMessage (S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); break; + case SNAPSHOT_INCONSISTENT: + S9xMessage (S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; default: case FILE_NOT_FOUND: - sprintf (String, "ROM image \"%s\" for freeze file not found", - ROMFilename); + sprintf (String, SAVE_ERR_ROM_NOT_FOUND, ROMFilename); S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); - WaitPrompt(String); break; } S9xCloseSnapshotFile (snapshot); @@ -835,20 +1048,50 @@ bool8 S9xUnfreezeGame (const char *filename) } #ifndef NGC - if(!S9xMovieActive()) + if(S9xMovieActive()) { - sprintf(String, "Loaded %s", S9xBasename (filename)); + const char * name = S9xBasename (filename); + if(name && strlen(name) > 3) + name += strlen(name) - 3; + else + name = filename; + if(S9xMovieReadOnly()) + sprintf(String, MOVIE_INFO_REWIND " %s", name); + else + sprintf(String, MOVIE_INFO_RERECORD " %s", name); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + GFX.InfoStringTimeout /= 4; + } + else + { + sprintf(String, SAVE_INFO_LOAD " %s", S9xBasename (filename)); S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); } S9xCloseSnapshotFile (snapshot); - #endif return (TRUE); } + +#ifndef NGC + // failed; error message: + { + char name [PATH_MAX]; + strcpy(name, S9xBasename (filename)); + int len = strlen(name); + if(len > 3 && name[len-3] == 'z' && name[len-2] == 's') + name[len-3] = name[len-2] = '0'; + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, name); + S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, String); + } + return (FALSE); +#endif } +bool diagnostic_freezing = false; +//#define DIAGNOSTIC_FREEZING_SUPPORT + void S9xFreezeToStream (STREAM stream) { char buffer [1024]; @@ -868,7 +1111,7 @@ void S9xFreezeToStream (STREAM stream) SoundData.channels [i].previous16 [0] = (int16) SoundData.channels [i].previous [0]; SoundData.channels [i].previous16 [1] = (int16) SoundData.channels [i].previous [1]; } - sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, diagnostic_freezing ? 9999 : SNAPSHOT_VERSION); WRITE_STREAM (buffer, strlen (buffer), stream); sprintf (buffer, "NAM:%06d:%s%c", (int)strlen (Memory.ROMFilename) + 1, Memory.ROMFilename, 0); @@ -881,7 +1124,7 @@ void S9xFreezeToStream (STREAM stream) // RAM and VRAM FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); - FreezeBlock (stream, "SRA", ::SRAM, 0x20000); + FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); if (Settings.APUEnabled) { @@ -928,7 +1171,7 @@ void S9xFreezeToStream (STREAM stream) } #ifndef NGC - if (S9xMovieActive ()) + if (S9xMovieActive ()) { uint8* movie_freeze_buf; uint32 movie_freeze_size; @@ -945,6 +1188,55 @@ void S9xFreezeToStream (STREAM stream) } #endif + // DSP1 chip + if(Settings.DSP1Master) + { + S9xPreSaveDSP1(); + FreezeStruct (stream, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); + } + + if (Settings.C4) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + FreezeBlock (stream, "CX4", C4Ram, 8192); +#else + FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); +#endif + } + +#ifndef ZSNES_FX + if (Settings.SuperFX) + FreezeStruct (stream, "SFX", &GSU, SnapFX, COUNT (SnapFX)); +#endif + +#ifndef NGC + if(Settings.SnapshotScreenshots) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); + ssi->Height = min(IPPU.RenderedScreenHeight, MAX_SNES_HEIGHT); + ssi->Interlaced = GFX.DoInterlace; + + uint8 *rowpix=ssi->Data; + uint16 *screen=GFX.Screen; + for(int y=0; yHeight; y++, screen+=GFX.RealPPL){ + for(int x=0; xWidth; x++){ + uint32 r, g, b; + DECOMPOSE_PIXEL(screen[x], r, g, b); + *(rowpix++) = r; // save pixel as 15-bits-in-3-bytes, for simplicity + *(rowpix++) = g; + *(rowpix++) = b; + } + } + memset(rowpix, 0, sizeof(ssi->Data) + ssi->Data - rowpix); + + FreezeStruct (stream, "SHO", ssi, SnapScreenshot, COUNT (SnapScreenshot)); + delete ssi; + } +#endif + S9xSetSoundMute (FALSE); #ifdef ZSNES_FX if (Settings.SuperFX) @@ -952,6 +1244,8 @@ void S9xFreezeToStream (STREAM stream) #endif } +bool unfreezing_from_stream = false; + int S9xUnfreezeFromStream (STREAM stream) { char buffer [_MAX_PATH + 1]; @@ -960,14 +1254,13 @@ int S9xUnfreezeFromStream (STREAM stream) int version; int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; - -#ifdef NGC +#ifdef NGC GetMem(buffer, len); #else if (READ_STREAM (buffer, len, stream) != len) return (WRONG_FORMAT); #endif - if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) + if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) return (WRONG_FORMAT); if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) return (WRONG_VERSION); @@ -975,8 +1268,10 @@ int S9xUnfreezeFromStream (STREAM stream) if ((result = UnfreezeBlock (stream, "NAM", (uint8 *) rom_filename, _MAX_PATH)) != SUCCESS) return (result); -#ifndef NGC - if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && + unfreezing_from_stream = true; + +#ifndef NGC + if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) { S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, @@ -1005,6 +1300,11 @@ int S9xUnfreezeFromStream (STREAM stream) uint8* local_control_data = NULL; uint8* local_timing_data = NULL; uint8* local_bsx_data = NULL; + uint8* local_dsp1 = NULL; + uint8* local_cx4_data = NULL; + uint8* local_superfx = NULL; + uint8* local_screenshot = NULL; + uint8* local_dummy[2] = {NULL,NULL}; do { @@ -1044,46 +1344,72 @@ int S9xUnfreezeFromStream (STREAM stream) if ((result = UnfreezeStructCopy (stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT (SnapSA1Registers), version)) != SUCCESS) break; } + else if (Settings.SA1) + break; if ((result = UnfreezeStructCopy (stream, "SP7", &local_spc, SnapSPC7110, COUNT(SnapSPC7110), version)) != SUCCESS) - { - if(Settings.SPC7110) + if (Settings.SPC7110) break; - } - if ((result = UnfreezeStructCopy (stream, "RTC", &local_spc_rtc, SnapS7RTC, COUNT (SnapS7RTC), version)) != SUCCESS) - { - if(Settings.SPC7110RTC) - break; - } - if ((result = UnfreezeStructCopy (stream, "BSX", &local_bsx_data, SnapBSX, COUNT (SnapBSX), version)) != SUCCESS && version > 1) - { + if ((result = UnfreezeStructCopy (stream, "RTC", &local_spc_rtc, SnapS7RTC, COUNT (SnapS7RTC), version)) != SUCCESS) + if (Settings.SPC7110RTC) + break; + + if ((result = UnfreezeStructCopy (stream, "BSX", &local_bsx_data, SnapBSX, COUNT (SnapBSX), version)) != SUCCESS) if (Settings.BS) break; - } -#ifndef NGC - if (S9xMovieActive ()) +#ifndef NGC + // movie { SnapshotMovieInfo mi; if ((result = UnfreezeStruct (stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie), version)) != SUCCESS) { - result = NOT_A_MOVIE_SNAPSHOT; - break; - } + if (S9xMovieActive ()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } else { - if ((result = UnfreezeBlockCopy (stream, "MID", &local_movie_data, mi.MovieInputDataSize)) != SUCCESS) - { - result = NOT_A_MOVIE_SNAPSHOT; - break; - } + if ((result = UnfreezeBlockCopy (stream, "MID", &local_movie_data, mi.MovieInputDataSize)) != SUCCESS) + { + if (S9xMovieActive ()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } - if (!S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize)) - { - result = WRONG_MOVIE_SNAPSHOT; - break; + if (S9xMovieActive ()) + { + result = S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize); + if(result != SUCCESS) + break; + } } } +#endif + if ((result = UnfreezeStructCopy (stream, "DSP", &local_dsp1, SnapDSP1, COUNT(SnapDSP1), version)) != SUCCESS) + if(Settings.DSP1Master) + break; + + if ((result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192)) != SUCCESS) + if(Settings.C4) + break; + +#ifndef ZSNES_FX + if ((result = UnfreezeStructCopy (stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version)) != SUCCESS) +// if (Settings.SuperFX) +// break; // what if the savestate was made with ZSNES_FX on? + {} +#endif + + UnfreezeStructCopy (stream, "IPU", &local_dummy[0], SnapIPPU, COUNT(SnapIPPU), version); // obsolete + UnfreezeStructCopy (stream, "GFX", &local_dummy[1], SnapGFX, COUNT(SnapGFX), version); // obsolete + +#ifndef NGC + UnfreezeStructCopy (stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); #endif result=SUCCESS; @@ -1103,7 +1429,7 @@ int S9xUnfreezeFromStream (STREAM stream) UnfreezeStructFromCopy (DMA, SnapDMA, COUNT (SnapDMA), local_dma, version); memcpy (Memory.VRAM, local_vram, 0x10000); memcpy (Memory.RAM, local_ram, 0x20000); - memcpy (::SRAM, local_sram, 0x20000); + memcpy (Memory.SRAM, local_sram, 0x20000); memcpy (Memory.FillRAM, local_fillram, 0x8000); if(local_apu) { @@ -1142,6 +1468,15 @@ int S9xUnfreezeFromStream (STREAM stream) } S9xControlPostLoad(&ctl_snap); + if(local_movie_data) // restore last displayed pad_read status + { + extern bool8 pad_read, pad_read_last; + bool8 pad_read_temp = pad_read; + pad_read = pad_read_last; + //S9xUpdateFrameCounter (-1); + pad_read = pad_read_temp; + } + if (local_timing_data) UnfreezeStructFromCopy (&Timings, SnapTimings, COUNT (SnapTimings), local_timing_data, version); else // Must be an old snes9x savestate @@ -1152,27 +1487,112 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) UnfreezeStructFromCopy (&BSX, SnapBSX, COUNT (SnapBSX), local_bsx_data, version); + if(local_dsp1) + { + UnfreezeStructFromCopy (&DSP1, SnapDSP1, COUNT (SnapDSP1), local_dsp1, version); + S9xPostLoadDSP1(); + } + + if (local_cx4_data) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + memcpy(C4Ram, local_cx4_data, 8192); +#else + memcpy(Memory.C4RAM, local_cx4_data, 8192); +#endif + } + +#ifndef ZSNES_FX + if(local_superfx) + { + UnfreezeStructFromCopy (&GSU, SnapFX, COUNT (SnapFX), local_superfx, version); + GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; + GSU.pfRpix = fx_apfPlotTable[GSU.vMode + 5]; + } +#endif +#ifndef NGC + if(GFX.Screen) + if(local_screenshot) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + UnfreezeStructFromCopy (ssi, SnapScreenshot, COUNT (SnapScreenshot), local_screenshot, version); + IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH); + IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT); + const bool scaleDownX = IPPU.RenderedScreenWidth < ssi->Width; + const bool scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED; + GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0; + + uint8 *rowpix=ssi->Data; + uint16 *screen=GFX.Screen; + for(int y=0; y>1; + g = (g + *(rowpix++))>>1; + b = (b + *(rowpix++))>>1; + if(x+x+1 >= ssi->Width) + break; + } + screen[x] = BUILD_PIXEL(r, g, b); + } + if(scaleDownY) + { + rowpix += 3*ssi->Width; + if(y+y+1 >= ssi->Height) + break; + } + } + + // black out what we might have missed + for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32)(IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL*2); + delete ssi; + } + else + { + // couldn't load graphics, so black out the screen instead + for (uint32 y = 0; y < (uint32)(IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL*2); + } +#endif Memory.FixROMSpeed (); CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); IPPU.ColorsChanged = TRUE; IPPU.OBJChanged = TRUE; - CPU.InDMA = CPU.InWRAM_DMA = FALSE; + CPU.InDMA = CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; + IPPU.RenderThisFrame = TRUE; // was FALSE, but for most games it's more useful to see that frame if (local_apu) { + if (APU.OldCycles != -99999999) + { + // Must be <= v1.5 savestate + printf("Older APU Cycles found.\n"); + APU.Cycles = (APU.OldCycles << SNES_APU_ACCURACY); + APU.OldCycles = -99999999; + } + S9xSetSoundMute (FALSE); IAPU.PC = IAPU.RAM + APURegisters.PC; S9xAPUUnpackStatus (); + IAPU.APUExecuting = TRUE; if (APUCheckDirectPage ()) IAPU.DirectPage = IAPU.RAM + 0x100; else IAPU.DirectPage = IAPU.RAM; Settings.APUEnabled = TRUE; - IAPU.APUExecuting = TRUE; } else { @@ -1238,7 +1658,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (Settings.SDD1) S9xSDD1PostLoadState (); - IAPU.NextAPUTimerPos = CPU.Cycles << SNES_APUTIMER_ACCURACY; + IAPU.NextAPUTimerPos = (CPU.Cycles << SNES_APU_ACCURACY); IAPU.APUTimerCounter = 0; } @@ -1262,6 +1682,14 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_control_data) delete [] local_control_data; if (local_timing_data) delete [] local_timing_data; if (local_bsx_data) delete [] local_bsx_data; + if (local_dsp1) delete [] local_dsp1; + if (local_cx4_data) delete [] local_cx4_data; + if (local_superfx) delete [] local_superfx; + if (local_screenshot) delete [] local_screenshot; + for(int i=0; i<2; i++) + if (local_dummy[i]) delete [] local_dummy[i]; + + unfreezing_from_stream = false; return (result); } @@ -1274,8 +1702,10 @@ int FreezeSize (int size, int type) switch (type) { case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: return (size * 2); case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: return (size * 4); default: return (size); @@ -1292,8 +1722,26 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, for (i = 0; i < num_fields; i++) { + if(fields[i].debuted_in > SNAPSHOT_VERSION) + { + fprintf(stderr, "%s[%p]: field has bad debuted_in value %d, > %d.", name, (void *)fields, fields[i].debuted_in, SNAPSHOT_VERSION); + continue; + } + if (SNAPSHOT_VERSION=fields[i].deleted_in) continue; - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *ptr++ = *((uint8 *) base + fields [i].offset); - break; - case 2: - word = *((uint16 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - break; - case 4: - dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - break; - case 8: - qword = *((int64 *) ((uint8 *) base + fields [i].offset)); + if (SNAPSHOT_VERSION> 8); + *ptr++ = (uint8) word; + break; + case 4: + dword = *((uint32 *) (addr)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + case 8: + qword = *((int64 *) (addr)); *ptr++ = (uint8) (qword >> 56); *ptr++ = (uint8) (qword >> 48); *ptr++ = (uint8) (qword >> 40); @@ -1340,22 +1829,25 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, break; } break; - case uint8_ARRAY_V: - memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); + case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: + memmove (ptr, addr, fields[i].size); + ptr += fields[i].size; + break; + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + word = *((uint16 *) (addr + j * 2)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + } + break; + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + dword = *((uint32 *) (addr + j * 4)); *ptr++ = (uint8) (dword >> 24); *ptr++ = (uint8) (dword >> 16); *ptr++ = (uint8) (dword >> 8); @@ -1365,21 +1857,32 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields, } } //fprintf(stderr, "%s: Wrote %d bytes\n", name, ptr-block); - -#ifndef NGC +#ifndef NGC FreezeBlock (stream, name, block, len); #else NGCFreezeBlock(name, block, len); #endif - - delete[] block; + delete[] block; } void FreezeBlock (STREAM stream, char *name, uint8 *block, int size) { - char buffer [512]; - sprintf (buffer, "%s:%06d:", name, size); - WRITE_STREAM (buffer, strlen (buffer), stream); + char buffer [512]; + + if(size <= 999999) // check if it fits in 6 digits. (letting it go over and using strlen isn't safe) + sprintf (buffer, "%s:%06d:", name, size); + else + { + // to make it fit, pack it in the bytes instead of as digits + sprintf (buffer, "%s:------:", name); + buffer[6] = (unsigned char)((unsigned)size >> 24); + buffer[7] = (unsigned char)((unsigned)size >> 16); + buffer[8] = (unsigned char)((unsigned)size >> 8); + buffer[9] = (unsigned char)((unsigned)size >> 0); + } + buffer[11] = 0; + + WRITE_STREAM (buffer, 11, stream); WRITE_STREAM (block, size, stream); } @@ -1388,18 +1891,18 @@ void FreezeBlock (STREAM stream, char *name, uint8 *block, int size) void NGCFreezeStruct() { STREAM s = NULL; - + FreezeStruct (s,"CPU", &CPU, SnapCPU, COUNT (SnapCPU)); FreezeStruct (s,"REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); FreezeStruct (s,"PPU", &PPU, SnapPPU, COUNT (SnapPPU)); FreezeStruct (s,"DMA", DMA, SnapDMA, COUNT (SnapDMA)); - + // RAM and VRAM NGCFreezeBlock ("VRA", Memory.VRAM, 0x10000); NGCFreezeBlock ("RAM", Memory.RAM, 0x20000); - NGCFreezeBlock ("SRA", ::SRAM, 0x20000); + NGCFreezeBlock ("SRA", Memory.SRAM, 0x20000); NGCFreezeBlock ("FIL", Memory.FillRAM, 0x8000); - + if (Settings.APUEnabled) { // APU @@ -1415,7 +1918,7 @@ void NGCFreezeStruct() struct SControlSnapshot ctl_snap; S9xControlPreSave(&ctl_snap); FreezeStruct (s,"CTL", &ctl_snap, SnapControls, COUNT (SnapControls)); - + // Timings FreezeStruct (s,"TIM", &Timings, SnapTimings, COUNT (SnapTimings)); @@ -1424,7 +1927,7 @@ void NGCFreezeStruct() { S9xSA1PackStatus (); FreezeStruct (s,"SA1", &SA1, SnapSA1, COUNT (SnapSA1)); - FreezeStruct (s,"SAR", &SA1Registers, SnapSA1Registers, + FreezeStruct (s,"SAR", &SA1Registers, SnapSA1Registers, COUNT (SnapSA1Registers)); } @@ -1443,6 +1946,29 @@ void NGCFreezeStruct() { FreezeStruct (s,"BSX", &BSX, SnapBSX, COUNT (SnapBSX)); } + + // DSP1 chip + if(Settings.DSP1Master) + { + S9xPreSaveDSP1(); + FreezeStruct (s, "DSP", &DSP1, SnapDSP1, COUNT (SnapDSP1)); + } + + if (Settings.C4) + { +#ifdef ZSNES_C4 + extern uint8 *C4Ram; + if (C4Ram) + NGCFreezeBlock ("CX4", C4Ram, 8192); +#else + NGCFreezeBlock ("CX4", Memory.C4RAM, 8192); +#endif + } + +#ifndef ZSNES_FX + if (Settings.SuperFX) + FreezeStruct (s, "SFX", &GSU, SnapFX, COUNT (SnapFX)); +#endif } #endif @@ -1452,20 +1978,36 @@ void NGCFreezeStruct() int UnfreezeBlock (STREAM stream, char *name, uint8 *block, int size) { #ifndef NGC - char buffer [20], *e; + char buffer [20]; int len = 0; int rem = 0; long rewind = FIND_STREAM(stream); - if (READ_STREAM (buffer, 11, stream) != 11 || - strncmp (buffer, name, 3) != 0 || buffer [3] != ':' || - buffer[10] != ':' || - (len = strtol (&buffer [4], &e, 10)) == 0 || e != buffer+10) + size_t l = READ_STREAM (buffer, 11, stream); + buffer[l] = 0; + if (l != 11 + || strncmp (buffer, name, 3) != 0 + || buffer[3] != ':') { - REVERT_STREAM(stream, rewind, 0); - return (WRONG_FORMAT); + err: + fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); + REVERT_STREAM(stream, FIND_STREAM(stream)-l, 0); + return (WRONG_FORMAT); } + if(buffer[4] == '-') + { + len = (((unsigned char)buffer[6]) << 24) + | (((unsigned char)buffer[7]) << 16) + | (((unsigned char)buffer[8]) << 8) + | (((unsigned char)buffer[9]) << 0); + } + else + { + len = atoi(buffer+4); + } + if(len <= 0) goto err; + if (len > size) { rem = len - size; @@ -1493,7 +2035,6 @@ int UnfreezeBlock (STREAM stream, char *name, uint8 *block, int size) #else return NGCUnFreezeBlock(name, block, size); #endif - } int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size) @@ -1536,8 +2077,8 @@ int UnfreezeStructCopy (STREAM stream, char *name, uint8** block, FreezeData *fi for (i = 0; i < num_fields; i++) { - if (version>=fields [i].debuted_in && version=fields[i].debuted_in && version=fields[i].deleted_in) continue; + if (version=fields[i].deleted_in) continue; base = (SNAPSHOT_VERSION>=fields[i].deleted_in)?((void *)&Obsolete):sbase; - switch (fields [i].type) + + uint8 *addr = (uint8 *) base + fields[i].offset; + + // determine real address of indirect-type fields + // (where the structure contains a pointer to an array rather than the array itself) + if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) + addr = (uint8 *)(*((pint*)addr)); + + switch (fields[i].type) { case INT_V: - switch (fields [i].size) + case POINTER_V: + switch (fields[i].size) { case 1: if(fields[i].offset<0){ ptr++; break; } - *((uint8 *) base + fields [i].offset) = *ptr++; + *(addr) = *ptr++; break; case 2: if(fields[i].offset<0){ ptr+=2; break; } word = *ptr++ << 8; word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; + *((uint16 *) (addr)) = word; break; case 4: if(fields[i].offset<0){ ptr+=4; break; } @@ -1580,7 +2130,7 @@ void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fields, ui dword |= *ptr++ << 16; dword |= *ptr++ << 8; dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; + *((uint32 *) (addr)) = dword; break; case 8: if(fields[i].offset<0){ ptr+=8; break; } @@ -1592,37 +2142,51 @@ void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fields, ui qword |= (int64) *ptr++ << 16; qword |= (int64) *ptr++ << 8; qword |= (int64) *ptr++; - *((int64 *) ((uint8 *) base + fields [i].offset)) = qword; + *((int64 *) (addr)) = qword; break; + default: + assert(0); + break; } break; case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: if(fields[i].offset>=0) - memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); - ptr += fields [i].size; + memmove (addr, ptr, fields[i].size); + ptr += fields[i].size; break; case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: if(fields[i].offset<0){ ptr+=fields[i].size*2; break; } - for (j = 0; j < fields [i].size; j++) + for (j = 0; j < fields[i].size; j++) { word = *ptr++ << 8; word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; + *((uint16 *) (addr + j * 2)) = word; } break; case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: if(fields[i].offset<0){ ptr+=fields[i].size*4; break; } - for (j = 0; j < fields [i].size; j++) + for (j = 0; j < fields[i].size; j++) { dword = *ptr++ << 24; dword |= *ptr++ << 16; dword |= *ptr++ << 8; dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; + *((uint32 *) (addr + j * 4)) = dword; } break; } - } + + // convert pointer-type saves from relative to absolute pointers + if(fields[i].type == POINTER_V) + { + int relativeAddr = (int)*((pint*)((uint8 *) base + fields[i].offset)); + uint8* relativeTo = (uint8*)*((pint*)((uint8 *) base + fields[i].offset2)); + *((pint *) (addr)) = (pint)(relativeTo + relativeAddr); + } + } //fprintf(stderr, "%p: Unfroze %d bytes\n", fields, ptr-block); } @@ -1644,11 +2208,11 @@ bool8 S9xSPCDump (const char *filename) FILE *fs; - S9xSetSoundMute (TRUE); - if (!(fs = fopen (filename, "wb"))) return (FALSE); + S9xSetSoundMute (TRUE); + // The SPC file format: // 0000: header: 'SNES-SPC700 Sound File Data v0.30',26,26,26 // 0036: version: $1e @@ -1710,161 +2274,161 @@ bool8 S9xUnfreezeZSNES (const char *filename) S9xSetSoundMute (TRUE); // 28 Curr cycle - CPU.V_Counter = READ_WORD (&t [29]); + CPU.V_Counter = READ_WORD (&t[29]); // 33 instrset - Settings.APUEnabled = t [36]; + Settings.APUEnabled = t[36]; // 34 bcycpl cycles per scanline // 35 cycphb cyclers per hblank - Registers.A.W = READ_WORD (&t [41]); - Registers.DB = t [43]; - Registers.PB = t [44]; - Registers.S.W = READ_WORD (&t [45]); - Registers.D.W = READ_WORD (&t [47]); - Registers.X.W = READ_WORD (&t [49]); - Registers.Y.W = READ_WORD (&t [51]); - Registers.P.W = READ_WORD (&t [53]); - Registers.PCw = READ_WORD (&t [55]); + Registers.A.W = READ_WORD (&t[41]); + Registers.DB = t[43]; + Registers.PB = t[44]; + Registers.S.W = READ_WORD (&t[45]); + Registers.D.W = READ_WORD (&t[47]); + Registers.X.W = READ_WORD (&t[49]); + Registers.Y.W = READ_WORD (&t[51]); + Registers.P.W = READ_WORD (&t[53]); + Registers.PCw = READ_WORD (&t[55]); fread (t, 1, 8, fs); fread (t, 1, 3019, fs); - S9xSetCPU (t [2], 0x4200); - Memory.FillRAM [0x4210] = t [3]; - PPU.IRQVBeamPos = READ_WORD (&t [4]); - PPU.IRQHBeamPos = READ_WORD (&t [2527]); - PPU.Brightness = t [6]; - PPU.ForcedBlanking = t [8] >> 7; + S9xSetCPU (t[2], 0x4200); + Memory.FillRAM [0x4210] = t[3]; + PPU.IRQVBeamPos = READ_WORD (&t[4]); + PPU.IRQHBeamPos = READ_WORD (&t[2527]); + PPU.Brightness = t[6]; + PPU.ForcedBlanking = t[8] >> 7; int i; for (i = 0; i < 544; i++) - S9xSetPPU (t [0464 + i], 0x2104); + S9xSetPPU (t[0464 + i], 0x2104); - PPU.OBJNameBase = READ_WORD (&t [9]); - PPU.OBJNameSelect = READ_WORD (&t [13]) - PPU.OBJNameBase; - switch (t [18]) + PPU.OBJNameBase = READ_WORD (&t[9]); + PPU.OBJNameSelect = READ_WORD (&t[13]) - PPU.OBJNameBase; + switch (t[18]) { case 4: - if (t [17] == 1) + if (t[17] == 1) PPU.OBJSizeSelect = 0; else PPU.OBJSizeSelect = 6; break; case 16: - if (t [17] == 1) + if (t[17] == 1) PPU.OBJSizeSelect = 1; else PPU.OBJSizeSelect = 3; break; default: case 64: - if (t [17] == 1) + if (t[17] == 1) PPU.OBJSizeSelect = 2; else - if (t [17] == 4) + if (t[17] == 4) PPU.OBJSizeSelect = 4; else PPU.OBJSizeSelect = 5; break; } - PPU.OAMAddr = READ_WORD (&t [25]); - PPU.SavedOAMAddr = READ_WORD (&t [27]); - PPU.FirstSprite = t [29]; - PPU.BGMode = t [30]; - PPU.BG3Priority = t [31]; - PPU.BG[0].BGSize = (t [32] >> 0) & 1; - PPU.BG[1].BGSize = (t [32] >> 1) & 1; - PPU.BG[2].BGSize = (t [32] >> 2) & 1; - PPU.BG[3].BGSize = (t [32] >> 3) & 1; - PPU.Mosaic = t [33] + 1; - PPU.BGMosaic [0] = (t [34] & 1) != 0; - PPU.BGMosaic [1] = (t [34] & 2) != 0; - PPU.BGMosaic [2] = (t [34] & 4) != 0; - PPU.BGMosaic [3] = (t [34] & 8) != 0; - PPU.BG [0].SCBase = READ_WORD (&t [35]) >> 1; - PPU.BG [1].SCBase = READ_WORD (&t [37]) >> 1; - PPU.BG [2].SCBase = READ_WORD (&t [39]) >> 1; - PPU.BG [3].SCBase = READ_WORD (&t [41]) >> 1; - PPU.BG [0].SCSize = t [67]; - PPU.BG [1].SCSize = t [68]; - PPU.BG [2].SCSize = t [69]; - PPU.BG [3].SCSize = t [70]; - PPU.BG[0].NameBase = READ_WORD (&t [71]) >> 1; - PPU.BG[1].NameBase = READ_WORD (&t [73]) >> 1; - PPU.BG[2].NameBase = READ_WORD (&t [75]) >> 1; - PPU.BG[3].NameBase = READ_WORD (&t [77]) >> 1; - PPU.BG[0].HOffset = READ_WORD (&t [79]); - PPU.BG[1].HOffset = READ_WORD (&t [81]); - PPU.BG[2].HOffset = READ_WORD (&t [83]); - PPU.BG[3].HOffset = READ_WORD (&t [85]); - PPU.BG[0].VOffset = READ_WORD (&t [89]); - PPU.BG[1].VOffset = READ_WORD (&t [91]); - PPU.BG[2].VOffset = READ_WORD (&t [93]); - PPU.BG[3].VOffset = READ_WORD (&t [95]); - PPU.VMA.Increment = READ_WORD (&t [97]) >> 1; - PPU.VMA.High = t [99]; + PPU.OAMAddr = READ_WORD (&t[25]); + PPU.SavedOAMAddr = READ_WORD (&t[27]); + PPU.FirstSprite = t[29]; + PPU.BGMode = t[30]; + PPU.BG3Priority = t[31]; + PPU.BG[0].BGSize = (t[32] >> 0) & 1; + PPU.BG[1].BGSize = (t[32] >> 1) & 1; + PPU.BG[2].BGSize = (t[32] >> 2) & 1; + PPU.BG[3].BGSize = (t[32] >> 3) & 1; + PPU.Mosaic = t[33] + 1; + PPU.BGMosaic [0] = (t[34] & 1) != 0; + PPU.BGMosaic [1] = (t[34] & 2) != 0; + PPU.BGMosaic [2] = (t[34] & 4) != 0; + PPU.BGMosaic [3] = (t[34] & 8) != 0; + PPU.BG [0].SCBase = READ_WORD (&t[35]) >> 1; + PPU.BG [1].SCBase = READ_WORD (&t[37]) >> 1; + PPU.BG [2].SCBase = READ_WORD (&t[39]) >> 1; + PPU.BG [3].SCBase = READ_WORD (&t[41]) >> 1; + PPU.BG [0].SCSize = t[67]; + PPU.BG [1].SCSize = t[68]; + PPU.BG [2].SCSize = t[69]; + PPU.BG [3].SCSize = t[70]; + PPU.BG[0].NameBase = READ_WORD (&t[71]) >> 1; + PPU.BG[1].NameBase = READ_WORD (&t[73]) >> 1; + PPU.BG[2].NameBase = READ_WORD (&t[75]) >> 1; + PPU.BG[3].NameBase = READ_WORD (&t[77]) >> 1; + PPU.BG[0].HOffset = READ_WORD (&t[79]); + PPU.BG[1].HOffset = READ_WORD (&t[81]); + PPU.BG[2].HOffset = READ_WORD (&t[83]); + PPU.BG[3].HOffset = READ_WORD (&t[85]); + PPU.BG[0].VOffset = READ_WORD (&t[89]); + PPU.BG[1].VOffset = READ_WORD (&t[91]); + PPU.BG[2].VOffset = READ_WORD (&t[93]); + PPU.BG[3].VOffset = READ_WORD (&t[95]); + PPU.VMA.Increment = READ_WORD (&t[97]) >> 1; + PPU.VMA.High = t[99]; #ifndef CORRECT_VRAM_READS - IPPU.FirstVRAMRead = t [100]; + IPPU.FirstVRAMRead = t[100]; #endif - S9xSetPPU (t [2512], 0x2115); - PPU.VMA.Address = READ_DWORD (&t [101]); + S9xSetPPU (t[2512], 0x2115); + PPU.VMA.Address = READ_DWORD (&t[101]); for (i = 0; i < 512; i++) - S9xSetPPU (t [1488 + i], 0x2122); + S9xSetPPU (t[1488 + i], 0x2122); - PPU.CGADD = (uint8) READ_WORD (&t [105]); - Memory.FillRAM [0x212c] = t [108]; - Memory.FillRAM [0x212d] = t [109]; - PPU.ScreenHeight = READ_WORD (&t [111]); - Memory.FillRAM [0x2133] = t [2526]; - Memory.FillRAM [0x4202] = t [113]; - Memory.FillRAM [0x4204] = t [114]; - Memory.FillRAM [0x4205] = t [115]; - Memory.FillRAM [0x4214] = t [116]; - Memory.FillRAM [0x4215] = t [117]; - Memory.FillRAM [0x4216] = t [118]; - Memory.FillRAM [0x4217] = t [119]; - PPU.VBeamPosLatched = READ_WORD (&t [122]); - PPU.HBeamPosLatched = READ_WORD (&t [120]); - PPU.Window1Left = t [127]; - PPU.Window1Right = t [128]; - PPU.Window2Left = t [129]; - PPU.Window2Right = t [130]; - S9xSetPPU (t [131] | (t [132] << 4), 0x2123); - S9xSetPPU (t [133] | (t [134] << 4), 0x2124); - S9xSetPPU (t [135] | (t [136] << 4), 0x2125); - S9xSetPPU (t [137], 0x212a); - S9xSetPPU (t [138], 0x212b); - S9xSetPPU (t [139], 0x212e); - S9xSetPPU (t [140], 0x212f); - S9xSetPPU (t [141], 0x211a); - PPU.MatrixA = READ_WORD (&t [142]); - PPU.MatrixB = READ_WORD (&t [144]); - PPU.MatrixC = READ_WORD (&t [146]); - PPU.MatrixD = READ_WORD (&t [148]); - PPU.CentreX = READ_WORD (&t [150]); - PPU.CentreY = READ_WORD (&t [152]); + PPU.CGADD = (uint8) READ_WORD (&t[105]); + Memory.FillRAM [0x212c] = t[108]; + Memory.FillRAM [0x212d] = t[109]; + PPU.ScreenHeight = READ_WORD (&t[111]); + Memory.FillRAM [0x2133] = t[2526]; + Memory.FillRAM [0x4202] = t[113]; + Memory.FillRAM [0x4204] = t[114]; + Memory.FillRAM [0x4205] = t[115]; + Memory.FillRAM [0x4214] = t[116]; + Memory.FillRAM [0x4215] = t[117]; + Memory.FillRAM [0x4216] = t[118]; + Memory.FillRAM [0x4217] = t[119]; + PPU.VBeamPosLatched = READ_WORD (&t[122]); + PPU.HBeamPosLatched = READ_WORD (&t[120]); + PPU.Window1Left = t[127]; + PPU.Window1Right = t[128]; + PPU.Window2Left = t[129]; + PPU.Window2Right = t[130]; + S9xSetPPU (t[131] | (t[132] << 4), 0x2123); + S9xSetPPU (t[133] | (t[134] << 4), 0x2124); + S9xSetPPU (t[135] | (t[136] << 4), 0x2125); + S9xSetPPU (t[137], 0x212a); + S9xSetPPU (t[138], 0x212b); + S9xSetPPU (t[139], 0x212e); + S9xSetPPU (t[140], 0x212f); + S9xSetPPU (t[141], 0x211a); + PPU.MatrixA = READ_WORD (&t[142]); + PPU.MatrixB = READ_WORD (&t[144]); + PPU.MatrixC = READ_WORD (&t[146]); + PPU.MatrixD = READ_WORD (&t[148]); + PPU.CentreX = READ_WORD (&t[150]); + PPU.CentreY = READ_WORD (&t[152]); PPU.M7HOFS = PPU.BG[0].HOffset; PPU.M7VOFS = PPU.BG[0].VOffset; // JoyAPos t[154] // JoyBPos t[155] - Memory.FillRAM [0x2134] = t [156]; // Matrix mult - Memory.FillRAM [0x2135] = t [157]; // Matrix mult - Memory.FillRAM [0x2136] = t [158]; // Matrix mult - PPU.WRAM = READ_DWORD (&t [161]); + Memory.FillRAM [0x2134] = t[156]; // Matrix mult + Memory.FillRAM [0x2135] = t[157]; // Matrix mult + Memory.FillRAM [0x2136] = t[158]; // Matrix mult + PPU.WRAM = READ_DWORD (&t[161]); for (i = 0; i < 128; i++) - S9xSetCPU (t [165 + i], 0x4300 + i); + S9xSetCPU (t[165 + i], 0x4300 + i); - if (t [294]) + if (t[294]) CPU.IRQActive |= PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE; - S9xSetCPU (t [296], 0x420c); + S9xSetCPU (t[296], 0x420c); // hdmadata t[297] + 8 * 19 - PPU.FixedColourRed = t [450]; - PPU.FixedColourGreen = t [451]; - PPU.FixedColourBlue = t [452]; - S9xSetPPU (t [454], 0x2130); - S9xSetPPU (t [455], 0x2131); + PPU.FixedColourRed = t[450]; + PPU.FixedColourGreen = t[451]; + PPU.FixedColourBlue = t[452]; + S9xSetPPU (t[454], 0x2130); + S9xSetPPU (t[455], 0x2131); // vraminctype ... fread (Memory.RAM, 1, 128 * 1024, fs); @@ -1881,31 +2445,31 @@ bool8 S9xUnfreezeZSNES (const char *filename) // SNES SPC700 state and internal ZSNES SPC700 emulation state fread (t, 1, 304, fs); - APURegisters.PC = READ_DWORD (&t [0]); - APURegisters.YA.B.A = t [4]; - APURegisters.X = t [8]; - APURegisters.YA.B.Y = t [12]; - APURegisters.P = t [16]; - APURegisters.S = t [24]; + APURegisters.PC = READ_DWORD (&t[0]); + APURegisters.YA.B.A = t[4]; + APURegisters.X = t[8]; + APURegisters.YA.B.Y = t[12]; + APURegisters.P = t[16]; + APURegisters.S = t[24]; - APU.Cycles = READ_DWORD (&t [32]); + APU.Cycles = READ_DWORD (&t[32]) << SNES_APU_ACCURACY; APU.ShowROM = (IAPU.RAM [0xf1] & 0x80) != 0; - APU.OutPorts [0] = t [36]; - APU.OutPorts [1] = t [37]; - APU.OutPorts [2] = t [38]; - APU.OutPorts [3] = t [39]; + APU.OutPorts [0] = t[36]; + APU.OutPorts [1] = t[37]; + APU.OutPorts [2] = t[38]; + APU.OutPorts [3] = t[39]; - APU.TimerEnabled [0] = (t [40] & 1) != 0; - APU.TimerEnabled [1] = (t [40] & 2) != 0; - APU.TimerEnabled [2] = (t [40] & 4) != 0; - S9xSetAPUTimer (0xfa, t [41]); - S9xSetAPUTimer (0xfb, t [42]); - S9xSetAPUTimer (0xfc, t [43]); - APU.Timer [0] = t [44]; - APU.Timer [1] = t [45]; - APU.Timer [2] = t [46]; + APU.TimerEnabled [0] = (t[40] & 1) != 0; + APU.TimerEnabled [1] = (t[40] & 2) != 0; + APU.TimerEnabled [2] = (t[40] & 4) != 0; + S9xSetAPUTimer (0xfa, t[41]); + S9xSetAPUTimer (0xfb, t[42]); + S9xSetAPUTimer (0xfc, t[43]); + APU.Timer [0] = t[44]; + APU.Timer [1] = t[45]; + APU.Timer [2] = t[46]; - memmove (APU.ExtraRAM, &t [48], 64); + memmove (APU.ExtraRAM, &t[48], 64); // Internal ZSNES sound DSP state fread (t, 1, 1068, fs); @@ -1923,15 +2487,15 @@ bool8 S9xUnfreezeZSNES (const char *filename) case APU_KOFF: break; case APU_FLG: - t [i] &= ~APU_SOFT_RESET; + t[i] &= ~APU_SOFT_RESET; default: IAPU.RAM [0xf2] = i; - S9xSetAPUDSP (t [i]); + S9xSetAPUDSP (t[i]); break; } } IAPU.RAM [0xf2] = APU_KON; - S9xSetAPUDSP (t [APU_KON]); + S9xSetAPUDSP (t[APU_KON]); IAPU.RAM [0xf2] = saved; S9xSetSoundMute (FALSE); @@ -1953,37 +2517,37 @@ bool8 S9xUnfreezeZSNES (const char *filename) if (Settings.SuperFX) { - fread (::SRAM, 1, 64 * 1024, fs); + fread (Memory.SRAM, 1, 64 * 1024, fs); fseek (fs, 64 * 1024, SEEK_CUR); fread (Memory.FillRAM + 0x7000, 1, 692, fs); } if (Settings.SA1) { fread (t, 1, 2741, fs); - S9xSetSA1 (t [4], 0x2200); // Control - S9xSetSA1 (t [12], 0x2203); // ResetV low - S9xSetSA1 (t [13], 0x2204); // ResetV hi - S9xSetSA1 (t [14], 0x2205); // NMI low - S9xSetSA1 (t [15], 0x2206); // NMI hi - S9xSetSA1 (t [16], 0x2207); // IRQ low - S9xSetSA1 (t [17], 0x2208); // IRQ hi - S9xSetSA1 (((READ_DWORD (&t [28]) - (4096*1024-0x6000))) >> 13, 0x2224); - S9xSetSA1 (t [36], 0x2201); - S9xSetSA1 (t [41], 0x2209); + S9xSetSA1 (t[4], 0x2200); // Control + S9xSetSA1 (t[12], 0x2203); // ResetV low + S9xSetSA1 (t[13], 0x2204); // ResetV hi + S9xSetSA1 (t[14], 0x2205); // NMI low + S9xSetSA1 (t[15], 0x2206); // NMI hi + S9xSetSA1 (t[16], 0x2207); // IRQ low + S9xSetSA1 (t[17], 0x2208); // IRQ hi + S9xSetSA1 (((READ_DWORD (&t[28]) - (4096*1024-0x6000))) >> 13, 0x2224); + S9xSetSA1 (t[36], 0x2201); + S9xSetSA1 (t[41], 0x2209); - SA1Registers.A.W = READ_DWORD (&t [592]); - SA1Registers.X.W = READ_DWORD (&t [596]); - SA1Registers.Y.W = READ_DWORD (&t [600]); - SA1Registers.D.W = READ_DWORD (&t [604]); - SA1Registers.DB = t [608]; - SA1Registers.PB = t [612]; - SA1Registers.S.W = READ_DWORD (&t [616]); - SA1Registers.PCw = READ_DWORD (&t [636]); - SA1Registers.P.W = t [620] | (t [624] << 8); + SA1Registers.A.W = READ_DWORD (&t[592]); + SA1Registers.X.W = READ_DWORD (&t[596]); + SA1Registers.Y.W = READ_DWORD (&t[600]); + SA1Registers.D.W = READ_DWORD (&t[604]); + SA1Registers.DB = t[608]; + SA1Registers.PB = t[612]; + SA1Registers.S.W = READ_DWORD (&t[616]); + SA1Registers.PCw = READ_DWORD (&t[636]); + SA1Registers.P.W = t[620] | (t[624] << 8); memmove (&Memory.FillRAM [0x3000], t + 692, 2 * 1024); - fread (::SRAM, 1, 64 * 1024, fs); + fread (Memory.SRAM, 1, 64 * 1024, fs); fseek (fs, 64 * 1024, SEEK_CUR); S9xFixSA1AfterSnapshotLoad (); } @@ -2130,7 +2694,7 @@ fread(&temp, 1, 4, fs); Memory.FixROMSpeed (); IPPU.ColorsChanged = TRUE; IPPU.OBJChanged = TRUE; - CPU.InDMA = CPU.InWRAM_DMA = FALSE; + CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; S9xFixColourBrightness (); IPPU.RenderThisFrame = FALSE; diff --git a/source/snes9x/snapshot.h b/source/snes9x/snapshot.h index b6eb433..9bea7a0 100644 --- a/source/snes9x/snapshot.h +++ b/source/snes9x/snapshot.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _SNAPSHOT_H_ #define _SNAPSHOT_H_ @@ -148,7 +167,7 @@ #include "snes9x.h" #define SNAPSHOT_MAGIC "#!snes9x" -#define SNAPSHOT_VERSION 2 +#define SNAPSHOT_VERSION 4 #define SUCCESS 1 #define WRONG_FORMAT (-1) @@ -156,6 +175,7 @@ #define FILE_NOT_FOUND (-3) #define WRONG_MOVIE_SNAPSHOT (-4) #define NOT_A_MOVIE_SNAPSHOT (-5) +#define SNAPSHOT_INCONSISTENT (-6) START_EXTERN_C void S9xResetSaveTimer(bool8 dontsave); diff --git a/source/snes9x/snes9x.cpp b/source/snes9x/snes9x.cpp index f8f0155..440d75d 100644 --- a/source/snes9x/snes9x.cpp +++ b/source/snes9x/snes9x.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include #include @@ -160,7 +179,9 @@ #ifndef NGC #include "netplay.h" +#include "logger.h" #endif +#include "gfx.h" #ifdef DEBUGGER extern FILE *trace; @@ -182,11 +203,10 @@ void S9xUsage () S9xMessage(S9X_INFO, S9X_USAGE, "-ratio or -ra Ratio of 65c816 to SPC700 instructions (ignored)"); #endif S9xMessage(S9X_INFO, S9X_USAGE, "-soundquality, -sq, or -r Set sound playback quality"); -#ifdef __sgi -/* BS: changed the sample rate values to match the IRIX options */ +#ifndef __MSDOS__ S9xMessage (S9X_INFO, S9X_USAGE, "\ 0 - off, 1 - 8192, 2 - 11025, 3 - 16000,\n\ - 4 - 22050 (default), 5 - 32000, 6 - 44100,\n\ + 4 - 22050, 5 - 32000 (default), 6 - 44100,\n\ 7 - 48000"); #else S9xMessage (S9X_INFO, S9X_USAGE, "\ @@ -202,8 +222,7 @@ void S9xUsage () #ifdef USE_THREADS S9xMessage(S9X_INFO, S9X_USAGE, "-threadsound or -ts Use a separate thread to output sound"); #endif - S9xMessage(S9X_INFO, S9X_USAGE, "-interpolatedsound or -is <0-3> Select sound interpolation method\n\ - 0=none, 1=linear, 2=cubic, 3=gaussian"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nois Turn off interpolated sound"); S9xMessage(S9X_INFO, S9X_USAGE, "-echo or -e Enable DSP echo effects at startup"); S9xMessage(S9X_INFO, S9X_USAGE, "-noecho or -ne Disable DSP echo effects at startup"); S9xMessage(S9X_INFO, S9X_USAGE, "-envx or -ex Enable volume envelope height reading"); @@ -211,7 +230,7 @@ void S9xUsage () S9xMessage(S9X_INFO, S9X_USAGE, "-nomastervolume or -nmv Disable master volume setting"); S9xMessage(S9X_INFO, S9X_USAGE, "-fix 'Fix' sound frequencies"); S9xMessage(S9X_INFO, S9X_USAGE, ""); - + /* FEATURE OPTIONS */ S9xMessage(S9X_INFO, S9X_USAGE, "-conf Use specified conf file (after standard files)"); S9xMessage(S9X_INFO, S9X_USAGE, "-nostdconf Do not load the standard config files"); @@ -258,11 +277,17 @@ void S9xUsage () S9xMessage(S9X_INFO, S9X_USAGE, "-nodsp1 Force detection of no DSP-1 chip"); S9xMessage(S9X_INFO, S9X_USAGE, ""); -#ifdef DEBUGGER + /* Multi ROMs OPTIONS */ + S9xMessage(S9X_INFO, S9X_USAGE, "-multi Enable multi cartridge system"); + S9xMessage(S9X_INFO, S9X_USAGE, "-carta ROM in slot A. Use with -multi"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cartb ROM in slot B. Use with -multi"); + /* OPTIONS FOR DEBUGGING USE */ - S9xMessage(S9X_INFO, S9X_USAGE, "-cycles or -h <1-199> Percentage of CPU cycles to execute per scanline"); + S9xMessage(S9X_INFO, S9X_USAGE, "-hdmahacks or -h <1-199> Changes HDMA transfer timing"); S9xMessage(S9X_INFO, S9X_USAGE, "-speedhacks or -sh Enable speed hacks"); S9xMessage(S9X_INFO, S9X_USAGE, "-nospeedhacks or -nsh Disable speed hacks"); + S9xMessage(S9X_INFO, S9X_USAGE, "-invalidvramaccess Allow invalid VRAM access"); +#ifdef DEBUGGER S9xMessage(S9X_INFO, S9X_USAGE, "-debug or -d Set the Debugger flag at startup"); S9xMessage(S9X_INFO, S9X_USAGE, "-trace or -t Begin CPU instruction tracing at startup"); S9xMessage(S9X_INFO, S9X_USAGE, "-noirq Disable processor IRQ (for debugging)"); @@ -296,7 +321,7 @@ void S9xUsage () S9xMessage(S9X_INFO, S9X_USAGE, " one-justifier ditto"); S9xMessage(S9X_INFO, S9X_USAGE, " two-justifiers Blue & Pink Justifiers"); S9xMessage(S9X_INFO, S9X_USAGE, " mp5:#### MP5 with the 4 named pads (1-8 or n)"); - + S9xMessage(S9X_INFO, S9X_USAGE, ""); #ifdef NETPLAY_SUPPORT @@ -316,15 +341,24 @@ void S9xUsage () S9xMessage(S9X_INFO, S9X_USAGE, "-ahiunit Set AHI Unit to "); S9xMessage(S9X_INFO, S9X_USAGE, ""); #endif - + S9xMessage(S9X_INFO, S9X_USAGE, " DeHackEd's commands:"); + S9xMessage(S9X_INFO, S9X_USAGE, "-dumpstreams Save audio/video data to disk"); + S9xMessage(S9X_INFO, S9X_USAGE, "-mute Don't output audio to sound card, use with above."); + S9xMessage(S9X_INFO, S9X_USAGE, "-upanddown Override protection from pressing"); + S9xMessage(S9X_INFO, S9X_USAGE, " left+right or up+down together"); + S9xMessage(S9X_INFO, S9X_USAGE, "-autodemo Start emulator playing a movie"); + S9xMessage(S9X_INFO, S9X_USAGE, "-maxframes Stop emulator after playing specified"); + S9xMessage(S9X_INFO, S9X_USAGE, " number of frames. Requires -dumpstreams"); + S9xMessage(S9X_INFO, S9X_USAGE, "-oldturbo Turbo button renders all frames, but slower"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); #ifndef NGC - S9xExtraUsage(); + S9xExtraUsage(); #endif S9xMessage (S9X_INFO, S9X_USAGE, "\ \nROM image needs to be in Super MagiCom (*.smc), Super FamiCom (*.sfc),\n\ *.fig, or split (*.1, *.2, or sf32527a, sf32527b, etc) format and can be\n\ -compressed with zip, gzip, or compress.\n"); +compressed with zip, gzip, JMA, or compress.\n"); exit (1); } @@ -422,13 +456,13 @@ char *S9xParseArgs (char **argv, int argc) S9xUsage (); } else if (strcasecmp (argv [i], "-h") == 0 || - strcasecmp (argv [i], "-cycles") == 0) + strcasecmp (argv [i], "-hdmahacks") == 0) { if (i + 1 < argc) { int p = atoi (argv [++i]); if (p > 0 && p < 200) - Settings.CyclesPercentage = p; + Settings.HDMATimingHack = p; } else S9xUsage (); @@ -453,6 +487,10 @@ char *S9xParseArgs (char **argv, int argc) { Settings.ShutdownMaster = TRUE; } + else if (strcasecmp (argv [i], "-invalidvramaccess") == 0) + { + Settings.BlockInvalidVRAMAccess = FALSE; + } else if (strcasecmp (argv [i], "-p") == 0 || strcasecmp (argv [i], "-pal") == 0) { @@ -529,7 +567,7 @@ char *S9xParseArgs (char **argv, int argc) Settings.ForceNoTransparency = TRUE; Settings.ForceTransparency = FALSE; } - else if (strcasecmp (argv [i], "-hi") == 0 || + else if (strcasecmp (argv [i], "-hi") == 0 || strcasecmp (argv [i], "-hires") == 0) { Settings.SupportHiRes = TRUE; @@ -543,6 +581,8 @@ char *S9xParseArgs (char **argv, int argc) { Settings.DisplayFrameRate = TRUE; } + else if (strcasecmp (argv [i], "-nomessagesinimage") == 0) + Settings.AutoDisplayMessages = FALSE; else if (strcasecmp (argv [i], "-i") == 0 || strcasecmp (argv [i], "-interleaved") == 0) Settings.ForceInterleaved = TRUE; @@ -669,14 +709,8 @@ char *S9xParseArgs (char **argv, int argc) double ft; if (sscanf (argv [++i], "%lf", &ft) == 1) { -#ifdef __WIN32__ - Settings.FrameTimePAL = (int32) (ft * 1000); - Settings.FrameTimeNTSC = (int32) (ft * 1000); -#else - Settings.FrameTimePAL = (int32) ft; - Settings.FrameTimeNTSC = (int32) ft; -#endif - + Settings.FrameTimePAL = (int32) ft; + Settings.FrameTimeNTSC = (int32) ft; } } else @@ -739,10 +773,9 @@ char *S9xParseArgs (char **argv, int argc) Settings.SoundEnvelopeHeightReading = TRUE; Settings.InterpolatedSound = TRUE; } - else if (strcasecmp (argv [i], "-interpolatedsound") == 0 || - strcasecmp (argv [i], "-is") == 0) + else if (strcasecmp (argv [i], "-nois") == 0) { - Settings.InterpolatedSound = TRUE; + Settings.InterpolatedSound = FALSE; } #ifdef USE_THREADS else if (strcasecmp (argv [i], "-threadsound") == 0 || @@ -833,6 +866,26 @@ char *S9xParseArgs (char **argv, int argc) } } #endif + else if (strcasecmp (argv[i], "-dumpstreams") == 0) + dumpstreams = 1; + else if (strcasecmp (argv[i], "-maxframes") == 0) + maxframes = atoi(argv[++i]); + else if (strcasecmp (argv[i], "-mute") == 0) + Settings.Mute = 1; + else if (strcasecmp (argv[i], "-upanddown") == 0) + Settings.UpAndDown = 1; + else if (strcasecmp (argv[i], "-oldturbo") == 0) + Settings.OldTurbo = 1; + else if (strcasecmp(argv[i], "-autodemo") == 0) { + i++; + if (!argv[i]) + abort(); + strcpy(autodemo, argv[i]); + } + else if (strcasecmp(argv[i], "-keypress") == 0) // videologger output of controller 1 + Settings.DisplayPressedKeys = 1; + else if (strcasecmp(argv[i], "-keypress2") == 0) // S9xDisplayMessages output of all controllers and peripherals + Settings.DisplayPressedKeys = 2; else if (strcasecmp (argv [i], "-conf") == 0) { if (++i>=argc) S9xUsage(); @@ -842,6 +895,33 @@ char *S9xParseArgs (char **argv, int argc) { // Do nothing, S9xLoadConfigFiles() handled it } + else if (strcasecmp (argv [i], "-version") == 0) + { + printf("Snes9X " VERSION "\n"); + exit(0); + } + else if (strcasecmp (argv [i], "-help") == 0) + { + S9xUsage(); + } + else if (strcasecmp (argv [i], "-multi") == 0) + { + Settings.Multi = TRUE; + } + else if (strcasecmp (argv [i], "-carta") == 0) + { + if (i + 1 < argc) + { + strncpy (Settings.CartAName, argv [++i], _MAX_PATH); + } + } + else if (strcasecmp (argv [i], "-cartb") == 0) + { + if (i + 1 < argc) + { + strncpy (Settings.CartBName, argv [++i], _MAX_PATH); + } + } else S9xParseArg (argv, i, argc); @@ -855,7 +935,6 @@ char *S9xParseArgs (char **argv, int argc) #endif return (rom_filename); - } #ifndef NGC @@ -883,7 +962,7 @@ void S9xParseCheatsFile (const char *rom_filename) { while(fgets(buf, 80, f) != NULL) { - if ((p = strrchr (buf, '\n')) != NULL) + if ((p = strrchr (buf, '\n')) != NULL) *p = '\0'; if (((error = S9xGameGenieToRaw (buf, address, byte)) == NULL) || ((error = S9xProActionReplayToRaw (buf, address, byte)) == NULL)) @@ -954,7 +1033,7 @@ static void parse_crosshair_spec(enum crosscontrols ctl, const char *spec){ static bool try_load(const char *fname, ConfigFile &conf){ STREAM fp; if((fp=OPEN_STREAM(fname, "r"))!=NULL){ - fprintf(stderr, "Reading config file %s\n", fname); + fprintf(stdout, "Reading config file %s\n", fname); conf.LoadFile(new fReader(fp)); CLOSE_STREAM(fp); return true; @@ -973,7 +1052,7 @@ void S9xLoadConfigFiles(char **argv, int argc){ } } - ConfigFile conf; + static ConfigFile conf; // static because some of its functions return pointers that would otherwise become invalid after this function conf.Clear(); if(!skip){ @@ -1009,10 +1088,11 @@ void S9xLoadConfigFiles(char **argv, int argc){ /* Parse config file here */ Settings.NextAPUEnabled=conf.GetBool("Sound::APUEnabled", Settings.APUEnabled); Settings.SoundSkipMethod=conf.GetInt("Sound::SoundSkip", 0); - i=conf.GetInt("CPU::Cycles", 100); - if(i>0 && i<200) Settings.CyclesPercentage = i; + i=conf.GetInt("CPU::HDMATimingHack", 100); + if(i>0 && i<200) Settings.HDMATimingHack = i; Settings.DisableHDMA=conf.GetBool("Settings::DisableHDMA", false); - Settings.ShutdownMaster=conf.GetBool("Settings::SpeedHacks", true); + Settings.ShutdownMaster=conf.GetBool("Settings::SpeedHacks", false); + Settings.BlockInvalidVRAMAccess=conf.GetBool("Settings::BlockInvalidVRAMAccess", true); Settings.ForcePAL=conf.GetBool("ROM::PAL", false); Settings.ForceNTSC=conf.GetBool("ROM::NTSC", false); if(!strcasecmp(conf.GetString("Settings::FrameSkip", "Auto"),"Auto")){ @@ -1023,6 +1103,7 @@ void S9xLoadConfigFiles(char **argv, int argc){ Settings.TurboSkipFrames=conf.GetUInt("Settings::TurboFrameSkip", 15); Settings.TurboMode=conf.GetBool("Settings::TurboMode",false); Settings.StretchScreenshots=conf.GetInt("Settings::StretchScreenshots",1); + Settings.InitialInfoStringTimeout=conf.GetInt("Settings::MessageDisplayTime",120); Settings.AutoSaveDelay=conf.GetUInt("Settings::AutoSaveDelay", 30); Settings.ForceHiROM=conf.GetBool("ROM::HiROM", false); Settings.ForceLoROM=conf.GetBool("ROM::LoROM", false); @@ -1045,6 +1126,11 @@ void S9xLoadConfigFiles(char **argv, int argc){ } Settings.SupportHiRes=conf.GetBool("Display::HiRes", true); Settings.DisplayFrameRate=conf.GetBool("Display::FrameRate", false); + if(conf.Exists("Display::DisplayInput")) + Settings.DisplayPressedKeys=conf.GetBool("Display::DisplayInput", false)?1:0; +// GFX.FrameDisplay=conf.GetBool("Display::DisplayFrameCount", false); + GFX.FrameDisplay=TRUE; + Settings.AutoDisplayMessages=conf.GetBool("Display::MessagesInImage", true); if(conf.Exists("ROM::Interleaved")){ Settings.ForceInterleaved=conf.GetBool("ROM::Interleaved", false); Settings.ForceNotInterleaved=!Settings.ForceInterleaved; @@ -1068,14 +1154,8 @@ void S9xLoadConfigFiles(char **argv, int argc){ double ft; if (sscanf(conf.GetString("Settings::FrameTime"), "%lf", &ft) == 1) { -#ifdef __WIN32__ - Settings.FrameTimePAL = (int32) (ft * 1000); - Settings.FrameTimeNTSC = (int32) (ft * 1000); -#else Settings.FrameTimePAL = (int32) ft; Settings.FrameTimeNTSC = (int32) ft; -#endif - } } Settings.FrameTime = Settings.FrameTimeNTSC; @@ -1094,7 +1174,7 @@ void S9xLoadConfigFiles(char **argv, int argc){ Settings.SoundEnvelopeHeightReading=conf.GetBool("Sound::EnvelopeHeightReading"); Settings.DisableSampleCaching=!conf.GetBool("Sound::SampleCaching"); Settings.DisableMasterVolume=!conf.GetBool("Sound::MasterVolume"); - Settings.InterpolatedSound=conf.GetBool("Sound::Interpolate", false); + Settings.InterpolatedSound=conf.GetBool("Sound::Interpolate", true); if(conf.Exists("Sound::Sync")){ Settings.SoundSync=conf.GetInt("Sound::Sync", 1); if(Settings.SoundSync>2) Settings.SoundSync=1; @@ -1147,7 +1227,7 @@ void S9xLoadConfigFiles(char **argv, int argc){ Settings.Port = NP_DEFAULT_PORT; if(conf.Exists("Netplay::Port")){ Settings.NetPlay = TRUE; - Settings.Port = -conf.GetUInt("Netplay::Port"); + Settings.Port = -(int)conf.GetUInt("Netplay::Port"); } Settings.ServerName[0]='\0'; if(conf.Exists("Netplay::Server")){ @@ -1169,6 +1249,12 @@ void S9xLoadConfigFiles(char **argv, int argc){ } #endif Settings.JoystickEnabled=conf.GetBool("Controls::Joystick", Settings.JoystickEnabled); + Settings.UpAndDown=conf.GetBool("Controls::AllowLeftRight", false); + Settings.SnapshotScreenshots=conf.GetBool("Settings::SnapshotScreenshots", true); + Settings.MovieTruncate=conf.GetBool("Settings::MovieTruncateAtEnd", false); + Settings.MovieNotifyIgnored=conf.GetBool("Settings::MovieNotifyIgnored", false); + Settings.DisplayWatchedAddresses=conf.GetBool("Settings::DisplayWatchedAddresses", false); + Settings.WrongMovieStateProtection=conf.GetBool("Settings::WrongMovieStateProtection", true); rom_filename=conf.GetStringDup("ROM::Filename", NULL); S9xParsePortConfig(conf, 1); diff --git a/source/snes9x/snes9x.h b/source/snes9x/snes9x.h index 83e8e41..18d3e0e 100644 --- a/source/snes9x/snes9x.h +++ b/source/snes9x/snes9x.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,22 +158,24 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _SNES9X_H_ #define _SNES9X_H_ -#define VERSION "1.5" +#define VERSION "1.51" #include #include #ifdef __WIN32__ -#include "..\wsnes9x.h" +#include #ifdef ZLIB -#include "..\zlib\zlib.h" +#include #endif #endif -#include "language.h" +//#include "language.h" // files should include this as needed, no need to recompile practically everything when it changes #include "port.h" #include "65c816.h" @@ -170,9 +189,8 @@ #ifdef ZLIB #ifndef __WIN32__ -#include "zlib.h" +#include #endif - #define STREAM gzFile #define READ_STREAM(p,l,s) gzread (s,p,l) #define WRITE_STREAM(p,l,s) gzwrite (s,p,l) @@ -200,8 +218,10 @@ #define SNES_WIDTH 256 #define SNES_HEIGHT 224 #define SNES_HEIGHT_EXTENDED 239 -#define IMAGE_WIDTH (Settings.SupportHiRes ? SNES_WIDTH * 2 : SNES_WIDTH) -#define IMAGE_HEIGHT (Settings.SupportHiRes ? SNES_HEIGHT_EXTENDED * 2 : SNES_HEIGHT_EXTENDED) +#define MAX_SNES_WIDTH (SNES_WIDTH * 2) +#define MAX_SNES_HEIGHT (SNES_HEIGHT_EXTENDED * 2) +#define IMAGE_WIDTH (Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH) +#define IMAGE_HEIGHT (Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED) #define NTSC_MASTER_CLOCK 21477272.0 #define PAL_MASTER_CLOCK 21281370.0 @@ -228,8 +248,10 @@ #define SNES_HDMA_INIT_HC 20 // FIXME: not true #define SNES_RENDER_START_HC (48 * ONE_DOT_CYCLE) // FIXME: Snes9x renders a line at a time. -#define SNES_APUTIMER_ACCURACY 10 -#define SNES_APUTIMER2_CYCLE_SHIFT ((int32) ((SNES_CYCLES_PER_SCANLINE << SNES_APUTIMER_ACCURACY) * (1.0 / 64000.0) / SNES_SCANLINE_TIME + 0.5)) +#define SNES_APU_CLOCK 1024000.0 // 1026900.0? +#define SNES_APU_ACCURACY 10 +#define SNES_APU_ONE_CYCLE_SCALED ((int32) (NTSC_MASTER_CLOCK / SNES_APU_CLOCK * (1 << SNES_APU_ACCURACY))) +#define SNES_APUTIMER2_CYCLE_SCALED ((int32) (NTSC_MASTER_CLOCK / 64000.0 * (1 << SNES_APU_ACCURACY))) #define AUTO_FRAMERATE 200 @@ -258,7 +280,7 @@ #define PROCESS_SOUND_FLAG (1 << 8) #define FRAME_ADVANCE_FLAG (1 << 9) #define DELAYED_NMI_FLAG2 (1 << 10) -#define IRQ_PENDING_FLAG (1 << 11) +#define IRQ_FLAG (1 << 11) #define HALTED_FLAG (1 << 12) struct SCPUState{ @@ -267,8 +289,8 @@ struct SCPUState{ bool8 NMIActive; bool8 IRQActive; bool8 WaitingForInterrupt; - bool8 InDMA; - bool8 InWRAM_DMA; + bool8 InDMAorHDMA; + bool8 InWRAMDMAorHDMA; uint8 WhichEvent; uint8 *PCBase; uint32 PBPCAtOpcodeStart; @@ -284,6 +306,11 @@ struct SCPUState{ bool8 SRAMModified; bool8 BRKTriggered; bool8 TriedInterleavedMode2; + int32 IRQPending; + bool8 InDMA; + bool8 InHDMA; + uint8 HDMARanInDMA; + int32 PrevCycles; }; struct STimings { @@ -299,6 +326,7 @@ struct STimings { int32 WRAMRefreshPos; int32 RenderPos; bool8 InterlaceField; + int32 DMACPUSync; }; enum { @@ -321,7 +349,7 @@ struct SSettings{ bool8 APUEnabled; bool8 Shutdown; uint8 SoundSkipMethod; - int32 CyclesPercentage; + int32 HDMATimingHack; bool8 DisableIRQ; bool8 Paused; bool8 ForcedPause; @@ -368,7 +396,7 @@ struct SSettings{ bool8 ForceSDD1; bool8 ForceNoSDD1; bool8 SRTC; - + bool8 ShutdownMaster; bool8 MultiPlayer5Master; bool8 SuperScopeMaster; @@ -395,17 +423,22 @@ struct SSettings{ bool8 DisableSampleCaching; bool8 DisableMasterVolume; bool8 SoundSync; + bool8 FakeMuteFix; bool8 InterpolatedSound; bool8 ThreadSound; bool8 Mute; bool8 NextAPUEnabled; uint8 AltSampleDecode; bool8 FixFrequency; - + /* Graphics options */ bool8 Transparency; bool8 SupportHiRes; - bool8 Mode7Interpolate; + bool8 Mode7Interpolate; // no longer used? + bool8 AutoDisplayMessages; + uint8 BG_Forced; + bool8 SnapshotScreenshots; + uint32 InitialInfoStringTimeout; // Messages normally display for this many frames /* SNES graphics options */ bool8 BGLayering; @@ -415,6 +448,12 @@ struct SSettings{ bool8 DisableHDMA; bool8 DisplayFrameRate; bool8 DisableRangeTimeOver; /* XXX: unused */ + bool8 DisplayWatchedAddresses; + + /* Multi ROMs */ + bool8 Multi; + char CartAName[_MAX_PATH + 1]; + char CartBName[_MAX_PATH + 1]; /* Others */ bool8 NetPlay; @@ -426,9 +465,16 @@ struct SSettings{ int32 AutoSaveDelay; /* Time in seconds before S-RAM auto-saved if modified. */ bool8 ApplyCheats; bool8 TurboMode; + bool8 OldTurbo; + bool8 UpAndDown; + uint8 DisplayPressedKeys; // The value indicates how to do it. + uint32 HighSpeedSeek; uint32 TurboSkipFrames; uint32 AutoMaxSkipFrames; - + bool8 MovieTruncate; + bool8 MovieNotifyIgnored; + bool8 WrongMovieStateProtection; + /* Fixes for individual games */ bool8 WinterGold; bool8 BS; /* Japanese Satellite System games. */ @@ -437,6 +483,7 @@ struct SSettings{ uint8 APURAMInitialValue; bool8 SampleCatchup; int8 SETA; + bool8 BlockInvalidVRAMAccess; bool8 TakeScreenshot; int8 StretchScreenshots; uint16 DisplayColor; diff --git a/source/snes9x/soundux.cpp b/source/snes9x/soundux.cpp index d551eb8..3247e91 100644 --- a/source/snes9x/soundux.cpp +++ b/source/snes9x/soundux.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifdef __DJGPP__ #include #undef TRUE @@ -306,7 +325,7 @@ void S9xAPUSetEndX (int); void S9xSetEnvRate (Channel *, int32, int32); void MixStereo (int); void MixMono (int); - + static void S9xSetSoundFrequency (int, int); static void S9xConvertSoundOldValues (); static void DecodeBlock (Channel *); @@ -317,6 +336,7 @@ STATIC inline uint8 *S9xGetSampleAddress (int); EXTERN_C void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); EXTERN_C void DecodeBlockAsm2 (int8 *, int16 *, int32 *, int32 *); +static bool8 DoFakeMute = FALSE; STATIC inline uint8 *S9xGetSampleAddress (int sample_number) { @@ -330,10 +350,12 @@ void S9xAPUSetEndOfSample (int i, Channel *ch) ch->mode = MODE_NONE; ch->out_sample = 0; ch->xenvx = 0; + if(!DoFakeMute) { APU.DSP[APU_ENDX] |= 1 << i; APU.DSP[APU_KON] &= ~(1 << i); APU.DSP[APU_KOFF] &= ~(1 << i); APU.KeyedChannels &= ~(1 << i); + } } #ifdef __DJGPP @@ -342,7 +364,9 @@ END_OF_FUNCTION (S9xAPUSetEndOfSample) void S9xAPUSetEndX (int i) { + if(!DoFakeMute) { APU.DSP[APU_ENDX] |= 1 << i; + } } #ifdef __DJGPP @@ -487,8 +511,8 @@ void S9xPrepareSoundForSnapshotSave (bool8 restore) { for (i = 0; i < NUM_CHANNELS; i++) { - Channel *ch = &SoundData.channels[i]; - + Channel *ch = &SoundData.channels[i]; + ch->count = 0; ch->envx = ch->xenvx >> 4; ch->envx_target = ch->xenvx_target >> 4; @@ -500,32 +524,32 @@ void S9xPrepareSoundForSnapshotSave (bool8 restore) if (env_counter_max < ch->xenv_count) ch->env_error = 0; - else + else ch->env_error = (uint32) ((double) FIXED_POINT / env_counter_max * (env_counter_max - ch->xenv_count)); if (ch->xenv_rate < 0) ch->erate = 0; - else + else ch->erate = (uint32) ((double) FIXED_POINT / env_counter_max * ch->xenv_rate); - + for (j = 0; j < 32; j++) if (env_counter_table[j] == ch->xattack_rate) break; ch->attack_rate = OldAttackRate[(unsigned) (((j - 1) >> 1) & 0xF)]; - + for (j = 0; j < 32; j++) if (env_counter_table[j] == ch->xdecay_rate) break; ch->decay_rate = OldDecayRate[(unsigned) (((j - 0x10) >> 1) & 0x7)]; - + for (j = 0; j < 32; j++) if (env_counter_table[j] == ch->xsustain_rate) break; - ch->sustain_rate = OldSustainRate[(unsigned) (j & 0x1F)]; + ch->sustain_rate = OldSustainRate[(unsigned) (j & 0x1F)]; } - + for (j = 0; j < 32; j++) if (env_counter_table[j] == SoundData.noise_rate) break; @@ -533,7 +557,7 @@ void S9xPrepareSoundForSnapshotSave (bool8 restore) for (i = 0; i < NUM_CHANNELS; i++) { Channel *ch = &SoundData.channels[i]; - + temp_hertz[i] = ch->hertz; if (ch->type == SOUND_NOISE) ch->hertz = OldNoiseFreq[(unsigned) (j & 0x1F)]; @@ -544,7 +568,7 @@ void S9xPrepareSoundForSnapshotSave (bool8 restore) for (i = 0; i < NUM_CHANNELS; i++) { Channel *ch = &SoundData.channels[i]; - + ch->hertz = temp_hertz[i]; } } @@ -558,38 +582,38 @@ static void S9xConvertSoundOldValues () for (i = 0; i < NUM_CHANNELS; i++) { Channel *ch = &SoundData.channels[i]; - + ch->xenvx = ch->envx << 4; ch->xenvx_target = ch->envx_target << 4; ch->out_sample = ((ch->sample * ch->xenvx) >> 11) & ~1; ch->xsustain_level = ch->sustain_level << 8; ch->xenv_rate = (int32) ((double) ch->erate * env_counter_max / FIXED_POINT); - ch->xenv_count = env_counter_max - + ch->xenv_count = env_counter_max - (int32) ((double) ch->env_error * env_counter_max / FIXED_POINT); - + for (j = 0; j < 16; j++) if (OldAttackRate[j] == ch->attack_rate) break; ch->xattack_rate = env_counter_table[(unsigned) (((j << 1) + 1) & 0x1F)]; - + for (j = 0; j < 8; j++) if (OldDecayRate[j] == ch->decay_rate) break; ch->xdecay_rate = env_counter_table[(unsigned) (((j << 1) + 0x10) & 0x1F)]; - + for (j = 0; j < 32; j++) if (OldSustainRate[j] == ch->sustain_rate) break; ch->xsustain_rate = env_counter_table[(unsigned) (j & 0x1F)]; - + if (ch->type == SOUND_NOISE) { old_noise_freq = ch->hertz; ch->hertz = 32000; } } - + if (old_noise_freq) { for (j = 0; j < 32; j++) @@ -616,7 +640,7 @@ void S9xFixSoundAfterSnapshotLoad (int version) S9xSetFilterCoefficient (5, (signed char) APU.DSP[APU_C5]); S9xSetFilterCoefficient (6, (signed char) APU.DSP[APU_C6]); S9xSetFilterCoefficient (7, (signed char) APU.DSP[APU_C7]); - + if (version < 2) S9xConvertSoundOldValues (); @@ -633,7 +657,7 @@ void S9xFixSoundAfterSnapshotLoad (int version) SoundData.channels[i].previous[0] = (int32) SoundData.channels[i].previous16[0]; SoundData.channels[i].previous[1] = (int32) SoundData.channels[i].previous16[1]; } - + SoundData.noise_count = 0; SoundData.master_volume[Settings.ReverseStereo] = SoundData.master_volume_left; @@ -645,7 +669,7 @@ void S9xFixSoundAfterSnapshotLoad (int version) void S9xSetFilterCoefficient (int tap, int value) { FilterTaps[tap & 7] = value; - SoundData.no_filter = + SoundData.no_filter = FilterTaps[0] == 127 && FilterTaps[1] == 0 && FilterTaps[2] == 0 && @@ -659,7 +683,7 @@ void S9xSetFilterCoefficient (int tap, int value) void S9xSetSoundADSR (int channel, int ar, int dr, int sr, int sl) { Channel *ch = &SoundData.channels[channel]; - + ch->xattack_rate = env_counter_table[(ar << 1) + 1]; ch->xdecay_rate = env_counter_table[(dr << 1) + 0x10]; ch->xsustain_rate = env_counter_table[sr]; @@ -670,7 +694,7 @@ void S9xSetSoundADSR (int channel, int ar, int dr, int sr, int sl) case SOUND_ATTACK: S9xSetEnvRate (ch, ch->xattack_rate, ENV_MAX); break; - + case SOUND_DECAY: S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); break; @@ -801,13 +825,13 @@ static void AltDecodeBlock (Channel *ch) sample2 = sample1 << 4; sample2 >>= 4; sample1 >>= 4; - + out = (sample1 << shift) - prev1 + (prev1 >> 4); prev1 = (int16) prev0; prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - (prev0 >> 4); - + out = (sample2 << shift) - prev1 + (prev1 >> 4); prev1 = (int16) prev0; prev0 &= ~3; @@ -824,18 +848,18 @@ static void AltDecodeBlock (Channel *ch) sample2 >>= 4; sample1 >>= 4; out = (sample1 << shift); - + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); prev1 = (int16) prev0; prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - (prev0 >> 4) - (prev1 >> 6); - + out = (sample2 << shift); out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); prev1 = (int16) prev0; prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - (prev0 >> 4) - (prev1 >> 6); } break; @@ -889,16 +913,16 @@ static void AltDecodeBlock2 (Channel *ch) sample2 = sample1 << 4; sample2 >>= 4; sample1 >>= 4; - + out = (int32) (sample1 << shift); - + prev1 = prev0; prev0 = out; CLIP16(out); *raw++ = (int16) out; - + out = (int32) (sample2 << shift); - + prev1 = prev0; prev0 = out; CLIP16(out); @@ -915,15 +939,15 @@ static void AltDecodeBlock2 (Channel *ch) sample1 >>= 4; out = (int32) (sample1 << shift); out += (int32) ((double) prev0 * 15/16); - + prev1 = prev0; prev0 = out; CLIP16(out); *raw++ = (int16) out; - + out = (int32) (sample2 << shift); out += (int32) ((double) prev0 * 15/16); - + prev1 = prev0; prev0 = out; CLIP16(out); @@ -938,21 +962,21 @@ static void AltDecodeBlock2 (Channel *ch) sample2 = sample1 << 4; sample2 >>= 4; sample1 >>= 4; - + out = ((sample1 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; - + prev1 = prev0; prev0 = (int16) out; *raw++ = (int16) out; - + out = ((sample2 << shift) * 256 + (prev0 & ~0x2) * 488 - prev1 * 240) >> 8; - + prev1 = prev0; prev0 = (int16) out; *raw++ = (int16) out; } break; - + case 3: for (i = 8; i != 0; i--) { @@ -962,19 +986,19 @@ static void AltDecodeBlock2 (Channel *ch) sample1 >>= 4; out = (int32) (sample1 << shift); out += (int32) ((double) prev0 * 115/64 - (double) prev1 * 13/16); - + prev1 = prev0; prev0 = out; - + CLIP16(out); *raw++ = (int16) out; - + out = (int32) (sample2 << shift); out += (int32) ((double) prev0 * 115/64 - (double) prev1 * 13/16); - + prev1 = prev0; prev0 = out; - + CLIP16(out); *raw++ = (int16) out; } @@ -1042,7 +1066,7 @@ static void DecodeBlock (Channel *ch) sample2 >>= 4; //Sample 1 = Top Nibble, shifted down and Sign Extended. sample1 >>= 4; - + for (int nybblesmp = 0; nybblesmp < 2; nybblesmp++) { out = (nybblesmp ? sample2 : sample1); @@ -1050,19 +1074,19 @@ static void DecodeBlock (Channel *ch) out = (out << shift) >> 1; else out &= ~0x7FF; - + switch (filter) { case 0x00: // Method0 -[Smp] break; - + case 0x04: // Method1 -[Delta]+[Smp-1](15/16) out += prev0 >> 1; out += (-prev0) >> 5; break; - + case 0x08: // Method2 -[Delta]+[Smp-1](61/32)-[Smp-2](15/16) out += prev0; @@ -1070,7 +1094,7 @@ static void DecodeBlock (Channel *ch) out -= prev1 >> 1; out += prev1 >> 5; break; - + case 0x0C: // Method3 -[Delta]+[Smp-1](115/64)-[Smp-2](13/16) out += prev0; @@ -1081,7 +1105,7 @@ static void DecodeBlock (Channel *ch) } CLIP16(out); - + prev1 = (signed short) prev0; prev0 = *raw++ = (signed short) (out << 1); } @@ -1095,18 +1119,20 @@ static void DecodeBlock (Channel *ch) void MixStereo (int sample_count) { + DoFakeMute=Settings.FakeMuteFix; + static int32 noise_cache[256]; static int32 wave[SOUND_BUFFER_SIZE]; int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; - + int32 noise_index = 0; int32 noise_count = 0; - + if (APU.DSP[APU_NON]) { noise_count = SoundData.noise_count; - + for (uint32 I = 0; I < (uint32) sample_count; I += 2) { noise_count -= SoundData.noise_rate; @@ -1124,9 +1150,9 @@ void MixStereo (int sample_count) { Channel *ch = &SoundData.channels[J]; uint32 freq = ch->frequency; - + bool8 last_block = FALSE; - + if (ch->type == SOUND_NOISE) { noise_index = 0; @@ -1135,10 +1161,10 @@ void MixStereo (int sample_count) if (ch->state == SOUND_SILENT || last_block || !(so.sound_switch & (1 << J))) continue; - + bool8 mod1 = pitch_mod & (1 << J); bool8 mod2 = pitch_mod & (1 << (J + 1)); - + if (ch->needs_decode) { DecodeBlock(ch); @@ -1146,9 +1172,9 @@ void MixStereo (int sample_count) ch->sample = ch->block[0]; ch->sample_pointer = 0; } - + for (uint32 I = 0; I < (uint32) sample_count; I += 2) - { + { switch (ch->state) { case SOUND_ATTACK: @@ -1163,12 +1189,12 @@ void MixStereo (int sample_count) ch->xenv_count += env_counter_max; } } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; - if (ch->xsustain_level != ENV_RANGE) + if (ch->xsustain_level != ENV_RANGE) { ch->state = SOUND_DECAY; S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); @@ -1179,9 +1205,9 @@ void MixStereo (int sample_count) S9xSetEnvRate (ch, ch->xsustain_rate, 0); } } - + break; - + case SOUND_DECAY: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1203,9 +1229,9 @@ void MixStereo (int sample_count) S9xSetEnvRate (ch, ch->xsustain_rate, 0); } } - + break; - + case SOUND_SUSTAIN: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1221,7 +1247,7 @@ void MixStereo (int sample_count) } break; - + case SOUND_RELEASE: ch->xenv_count -= env_counter_max; while (ch->xenv_count <= 0) @@ -1237,7 +1263,7 @@ void MixStereo (int sample_count) } break; - + case SOUND_INCREASE_LINEAR: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1245,7 +1271,7 @@ void MixStereo (int sample_count) ch->xenvx += (ENV_RANGE >> 6); // 1/64 ch->xenv_count += env_counter_max; } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; @@ -1253,9 +1279,9 @@ void MixStereo (int sample_count) ch->mode = MODE_GAIN; S9xSetEnvRate (ch, 0, 0); } - + break; - + case SOUND_INCREASE_BENT_LINE: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1264,10 +1290,10 @@ void MixStereo (int sample_count) ch->xenvx += (ENV_RANGE >> 8); // 1/256 else ch->xenvx += (ENV_RANGE >> 6); // 1/64 - + ch->xenv_count += env_counter_max; } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; @@ -1275,9 +1301,9 @@ void MixStereo (int sample_count) ch->mode = MODE_GAIN; S9xSetEnvRate (ch, 0, 0); } - + break; - + case SOUND_DECREASE_LINEAR: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1285,7 +1311,7 @@ void MixStereo (int sample_count) ch->xenvx -= (ENV_RANGE >> 6); // 1/64 ch->xenv_count += env_counter_max; } - + if (ch->xenvx <= 0) { S9xAPUSetEndOfSample (J, ch); @@ -1293,7 +1319,7 @@ void MixStereo (int sample_count) } break; - + case SOUND_DECREASE_EXPONENTIAL: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1301,7 +1327,7 @@ void MixStereo (int sample_count) ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 ch->xenv_count += env_counter_max; } - + if (ch->xenvx <= 0) { S9xAPUSetEndOfSample (J, ch); @@ -1309,7 +1335,7 @@ void MixStereo (int sample_count) } break; - + case SOUND_GAIN: S9xSetEnvRate (ch, 0, 0); @@ -1324,11 +1350,11 @@ void MixStereo (int sample_count) ch->nb_sample[ch->nb_index] = ch->sample; ch->nb_index = (ch->nb_index + 1) & 3; - ch->sample_pointer++; + ch->sample_pointer++; if (ch->sample_pointer == SOUND_DECODE_LENGTH) { ch->sample_pointer = 0; - + if (ch->last_block) { S9xAPUSetEndX (J); @@ -1343,7 +1369,7 @@ void MixStereo (int sample_count) ch->nb_sample[ch->nb_index] = 0; ch->nb_index = (ch->nb_index + 1) & 3; } - + break; } else @@ -1353,13 +1379,13 @@ void MixStereo (int sample_count) ch->block_pointer = READ_WORD(dir + 2); // loop pointer } } - + DecodeBlock (ch); } ch->sample = ch->block[ch->sample_pointer]; } - + int32 outx, d; if (ch->type == SOUND_SAMPLE) @@ -1386,21 +1412,21 @@ void MixStereo (int sample_count) noise_count += env_counter_max; noise_index = (noise_index + 1) & 0xFF; } - + outx = noise_cache[noise_index] >> 16; } - + outx = ((outx * ch->xenvx) >> 11) & ~1; ch->out_sample = outx; - + if (mod2) wave[I >> 1] = outx; int32 VL, VR; - + VL = (outx * ch->volume_left ) >> 7; VR = (outx * ch->volume_right) >> 7; - + MixBuffer[I ^ Settings.ReverseStereo ] += VL; MixBuffer[I + (1 ^ Settings.ReverseStereo)] += VR; ch->echo_buf_ptr[I ^ Settings.ReverseStereo ] += VL; @@ -1409,7 +1435,8 @@ void MixStereo (int sample_count) stereo_exit: ; } - + DoFakeMute=FALSE; + if (APU.DSP[APU_NON]) SoundData.noise_count = noise_count; } @@ -1420,18 +1447,20 @@ END_OF_FUNCTION(MixStereo); void MixMono (int sample_count) { + DoFakeMute=Settings.FakeMuteFix; + static int32 noise_cache[256]; static int32 wave[SOUND_BUFFER_SIZE]; int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON]; - + int32 noise_index = 0; int32 noise_count = 0; - + if (APU.DSP[APU_NON]) { noise_count = SoundData.noise_count; - + for (uint32 I = 0; I < (uint32) sample_count; I++) { noise_count -= SoundData.noise_rate; @@ -1449,9 +1478,9 @@ void MixMono (int sample_count) { Channel *ch = &SoundData.channels[J]; uint32 freq = ch->frequency; - + bool8 last_block = FALSE; - + if (ch->type == SOUND_NOISE) { noise_index = 0; @@ -1460,10 +1489,10 @@ void MixMono (int sample_count) if (ch->state == SOUND_SILENT || last_block || !(so.sound_switch & (1 << J))) continue; - + bool8 mod1 = pitch_mod & (1 << J); bool8 mod2 = pitch_mod & (1 << (J + 1)); - + if (ch->needs_decode) { DecodeBlock(ch); @@ -1471,9 +1500,9 @@ void MixMono (int sample_count) ch->sample = ch->block[0]; ch->sample_pointer = 0; } - + for (uint32 I = 0; I < (uint32) sample_count; I++) - { + { switch (ch->state) { case SOUND_ATTACK: @@ -1488,12 +1517,12 @@ void MixMono (int sample_count) ch->xenv_count += env_counter_max; } } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; - if (ch->xsustain_level != ENV_RANGE) + if (ch->xsustain_level != ENV_RANGE) { ch->state = SOUND_DECAY; S9xSetEnvRate (ch, ch->xdecay_rate, ch->xsustain_level); @@ -1504,9 +1533,9 @@ void MixMono (int sample_count) S9xSetEnvRate (ch, ch->xsustain_rate, 0); } } - + break; - + case SOUND_DECAY: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1528,9 +1557,9 @@ void MixMono (int sample_count) S9xSetEnvRate (ch, ch->xsustain_rate, 0); } } - + break; - + case SOUND_SUSTAIN: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1546,7 +1575,7 @@ void MixMono (int sample_count) } break; - + case SOUND_RELEASE: ch->xenv_count -= env_counter_max; while (ch->xenv_count <= 0) @@ -1562,7 +1591,7 @@ void MixMono (int sample_count) } break; - + case SOUND_INCREASE_LINEAR: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1570,7 +1599,7 @@ void MixMono (int sample_count) ch->xenvx += (ENV_RANGE >> 6); // 1/64 ch->xenv_count += env_counter_max; } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; @@ -1578,9 +1607,9 @@ void MixMono (int sample_count) ch->mode = MODE_GAIN; S9xSetEnvRate (ch, 0, 0); } - + break; - + case SOUND_INCREASE_BENT_LINE: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1589,10 +1618,10 @@ void MixMono (int sample_count) ch->xenvx += (ENV_RANGE >> 8); // 1/256 else ch->xenvx += (ENV_RANGE >> 6); // 1/64 - + ch->xenv_count += env_counter_max; } - + if (ch->xenvx > ENV_MAX) { ch->xenvx = ENV_MAX; @@ -1600,9 +1629,9 @@ void MixMono (int sample_count) ch->mode = MODE_GAIN; S9xSetEnvRate (ch, 0, 0); } - + break; - + case SOUND_DECREASE_LINEAR: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1610,7 +1639,7 @@ void MixMono (int sample_count) ch->xenvx -= (ENV_RANGE >> 6); // 1/64 ch->xenv_count += env_counter_max; } - + if (ch->xenvx <= 0) { S9xAPUSetEndOfSample (J, ch); @@ -1618,7 +1647,7 @@ void MixMono (int sample_count) } break; - + case SOUND_DECREASE_EXPONENTIAL: ch->xenv_count -= ch->xenv_rate; while (ch->xenv_count <= 0) @@ -1626,7 +1655,7 @@ void MixMono (int sample_count) ch->xenvx -= ((ch->xenvx - 1) >> 8) + 1; // 1 - 1/256 ch->xenv_count += env_counter_max; } - + if (ch->xenvx <= 0) { S9xAPUSetEndOfSample (J, ch); @@ -1634,7 +1663,7 @@ void MixMono (int sample_count) } break; - + case SOUND_GAIN: S9xSetEnvRate (ch, 0, 0); @@ -1649,11 +1678,11 @@ void MixMono (int sample_count) ch->nb_sample[ch->nb_index] = ch->sample; ch->nb_index = (ch->nb_index + 1) & 3; - ch->sample_pointer++; + ch->sample_pointer++; if (ch->sample_pointer == SOUND_DECODE_LENGTH) { ch->sample_pointer = 0; - + if (ch->last_block) { S9xAPUSetEndX (J); @@ -1668,7 +1697,7 @@ void MixMono (int sample_count) ch->nb_sample[ch->nb_index] = 0; ch->nb_index = (ch->nb_index + 1) & 3; } - + break; } else @@ -1678,13 +1707,13 @@ void MixMono (int sample_count) ch->block_pointer = READ_WORD(dir + 2); // loop pointer } } - + DecodeBlock (ch); } ch->sample = ch->block[ch->sample_pointer]; } - + int32 outx, d; if (ch->type == SOUND_SAMPLE) @@ -1711,27 +1740,28 @@ void MixMono (int sample_count) noise_count += env_counter_max; noise_index = (noise_index + 1) & 0xFF; } - + outx = noise_cache[noise_index] >> 16; } - + outx = ((outx * ch->xenvx) >> 11) & ~1; ch->out_sample = outx; - + if (mod2) wave[I] = outx; int32 V; - + V = (outx * ch->volume_left ) >> 7; - + MixBuffer[I] += V; ch->echo_buf_ptr[I] += V; } mono_exit: ; } - + DoFakeMute=FALSE; + if (APU.DSP[APU_NON]) SoundData.noise_count = noise_count; } @@ -1763,7 +1793,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) memset (MixBuffer, 0, sample_count * sizeof (MixBuffer[0])); if (!Settings.DisableSoundEcho) memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer[0])); - + if (so.stereo) MixStereo (sample_count); else @@ -1789,11 +1819,11 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 15] = E; E = (E * 127) >> 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -1802,10 +1832,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + E * SoundData.echo_volume[J & 1]) >> 7; CLIP16(I); @@ -1818,7 +1848,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 15] = E; E = E * FilterTaps[0]; E += Loop[(FIRIndex - 2) & 15] * FilterTaps[1]; @@ -1830,7 +1860,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) E += Loop[(FIRIndex - 14) & 15] * FilterTaps[7]; E >>= 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -1839,10 +1869,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + E * SoundData.echo_volume[J & 1]) >> 7; CLIP16(I); @@ -1859,7 +1889,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 7] = E; E = (E * 127) >> 7; FIRIndex++; @@ -1872,12 +1902,12 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[0] + - E * SoundData.echo_volume[0]) >> 7; + E * SoundData.echo_volume[0]) >> 7; CLIP16(I); ((int16 *) buffer) [J] = I; } @@ -1888,7 +1918,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 7] = E; E = E * FilterTaps[0]; E += Loop[(FIRIndex - 1) & 7] * FilterTaps[1]; @@ -1900,7 +1930,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) E += Loop[(FIRIndex - 7) & 7] * FilterTaps[7]; E >>= 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -1909,12 +1939,12 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[0] + - E * SoundData.echo_volume[0]) >> 7; + E * SoundData.echo_volume[0]) >> 7; CLIP16(I); ((int16 *) buffer) [J] = I; } @@ -1926,7 +1956,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) // 16-bit mono or stereo sound, no echo for (J = 0; J < sample_count; J++) { - I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 7; + I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 7; CLIP16(I); ((int16 *) buffer) [J] = I; } @@ -1963,11 +1993,11 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 15] = E; E = (E * 127) >> 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -1976,10 +2006,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + E * SoundData.echo_volume[J & 1]) >> 15; CLIP8(I); @@ -1992,7 +2022,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 15] = E; E = E * FilterTaps[0]; E += Loop[(FIRIndex - 2) & 15] * FilterTaps[1]; @@ -2004,7 +2034,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) E += Loop[(FIRIndex - 14) & 15] * FilterTaps[7]; E >>= 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -2013,10 +2043,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[J & 1] + E * SoundData.echo_volume[J & 1]) >> 15; CLIP8(I); @@ -2033,7 +2063,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 7] = E; E = (E * 127) >> 7; FIRIndex++; @@ -2046,10 +2076,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[0] + E * SoundData.echo_volume[0]) >> 15; CLIP8(I); @@ -2062,7 +2092,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) for (J = 0; J < sample_count; J++) { int E = Echo[SoundData.echo_ptr]; - + Loop[FIRIndex & 7] = E; E = E * FilterTaps[0]; E += Loop[(FIRIndex - 1) & 7] * FilterTaps[1]; @@ -2074,7 +2104,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count) E += Loop[(FIRIndex - 7) & 7] * FilterTaps[7]; E >>= 7; FIRIndex++; - + if (SoundData.echo_write_enabled) { I = EchoBuffer[J] + ((E * SoundData.echo_feedback) >> 7); @@ -2083,10 +2113,10 @@ void S9xMixSamples (uint8 *buffer, int sample_count) } else // FIXME: Snes9x's echo buffer is not in APU_RAM Echo[SoundData.echo_ptr] = 0; - + if (++SoundData.echo_ptr >= SoundData.echo_buffer_size) SoundData.echo_ptr = 0; - + I = (MixBuffer[J] * SoundData.master_volume[0] + E * SoundData.echo_volume[0]) >> 15; CLIP8(I); @@ -2100,14 +2130,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count) // 8-bit mono or stereo sound, no echo for (J = 0; J < sample_count; J++) { - I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 15; + I = (MixBuffer[J] * SoundData.master_volume[J & 1]) >> 15; CLIP8(I); buffer[J] = I + 128; } } } } - } #ifdef __DJGPP @@ -2134,8 +2163,20 @@ void S9xResetSound (bool8 full) SoundData.channels[i].xdecay_rate = 0; SoundData.channels[i].xsustain_rate = 0; SoundData.channels[i].xsustain_level = 0; + if(full) + { + SoundData.channels[i].out_sample = 0; + SoundData.channels[i].block_pointer = 0; + SoundData.channels[i].sample_pointer = 0; + SoundData.channels[i].sample = 0; + SoundData.channels[i].sample_number = 0; + SoundData.channels[i].last_block = 0; + for(int j = 0 ; j < 2 ; j++) SoundData.channels[i].previous[j] = 0; + for(int j = 0 ; j < 2 ; j++) SoundData.channels[i].previous16[j] = 0; + for(int j = 0 ; j < 16 ; j++) SoundData.channels[i].decoded[j] = 0; + } } - + FilterTaps [0] = 127; FilterTaps [1] = 0; FilterTaps [2] = 0; @@ -2144,7 +2185,7 @@ void S9xResetSound (bool8 full) FilterTaps [5] = 0; FilterTaps [6] = 0; FilterTaps [7] = 0; - + rand_seed = 1; so.mute_sound = TRUE; @@ -2154,7 +2195,7 @@ void S9xResetSound (bool8 full) so.samples_mixed_so_far = 0; so.play_position = 0; so.err_counter = 0; - + if (full) { SoundData.echo_volume_left = 0; @@ -2172,9 +2213,9 @@ void S9xResetSound (bool8 full) memset (Loop, 0, sizeof (Loop)); memset (Echo, 0, sizeof (Echo)); } - + // At least Super Bomberman 2 requires the defaule master volume is not zero. -#if 1 +#if 1 SoundData.master_volume_left = 127; SoundData.master_volume_right = 127; SoundData.master_volume [0] = SoundData.master_volume [1] = 127; @@ -2187,7 +2228,7 @@ void S9xResetSound (bool8 full) SoundData.echo_ptr = 0; SoundData.echo_feedback = 0; SoundData.echo_buffer_size = 1; - + if (so.playback_rate) so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME * so.playback_rate); else @@ -2198,7 +2239,7 @@ void S9xSetPlaybackRate (uint32 playback_rate) { if (playback_rate > 48000) playback_rate = 48000; - + so.playback_rate = playback_rate; so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME * so.playback_rate); @@ -2260,7 +2301,7 @@ bool8 S9xSetSoundMode (int channel, int mode) return (TRUE); } break; - + case MODE_DECREASE_LINEAR: case MODE_DECREASE_EXPONENTIAL: case MODE_GAIN: @@ -2269,11 +2310,11 @@ bool8 S9xSetSoundMode (int channel, int mode) ch->mode = mode; if (ch->state != SOUND_SILENT) ch->state = mode; - + return (TRUE); } break; - + case MODE_INCREASE_LINEAR: case MODE_INCREASE_BENT_LINE: if (ch->mode != MODE_RELEASE) @@ -2281,11 +2322,11 @@ bool8 S9xSetSoundMode (int channel, int mode) ch->mode = mode; if (ch->state != SOUND_SILENT) ch->state = mode; - + return (TRUE); } break; - + case MODE_ADSR: if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) { @@ -2311,7 +2352,7 @@ void S9xPlaySample (int channel) ch->xenvx = 0; S9xFixEnvelope (channel, - APU.DSP[APU_GAIN + (channel << 4)], + APU.DSP[APU_GAIN + (channel << 4)], APU.DSP[APU_ADSR1 + (channel << 4)], APU.DSP[APU_ADSR2 + (channel << 4)]); @@ -2366,36 +2407,36 @@ void S9xPlaySample (int channel) ch->xenvx = 0; S9xSetEnvRate (ch, ch->xattack_rate, ENV_MAX); } - + break; #endif - + case MODE_GAIN: ch->state = SOUND_GAIN; break; - + case MODE_INCREASE_LINEAR: ch->state = SOUND_INCREASE_LINEAR; break; - + case MODE_INCREASE_BENT_LINE: ch->state = SOUND_INCREASE_BENT_LINE; break; - + case MODE_DECREASE_LINEAR: ch->state = SOUND_DECREASE_LINEAR; break; - + case MODE_DECREASE_EXPONENTIAL: ch->state = SOUND_DECREASE_EXPONENTIAL; break; - + default: break; } S9xFixEnvelope (channel, - APU.DSP[APU_GAIN + (channel << 4)], + APU.DSP[APU_GAIN + (channel << 4)], APU.DSP[APU_ADSR1 + (channel << 4)], APU.DSP[APU_ADSR2 + (channel << 4)]); } diff --git a/source/snes9x/soundux.h b/source/snes9x/soundux.h index 482429f..1357061 100644 --- a/source/snes9x/soundux.h +++ b/source/snes9x/soundux.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _SOUND_H_ #define _SOUND_H_ @@ -230,7 +249,7 @@ typedef struct { int32 envx; // ** unused short left_vol_level; // ** unused short right_vol_level; // ** unused - short envx_target; // ** unused + short envx_target; // ** unused uint32 env_error; // ** unused uint32 erate; // ** unused int32 direction; // ** unused diff --git a/source/snes9x/spc700.cpp b/source/snes9x/spc700.cpp index 95db72e..abbf360 100644 --- a/source/snes9x/spc700.cpp +++ b/source/snes9x/spc700.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include "snes9x.h" #include "spc700.h" #include "memmap.h" @@ -180,24 +199,21 @@ END_EXTERN_C #ifdef SPC700_SHUTDOWN #define APUShutdown() \ - if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ - { \ +if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ +{ \ if (IAPU.WaitCounter == 0) \ { \ - if (!ICPU.CPUExecuting) \ - { \ - APU.Cycles = CPU.Cycles = CPU.NextEvent; \ - S9xUpdateAPUTimer(); \ - } \ - else \ - IAPU.APUExecuting = FALSE; \ + if (!ICPU.CPUExecuting) \ + S9xAPUExecute(); \ + else \ + IAPU.APUExecuting = FALSE; \ } \ else \ if (IAPU.WaitCounter >= 2) \ - IAPU.WaitCounter = 1; \ + IAPU.WaitCounter = 1; \ else \ - IAPU.WaitCounter--; \ - } + IAPU.WaitCounter--; \ +} #else #define APUShutdown() #endif @@ -225,6 +241,7 @@ void STOP (char *s) WARN(s); APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; IAPU.APUExecuting = FALSE; + Settings.APUEnabled = FALSE; // re-enabled on next APU reset #ifdef DEBUGGER CPU.Flags |= DEBUG_MODE_FLAG; #else @@ -302,7 +319,7 @@ APUSetZN8 ((uint8) Int16); #define PushW(w)\ if(APURegisters.S==0){ \ *(IAPU.RAM + 0x1ff) = (w);\ - *(IAPU.RAM + 0x100) = (w >> 8);\ + *(IAPU.RAM + 0x100) = ((w) >> 8);\ } else { \ *(uint16 *) (IAPU.RAM + 0xff + APURegisters.S) = (w);\ } \ @@ -316,7 +333,7 @@ APUSetZN8 ((uint8) Int16); } #else #define PushW(w)\ - *(IAPU.RAM + 0x100 + APURegisters.S--) = (w >> 8);\ + *(IAPU.RAM + 0x100 + APURegisters.S--) = ((w) >> 8);\ *(IAPU.RAM + 0x100 + APURegisters.S--) = (w); #define PopW(w)\ APURegisters.S += 2;\ @@ -930,7 +947,7 @@ void Apu0E () Absolute (); Work8 = S9xAPUGetByte (IAPU.Address); S9xAPUSetByte (Work8 | APURegisters.YA.B.A, IAPU.Address); - Work8 &= APURegisters.YA.B.A; + Work8 = APURegisters.YA.B.A - Work8; APUSetZN8 (Work8); IAPU.PC += 3; } @@ -941,7 +958,7 @@ void Apu4E () Absolute (); Work8 = S9xAPUGetByte (IAPU.Address); S9xAPUSetByte (Work8 & ~APURegisters.YA.B.A, IAPU.Address); - Work8 &= APURegisters.YA.B.A; + Work8 = APURegisters.YA.B.A - Work8; APUSetZN8 (Work8); IAPU.PC += 3; } @@ -978,6 +995,7 @@ void ApuFF () APU.Flags |= HALTED_FLAG; APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; IAPU.APUExecuting = FALSE; + Settings.APUEnabled = FALSE; // re-enabled on next APU reset } void Apu10 () @@ -1543,7 +1561,7 @@ void Apu2E () // CBNE dp,rel Work8 = OP1; Relative2 (); - + if (S9xAPUGetByteZ (Work8) != APURegisters.YA.B.A) { IAPU.PC = IAPU.RAM + (uint16) Int16; diff --git a/source/snes9x/spc700.h b/source/snes9x/spc700.h index 2bdbe63..fb29bb7 100644 --- a/source/snes9x/spc700.h +++ b/source/snes9x/spc700.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,16 +158,11 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _SPC700_H_ #define _SPC700_H_ -#ifdef SPCTOOL -#define NO_CHANNEL_STRUCT -#include "spctool/dsp.h" -#include "spctool/spc700.h" -#include "spctool/soundmod.h" -#endif - #define Carry 1 #define Zero 2 #define Interrupt 4 @@ -206,54 +218,20 @@ struct SAPURegisters{ EXTERN_C struct SAPURegisters APURegisters; -// Needed by ILLUSION OF GAIA -//#define ONE_APU_CYCLE 14 -#define ONE_APU_CYCLE 21 - -// Needed by all games written by the software company called Human -//#define ONE_APU_CYCLE_HUMAN 17 -#define ONE_APU_CYCLE_HUMAN 21 - -// 1.953us := 1.024065.54MHz - -#ifdef SPCTOOL -EXTERN_C int32 ESPC (int32); - -#define APU_EXECUTE() \ -{ \ - int32 l = (CPU.Cycles - APU.Cycles) / 14; \ - if (l > 0) \ - { \ - l -= _EmuSPC(l); \ - APU.Cycles += l * 14; \ - } \ -} - -#else - #ifdef DEBUGGER #define APU_EXECUTE1() \ { \ - if (APU.Flags & TRACE_FLAG) \ - S9xTraceAPU ();\ - APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ - (*S9xApuOpcodes[*IAPU.PC]) (); \ + if (APU.Flags & TRACE_FLAG) \ + S9xTraceAPU (); \ + APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ + (*S9xApuOpcodes[*IAPU.PC]) (); \ } #else #define APU_EXECUTE1() \ { \ - APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ - (*S9xApuOpcodes[*IAPU.PC]) (); \ -} -#endif - -#define APU_EXECUTE() \ -if (IAPU.APUExecuting) \ -{\ - while (APU.Cycles <= CPU.Cycles) \ - APU_EXECUTE1(); \ + APU.Cycles += S9xAPUCycles [*IAPU.PC]; \ + (*S9xApuOpcodes[*IAPU.PC]) (); \ } #endif #endif - diff --git a/source/snes9x/spc7110.cpp b/source/snes9x/spc7110.cpp index 45e72cf..36b4747 100644 --- a/source/snes9x/spc7110.cpp +++ b/source/snes9x/spc7110.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + //#define SPC7110_DEBUG #include "spc7110.h" @@ -152,11 +171,12 @@ //Windows includes #ifdef __WIN32__ #ifndef _XBOX // chdir and getcwd not supported on Xbox hardware +#include "win32/wsnes9x.h" // FIXME: shouldn't be necessary #include #define chdir _chdir #define getcwd _getcwd #endif -#define FREEZEFOLDER GUI.FreezeFileDir +#undef PATH_MAX //zinx suggested this, for *nix compatibility #define PATH_MAX MAX_PATH #else // Unix @@ -164,8 +184,6 @@ #include #ifdef __MACOSX__ const char * S9xGetSPC7110Directory(void); -#else -#define FREEZEFOLDER S9xGetDirectory (PATCH_DIR) #endif #endif #include "display.h" @@ -173,7 +191,6 @@ const char * S9xGetSPC7110Directory(void); #ifndef NGC extern "C" char *osd_GetPackDir(); #endif - //really not needed, but usually MS adds the _ to POSIX functions, //while *nix doesn't, so this was to "un-M$" the function. #define splitpath _splitpath @@ -189,6 +206,8 @@ void (*CleanUp7110)(void)=NULL; void (*LoadUp7110)(char*)=&SPC7110Load; void (*Copy7110)(void)=NULL; +static void SetSPC7110SRAMMap (uint8); + //size and offset of the pack data //offset and size of reads from pack typedef struct SPC7110DecompressionLocationStruct @@ -279,9 +298,9 @@ void S9xSpc7110Init() s7r.offset_add=0; s7r.AlignBy=1; -#ifndef NGC + #ifndef NGC (*LoadUp7110)(osd_GetPackDir()); -#endif + #endif if(Settings.SPC7110RTC) Settings.TurboMode=false; @@ -301,26 +320,26 @@ void MovePackData() log->used_len=s7r.bank50Internal; log->used_offset=decompack->last_offset; } - + //set up for next logging decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); - + decompack->last_idx=s7r.reg4804; //start decompression int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; - + //the table is a offset multiplier byte and a big-endian pointer int j= 4*s7r.reg4804; j+=s7r.DataRomOffset; j+=table; - + //set proper offsetting. if(s7r.reg480B==0) s7r.AlignBy=0; else { - switch(ROM[j]) + switch(Memory.ROM[j]) { case 0x03: s7r.AlignBy=8; @@ -385,7 +404,7 @@ void ReadPackData() static int table_age_3; static int table_age_4; static int table_age_5; - + int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; if(table==0) @@ -402,20 +421,20 @@ void ReadPackData() log->used_len=s7r.bank50Internal; log->used_offset=decompack->last_offset; } - + decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); - + decompack->last_idx=s7r.reg4804; - + int j= 4*s7r.reg4804; j+=s7r.DataRomOffset; j+=table; - + if(s7r.reg480B==0) s7r.AlignBy=0; else { - switch(ROM[j]) + switch(Memory.ROM[j]) { case 0x03: s7r.AlignBy=8; @@ -461,10 +480,10 @@ void ReadPackData() table_age_4=table_age_3; table_age_3=table_age_2; table_age_2=decompack->idx; - + #ifdef __MACOSX__ char name[PATH_MAX + 1], bfname[11]; - strcpy(name, S9xGetSPC7110Directory()); + strcpy(name, S9xGetSPC7110Directory()); sprintf(bfname, "%06X.bin", table); strcat(name, bfname); #else @@ -474,10 +493,11 @@ void ReadPackData() char dir [_MAX_DIR + 1]; char fname [_MAX_FNAME + 1]; char ext [_MAX_EXT + 1]; - if (strlen (FREEZEFOLDER)) + const char* patchDir = S9xGetDirectory (PATCH_DIR); + if (patchDir && strlen (patchDir)) { //splitpath (Memory.ROMFilename, drive, dir, fname, ext); - strcpy (name, FREEZEFOLDER); + strcpy (name, patchDir); strcat (name, "/"); } else @@ -543,21 +563,21 @@ void GetPackData() log->used_len=s7r.bank50Internal; log->used_offset=decompack->last_offset; } - + decompack->last_offset=(s7r.reg4805)|(s7r.reg4806<<8); - + decompack->last_idx=s7r.reg4804; int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; - + int j= 4*s7r.reg4804; j+=s7r.DataRomOffset; j+=table; - + if(s7r.reg480B==0) s7r.AlignBy=0; else { - switch(ROM[j]) + switch(Memory.ROM[j]) { case 0x03: s7r.AlignBy=8; @@ -641,7 +661,7 @@ uint8 S9xGetSPC7110(uint16 Address) i+=s7r.bank50Internal; i%=DECOMP_BUFFER_SIZE; s7r.reg4800=s7r.bank50[i]; - + s7r.bank50Internal++; s7r.bank50Internal%=DECOMP_BUFFER_SIZE; #ifdef SPC7110_DEBUG @@ -678,10 +698,10 @@ uint8 S9xGetSPC7110(uint16 Address) case 0x480B: return s7r.reg480B; //decompression finished: just emulated by switching each read. - case 0x480C: + case 0x480C: s7r.reg480C^=0x80; return s7r.reg480C^0x80; - + //Data access port //reads from the data ROM (anywhere over the first 8 mbits //behavior is complex, will document later, @@ -714,13 +734,13 @@ uint8 S9xGetSPC7110(uint16 Address) else r4814=0; s7r.reg4815=(uint8)(r4814>>8); s7r.reg4814=(uint8)(r4814&0x00FF); - + } } i+=s7r.DataRomOffset; - uint8 tmp=ROM[i]; + uint8 tmp=Memory.ROM[i]; i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; - + if(s7r.reg4818&0x02) { } @@ -730,7 +750,7 @@ uint8 S9xGetSPC7110(uint16 Address) { signed short inc; inc=(s7r.reg4817<<8)|s7r.reg4816; - + if(!(s7r.reg4818&0x10)) i+=inc; else @@ -750,7 +770,7 @@ uint8 S9xGetSPC7110(uint16 Address) r4814+=inc; s7r.reg4815=(r4814&0xFF00)>>8; s7r.reg4814=r4814&0xFF; - + } } //is signed @@ -778,7 +798,7 @@ uint8 S9xGetSPC7110(uint16 Address) r4814+=inc; s7r.reg4815=(r4814&0xFF00)>>8; s7r.reg4814=r4814&0xFF; - + } } } @@ -804,15 +824,15 @@ uint8 S9xGetSPC7110(uint16 Address) r4814+=1; s7r.reg4815=(r4814&0xFF00)>>8; s7r.reg4814=r4814&0xFF; - + } } } - + #ifdef SPC7110_DEBUG printf("Returned %02X\n", tmp); #endif - + i%=s7r.DataRomSize; s7r.reg4811=i&0x00FF; s7r.reg4812=(i&0x00FF00)>>8; @@ -857,15 +877,15 @@ uint8 S9xGetSPC7110(uint16 Address) adj=(s7r.reg4815<<8)|s7r.reg4814; i+=adj; } - + i%=s7r.DataRomSize; i+=s7r.DataRomOffset; - uint8 tmp=ROM[i]; + uint8 tmp=Memory.ROM[i]; i=((s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811); if(0x60==(s7r.reg4818&0x60)) { i=((s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811); - + if(!(s7r.reg4818&0x10)) { if(s7r.reg4818&0x08) @@ -911,7 +931,7 @@ uint8 S9xGetSPC7110(uint16 Address) return tmp; } else return 0; - + //multiplicand low or dividend lowest case 0x4820: return s7r.reg4820; //multiplicand high or divdend lower @@ -928,7 +948,7 @@ uint8 S9xGetSPC7110(uint16 Address) case 0x4826: return s7r.reg4826; //divisor high case 0x4827: return s7r.reg4827; - + //result lowest case 0x4828: return s7r.reg4828; @@ -1070,16 +1090,16 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) { s7r.reg480B=data; int table=(s7r.reg4803<<16)|(s7r.reg4802<<8)|s7r.reg4801; - + int j= 4*s7r.reg4804; j+=s7r.DataRomOffset; j+=table; - + if(s7r.reg480B==0) s7r.AlignBy=0; else { - switch(ROM[j]) + switch(Memory.ROM[j]) { case 0x03: s7r.AlignBy=8; @@ -1179,13 +1199,13 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) s7r.reg4813=((i&0xFF0000)>>16); } } - + } } - + s7r.written|=0x08; break; - + //data port adjust high (has a funky immediate increment mode) case 0x4815: s7r.reg4815=data; @@ -1202,7 +1222,7 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) else { uint32 i=(s7r.reg4813<<16)|(s7r.reg4812<<8)|s7r.reg4811; - + if(s7r.reg4818&0x08) { i+=(signed char)s7r.reg4814; @@ -1297,7 +1317,7 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) int mul; short m1=(short)((s7r.reg4824)|(s7r.reg4825<<8)); short m2=(short)((s7r.reg4820)|(s7r.reg4821<<8)); - + mul=m1*m2; s7r.reg4828=(uint8)(mul&0x000000FF); s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); @@ -1309,7 +1329,7 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) uint32 mul; uint16 m1=(uint16)((s7r.reg4824)|(s7r.reg4825<<8)); uint16 m2=(uint16)((s7r.reg4820)|(s7r.reg4821<<8)); - + mul=m1*m2; s7r.reg4828=(uint8)(mul&0x000000FF); s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); @@ -1386,7 +1406,7 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) //SRAM toggle case 0x4830: - Memory.SPC7110Sram(data); + SetSPC7110SRAMMap(data); s7r.reg4830=data; break; //Bank DX mapping @@ -1439,7 +1459,7 @@ void S9xSetSPC7110 (uint8 data, uint16 Address) } else { - + if(0x0D==rtc_f9.index) { if(data&0x08) @@ -1530,7 +1550,7 @@ uint8 S9xGetSPC7110Byte(uint32 Address) } i+=Address&0x000FFFFF; i+=s7r.DataRomOffset; - return ROM[i]; + return Memory.ROM[i]; } } /**********************************************************************************************/ @@ -1541,7 +1561,7 @@ uint8 S9xGetSPC7110Byte(uint32 Address) int S9xRTCDaysInMonth( int month, int year ) { int mdays; - + switch ( month ) { case 2: @@ -1550,19 +1570,19 @@ int S9xRTCDaysInMonth( int month, int year ) else mdays = 28; break; - + case 4: case 6: case 9: case 11: mdays = 30; break; - + default: // months 1,3,5,7,8,10,12 mdays = 31; break; } - + return mdays; } @@ -1581,22 +1601,22 @@ void S9xUpdateRTC () { time_t cur_systime; long time_diff; - + // Keep track of game time by computing the number of seconds that pass on the system // clock and adding the same number of seconds to the RTC clock structure. - + if (rtc_f9.init && 0==(rtc_f9.reg[0x0D]&0x01) && 0==(rtc_f9.reg[0x0F]&0x03)) { cur_systime = time (NULL); - + // This method assumes one time_t clock tick is one second // which should work on PCs and GNU systems. // If your tick interval is different adjust the // DAYTICK, HOURTICK, and MINUTETICK defines - + time_diff = (long) (cur_systime - rtc_f9.last_used); rtc_f9.last_used = cur_systime; - + if ( time_diff > 0 ) { int seconds; @@ -1606,12 +1626,12 @@ void S9xUpdateRTC () int month; int year; int temp_days; - + int year_hundreds; int year_tens; int year_ones; - - + + if ( time_diff > DAYTICKS ) { days = time_diff / DAYTICKS; @@ -1621,7 +1641,7 @@ void S9xUpdateRTC () { days = 0; } - + if ( time_diff > HOURTICKS ) { hours = time_diff / HOURTICKS; @@ -1631,7 +1651,7 @@ void S9xUpdateRTC () { hours = 0; } - + if ( time_diff > MINUTETICKS ) { minutes = time_diff / MINUTETICKS; @@ -1641,7 +1661,7 @@ void S9xUpdateRTC () { minutes = 0; } - + if ( time_diff > 0 ) { seconds = time_diff; @@ -1650,29 +1670,29 @@ void S9xUpdateRTC () { seconds = 0; } - - + + seconds += (rtc_f9.reg[1]*10 + rtc_f9.reg[0]); if ( seconds >= 60 ) { seconds -= 60; minutes += 1; } - + minutes += (rtc_f9.reg[3]*10 + rtc_f9.reg[2]); if ( minutes >= 60 ) { minutes -= 60; hours += 1; } - + hours += (rtc_f9.reg[5]*10 + rtc_f9.reg[4]); if ( hours >= 24 ) { hours -= 24; days += 1; } - + year = rtc_f9.reg[11]*10 + rtc_f9.reg[10]; year += ( 1900 ); month = rtc_f9.reg[8]+10*rtc_f9.reg[9]; @@ -1696,7 +1716,7 @@ void S9xUpdateRTC () year_ones = year_tens % 10; year_tens /= 10; year_hundreds = (year - 1000) / 100; - + rtc_f9.reg[0] = seconds % 10; rtc_f9.reg[1] = seconds / 10; rtc_f9.reg[2] = minutes % 10; @@ -1734,7 +1754,7 @@ uint8* Get7110BasePtr(uint32 Address) default:i=0; } i+=Address&0x000F0000; - return &ROM[i]; + return &Memory.ROM[i]; } //end extern } @@ -1773,7 +1793,7 @@ bool Load7110Index(char* filename) decompack->tableEnts[i].location[index].size=size; decompack->tableEnts[i].location[index].used_len=0; decompack->tableEnts[i].location[index].used_offset=0; - + } while(!feof(fp)); fclose(fp); @@ -1784,7 +1804,6 @@ bool Load7110Index(char* filename) //Cache 1 load function void SPC7110Load(char* dirname) { -#ifndef NGC char temp_path[PATH_MAX]; int i=0; @@ -1795,15 +1814,13 @@ void SPC7110Load(char* dirname) #endif ZeroMemory(decompack, sizeof(Pack7110)); - -#ifndef _XBOX -#ifndef NGC + +#ifndef _XBOX if(-1==chdir(dirname)) { S9xMessage(0,0,"Graphics Pack not found!"); } #endif -#endif #ifndef _XBOX Load7110Index("index.bin"); @@ -1823,11 +1840,8 @@ void SPC7110Load(char* dirname) sprintf(binname,"%s%06X.bin",filename,decompack->tableEnts[i].table); #endif struct stat buf; - -#ifndef NGC if(-1!=stat(binname, &buf)) decompack->binfiles[i]=new uint8[buf.st_size]; -#endif FILE* fp=fopen(binname, "rb"); if(fp) { @@ -1837,10 +1851,8 @@ void SPC7110Load(char* dirname) } } -#ifndef _XBOX -#ifndef NGC +#ifndef _XBOX chdir(temp_path); -#endif #endif Copy7110=&MovePackData; @@ -1865,7 +1877,7 @@ void SPC7110Open(char* dirname) #endif ZeroMemory(decompack, sizeof(Pack7110)); - + #ifndef _XBOX if(-1==chdir(dirname)) { @@ -1915,7 +1927,7 @@ void SPC7110Grab(char* dirname) ZeroMemory(decompack, sizeof(Pack7110)); #ifndef _XBOX - + if(-1==chdir(dirname)) { S9xMessage(0,0,"Graphics Pack not found!"); @@ -1941,8 +1953,6 @@ void SPC7110Grab(char* dirname) #endif struct stat buf; //add load/no load calculations here - -#ifndef NGC if(-1!=stat(binname, &buf)) { if(buf.st_sizetableEnts[j].location[k].used_len&0xFF; - fwrite(&ent_temp,1,1,flog);//lsb of + fwrite(&ent_temp,1,1,flog);//lsb of ent_temp=(decompack->tableEnts[j].location[k].used_len>>8)&0xFF; fwrite(&ent_temp,1,1,flog);//msb of ent_temp=(decompack->tableEnts[j].location[k].used_offset)&0xFF; @@ -2349,6 +2354,25 @@ void Do7110Logging() } } } + +static void SetSPC7110SRAMMap (uint8 newstate) +{ + if (newstate & 0x80) + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_HIROM_SRAM; + } + else + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_RONLY_SRAM; + } +} + bool8 S9xSaveSPC7110RTC (S7RTC *rtc_f9) { FILE* fp; @@ -2396,7 +2420,7 @@ bool8 S9xLoadSPC7110RTC (S7RTC *rtc_f9) rtc_f9->index|=(temp<<8); fread(&rtc_f9->control,1,1,fp); fread(&rtc_f9->init,1,1,fp); - + fread(&temp,1,1,fp); rtc_f9->last_used=temp; fread(&temp,1,1,fp); diff --git a/source/snes9x/spc7110.h b/source/snes9x/spc7110.h index 2db39d4..7d12b78 100644 --- a/source/snes9x/spc7110.h +++ b/source/snes9x/spc7110.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _spc7110_h #define _spc7110_h #include "port.h" diff --git a/source/snes9x/srtc.cpp b/source/snes9x/srtc.cpp index 319de1c..9dd76e4 100644 --- a/source/snes9x/srtc.cpp +++ b/source/snes9x/srtc.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #include "snes9x.h" #include "srtc.h" @@ -191,7 +210,7 @@ static int month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 }; * * restore the rtc data structure * rtc.system_timestamp = time (NULL); - * + * * *********************************************************************************************/ @@ -309,7 +328,7 @@ void S9xUpdateSrtcTime () time_diff = (long) (cur_systime - rtc.system_timestamp); rtc.system_timestamp = cur_systime; - + if ( time_diff > 0 ) { int seconds; @@ -578,25 +597,23 @@ void S9xSRTCPreSaveState () if (s > 0x20000) s = 0x20000; - SRAM [s + 0] = rtc.needs_init; - SRAM [s + 1] = rtc.count_enable; - memmove (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); - SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; - SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; + Memory.SRAM [s + 0] = rtc.needs_init; + Memory.SRAM [s + 1] = rtc.count_enable; + memmove (&Memory.SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); + Memory.SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; + Memory.SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; #ifdef LSB_FIRST - memmove (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); + memmove (&Memory.SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); #else -#ifndef NGC - SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); - SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); - SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); - SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); - SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); - SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); - SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); - SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); -#endif + Memory.SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); + Memory.SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); + Memory.SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); + Memory.SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); + Memory.SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); + Memory.SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); + Memory.SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); + Memory.SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); #endif } } @@ -610,25 +627,23 @@ void S9xSRTCPostLoadState () if (s > 0x20000) s = 0x20000; - rtc.needs_init = SRAM [s + 0]; - rtc.count_enable = SRAM [s + 1]; - memmove (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); - rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; - rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; + rtc.needs_init = Memory.SRAM [s + 0]; + rtc.count_enable = Memory.SRAM [s + 1]; + memmove (rtc.data, &Memory.SRAM [s + 2], MAX_RTC_INDEX + 1); + rtc.index = Memory.SRAM [s + 3 + MAX_RTC_INDEX]; + rtc.mode = Memory.SRAM [s + 4 + MAX_RTC_INDEX]; #ifdef LSB_FIRST - memmove (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); + memmove (&rtc.system_timestamp, &Memory.SRAM [s + 5 + MAX_RTC_INDEX], 8); #else -#ifndef NGC - rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); - rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); - rtc.system_timestamp |= (SRAM [s + 7 + MAX_RTC_INDEX] << 16); - rtc.system_timestamp |= (SRAM [s + 8 + MAX_RTC_INDEX] << 24); - rtc.system_timestamp |= (SRAM [s + 9 + MAX_RTC_INDEX] << 32); - rtc.system_timestamp |= (SRAM [s + 10 + MAX_RTC_INDEX] << 40); - rtc.system_timestamp |= (SRAM [s + 11 + MAX_RTC_INDEX] << 48); - rtc.system_timestamp |= (SRAM [s + 12 + MAX_RTC_INDEX] << 56); -#endif + rtc.system_timestamp |= (Memory.SRAM [s + 5 + MAX_RTC_INDEX] << 0); + rtc.system_timestamp |= (Memory.SRAM [s + 6 + MAX_RTC_INDEX] << 8); + rtc.system_timestamp |= (Memory.SRAM [s + 7 + MAX_RTC_INDEX] << 16); + rtc.system_timestamp |= (Memory.SRAM [s + 8 + MAX_RTC_INDEX] << 24); + rtc.system_timestamp |= (Memory.SRAM [s + 9 + MAX_RTC_INDEX] << 32); + rtc.system_timestamp |= (Memory.SRAM [s + 10 + MAX_RTC_INDEX] << 40); + rtc.system_timestamp |= (Memory.SRAM [s + 11 + MAX_RTC_INDEX] << 48); + rtc.system_timestamp |= (Memory.SRAM [s + 12 + MAX_RTC_INDEX] << 56); #endif S9xUpdateSrtcTime (); } diff --git a/source/snes9x/srtc.h b/source/snes9x/srtc.h index f626779..895e233 100644 --- a/source/snes9x/srtc.h +++ b/source/snes9x/srtc.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _srtc_h_ #define _srtc_h_ diff --git a/source/snes9x/tile.cpp b/source/snes9x/tile.cpp index b91e1d6..71f3c21 100644 --- a/source/snes9x/tile.cpp +++ b/source/snes9x/tile.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + // This file includes itself multiple times. The other option would be to have // 4 files, where A includes B, and B includes C 3 times, and C includes D 5 // times. Look for the following marker to find where the divisions are. diff --git a/source/snes9x/tile.h b/source/snes9x/tile.h index 0f35141..8b6d20c 100644 --- a/source/snes9x/tile.h +++ b/source/snes9x/tile.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _TILE_H_ #define _TILE_H_ diff --git a/source/snes9x/unused/2xsai.cpp b/source/snes9x/unused/2xsai.cpp new file mode 100644 index 0000000..e966605 --- /dev/null +++ b/source/snes9x/unused/2xsai.cpp @@ -0,0 +1,1305 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#ifdef __DJGPP +#include +#endif + +#include "snes9x.h" +#include "port.h" +#include "gfx.h" + +#if (defined(USE_X86_ASM) && (defined (__i386__) || defined (__i486__) || \ + defined (__i586__) || defined (__WIN32__) || defined (__DJGPP))) +# ifndef MMX +# define MMX +# endif +#endif + +extern "C" +{ + +#ifdef MMX + void _2xSaILine (uint8 *srcPtr, uint8 *deltaPtr, uint32 srcPitch, + uint32 width, uint8 *dstPtr, uint32 dstPitch); + void _2xSaISuperEagleLine (uint8 *srcPtr, uint8 *deltaPtr, + uint32 srcPitch, uint32 width, + uint8 *dstPtr, uint32 dstPitch); + void _2xSaISuper2xSaILine (uint8 *srcPtr, uint8 *deltaPtr, + uint32 srcPitch, uint32 width, + uint8 *dstPtr, uint32 dstPitch); + void Init_2xSaIMMX (uint32 BitFormat); + void BilinearMMX (uint16 * A, uint16 * B, uint16 * C, uint16 * D, + uint16 * dx, uint16 * dy, uint8 *dP); + void BilinearMMXGrid0 (uint16 * A, uint16 * B, uint16 * C, uint16 * D, + uint16 * dx, uint16 * dy, uint8 *dP); + void BilinearMMXGrid1 (uint16 * A, uint16 * B, uint16 * C, uint16 * D, + uint16 * dx, uint16 * dy, uint8 *dP); + void EndMMX (); + +#endif +} + +bool8 cpu_mmx = 1; + +static uint32 colorMask = 0xF7DEF7DE; +static uint32 lowPixelMask = 0x08210821; +static uint32 qcolorMask = 0xE79CE79C; +static uint32 qlowpixelMask = 0x18631863; +static uint32 redblueMask = 0xF81F; +static uint32 greenMask = 0x7E0; + +int Init_2xSaI (uint32 BitFormat) +{ + if (BitFormat == 565) + { + colorMask = 0xF7DEF7DE; + lowPixelMask = 0x08210821; + qcolorMask = 0xE79CE79C; + qlowpixelMask = 0x18631863; + redblueMask = 0xF81F; + greenMask = 0x7E0; + } + else if (BitFormat == 555) + { + colorMask = 0x7BDE7BDE; + lowPixelMask = 0x04210421; + qcolorMask = 0x739C739C; + qlowpixelMask = 0x0C630C63; + redblueMask = 0x7C1F; + greenMask = 0x3E0; + } + else + { + return 0; + } + +#ifdef MMX + Init_2xSaIMMX (BitFormat); +#endif + + return 1; +} + +static inline int GetResult1 (uint32 A, uint32 B, uint32 C, uint32 D, + uint32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline int GetResult2 (uint32 A, uint32 B, uint32 C, uint32 D, + uint32 /* E */) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r -= 1; + if (y <= 1) + r += 1; + return r; +} + +static inline int GetResult (uint32 A, uint32 B, uint32 C, uint32 D) +{ + int x = 0; + int y = 0; + int r = 0; + + if (A == C) + x += 1; + else if (B == C) + y += 1; + if (A == D) + x += 1; + else if (B == D) + y += 1; + if (x <= 1) + r += 1; + if (y <= 1) + r -= 1; + return r; +} + +static inline uint32 INTERPOLATE (uint32 A, uint32 B) +{ + if (A != B) + { + return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + + (A & B & lowPixelMask)); + } + else + return A; +} + +static inline uint32 Q_INTERPOLATE (uint32 A, uint32 B, uint32 C, uint32 D) +{ + register uint32 x = ((A & qcolorMask) >> 2) + + ((B & qcolorMask) >> 2) + + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); + register uint32 y = (A & qlowpixelMask) + + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); + + y = (y >> 2) & qlowpixelMask; + return x + y; +} + +#define BLUE_MASK565 0x001F001F +#define RED_MASK565 0xF800F800 +#define GREEN_MASK565 0x07E007E0 + +#define BLUE_MASK555 0x001F001F +#define RED_MASK555 0x7C007C00 +#define GREEN_MASK555 0x03E003E0 + +void Super2xSaI (uint8 *srcPtr, uint32 srcPitch, + uint8 *deltaPtr, uint8 *dstPtr, uint32 dstPitch, + int width, int height) +{ + uint16 *bP; + uint8 *dP; + uint32 inc_bP; + +#ifdef MMX + if (cpu_mmx) + { + while (height--) + { + _2xSaISuper2xSaILine (srcPtr, deltaPtr, srcPitch, width, + dstPtr, dstPitch); + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } + } + else +#endif + + { + uint32 Nextline = srcPitch >> 1; + inc_bP = 1; + + while (height--) + { + bP = (uint16 *) srcPtr; + dP = (uint8 *) dstPtr; + + for (uint32 finish = width; finish; finish -= inc_bP) + { + uint32 color4, color5, color6; + uint32 color1, color2, color3; + uint32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + uint32 product1a, product1b, product2a, product2b; + +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + + colorB0 = *(bP - Nextline - 1); + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + colorB3 = *(bP - Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE (color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 + && color2 != colorA2 && color3 != colorA0) + product2b = + Q_INTERPOLATE (color3, color3, color3, color2); + else if (color5 == color2 && color2 == colorA2 + && colorA1 != color3 && color2 != colorA3) + product2b = + Q_INTERPOLATE (color2, color2, color2, color3); + else + product2b = INTERPOLATE (color2, color3); + + if (color6 == color3 && color6 == colorB1 + && color5 != colorB2 && color6 != colorB0) + product1b = + Q_INTERPOLATE (color6, color6, color6, color5); + else if (color5 == color2 && color5 == colorB2 + && colorB1 != color6 && color5 != colorB3) + product1b = + Q_INTERPOLATE (color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 + && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 + && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE (color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 + && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 + && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE (color2, color5); + else + product1a = color5; + +#ifdef MSB_FIRST + product1a = product1b | (product1a << 16); + product2a = product2b | (product2a << 16); +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((uint32 *) dP) = product1a; + *((uint32 *) (dP + dstPitch)) = product2a; + + bP += inc_bP; + dP += sizeof (uint32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } // while (height--) + } +} + +void SuperEagle (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint8 *dP; + uint16 *bP; + uint16 *xP; + uint32 inc_bP; + +#ifdef MMX + if (cpu_mmx) + { + while (height--) + { + _2xSaISuperEagleLine (srcPtr, deltaPtr, srcPitch, width, + dstPtr, dstPitch); + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } + } + else +#endif + + { + inc_bP = 1; + + uint32 Nextline = srcPitch >> 1; + + while (height--) + { + bP = (uint16 *) srcPtr; + xP = (uint16 *) deltaPtr; + dP = dstPtr; + for (uint32 finish = width; finish; finish -= inc_bP) + { + uint32 color4, color5, color6; + uint32 color1, color2, color3; + uint32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; + uint32 product1a, product1b, product2a, product2b; + + colorB1 = *(bP - Nextline); + colorB2 = *(bP - Nextline + 1); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + + // -------------------------------------- + if (color2 == color6 && color5 != color3) + { + product1b = product2a = color2; + if ((color1 == color2) || (color6 == colorB2)) + { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); +// product1a = color2; + } + else + { + product1a = INTERPOLATE (color5, color6); + } + + if ((color6 == colorS2) || (color2 == colorA1)) + { + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); +// product2b = color2; + } + else + { + product2b = INTERPOLATE (color2, color3); + } + } + else if (color5 == color3 && color2 != color6) + { + product2b = product1a = color5; + + if ((colorB1 == color5) || (color3 == colorS1)) + { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); +// product1b = color5; + } + else + { + product1b = INTERPOLATE (color5, color6); + } + + if ((color3 == colorA2) || (color4 == color5)) + { + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); +// product2a = color5; + } + else + { + product2a = INTERPOLATE (color2, color3); + } + + } + else if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } + else if (r < 0) + { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } + else + { + product2b = product1a = color5; + product1b = product2a = color2; + } + } + else + { + product2b = product1a = INTERPOLATE (color2, color6); + product2b = + Q_INTERPOLATE (color3, color3, color3, product2b); + product1a = + Q_INTERPOLATE (color5, color5, color5, product1a); + + product2a = product1b = INTERPOLATE (color5, color3); + product2a = + Q_INTERPOLATE (color2, color2, color2, product2a); + product1b = + Q_INTERPOLATE (color6, color6, color6, product1b); + +// product1a = color5; +// product1b = color6; +// product2a = color2; +// product2b = color3; + } +#ifdef MSB_FIRST + product1a = product1b | (product1a << 16); + product2a = product2b | (product2a << 16); +#else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); +#endif + + *((uint32 *) dP) = product1a; + *((uint32 *) (dP + dstPitch)) = product2a; + *xP = color5; + + bP += inc_bP; + xP += inc_bP; + dP += sizeof (uint32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } // endof: while (height--) + } +} + +void _2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint8 *dP; + uint16 *bP; + uint32 inc_bP; + +#ifdef MMX + if (cpu_mmx) + { + while (height--) + { + _2xSaILine (srcPtr, deltaPtr, srcPitch, width, dstPtr, dstPitch); + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } + } + else +#endif + + { + inc_bP = 1; + + uint32 Nextline = srcPitch >> 1; + + while (height--) + { + bP = (uint16 *) srcPtr; + dP = dstPtr; + + for (uint32 finish = width; finish; finish -= inc_bP) + { + + register uint32 colorA, colorB; + uint32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + + colorM, colorN, colorO, colorP; + uint32 product, product1, product2; + +//--------------------------------------- +// Map of the pixels: I|E F|J +// G|A B|K +// H|C D|L +// M|N O|P + colorI = *(bP - Nextline - 1); + colorE = *(bP - Nextline); + colorF = *(bP - Nextline + 1); + colorJ = *(bP - Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) + { + if (((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ))) + { + product = colorA; + } + else + { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM))) + { + product1 = colorA; + } + else + { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorA; + } + else if ((colorB == colorC) && (colorA != colorD)) + { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI))) + { + product = colorB; + } + else + { + product = INTERPOLATE (colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI))) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE (colorA, colorC); + } + product2 = colorB; + } + else if ((colorA == colorD) && (colorB == colorC)) + { + if (colorA == colorB) + { + product = colorA; + product1 = colorA; + product2 = colorA; + } + else + { + register int r = 0; + + product1 = INTERPOLATE (colorA, colorC); + product = INTERPOLATE (colorA, colorB); + + r += + GetResult1 (colorA, colorB, colorG, colorE, + colorI); + r += + GetResult2 (colorB, colorA, colorK, colorF, + colorJ); + r += + GetResult2 (colorB, colorA, colorH, colorN, + colorM); + r += + GetResult1 (colorA, colorB, colorL, colorO, + colorP); + + if (r > 0) + product2 = colorA; + else if (r < 0) + product2 = colorB; + else + { + product2 = + Q_INTERPOLATE (colorA, colorB, colorC, + colorD); + } + } + } + else + { + product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) + && (colorB != colorE) && (colorB == colorJ)) + { + product = colorA; + } + else + if ((colorB == colorE) && (colorB == colorD) + && (colorA != colorF) && (colorA == colorI)) + { + product = colorB; + } + else + { + product = INTERPOLATE (colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) + && (colorG != colorC) && (colorC == colorM)) + { + product1 = colorA; + } + else + if ((colorC == colorG) && (colorC == colorD) + && (colorA != colorH) && (colorA == colorI)) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE (colorA, colorC); + } + } + +#ifdef MSB_FIRST + product = product | (colorA << 16); + product1 = product2 | (product1 << 16); +#else + product = colorA | (product << 16); + product1 = product1 | (product2 << 16); +#endif + *((int32 *) dP) = product; + *((uint32 *) (dP + dstPitch)) = product1; + + bP += inc_bP; + dP += sizeof (uint32); + } // end of for ( finish= width etc..) + + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + deltaPtr += srcPitch; + } // endof: while (height--) + } +} + +#ifdef MMX +void Scale_2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 * /* deltaPtr */, + uint8 *dstPtr, uint32 dstPitch, + uint32 dstWidth, uint32 dstHeight, int width, int height) +{ + uint8 *dP; + uint16 *bP; + uint32 w; + uint32 h; + uint32 dw; + uint32 dh; + uint32 hfinish; + uint32 wfinish; + uint32 Nextline; + uint16 colorA[4]; + uint16 colorB[4]; + uint16 colorC[4]; + uint16 colorD[4]; + uint16 dx[4]; + uint16 dy[4]; + + Nextline = srcPitch >> 1; + + wfinish = (width - 1) << 16; // convert to fixed point + hfinish = (height - 1) << 16; // convert to fixed point + dw = wfinish / (dstWidth - 1); + dh = hfinish / (dstHeight - 1); + + for (h = 0; h < hfinish; h += dh) + { + uint32 y1, y2; + + y1 = h & 0xffff; // fraction part of fixed point + y2 = 0x10000 - y1; + bP = (uint16 *) (srcPtr + ((h >> 16) * srcPitch)); + dP = dstPtr; + + for (w = 0; w < wfinish;) + { + uint32 A, B, C, D; + uint32 E, F, G, H; + uint32 I, J, K, L; + uint32 x1, x2, a1, f1, f2; + uint32 position; + + for (int c = 0; c < 4; c++) + { + position = w >> 16; + A = bP[position]; // current pixel + B = bP[position + 1]; // next pixel + C = bP[position + Nextline]; + D = bP[position + Nextline + 1]; + E = bP[position - Nextline]; + F = bP[position - Nextline + 1]; + G = bP[position - 1]; + H = bP[position + Nextline - 1]; + I = bP[position + 2]; + J = bP[position + Nextline + 2]; + K = bP[position + Nextline + Nextline]; + L = bP[position + Nextline + Nextline + 1]; + + x1 = w & 0xffff; // fraction part of fixed point + x2 = 0x10000 - x1; + + /*1*/ + if (A == D && B != C) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y1 <= f1 && A == J && A != E) // close to B + { + a1 = f1 - y1; + colorA[c] = A; + colorB[c] = B; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y1 >= f1 && A == G && A != L) // close to C + { + a1 = y1 - f1; + colorA[c] = A; + colorB[c] = C; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (x1 >= f2 && A == E && A != J) // close to B + { + a1 = x1 - f2; + colorA[c] = A; + colorB[c] = B; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (x1 <= f2 && A == L && A != G) // close to C + { + a1 = f2 - x1; + colorA[c] = A; + colorB[c] = C; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y1 >= x1) // close to C + { + a1 = y1 - x1; + colorA[c] = A; + colorB[c] = C; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y1 <= x1) // close to B + { + a1 = x1 - y1; + colorA[c] = A; + colorB[c] = B; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + } + else + /*2*/ + if (B == C && A != D) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y2 >= f1 && B == H && B != F) // close to A + { + a1 = y2 - f1; + colorA[c] = B; + colorB[c] = A; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y2 <= f1 && B == I && B != K) // close to D + { + a1 = f1 - y2; + colorA[c] = B; + colorB[c] = D; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (x2 >= f2 && B == F && B != H) // close to A + { + a1 = x2 - f2; + colorA[c] = B; + colorB[c] = A; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (x2 <= f2 && B == K && B != I) // close to D + { + a1 = f2 - x2; + colorA[c] = B; + colorB[c] = D; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y2 >= x1) // close to A + { + a1 = y2 - x1; + colorA[c] = B; + colorB[c] = A; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + else if (y2 <= x1) // close to D + { + a1 = x1 - y2; + colorA[c] = B; + colorB[c] = D; + colorC[c] = 0; + colorD[c] = 0; + dx[c] = a1; + dy[c] = 0; + } + } + /*3*/ + else + { + colorA[c] = A; + colorB[c] = B; + colorC[c] = C; + colorD[c] = D; + dx[c] = x1; + dy[c] = y1; + } + w += dw; + } + BilinearMMX (colorA, colorB, colorC, colorD, dx, dy, dP); + dP += 8; + } + dstPtr += dstPitch; + }; + EndMMX (); + +} + +#else +static uint32 Bilinear (uint32 A, uint32 B, uint32 x) +{ + unsigned long areaA, areaB; + unsigned long result; + + if (A == B) + return A; + + areaB = (x >> 11) & 0x1f; // reduce 16 bit fraction to 5 bits + areaA = 0x20 - areaB; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + + result = ((areaA * A) + (areaB * B)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); + +} + +static uint32 Bilinear4 (uint32 A, uint32 B, uint32 C, uint32 D, uint32 x, + uint32 y) +{ + unsigned long areaA, areaB, areaC, areaD; + unsigned long result, xy; + + x = (x >> 11) & 0x1f; + y = (y >> 11) & 0x1f; + xy = (x * y) >> 5; + + A = (A & redblueMask) | ((A & greenMask) << 16); + B = (B & redblueMask) | ((B & greenMask) << 16); + C = (C & redblueMask) | ((C & greenMask) << 16); + D = (D & redblueMask) | ((D & greenMask) << 16); + + areaA = 0x20 + xy - x - y; + areaB = x - xy; + areaC = y - xy; + areaD = xy; + + result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5; + + return (result & redblueMask) | ((result >> 16) & greenMask); +} + +void Scale_2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 * /* deltaPtr */, + uint8 *dstPtr, uint32 dstPitch, + uint32 dstWidth, uint32 dstHeight, int width, int height) +{ + uint8 *dP; + uint16 *bP; + + uint32 w; + uint32 h; + uint32 dw; + uint32 dh; + uint32 hfinish; + uint32 wfinish; + + uint32 Nextline = srcPitch >> 1; + + wfinish = (width - 1) << 16; // convert to fixed point + dw = wfinish / (dstWidth - 1); + hfinish = (height - 1) << 16; // convert to fixed point + dh = hfinish / (dstHeight - 1); + + for (h = 0; h < hfinish; h += dh) + { + uint32 y1, y2; + + y1 = h & 0xffff; // fraction part of fixed point + bP = (uint16 *) (srcPtr + ((h >> 16) * srcPitch)); + dP = dstPtr; + y2 = 0x10000 - y1; + + w = 0; + + for (; w < wfinish;) + { + uint32 A, B, C, D; + uint32 E, F, G, H; + uint32 I, J, K, L; + uint32 x1, x2, a1, f1, f2; + uint32 position, product1; + + position = w >> 16; + A = bP[position]; // current pixel + B = bP[position + 1]; // next pixel + C = bP[position + Nextline]; + D = bP[position + Nextline + 1]; + E = bP[position - Nextline]; + F = bP[position - Nextline + 1]; + G = bP[position - 1]; + H = bP[position + Nextline - 1]; + I = bP[position + 2]; + J = bP[position + Nextline + 2]; + K = bP[position + Nextline + Nextline]; + L = bP[position + Nextline + Nextline + 1]; + + x1 = w & 0xffff; // fraction part of fixed point + x2 = 0x10000 - x1; + + /*0*/ + if (A == B && C == D && A == C) + product1 = A; + else + /*1*/ + if (A == D && B != C) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y1 <= f1 && A == J && A != E) // close to B + { + a1 = f1 - y1; + product1 = Bilinear (A, B, a1); + } + else if (y1 >= f1 && A == G && A != L) // close to C + { + a1 = y1 - f1; + product1 = Bilinear (A, C, a1); + } + else if (x1 >= f2 && A == E && A != J) // close to B + { + a1 = x1 - f2; + product1 = Bilinear (A, B, a1); + } + else if (x1 <= f2 && A == L && A != G) // close to C + { + a1 = f2 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 >= x1) // close to C + { + a1 = y1 - x1; + product1 = Bilinear (A, C, a1); + } + else if (y1 <= x1) // close to B + { + a1 = x1 - y1; + product1 = Bilinear (A, B, a1); + } + } + else + /*2*/ + if (B == C && A != D) + { + f1 = (x1 >> 1) + (0x10000 >> 2); + f2 = (y1 >> 1) + (0x10000 >> 2); + if (y2 >= f1 && B == H && B != F) // close to A + { + a1 = y2 - f1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= f1 && B == I && B != K) // close to D + { + a1 = f1 - y2; + product1 = Bilinear (B, D, a1); + } + else if (x2 >= f2 && B == F && B != H) // close to A + { + a1 = x2 - f2; + product1 = Bilinear (B, A, a1); + } + else if (x2 <= f2 && B == K && B != I) // close to D + { + a1 = f2 - x2; + product1 = Bilinear (B, D, a1); + } + else if (y2 >= x1) // close to A + { + a1 = y2 - x1; + product1 = Bilinear (B, A, a1); + } + else if (y2 <= x1) // close to D + { + a1 = x1 - y2; + product1 = Bilinear (B, D, a1); + } + } + /*3*/ + else + { + product1 = Bilinear4 (A, B, C, D, x1, y1); + } + +//end First Pixel + *(uint32 *) dP = product1; + dP += 2; + w += dw; + } + dstPtr += dstPitch; + } +} + +#endif + diff --git a/source/snes9x/unused/2xsaiwin.cpp b/source/snes9x/unused/2xsaiwin.cpp new file mode 100644 index 0000000..8ccc9d6 --- /dev/null +++ b/source/snes9x/unused/2xsaiwin.cpp @@ -0,0 +1,821 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +//#define MMX + +#include "snes9x/snes9x.h" +#include "snes9x/port.h" +#include "snes9x/gfx.h" + +#ifdef MMX +EXTERN_C void _2xSaILine (uint8 *srcPtr, uint8 *deltaPtr, uint32 srcPitch, uint32 width, + uint8 *dstPtr, uint32 dstPitch); +EXTERN_C void _2xSaISuperEagleLine (uint8 *srcPtr, uint8 *deltaPtr, uint32 srcPitch, uint32 width, + uint8 *dstPtr, uint32 dstPitch); +EXTERN_C int Init_2xSaIMMX (uint32 BitFormat); +#endif + +bool mmx_cpu = false; + +static uint32 colorMask = 0xF7DEF7DE; +static uint32 lowPixelMask = 0x08210821; +static uint32 qcolorMask = 0xE79CE79C; +static uint32 qlowpixelMask = 0x18631863; + + +int Init_2xSaI(uint32 BitFormat) +{ + if (BitFormat == 565) + { + colorMask = 0xF7DEF7DE; + lowPixelMask = 0x08210821; + qcolorMask = 0xE79CE79C; + qlowpixelMask = 0x18631863; + } + else + if (BitFormat == 555) + { + colorMask = 0x7BDE7BDE; + lowPixelMask = 0x04210421; + qcolorMask = 0x739C739C; + qlowpixelMask = 0x0C630C63; + } + else + { + return 0; + } +#ifdef MMX + Init_2xSaIMMX(BitFormat); +#endif + return 1; +} + +STATIC inline int GetResult1(uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r+=1; + if (y <= 1) r-=1; + return r; +} + +STATIC inline int GetResult2(uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r-=1; + if (y <= 1) r+=1; + return r; +} + + +STATIC inline int GetResult(uint32 A, uint32 B, uint32 C, uint32 D) +{ + int x = 0; + int y = 0; + int r = 0; + if (A == C) x+=1; else if (B == C) y+=1; + if (A == D) x+=1; else if (B == D) y+=1; + if (x <= 1) r+=1; + if (y <= 1) r-=1; + return r; +} + + +STATIC inline uint32 INTERPOLATE(uint32 A, uint32 B) +{ + if (A !=B) + { + return ( ((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask) ); + } + else return A; +} + + +STATIC inline uint32 Q_INTERPOLATE(uint32 A, uint32 B, uint32 C, uint32 D) +{ + register uint32 x = ((A & qcolorMask) >> 2) + + ((B & qcolorMask) >> 2) + + ((C & qcolorMask) >> 2) + + ((D & qcolorMask) >> 2); + register uint32 y = (A & qlowpixelMask) + + (B & qlowpixelMask) + + (C & qlowpixelMask) + + (D & qlowpixelMask); + y = (y>>2) & qlowpixelMask; + return x+y; +} + + + + +#define HOR +#define VER +void Super2xSaI(uint8 *srcPtr, uint32 srcPitch, + uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dP; + uint16 *bP; + +#ifdef MMX_BLA //no MMX version yet + if (cpu_mmx && width != 512) + { + for (height; height; height-=1) + { + bP = (uint16 *) srcPtr; + xP = (uint16 *) deltaPtr; + dP = (uint32 *) dstPtr; + _2xSaISuperEagleLine ((uint8 *) bP, (uint8 *) xP, srcPitch, width, (uint8 *) dP, dstPitch); + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + } + } + else + { +#endif + uint32 Nextline = srcPitch >> 1; + + for (height; height; height-=1) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + for (uint32 finish = width; finish; finish -= 1 ) + { + uint32 color4, color5, color6; + uint32 color1, color2, color3; + uint32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + uint32 product1a, product1b, + product2a, product2b; + +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + + colorB0 = *(bP- Nextline - 1); + colorB1 = *(bP- Nextline); + colorB2 = *(bP- Nextline + 1); + colorB3 = *(bP- Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6 && color5 != color6) + { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE (color5, color6); + } + + } + else + { + +#ifdef VER + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE (color2, color2, color2, color3); + else +#endif + product2b = INTERPOLATE (color2, color3); + +#ifdef VER + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE (color6, color5, color5, color5); + else +#endif + product1b = INTERPOLATE (color5, color6); + } + +#ifdef HOR + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE (color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE(color2, color5); + else +#endif + product2a = color2; + +#ifdef HOR + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE (color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE(color2, color5); + else +#endif + product1a = color5; + + + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); + + *(dP) = product1a; + *(dP+(dstPitch>>2)) = product2a; + + bP += 1; + dP += 1; + }//end of for ( finish= width etc..) + + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + }; //endof: for (height; height; height--) +#ifdef MMX_BLA + } +#endif +} + + + + + + +/*ONLY use with 640x480x16 or higher resolutions*/ +/*Only use this if 2*width * 2*height fits on the current screen*/ +void SuperEagle(uint8 *srcPtr, uint32 srcPitch, + uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dP; + uint16 *bP; + uint16 *xP; + +#ifdef MMX + if (mmx_cpu && width != 512) + { + for (height; height; height-=1) + { + bP = (uint16 *) srcPtr; + xP = (uint16 *) deltaPtr; + dP = (uint32 *) dstPtr; + _2xSaISuperEagleLine ((uint8 *) bP, (uint8 *) xP, srcPitch, width, (uint8 *)dP, dstPitch); + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + } + } + else + { +#endif + uint32 Nextline = srcPitch >> 1; + + for (height; height; height-=1) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + for (uint32 finish = width; finish; finish -= 1 ) + { + + uint32 color4, color5, color6; + uint32 color1, color2, color3; + uint32 colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + uint32 product1a, product1b, + product2a, product2b; + + colorB0 = *(bP- Nextline - 1); + colorB1 = *(bP- Nextline); + colorB2 = *(bP- Nextline + 1); + colorB3 = *(bP- Nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + Nextline - 1); + color2 = *(bP + Nextline); + color3 = *(bP + Nextline + 1); + colorS1 = *(bP + Nextline + 2); + + colorA0 = *(bP + Nextline + Nextline - 1); + colorA1 = *(bP + Nextline + Nextline); + colorA2 = *(bP + Nextline + Nextline + 1); + colorA3 = *(bP + Nextline + Nextline + 2); + + + //-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product1b = product2a = color2; + if ((color1 == color2 && color6 == colorS2) || + (color2 == colorA1 && color6 == colorB2)) + { + product1a = INTERPOLATE (color2, color5); + product1a = INTERPOLATE (color2, product1a); + product2b = INTERPOLATE (color2, color3); + product2b = INTERPOLATE (color2, product2b); +// product1a = color2; +// product2b = color2; + } + else + { + product1a = INTERPOLATE (color5, color6); + product2b = INTERPOLATE (color2, color3); + } + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1a = color5; + if ((colorB1 == color5 && color3 == colorA2) || + (color4 == color5 && color3 == colorS1)) + { + product1b = INTERPOLATE (color5, color6); + product1b = INTERPOLATE (color5, product1b); + product2a = INTERPOLATE (color5, color2); + product2a = INTERPOLATE (color5, product2a); +// product1b = color5; +// product2a = color5; + } + else + { + product1b = INTERPOLATE (color5, color6); + product2a = INTERPOLATE (color2, color3); + } + } + else + if (color5 == color3 && color2 == color6 && color5 != color6) + { + register int r = 0; + + r += GetResult (color6, color5, color1, colorA1); + r += GetResult (color6, color5, color4, colorB1); + r += GetResult (color6, color5, colorA2, colorS1); + r += GetResult (color6, color5, colorB2, colorS2); + + if (r > 0) + { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE (color5, color6); + } + else + if (r < 0) + { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE (color5, color6); + } + else + { + product2b = product1a = color5; + product1b = product2a = color2; + } + } + else + { + + if ((color2 == color5) || (color3 == color6)) + { + product1a = color5; + product2a = color2; + product1b = color6; + product2b = color3; + + } + else + { + product1b = product1a = INTERPOLATE (color5, color6); + product1a = INTERPOLATE (color5, product1a); + product1b = INTERPOLATE (color6, product1b); + + product2a = product2b = INTERPOLATE (color2, color3); + product2a = INTERPOLATE (color2, product2a); + product2b = INTERPOLATE (color3, product2b); + } + } + + + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); + + *(dP) = product1a; + *(dP+(dstPitch>>2)) = product2a; + + bP += 1; + dP += 1; + }//end of for ( finish= width etc..) + + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + }; //endof: for (height; height; height--) +#ifdef MMX + } +#endif +} + + + +/*ONLY use with 640x480x16 or higher resolutions*/ +/*Only use this if 2*width * 2*height fits on the current screen*/ +void _2xSaI(uint8 *srcPtr, uint32 srcPitch, + uint8 *deltaPtr, + uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + uint32 *dP; + uint16 *bP; + uint16 *xP; + +#ifdef MMX + if (mmx_cpu && width != 512) + { + for (height; height; height-=1) + { + + bP = (uint16 *) srcPtr; + xP = (uint16 *) deltaPtr; + dP = (uint32 *) dstPtr; + _2xSaILine ((uint8 *) bP, (uint8 *) xP, srcPitch, width, (uint8 *)dP, dstPitch); + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + } + } + else + { +#endif + uint32 Nextline = srcPitch >> 1; + + for (height; height; height-=1) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + for (uint32 finish = width; finish; finish -= 1 ) + { + + + register uint32 colorA, colorB; + uint32 colorC, colorD, + colorE, colorF, colorG, colorH, + colorI, colorJ, colorK, colorL, + colorM, colorN, colorO, colorP; + uint32 product, product1, product2; + + +//--------------------------------------- +// Map of the pixels: I|E F|J +// G|A B|K +// H|C D|L +// M|N O|P + colorI = *(bP- Nextline - 1); + colorE = *(bP- Nextline); + colorF = *(bP- Nextline + 1); + colorJ = *(bP- Nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + Nextline - 1); + colorC = *(bP + Nextline); + colorD = *(bP + Nextline + 1); + colorL = *(bP + Nextline + 2); + + colorM = *(bP + Nextline + Nextline - 1); + colorN = *(bP + Nextline + Nextline); + colorO = *(bP + Nextline + Nextline + 1); + colorP = *(bP + Nextline + Nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) + { + if ( ((colorA == colorE) && (colorB == colorL)) || + ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) ) + { + product = colorA; + } + else + { + product = INTERPOLATE(colorA, colorB); + } + + if (((colorA == colorG) && (colorC == colorO)) || + ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) ) + { + product1 = colorA; + } + else + { + product1 = INTERPOLATE(colorA, colorC); + } + product2 = colorA; + } + else + if ((colorB == colorC) && (colorA != colorD)) + { + if (((colorB == colorF) && (colorA == colorH)) || + ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) ) + { + product = colorB; + } + else + { + product = INTERPOLATE(colorA, colorB); + } + + if (((colorC == colorH) && (colorA == colorF)) || + ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) ) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE(colorA, colorC); + } + product2 = colorB; + } + else + if ((colorA == colorD) && (colorB == colorC)) + { + if (colorA == colorB) + { + product = colorA; + product1 = colorA; + product2 = colorA; + } + else + { + register int r = 0; + product1 = INTERPOLATE(colorA, colorC); + product = INTERPOLATE(colorA, colorB); + + r += GetResult1 (colorA, colorB, colorG, colorE, colorI); + r += GetResult2 (colorB, colorA, colorK, colorF, colorJ); + r += GetResult2 (colorB, colorA, colorH, colorN, colorM); + r += GetResult1 (colorA, colorB, colorL, colorO, colorP); + + if (r > 0) + product2 = colorA; + else + if (r < 0) + product2 = colorB; + else + { + product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); + } + } + } + else + { + product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) + { + product = colorA; + } + else + if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) + { + product = colorB; + } + else + { + product = INTERPOLATE(colorA, colorB); + } + + if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) + { + product1 = colorA; + } + else + if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) + { + product1 = colorC; + } + else + { + product1 = INTERPOLATE(colorA, colorC); + } + } + product = colorA | (product << 16); + product1 = product1 | (product2 << 16); + *(dP) = product; + *(dP+(dstPitch>>2)) = product1; + + bP += 1; + dP += 1; + }//end of for ( finish= width etc..) + + dstPtr += dstPitch << 1; + srcPtr += srcPitch; + deltaPtr += srcPitch; + }; //endof: for (height; height; height--) +#ifdef MMX + } +#endif +} + diff --git a/source/snes9x/unused/Makefile.in b/source/snes9x/unused/Makefile.in new file mode 100644 index 0000000..3d1766e --- /dev/null +++ b/source/snes9x/unused/Makefile.in @@ -0,0 +1,403 @@ +@ZSNESFX@ +@ZSNESC4@ +@ASMCPU@ +@SPC700ASM@ +@NETPLAY@ +UNZIP=1 +@JMA@ +@GLIDE@ +@OPENGL@ +@AIDO@ +#GUI=0 +@THREAD_SOUND@ +@ASMKREED@ +@SDD1_DECOMP@ +@CORRECT_VRAM_READS@ +@DREAMCAST@ +CHEATS=1 +2XSAI=1 + +#Fairly good and special-char-safe descriptor of the os being built on. +OS=`uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` +BUILDDIR=. +#BUILDDIR=build/$(OS) + +ifdef DREAMCAST +CPU=sh +ASMCPU=1 +CHEATS=0 +2XSAI=0 +else +CPU=i386 +endif + +ifdef ZSNESFX +FXOBJ=$(CPU)/fxemu2b.o $(CPU)/fxemu2.o $(CPU)/fxemu2c.o $(CPU)/fxtable.o $(CPU)/sfxproc.o $(CPU)/ZSNES.O +FXDEFINES=-DZSNES_FX -DEXECUTE_SUPERFX_PER_LINE +FXDEPENDS=zsnes_fx +FXNO_DEPENDS=c_fx +else +FXOBJ=fxinst.o fxemu.o fxdbg.o +FXDEFINES= +FXDEPENDS=c_fx +FXNO_DEPENDS=zsnes_fx +endif + +ifdef ZSNESC4 +C4OBJ=$(CPU)/C4.O $(CPU)/zsnesc4.o c4.o +C4DEFINES=-DZSNES_C4 +C4DEPENDS=zsnes_c4 +C4NO_DEPENDS=c_c4 +else +C4OBJ=c4.o c4emu.o +C4DEFINES= +C4DEPENDS=c_c4 +C4NO_DEPENDS=zsnes_c4 +endif + +SOUNDOBJ=spc700.o soundux.o apu.o @I386SPC@ +SOUNDDEFINES=-DSPC700_C + +ifdef ASMCPU +CPUOBJ=$(CPU)/cpuops.o $(CPU)/cpuexec.o $(CPU)/sa1ops.o +else +CPUOBJ=cpuops.o cpuexec.o sa1cpu.o +endif + +ifdef DREAMCAST +PLATFORMOBJ=dc/input.o dc/display.o dc/sound.o \ +dc/dc.o dc/menu.o dc/trace.o dc/lcd.o \ +dc/lain_blanker.o dc/td.o dc/md5.o +else +PLATFORMOBJ=unix/unix.o +endif + +ifdef CHEATS +CHEATOBJ=cheats.o cheats2.o +endif + +ifndef DREAMCAST +SNAPOBJ = snaporig.o snapshot.o +SCREENSHOTOBJ = screenshot.o +MOVIEOBJ = movie.o +endif + +ifdef 2XSAI +ifdef ASMKREED +KREEDOBJ=$(CPU)/2XSAIMMX.O $(CPU)/bilinear.o 2xsai.o +KREEDDEFINES=-DMMX +else +KREEDOBJ=2xsai.o +endif +endif + +ifdef SDD1_DECOMP +SDD1OBJ=sdd1emu.o +ifdef SDD1_VERIFY +SDD1DEFINES=-DSDD1_DECOMP -DSDD1_VERIFY +else +SDD1DEFINES=-DSDD1_DECOMP +endif +endif + +ifdef CORRECT_VRAM_READS +CORRVRAMDEFINES=-DCORRECT_VRAM_READS +endif + +SPC7110OBJ=spc7110.o +OBC1OBJ=obc1.o +SETAOBJ=seta.o seta010.o seta011.o seta018.o + +OBJECTS=$(CPUOBJ) $(SOUNDOBJ) apudebug.o $(FXOBJ) $(C4OBJ) \ + controls.o crosshairs.o cpu.o sa1.o debug.o sdd1.o tile.o srtc.o gfx.o \ + memmap.o clip.o dsp1.o ppu.o dma.o snes9x.o data.o globals.o reader.o \ + conffile.o bsx.o logger.o \ + $(SPC7110OBJ) $(OBC1OBJ) $(SETAOBJ) $(KREEDOBJ) $(SDD1OBJ) \ + $(CHEATOBJ) $(PLATFORMOBJ) $(SNAPOBJ) $(SCREENSHOTOBJ) $(MOVIEOBJ) + +ifdef NETPLAY +OBJECTS += netplay.o server.o +NETPLAYDEFINES=-DNETPLAY_SUPPORT +SERVER_OBJECTS=server.o unix/server_main.o globals.o netplay.o +endif + +ifdef UNZIP +OBJECTS += loadzip.o unzip/unzip.o unzip/explode.o unzip/unreduce.o unzip/unshrink.o +UNZIPDEFINES=-DUNZIP_SUPPORT +endif + +ifdef JMA +OBJECTS += jma/s9x-jma.o jma/7zlzma.o jma/crc32.o jma/iiostrm.o jma/inbyte.o jma/jma.o jma/lzma.o jma/lzmadec.o jma/winout.o +JMADEFINES = -DJMA_SUPPORT +endif + +ifdef THREAD_SOUND +CPUDEFINES += -DUSE_THREADS +EXTRALIBS += -lpthread +endif + +ifdef GLIDE +GLIDEOBJS = unix/glide.o +GLIDEDEFINES = -DUSE_GLIDE -I/usr/include/glide +GLIDELIBS = -lglide2x +endif + +ifdef OPENGL +OPENGLOBJS = unix/opengl.o +OPENGLDEFINES = -DUSE_OPENGL +OPENGLLIBS = -lGL -lGLU -ldl +endif + +ifdef AIDO +AIDOOBJS = unix/aido.o +AIDODEFINES = -DUSE_AIDO +endif + +JOYDEFINES = @JOYDEFINES@ + +ifdef DREAMCAST +CCC = sh-elf-c++ -fno-rtti +CC = sh-elf-gcc +NASM = fail +GASM = fail +else +CCC = @CXX@ @RTTIFLAG@ +CC = @CC@ +NASM = @NASM@ +GASM = @CXX@ +endif + +#INCLUDES = -I../zlib @X_INCLUDES@ +ifdef DREAMCAST +INCLUDES = -Idc +DEFS = -DDC +else +INCLUDES = @X_INCLUDES@ +DEFS = -DMITSHM +endif + +INCLUDES += -I. -Iunzip @CPUINC@ + +ifdef DREAMCAST +OPTIMISE=-O4 -ffreestanding -ffast-math -fschedule-insns2 -fomit-frame-pointer -fno-inline-functions -fno-defer-pop -fforce-addr -fstrict-aliasing -funroll-loops -fdelete-null-pointer-checks -fno-exceptions +CPUFLAGS=-ml -m4-single-only +else +OPTIMISE = @OPTIMIZE@ +endif + +DEFS += \ +-DCPU_SHUTDOWN \ +-DSPC700_SHUTDOWN \ +$(FXDEFINES) \ +$(C4DEFINES) \ +$(CPUDEFINES) \ +$(SOUNDDEFINES) \ +$(NETPLAYDEFINES) \ +$(UNZIPDEFINES) \ +$(JMADEFINES) \ +$(GLIDEDEFINES) \ +$(OPENGLDEFINES) \ +$(AIDODEFINES) \ +$(KREEDDEFINES) \ +$(SDD1DEFINES) \ +$(CORRVRAMDEFINES) \ +$(JOYDEFINES) \ +-DNO_INLINE_SET_GET @SYSDEFINES@ + +CCFLAGS = $(OPTIMISE) $(CPUFLAGS) $(INCLUDES) $(DEFS) + +CFLAGS=$(CCFLAGS) + +.SUFFIXES: .o .cpp .c .cc .h .m .i .S .asm .obj .O .CPP .C .ASM +#FIXME: Why is this set statically? +#LDLIBS = -L/usr/X11R6/lib +# -L../zlib + +ifdef GLIDE +all: Makefile configure gsnes9x +else +ifdef OPENGL +all: Makefile configure osnes9x +else +all: Makefile configure snes9x +endif +endif + +Makefile: configure Makefile.in + @echo "Makefile is older than configure or in-file. Run configure or touch Makefile." + exit 1 + +configure: configure.in + @echo "configure is older than in-file. Run autoconf or touch configure." + exit 1 + +#ggisnes9x +#xf86snes9x + +ifdef ASMCPU +OFFSET=offsets +else +OFFSET= +endif + +offsets: offsets.o + $(CCC) $(INCLUDES) -o $@ offsets.o + ./offsets >$(CPU)/offsets.h + +#../zlib/libz.a: +# cd ../zlib && sh ./configure && make + +snes9x: $(OBJECTS) unix/x11.o $(AIDOOBJS) $(OFFSET) + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) $(AIDOOBJS) $(GLIDEOBJS) $(OPENGLOBJS) unix/x11.o $(LDLIBS) $(GLIDELIBS) $(OPENGLLIBS) @SYSLIBS@ -lXext -lX11 $(EXTRALIBS) -lm + +unix/svga_keynames.h: unix/svga_get_keynames.pl + unix/svga_get_keynames.pl /usr/include/vgakeyboard.h > unix/svga_keynames.h + +unix/svga.o: unix/svga_keynames.h + +ssnes9x: $(OBJECTS) unix/svga.o + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) $(GLIDEOBJS) unix/svga.o $(LDLIBS) $(GLIDELIBS) @SYSLIBS@ -lvga -lvgagl $(EXTRALIBS) -lm + +gsnes9x: $(OBJECTS) $(GLIDEOBJS) + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) $(GLIDEOBJS) $(LDLIBS) @SYSLIBS@ -lglide $(EXTRALIBS) -lm + +ggisnes9x: $(OBJECTS) unix/ggi.o + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) unix/ggi.o $(LDLIBS) @SYSLIBS@ -lggi $(EXTRALIBS) -lm + +osnes9x: $(OBJECTS) unix/x11.o $(OPENGLOBJS) + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) unix/x11.o $(OPENGLOBJS) $(LDLIBS) $(OPENGLLIBS) @SYSLIBS@ -lXext -lX11 $(EXTRALIBS) -lm + +s9xserver: $(SERVER_OBJECTS) + $(CCC) $(INCLUDES) -o $@ $(SERVER_OBJECTS) + +jma/s9x-jma.o: jma/s9x-jma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/7zlzma.o: jma/7zlzma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/crc32.o: jma/crc32.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/iiostrm.o: jma/iiostrm.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/inbyte.o: jma/inbyte.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/jma.o: jma/jma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/lzma.o: jma/lzma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/lzmadec.o: jma/lzmadec.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +jma/winout.o: jma/winout.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ + +.cpp.o: + $(CCC) $(INCLUDES) -c $(CCFLAGS) $*.cpp -o $@ + +.c.o: + $(CC) $(INCLUDES) -c $(CCFLAGS) $*.c -o $@ + +.cpp.S: + $(GASM) $(INCLUDES) -S $(CCFLAGS) $*.cpp -o $@ + +.cpp.i: + $(GASM) $(INCLUDES) -E $(CCFLAGS) $*.cpp -o $@ + +.S.o: + $(GASM) $(INCLUDES) -c $(CCFLAGS) $*.S -o $@ + +.S.i: + $(GASM) $(INCLUDES) -c -E $(CCFLAGS) $*.S -o $@ + +.s.o: + @echo Compiling $*.s + sh-elf-as -little $*.s -o $@ + +.asm.o: + $(NASM) -f elf -DELF $(FXDEFINES) -i. -ii386 -o $@ $*.asm + +.obj.o: + cp $*.obj $*.o + +.CPP.O: + $(CCC) $(INCLUDES) -c $(CCFLAGS) -x c++ $*.CPP -o $@ + +.C.O: + $(CC) $(INCLUDES) -c $(CCFLAGS) $*.C -o $@ + +.ASM.O: + $(NASM) -f elf -DELF $(FXDEFINES) -i . -i i386 $*.ASM -o $@ + +unix/moc_snes9x_gui.cpp: unix/snes9x_gui.h + $(MOC) unix/snes9x_gui.h -o $@ + +clean: + rm -f $(OBJECTS) offsets.o unix/svga.o unix/aido.o unix/x11.o unix/ggi.o unix/xf86.o unix/glide.o + +#release: CCFLAGS += -DNO_DEBUGGER + +_bin-package: + RELNR=`grep "#define VERSION" snes9x.h | sed -e 's/"//g' | awk '{ print $$3 }'` && \ + echo $$RELNR && \ + RELNAME=snes9x-$${RELNR} && export RELNAME && \ + test \! -f $${RELNAME}.tar.gz && \ + DISTDIR=disttmp/$${RELNAME}/ && \ + rm -rf disttmp && \ + mkdir disttmp && \ + mkdir $${DISTDIR} && \ + cp snes9x $${DISTDIR} && \ + cp config.info hardware.txt problems.txt changes.txt ../faqs.txt ../readme.txt ../readme.unix $${DISTDIR} && \ + (cd disttmp && tar cvf - $${RELNAME}) | gzip -c > $${RELNAME}.tar.gz &&\ + rm -rf disttmp + +#FIXME: Should possibly have clean, but not in xenofarm build +bin-release: snes9x _bin-package + +#FIXME: Intelligent messages when bailing out. +#FIXME: See those ls:s? Don't look to closely at the statements... +_src-package: + RELNR=`grep "#define VERSION" snes9x.h | sed -e 's/"//g' | awk '{ print $$3 }'` && \ + echo $$RELNR && \ + RELNAME=snes9x-$${RELNR}-src && \ + test \! -f $${RELNAME}.tar.gz && \ + test \! `ls *~` && \ + test \! `ls *.o` && \ + test \! -f snes9x && \ + export RELNR && export RELNAME && \ + (cd .. && PWD=`pwd` && SNESDIR=`basename $$PWD` && cd .. && \ + DISTDIR=disttmp/$${RELNAME} && \ + rm -rf disttmp && \ + mkdir disttmp && \ + cp -r $${SNESDIR} $${DISTDIR} && \ + rm -f $${DISTDIR}/snes9x/config.* 2>/dev/null && \ + rm -f $${DISTDIR}/snes9x/conftezt.out.* 2>/dev/null && \ + rm -rf $${DISTDIR}/snes9x/autom4te.cache 2>/dev/null && \ + rm $${DISTDIR}/snes9x/Makefile && \ + find disttmp -name CVS -type f -exec rm "{}" \; && \ + find disttmp -name CVS -type d -exec rm "{}" \; && \ + (cd disttmp && tar cvf - $${RELNAME}) | gzip -c > $${RELNAME}.tar.gz && \ + mv $${RELNAME}.tar.gz $${SNESDIR}/snes9x/ ) && \ + rm -rf disttmp + +#Requires: +# 1. Prestine checkout +# 2. `autoconf` +# 3. `./configure` +src-release: depend _src-package + +xenofarm: + ./xenofarm.sh + cd build/xenofarm && tar cf - . > ../../../xenofarm_result.tar + gzip -f9 ../xenofarm_result.tar + +# And now for the impressive testsuite: +verify: snes9x + ./snes9x --selftest + +#FIXME: Make a auto-self-reference. +depend: + $(CC) $(CFLAGS) -MM -MG \ + `find . '(' -name '*.c' -o -name '*.cpp' -o -name '*.S' ')' -print -o -name msdos -prune` \ + | sed -e 's@^[^ :]*: *\([^ ]*/\)[^ /]*@\1&@' \ + >dependencies + +include dependencies + diff --git a/source/snes9x/unused/Makefile.mingw b/source/snes9x/unused/Makefile.mingw new file mode 100644 index 0000000..53ecfa3 --- /dev/null +++ b/source/snes9x/unused/Makefile.mingw @@ -0,0 +1,193 @@ +ASM=nasm +OBJFIX=win32/objfix.exe + +CFLAGSORIG=-Wall -I../zlib -I -I../FMOD/api/inc -DSPC700_SHUTDOWN -DNETPLAY_SUPPORT \ + -DCPU_SHUTDOWN -DZLIB -DVAR_CYCLES -DEXECUTE_SUPERFX_PER_LINE -D__WIN32__ -DUSE_OPENGL \ + -DUNZIP_SUPPORT -DHAVE_LIBPNG -DSDD1_DECOMP -DCORRECT_VRAM_READS -DNEW_COLOUR_BLENDING \ + -DWIN32 -D_WINDOWS -DSPC700_C -DJMA_SUPPORT -DZSNES_FX -DZSNES_C4 -DHAVE_STDINT_H -D_WIN32_IE=0x0501 +#-DFMOD_SUPPORT -DUSE_GLIDE + + +ifeq (${DEBUG},yes) +CFLAGS= ${CFLAGSORIG} -ggdb3 +else +CFLAGS= ${CFLAGSORIG} -O3 -DNDEBUG +endif + + +ifeq (${CROSS},yes) +CC=i586-mingw32-gcc +CPPC=i586-mingw32-g++ +WINDRES=i586-mingw32-windres +DEL=rm -f +SLASH=/ +else +CC=gcc +CPPC=g++ +WINDRES=windres +DEL=del +SLASH=\${blahblahblahblah} +endif + +LINK=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32 -lz -lpng -lcomctl32 -lwinmm -lopengl32 -lglu32 -lwsock32 -lddraw -ldsound -ldxguid -lvfw32 -mwindows +#-L..\..\FMOD\api\lib -lfmodvc -lglide2x -ldelayimp + +OBJS= 2xsai.obj apu.obj apudebug.obj bsx.obj c4.obj c4emu.obj cheats.obj cheats2.obj \ + clip.obj conffile.obj controls.obj cpu.obj cpuexec.obj cpuops.obj crosshairs.obj data.obj \ + debug.obj dma.obj dsp1.obj fxdbg.obj fxemu.obj fxinst.obj gfx.obj globals.obj loadzip.obj \ + logger.obj memmap.obj movie.obj netplay.obj obc1.obj ppu.obj reader.obj sa1.obj sa1cpu.obj \ + screenshot.obj sdd1.obj sdd1emu.obj server.obj seta.obj seta010.obj seta011.obj seta018.obj \ + snaporig.obj snapshot.obj snes9x.obj sound.obj soundux.obj spc700.obj spc7110.obj srtc.obj \ + tile.obj unzip/unreduce.obj i386/ZSNES.obj i386/fxemu2b.obj i386/fxtable.obj i386/fxemu2.obj \ + i386/fxemu2c.obj i386/sfxproc.obj i386/SPC.obj i386/zsnesc4.obj i386/C4.obj i386/2XSAIMMX.obj \ + i386/bilinear.obj jma/7zlzma.obj jma/crc32.obj jma/iiostrm.obj jma/inbyte.obj jma/jma.obj \ + jma/lzma.obj jma/lzmadec.obj jma/s9x-jma.obj jma/winout.obj unzip/unshrink.obj unzip/unzip.obj \ + unzip/explode.obj win32/auxmath.obj win32/AVIOutput.obj win32/directx.obj win32/InputCustom.obj \ + win32/render.obj win32/win32.obj win32/wconfig.obj win32/wsnes9x.obj win32/snes9x.obj + +#adler32.obj compress.obj deflate.obj emucrc32.obj gzio.obj infback.obj \ +#inffast.obj inflate.obj inftrees.obj minigzip.obj trees.obj uncompr.obj zutil.obj +#png.obj pngerror.obj pnggccrd.obj pngget.obj pngmem.obj \ +#pngpread.obj pngread.obj pngrio.obj pngrtran.obj pngrutil.obj pngset.obj pngtrans.obj \ +#pngvcrd.obj pngwio.obj pngwrite.obj pngwtran.obj pngwutil.obj + +.SUFFIXES: .c .cpp .asm .ASM + +%.obj: %.c + ${CC} ${CFLAGS} -o $@ -c $< + +%.obj: %.cpp + ${CPPC} ${CFLAGS} -o $@ -c $< + +%.obj: %.asm + ${ASM} -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o $@ $< + ${OBJFIX} $@ + +%.obj: %.ASM + ${ASM} -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o $@ $< + ${OBJFIX} $@ + +all: ${OBJFIX} ${OBJS} +ifeq (${DEBUG},yes) + ${CPPC} -ggdb3 -osnes9x-debug.exe ${OBJS} ${LINK} +else + ${CPPC} -s -osnes9x.exe ${OBJS} ${LINK} +endif + +${OBJFIX}: win32/objfix.c + gcc -O3 -s -o $@ win32/objfix.c +2xsai.obj: 2xsai.cpp +apu.obj: apu.cpp +apudebug.obj: apudebug.cpp +bsx.obj: bsx.cpp +c4.obj: c4.cpp +c4emu.obj: c4emu.cpp +cheats.obj: cheats.cpp +cheats2.obj: cheats2.cpp +clip.obj: clip.cpp +conffile.obj: conffile.cpp +controls.obj: controls.cpp +cpu.obj: cpu.cpp +cpuexec.obj: cpuexec.cpp +cpuops.obj: cpuops.cpp +crosshairs.obj: crosshairs.cpp +data.obj: data.cpp +debug.obj: debug.cpp +dma.obj: dma.cpp +dsp1.obj: dsp1.cpp +fxdbg.obj: fxdbg.cpp +fxemu.obj: fxemu.cpp +fxinst.obj: fxinst.cpp +gfx.obj: gfx.cpp +globals.obj: globals.cpp +loadzip.obj: loadzip.cpp +logger.obj: logger.cpp +memmap.obj: memmap.cpp +movie.obj: movie.cpp +netplay.obj: netplay.cpp +obc1.obj: obc1.cpp +ppu.obj: ppu.cpp +reader.obj: reader.cpp +sa1.obj: sa1.cpp +sa1cpu.obj: sa1cpu.cpp +screenshot.obj: screenshot.cpp +sdd1.obj: sdd1.cpp +sdd1emu.obj: sdd1emu.cpp +server.obj: server.cpp +seta.obj: seta.cpp +seta010.obj: seta010.cpp +seta011.obj: seta011.cpp +seta018.obj: seta018.cpp +snaporig.obj: snaporig.cpp +snapshot.obj: snapshot.cpp +snes9x.obj: snes9x.cpp +sound.obj: sound.cpp +soundux.obj: soundux.cpp +spc700.obj: spc700.cpp +spc7110.obj: spc7110.cpp +srtc.obj: srtc.cpp +tile.obj: tile.cpp +unzip/unreduce.obj: unzip/unreduce.c +unzip/unshrink.obj: unzip/unshrink.c +unzip/unzip.obj: unzip/unzip.c +unzip/explode.obj: unzip/explode.c +jma/7zlzma.obj: jma/7zlzma.cpp +jma/crc32.obj: jma/crc32.cpp +jma/iiostrm.obj: jma/iiostrm.cpp +jma/inbyte.obj: jma/inbyte.cpp +jma/jma.obj: jma/jma.cpp +jma/lzma.obj: jma/lzma.cpp +jma/lzmadec.obj: jma/lzmadec.cpp +jma/s9x-jma.obj: jma/s9x-jma.cpp +jma/winout.obj: jma/winout.cpp +win32/auxmath.obj: win32/auxmath.cpp +win32/AVIOutput.obj: win32/AVIOutput.cpp +win32/directx.obj: win32/directx.cpp +win32/InputCustom.obj: win32/InputCustom.cpp +win32/render.obj: win32/render.cpp +win32/wconfig.obj: win32/wconfig.cpp +win32/win32.obj: win32/win32.cpp +win32/wsnes9x.obj: win32/wsnes9x.cpp +win32/snes9x.obj: win32/rsrc/snes9x.rc + ${WINDRES} --include-dir win32/rsrc --language=0x413 -D_WIN32_IE=0x0501 win32/rsrc/snes9x.rc -owin32/snes9x.obj +#--language=0x809 + +#adler32.obj: ../zlib/adler32.c +#compress.obj: ../zlib/compress.c +#deflate.obj: ../zlib/deflate.c +#emucrc32.obj: ../zlib/emucrc32.c +#gzio.obj: ../zlib/gzio.c +#infback.obj: ../zlib/infback.c +#inffast.obj: ../zlib/inffast.c +#inflate.obj: ../zlib/inflate.c +#inftrees.obj: ../zlib/inftrees.c +#minigzip.obj: ../zlib/minigzip.c +#trees.obj: ../zlib/trees.c +#uncompr.obj: ../zlib/uncompr.c +#zutil.obj: ../zlib/zutil.c + +#png.obj: ../libpng/src/png.c +#pngerror.obj: ../libpng/src/pngerror.c +#pnggccrd.obj: ../libpng/src/pnggccrd.c +#pngget.obj: ../libpng/src/pngget.c +#pngmem.obj: ../libpng/src/pngmem.c +#pngpread.obj: ../libpng/src/pngpread.c +#pngread.obj: ../libpng/src/pngread.c +#pngrio.obj: ../libpng/src/pngrio.c +#pngrtran.obj: ../libpng/src/pngrtran.c +#pngrutil.obj: ../libpng/src/pngrutil.c +#pngset.obj: ../libpng/src/pngset.c +#pngtrans.obj: ../libpng/src/pngtrans.c +#pngvcrd.obj: ../libpng/src/pngvcrd.c +#pngwio.obj: ../libpng/src/pngwio.c +#pngwrite.obj: ../libpng/src/pngwrite.c +#pngwtran.obj: ../libpng/src/pngwtran.c +#pngwutil.obj: ../libpng/src/pngwutil.c + +clean: + ${DEL} *.obj + ${DEL} snes9x.exe + ${DEL} i386${SLASH}*.obj + ${DEL} jma${SLASH}*.obj + ${DEL} unzip${SLASH}*.obj + ${DEL} win32${SLASH}*.obj diff --git a/source/snes9x/unused/loadzip.cpp b/source/snes9x/unused/loadzip.cpp index 1d0a7f1..2eadd09 100644 --- a/source/snes9x/unused/loadzip.cpp +++ b/source/snes9x/unused/loadzip.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifdef UNZIP_SUPPORT /**********************************************************************************************/ /* Loadzip.CPP */ @@ -161,7 +180,7 @@ #include "snes9x.h" #include "memmap.h" -#include "unzip.h" +#include "unzip/unzip.h" #include #include #include @@ -172,7 +191,7 @@ bool8 LoadZip(const char* zipname, { *TotalFileSize = 0; *headers = 0; - + unzFile file = unzOpen(zipname); if(file == NULL) return (FALSE); @@ -203,7 +222,7 @@ bool8 LoadZip(const char* zipname, port = unzGoToNextFile(file); continue; } - + if ((int) info.uncompressed_size > filesize) { strcpy(filename,name); @@ -230,14 +249,14 @@ bool8 LoadZip(const char* zipname, char *ext = strrchr(filename,'.'); if(ext) ext++; else ext = tmp; - + uint8 *ptr = buffer; bool8 more = FALSE; printf("Using ROM %s in %s\n", filename, zipname); unzLocateFile(file,filename,1); unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0); - + if( unzOpenCurrentFile(file) != UNZ_OK ) { unzClose(file); @@ -248,17 +267,14 @@ bool8 LoadZip(const char* zipname, { assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512); int FileSize = info.uncompressed_size; - - int calc_size = FileSize / 0x2000; - calc_size *= 0x2000; - + int l = unzReadCurrentFile(file,ptr,FileSize); if(unzCloseCurrentFile(file) == UNZ_CRCERROR) { unzClose(file); return (FALSE); } - + if(l <= 0 || l != FileSize) { unzClose(file); @@ -280,13 +296,7 @@ bool8 LoadZip(const char* zipname, return (FALSE); } - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) - { - memmove (ptr, ptr + 512, calc_size); - (*headers)++; - FileSize -= 512; - } + FileSize = (int)Memory.HeaderRemove((uint32)FileSize, *headers, ptr); ptr += FileSize; (*TotalFileSize) += FileSize; @@ -312,7 +322,7 @@ bool8 LoadZip(const char* zipname, } else more = FALSE; - + if(more) { if( unzLocateFile(file,filename,1) != UNZ_OK || @@ -321,9 +331,9 @@ bool8 LoadZip(const char* zipname, break; printf(" ... and %s in %s\n", filename, zipname); } - + } while(more); - + unzClose(file); return (TRUE); } diff --git a/source/snes9x/unused/logger.cpp b/source/snes9x/unused/logger.cpp new file mode 100644 index 0000000..2ea1ad9 --- /dev/null +++ b/source/snes9x/unused/logger.cpp @@ -0,0 +1,338 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +#include +#include +#include "snes9x.h" +#include "gfx.h" +#include "soundux.h" +#include "movie.h" +#include "display.h" +#include "logger.h" + +#if !(defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) +#define __builtin_expect(exp,c) ((exp)!=(c)) +#endif + +int dumpstreams = 0; +int maxframes = -1; + +static int resetno = 0; +static int framecounter = 0; + +int fastforwardpoint = -1; +int fastforwarddistance = 0; + +int keypressscreen = 0; + +static int drift = 0; + +FILE *video=NULL, *audio=NULL; +char autodemo[128] = ""; + +int Logger_FrameCounter() +{ + return framecounter; +} + +void Logger_NextFrame() +{ + framecounter++; +} + +void breakpoint() +{ + +} + +void ResetLogger() +{ + char buffer[256*224*4]; + + if (!dumpstreams) + return; + + framecounter = 0; + drift=0; + + if (video) + fclose(video); + if (audio) + fclose(audio); + + sprintf(buffer, "videostream%d.dat", resetno); + video = fopen(buffer, "wb"); + if (!video) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + return; + } + + sprintf(buffer, "audiostream%d.dat", resetno); + audio = fopen(buffer, "wb"); + if (!audio) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + fclose(video); + return; + } + + char *logo = getenv("LOGO"); + if (!logo) + logo = "logo.dat"; + FILE *l = fopen(logo, "rb"); + if (l) + { + const int soundsize = (so.sixteen_bit ? 2 : 1)*(so.stereo?2:1)*so.playback_rate * Settings.FrameTime / 1000000; + printf("Soundsize: %d\n", soundsize); + while (!feof(l)) + { + if (fread(buffer, 1024,224, l) != 224) + break; + VideoLogger(buffer, 256, 224, 4,1024); + memset(buffer, 0, soundsize); + AudioLogger(buffer, soundsize); + } + fclose(l); + } + resetno++; +} + +char message[128]; +int messageframe; + + +void VideoLogger(void *pixels, int width, int height, int depth, int bytes_per_line) +{ + int fc = S9xMovieGetFrameCounter(); + if (fc > 0) + framecounter = fc; + else + framecounter++; + + if (video) + { + int i; + char *data = (char*)pixels; + for (i=0; i < height; i++) + fwrite(data + i*bytes_per_line, depth, width, video); + fflush(video); + fflush(audio); + drift++; + + if (maxframes > 0 && __builtin_expect(framecounter >= maxframes, 0)) + { + printf("-maxframes hit\ndrift:%d\n",drift); + S9xExit(); + } + + } + + if (Settings.DisplayPressedKeys==1 || keypressscreen) + { + uint16 MovieGetJoypad(int i); + + int buttons = MovieGetJoypad(0); + static char buffer[128]; + + // This string spacing pattern is optimized for the 256 pixel wide screen. + sprintf(buffer, "%s %s %s %s %s %s %c%c%c%c%c%c", + buttons & SNES_START_MASK ? "Start" : "_____", + buttons & SNES_SELECT_MASK ? "Select" : "______", + buttons & SNES_UP_MASK ? "Up" : "__", + buttons & SNES_DOWN_MASK ? "Down" : "____", + buttons & SNES_LEFT_MASK ? "Left" : "____", + buttons & SNES_RIGHT_MASK ? "Right" : "_____", + buttons & SNES_A_MASK ? 'A':'_', + buttons & SNES_B_MASK ? 'B':'_', + buttons & SNES_X_MASK ? 'X':'_', + buttons & SNES_Y_MASK ? 'Y':'_', + buttons & SNES_TL_MASK ? 'L':'_', + buttons & SNES_TR_MASK ? 'R':'_' + /*framecounter*/); + if (Settings.DisplayPressedKeys==1) + fprintf(stderr, "%s %d \r", buffer, framecounter); + //if (keypressscreen) + S9xSetInfoString(buffer); + } + + if (__builtin_expect(messageframe >= 0 && framecounter == messageframe, 0)) + { + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, message); + GFX.InfoStringTimeout = 300; + messageframe = -1; + } + +/* if (__builtin_expect(fastforwardpoint >= 0 && framecounter >= fastforwardpoint, 0)) + { + Settings.FramesToSkip = fastforwarddistance; + fastforwardpoint = -1; + }*/ +} + + +void AudioLogger(void *samples, int length) +{ + if (audio) + fwrite(samples, 1, length, audio); + drift--; +} diff --git a/source/snes9x/unused/logger.h b/source/snes9x/unused/logger.h new file mode 100644 index 0000000..330f251 --- /dev/null +++ b/source/snes9x/unused/logger.h @@ -0,0 +1,178 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +#ifndef LOGGER_H +#define LOGGER_H + +extern int dumpstreams; +extern char autodemo[128]; +extern int maxframes; +extern int logger_pivot; + +int Logger_FrameCounter(); +void Logger_NextFrame(); + +void ResetLogger(); +void VideoLogger(void *pixels, int width, int height, int depth, int bytes_per_row); +void AudioLogger(void *samples, int length); + +#endif diff --git a/source/snes9x/unused/makeasm.bat b/source/snes9x/unused/makeasm.bat new file mode 100644 index 0000000..856d4d1 --- /dev/null +++ b/source/snes9x/unused/makeasm.bat @@ -0,0 +1,14 @@ +@REM gcc -c -DEXECUTE_SUPERFX_PER_LINE -DMICROSOFT_C -DSPC700_C -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -Ii386 i386/cpuexec.S -o i386/cpuexec.obj +@REM gcc -c -DEXECUTE_SUPERFX_PER_LINE -DMICROSOFT_C -DSPC700_C -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -Ii386 i386/cpuops.S -o i386/cpuops.obj +@REM gcc -c -DEXECUTE_SUPERFX_PER_LINE -DMICROSOFT_C -DSPC700_C -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -Ii386 i386/sa1ops.S -o i386/sa1ops.obj +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/zsnes.obj i386/zsnes.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/fxemu2b.obj i386/fxemu2b.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/fxtable.obj i386/fxtable.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/fxemu2.obj i386/fxemu2.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/fxemu2c.obj i386/fxemu2c.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/sfxproc.obj i386/sfxproc.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/spc.obj i386/spc.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/zsnesc4.obj i386/zsnesc4.asm +@REM nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/c4.obj i386/c4.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/2xsaimmx.obj i386/2xsaimmx.asm +nasmw -d__DJGPP__=1 -dZSNES_FX -f win32 -i . -i i386 -o i386/bilinear.obj i386/bilinear.asm diff --git a/source/snes9x/unused/movie.cpp b/source/snes9x/unused/movie.cpp index 74d0ddc..09ed155 100644 --- a/source/snes9x/unused/movie.cpp +++ b/source/snes9x/unused/movie.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + // Input recording/playback code // (c) Copyright 2004 blip @@ -150,6 +169,7 @@ #endif #include #include +#include #if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) || defined(__MACOSX__) #include @@ -163,6 +183,7 @@ #ifndef W_OK #define W_OK 2 #endif +#define ftruncate chsize #endif #include "movie.h" @@ -170,12 +191,31 @@ #include "memmap.h" #include "cpuexec.h" #include "snapshot.h" +#include "controls.h" +#include "language.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif #define SMV_MAGIC 0x1a564d53 // SMV0x1a -#define SMV_VERSION 2 -#define SMV_HEADER_SIZE 32 +#define SMV_VERSION 4 +#define SMV_HEADER_SIZE 64 +#define SMV_EXTRAROMINFO_SIZE (3 + sizeof(uint32) + 23) #define CONTROLLER_DATA_SIZE 2 #define BUFFER_GROWTH_SIZE 4096 +#define PERIPHERAL_SUPPORT +#ifdef PERIPHERAL_SUPPORT + #define MOUSE_DATA_SIZE 5 + #define SCOPE_DATA_SIZE 6 + #define JUSTIFIER_DATA_SIZE 11 +#endif + +// HACK: reduce movie size by not storing changes that can only affect polled input in the movie for these types, because currently no port sets these types to polling +#define SKIPPED_POLLING_PORT_TYPE(x) ((x==CTL_NONE)||(x==CTL_JOYPAD)||(x==CTL_MP5)) + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif enum MovieState { @@ -197,33 +237,80 @@ static struct SMovie uint32 RerecordCount; uint8 ControllersMask; uint8 Opts; + uint8 SyncFlags; bool8 ReadOnly; - uint32 BytesPerFrame; + uint32 BytesPerSample; uint8* InputBuffer; uint32 InputBufferSize; uint8* InputBufferPtr; - bool8 FrameDisplay; - char FrameDisplayString[256]; + + uint32 ROMCRC32; + char ROMName [23]; + + uint32 CurrentSample; + uint32 MaxSample; + uint8 PortType[2]; + int8 PortIDs[2][4]; + + bool8 RecordedThisSession; + uint32 Version; } Movie; /* - For illustration: -struct MovieFileHeader -{ - uint32 magic; // SMV0x1a - uint32 version; - uint32 uid; // used to match savestates to a particular movie - uint32 rerecord_count; - uint32 length_frames; - uint8 flags[4]; - uint32 offset_to_savestate; // smvs have an embedded savestate - uint32 offset_to_controller_data; - // after the header comes extra metadata - // sizeof(metadata) = offset_to_savestate - sizeof(MovieFileHeader) -}; +// For illustration: + struct MovieFileHeader + { + uint32 magic; // SMV0x1a + uint32 version; // for Snes9x 1.51 this must be 4. In Snes9x 1.43 it was 1. + uint32 uid; // used to match savestates to a particular movie... this is also the date/time of first recording + uint32 rerecord_count; + uint32 length_frames; + uint8 flags[4]; // (ControllersMask, Opts, Reserved, SyncFlags) + uint32 offset_to_savestate; // pointer to embedded savestate or SRAM + uint32 offset_to_controller_data; // pointer to controller data + + uint32 length_samples; // number of recorded input samples, may be more than length_frames for peripheral-using games + uint8 PortType[2]; // for each controller port, 0=NONE, 1=JOYPAD, 2=MOUSE, 3=SUPERSCOPE, 4=JUSTIFIER, 5=MULTITAP + int8 PortIDs[2][4]; // for each port, then for each possible controller in the port, the controller ID number counting up from 0, or -1 if unplugged + uint8 reserved[18]; + }; + // sizeof(MovieFileHeader) == 64 + +// after the header comes extra metadata, i.e. author info + // sizeof(metadata) = (offset_to_savestate - sizeof(MovieFileHeader)) - sizeof(ExtraRomInfo); + // that should be an even number of bytes because the author info consists of 2-byte characters + +// after the metadata comes extra info about the ROM used for recording + struct ExtraRomInfo + { + uint8 reserved[3]; + uint32 romCRC32; + uint8 romName[23]; + }; + // sizeof(ExtraRomInfo) == 30 + +// after that comes the savestate or SRAM data (depending on the Opts flag) + // sizeof(SaveData) <= offset_to_controller_data - offset_to_savestate + +// after that comes the controller data + // sizeof(ControllerData) == length_samples * sizeof(InputSample) + // sizeof(InputSample) == 2*(sum of bits in ControllersMask) + 5*num_mouse_ports + 6*num_superscope_ports + 11*num_justifier_ports + */ -static int bytes_per_frame() +// some state for peripherals etc. (playback) +#ifdef PERIPHERAL_SUPPORT +uint8 prevPortType[2]; +int8 prevPortIDs[2][4]; +bool8 prevMouseMaster; +bool8 prevSuperScopeMaster; +bool8 prevJustifierMaster; +bool8 prevMultiPlayer5Master; +#endif +bool8 prevForcePal, prevPal, prevForceNTSC, delayedPrevRestore=false; +bool8 prevUpAndDown, prevSoundEnvelopeHeightReading, prevFakeMuteFix, prevSoundSync, prevCPUShutdown; + +static int bytes_per_sample() { int i; int num_controllers; @@ -237,31 +324,57 @@ static int bytes_per_frame() } } - return CONTROLLER_DATA_SIZE*num_controllers; + int bytes = CONTROLLER_DATA_SIZE*num_controllers; + +#ifdef PERIPHERAL_SUPPORT + for(int port=0; port<2; port++) + { + if(Movie.PortType[port] == CTL_MOUSE) bytes += MOUSE_DATA_SIZE; + if(Movie.PortType[port] == CTL_SUPERSCOPE) bytes += SCOPE_DATA_SIZE; + if(Movie.PortType[port] == CTL_JUSTIFIER) bytes += JUSTIFIER_DATA_SIZE; + // MP5 support is already handled by the regular controllers code + } +#endif + + return bytes; } -static inline uint32 Read32(const uint8*& ptr) +uint32 Read32(const uint8*& ptr) { uint32 v=(ptr[0] | (ptr[1]<<8) | (ptr[2]<<16) | (ptr[3]<<24)); ptr += 4; return v; } -static inline uint16 Read16(const uint8*& ptr) /* const version */ +uint16 Read16(const uint8*& ptr) /* const version */ { uint16 v=(ptr[0] | (ptr[1]<<8)); ptr += 2; return v; } -static inline uint16 Read16(uint8*& ptr) /* non-const version */ +uint16 Read16(uint8*& ptr) /* non-const version */ { uint16 v=(ptr[0] | (ptr[1]<<8)); ptr += 2; return v; } -static void Write32(uint32 v, uint8*& ptr) +static inline uint8 Read8(const uint8*& ptr) /* const version */ +{ + uint8 v=(ptr[0]); + ptr++; + return v; +} + +static inline uint8 Read8(uint8*& ptr) /* non-const version */ +{ + uint8 v=(ptr[0]); + ptr++; + return v; +} + +void Write32(uint32 v, uint8*& ptr) { ptr[0]=(uint8)(v&0xff); ptr[1]=(uint8)((v>>8)&0xff); @@ -270,13 +383,19 @@ static void Write32(uint32 v, uint8*& ptr) ptr += 4; } -static void Write16(uint16 v, uint8*& ptr) +void Write16(uint16 v, uint8*& ptr) { ptr[0]=(uint8)(v&0xff); ptr[1]=(uint8)((v>>8)&0xff); ptr += 2; } +static inline void Write8(uint8 v, uint8*& ptr) +{ + ptr[0]=(uint8)(v); + ptr++; +} + static int read_movie_header(FILE* fd, SMovie* movie) { uint8 header[SMV_HEADER_SIZE]; @@ -289,19 +408,81 @@ static int read_movie_header(FILE* fd, SMovie* movie) return WRONG_FORMAT; uint32 version=Read32(ptr); - if(version!=SMV_VERSION) + if(version>SMV_VERSION) return WRONG_VERSION; + // we can still get this basic info from v1 movies movie->MovieId=Read32(ptr); movie->RerecordCount=Read32(ptr); movie->MaxFrame=Read32(ptr); + movie->Version=version; - movie->ControllersMask=*ptr++; - movie->Opts=*ptr++; - ptr += 2; + int i, p, j; + for(j = 0; j < 2; j++) + { + if((j == 0 && version != 3) || (j == 1 && version == 3)) + { + movie->ControllersMask=Read8(ptr); + movie->Opts=Read8(ptr); + Read8(ptr); // reserved byte + movie->SyncFlags=Read8(ptr); - movie->SaveStateOffset=Read32(ptr); - movie->ControllerDataOffset=Read32(ptr); + movie->SaveStateOffset=Read32(ptr); + movie->ControllerDataOffset=Read32(ptr); + } + + // not part of original v1 SMV format: + + if((j == 1 && version > 3) || (j == 0 && version == 3)) + { + movie->MaxSample=Read32(ptr); + movie->PortType[0]=Read8(ptr); + movie->PortType[1]=Read8(ptr); + + for(p=0;p<2;p++) + for(i=0;i<4;i++) + movie->PortIDs[p][i]=Read8(ptr); + } + } + + if(version<3) + return WRONG_VERSION; + + // needs to be at least 1 sample per frame. So, assume that to make hex editing easier, at least for non-peripheral-using movies. + if(movie->MaxSample < movie->MaxFrame) + movie->MaxSample = movie->MaxFrame; + + + ptr += 18; // reserved bytes + + assert(ptr-header==SMV_HEADER_SIZE); + + return SUCCESS; +} + +static int read_movie_extrarominfo(FILE* fd, SMovie* movie) +{ + if((movie->SyncFlags & MOVIE_SYNC_HASROMINFO) != 0) + { + fseek(fd, movie->SaveStateOffset - SMV_EXTRAROMINFO_SIZE, SEEK_SET); + + uint8 extraRomInfo[SMV_EXTRAROMINFO_SIZE]; + if(fread(extraRomInfo, 1, SMV_EXTRAROMINFO_SIZE, fd) != SMV_EXTRAROMINFO_SIZE) + return WRONG_FORMAT; + + const uint8* ptr=extraRomInfo; + + ptr ++; // zero byte + ptr ++; // zero byte + ptr ++; // zero byte + movie->ROMCRC32=Read32(ptr); + strncpy(movie->ROMName,(const char*)ptr,23); ptr += 23; + } + else + { + movie->ROMCRC32=Memory.ROMCRC32; + strncpy(movie->ROMName,(const char*)Memory.ROMName,23); + } return SUCCESS; } @@ -317,23 +498,177 @@ static void write_movie_header(FILE* fd, const SMovie* movie) Write32(movie->RerecordCount, ptr); Write32(movie->MaxFrame, ptr); - *ptr++=movie->ControllersMask; - *ptr++=movie->Opts; - *ptr++=0; - *ptr++=0; + Write8(movie->ControllersMask, ptr); + Write8(movie->Opts, ptr); + Write8(0, ptr); // reserved byte + Write8(movie->SyncFlags, ptr); Write32(movie->SaveStateOffset, ptr); Write32(movie->ControllerDataOffset, ptr); + // not part of original v1 SMV format: + + Write32(movie->MaxSample, ptr); + Write8(movie->PortType[0], ptr); + Write8(movie->PortType[1], ptr); + + int i, p; + for(p=0;p<2;p++) + for(i=0;i<4;i++) + Write8(movie->PortIDs[p][i], ptr); + + // 18 reserved bytes, could be anything, ignored by this version when reading + for(i=0;i<18-4;i++) + Write8(0, ptr); + Write32(movie->RerecordCount/2, ptr); // why not... + + assert(ptr-header==SMV_HEADER_SIZE); + fwrite(header, 1, SMV_HEADER_SIZE, fd); + + assert(!ferror(fd)); +} + +static void write_movie_extrarominfo(FILE* fd, const SMovie* movie) +{ + if((movie->SyncFlags & MOVIE_SYNC_HASROMINFO) != 0) // should be true... + { + uint8 extraRomInfo [SMV_EXTRAROMINFO_SIZE]; + uint8* ptr = extraRomInfo; + + *ptr++=0; // zero byte + *ptr++=0; // zero byte + *ptr++=0; // zero byte + Write32(movie->ROMCRC32, ptr); + strncpy((char*)ptr,movie->ROMName,23); ptr += 23; + + fwrite(extraRomInfo, 1, SMV_EXTRAROMINFO_SIZE, fd); + assert(!ferror(fd)); + } } static void flush_movie() { + if(!Movie.File) + return; + fseek(Movie.File, 0, SEEK_SET); write_movie_header(Movie.File, &Movie); fseek(Movie.File, Movie.ControllerDataOffset, SEEK_SET); - fwrite(Movie.InputBuffer, 1, Movie.BytesPerFrame*(Movie.MaxFrame+1), Movie.File); + fwrite(Movie.InputBuffer, 1, Movie.BytesPerSample*(Movie.MaxSample+1), Movie.File); + assert(!ferror(Movie.File)); +} + +static void store_previous_settings() +{ +#ifdef PERIPHERAL_SUPPORT + for(int i=0; i<2; i++){ + enum controllers pt; + S9xGetController(i, &pt, &prevPortIDs[i][0],&prevPortIDs[i][1],&prevPortIDs[i][2],&prevPortIDs[i][3]); + prevPortType[i] = (uint8) pt; + } + prevMouseMaster = Settings.MouseMaster; + prevSuperScopeMaster = Settings.SuperScopeMaster; + prevJustifierMaster = Settings.JustifierMaster; + prevMultiPlayer5Master = Settings.MultiPlayer5Master; +#endif + if(!delayedPrevRestore) + { + prevPal = Settings.PAL; + prevCPUShutdown = Settings.ShutdownMaster; + } + delayedPrevRestore = false; + prevForcePal = Settings.ForcePAL; + prevForceNTSC = Settings.ForceNTSC; + prevUpAndDown = Settings.UpAndDown; + prevSoundEnvelopeHeightReading = Settings.SoundEnvelopeHeightReading; + prevFakeMuteFix = Settings.FakeMuteFix; + prevSoundSync = Settings.SoundSync; +} + +static void restore_previous_settings() +{ +#ifdef PERIPHERAL_SUPPORT + Settings.MouseMaster = prevMouseMaster; + Settings.SuperScopeMaster = prevSuperScopeMaster; + Settings.JustifierMaster = prevJustifierMaster; + Settings.MultiPlayer5Master = prevMultiPlayer5Master; + S9xSetController(0, (enum controllers)prevPortType[0], prevPortIDs[0][0],prevPortIDs[0][1],prevPortIDs[0][2],prevPortIDs[0][3]); + S9xSetController(1, (enum controllers)prevPortType[1], prevPortIDs[1][0],prevPortIDs[1][1],prevPortIDs[1][2],prevPortIDs[1][3]); +#endif + Settings.ForcePAL = prevForcePal; + Settings.ForceNTSC = prevForceNTSC; + Settings.SoundEnvelopeHeightReading = prevSoundEnvelopeHeightReading; + Settings.FakeMuteFix = prevFakeMuteFix; +// Settings.PAL = prevPal; // changing this after the movie while it's still emulating would be bad +// Settings.ShutdownMaster = prevCPUShutdown; // changing this after the movie while it's still emulating would be bad + delayedPrevRestore = true; // wait to change the above 2 settings until later +// Settings.UpAndDown = prevUpAndDown; // doesn't actually affect synchronization, so leave the setting alone; the port can change it if it wants +// Settings.SoundSync = prevSoundSync; // doesn't seem to affect synchronization, so leave the setting alone; the port can change it if it wants +} + +static void store_movie_settings() +{ +#ifdef PERIPHERAL_SUPPORT + for(int i=0; i<2; i++){ + enum controllers pt; + S9xGetController(i, &pt, &Movie.PortIDs[i][0],&Movie.PortIDs[i][1],&Movie.PortIDs[i][2],&Movie.PortIDs[i][3]); + Movie.PortType[i] = (uint8) pt; + } + if(!Movie.PortType[0] && !Movie.PortType[1]) + fprintf(stderr, "WARNING: S9xMovieCreate: no controller ports set\n"); +#endif + if(Settings.PAL) + Movie.Opts |= MOVIE_OPT_PAL; + else + Movie.Opts &= ~MOVIE_OPT_PAL; + Movie.SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; + if(Settings.UpAndDown) Movie.SyncFlags |= MOVIE_SYNC_LEFTRIGHT; + if(Settings.SoundEnvelopeHeightReading) Movie.SyncFlags |= MOVIE_SYNC_VOLUMEENVX; + if(Settings.FakeMuteFix || !Settings.APUEnabled) Movie.SyncFlags |= MOVIE_SYNC_FAKEMUTE; + if(Settings.SoundSync) Movie.SyncFlags |= MOVIE_SYNC_SYNCSOUND; + if(!Settings.ShutdownMaster) Movie.SyncFlags |= MOVIE_SYNC_NOCPUSHUTDOWN; +} + +static void restore_movie_settings() +{ +#ifdef PERIPHERAL_SUPPORT + Settings.MouseMaster = (Movie.PortType[0] == CTL_MOUSE || Movie.PortType[1] == CTL_MOUSE); + Settings.SuperScopeMaster = (Movie.PortType[0] == CTL_SUPERSCOPE || Movie.PortType[1] == CTL_SUPERSCOPE); + Settings.JustifierMaster = (Movie.PortType[0] == CTL_JUSTIFIER || Movie.PortType[1] == CTL_JUSTIFIER); + Settings.MultiPlayer5Master = (Movie.PortType[0] == CTL_MP5 || Movie.PortType[1] == CTL_MP5); + S9xSetController(0, (enum controllers)Movie.PortType[0], Movie.PortIDs[0][0],Movie.PortIDs[0][1],Movie.PortIDs[0][2],Movie.PortIDs[0][3]); + S9xSetController(1, (enum controllers)Movie.PortType[1], Movie.PortIDs[1][0],Movie.PortIDs[1][1],Movie.PortIDs[1][2],Movie.PortIDs[1][3]); +#endif + if(Movie.Opts & MOVIE_OPT_PAL) + { + Settings.ForcePAL = Settings.PAL = TRUE; // OK to change while starting playing a movie because either we are re-loading the ROM or we are entering a state that already had this setting set + Settings.ForceNTSC = FALSE; + } + else + { + Settings.ForcePAL = Settings.PAL = FALSE; // OK to change while starting playing a movie because either we are re-loading the ROM or we are entering a state that already had this setting set + Settings.ForceNTSC = TRUE; + } + Settings.SoundEnvelopeHeightReading = (Movie.SyncFlags & MOVIE_SYNC_VOLUMEENVX) ? TRUE : FALSE; + Settings.FakeMuteFix = (Movie.SyncFlags & MOVIE_SYNC_FAKEMUTE) ? TRUE : FALSE; + Settings.ShutdownMaster = (Movie.SyncFlags & MOVIE_SYNC_NOCPUSHUTDOWN) ? FALSE : TRUE; // OK to change while starting playing a movie because either we are re-loading the ROM or we are entering a state that already had this setting set +// Settings.UpAndDown = (Movie.SyncFlags & MOVIE_SYNC_LEFTRIGHT) ? TRUE : FALSE; // doesn't actually affect synchronization, so leave the setting alone; the port can change it if it wants +// Settings.SoundSync = (Movie.SyncFlags & MOVIE_SYNC_SYNCSOUND) ? TRUE : FALSE; // doesn't seem to affect synchronization, so leave the setting alone; the port can change it if it wants +} + +// file must still be open for this to work +static void truncate_movie() +{ + if(!Settings.MovieTruncate || !Movie.File) + return; + + assert(Movie.SaveStateOffset <= Movie.ControllerDataOffset); + if(Movie.SaveStateOffset > Movie.ControllerDataOffset) + return; + + const unsigned long length = Movie.ControllerDataOffset + Movie.BytesPerSample * (Movie.MaxSample + 1); + ftruncate(fileno(Movie.File), length); } static void change_state(MovieState new_state) @@ -346,19 +681,21 @@ static void change_state(MovieState new_state) flush_movie(); } - Movie.State=new_state; - if(new_state==MOVIE_STATE_NONE) { + // truncate movie to MaxSample length if Settings.MovieTruncate is true + truncate_movie(); + fclose(Movie.File); Movie.File=NULL; - // FIXME: truncate movie to MaxFrame length - /* truncate() could be used, if it's certain - * that the savestate block is never after - * the controller data block. It is not guaranteed - * by the format. - */ + + if(S9xMoviePlaying() || S9xMovieRecording()) // even if recording, it could have been switched to from playback + { + restore_previous_settings(); + } } + + Movie.State=new_state; } static void reserve_buffer_space(uint32 space_needed) @@ -377,10 +714,41 @@ static void reserve_buffer_space(uint32 space_needed) /* accessors into controls.cpp static variables */ uint16 MovieGetJoypad(int i); void MovieSetJoypad(int i, uint16 buttons); +#ifdef PERIPHERAL_SUPPORT +bool MovieGetMouse(int i, uint8 out [MOUSE_DATA_SIZE]); +void MovieSetMouse(int i, const uint8 in [MOUSE_DATA_SIZE], bool inPolling); +bool MovieGetScope(int i, uint8 out [SCOPE_DATA_SIZE]); +void MovieSetScope(int i, const uint8 in [SCOPE_DATA_SIZE]); +bool MovieGetJustifier(int i, uint8 out [JUSTIFIER_DATA_SIZE]); +void MovieSetJustifier(int i, const uint8 in [JUSTIFIER_DATA_SIZE]); +#endif -static void read_frame_controller_data() +static void read_frame_controller_data(bool addFrame) { int i; + + // one sample of all 1 bits = reset code + // (the SNES controller doesn't have enough buttons to possibly generate this sequence) + // (a single bit indicator was not used, to avoid having to special-case peripheral recording here) + if(Movie.InputBufferPtr[0] == 0xFF) + { + bool reset = true; + for(i=1; i<(int)Movie.BytesPerSample; i++) + { + if(Movie.InputBufferPtr[i] != 0xFF) + { + reset = false; + break; + } + } + if(reset) + { + Movie.InputBufferPtr += Movie.BytesPerSample; + S9xSoftReset(); + return; + } + } + for(i=0; i<8; ++i) { if(Movie.ControllersMask & (1<0) { uint8 meta_buf[MOVIE_MAX_METADATA * sizeof(uint16)]; - int i; - - for(i=0; i=Movie.MaxFrame) + case MOVIE_STATE_RECORD: { - change_state(MOVIE_STATE_NONE); - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_END); - return; + reserve_buffer_space((uint32)((Movie.InputBufferPtr+Movie.BytesPerSample)-Movie.InputBuffer)); + memset(Movie.InputBufferPtr, 0xFF, Movie.BytesPerSample); + Movie.InputBufferPtr += Movie.BytesPerSample; + Movie.MaxSample = ++Movie.CurrentSample; + Movie.MaxFrame = ++Movie.CurrentFrame; + fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + assert(!ferror(Movie.File)); } - else + break; + default: break; + } +} + +void S9xMovieUpdate (bool addFrame) +{ +movieUpdateStart: + switch(Movie.State) + { + case MOVIE_STATE_PLAY: { - if(Movie.FrameDisplay) + if(Movie.CurrentFrame>=Movie.MaxFrame || Movie.CurrentSample>=Movie.MaxSample) { - sprintf(Movie.FrameDisplayString, "Playing frame: %d", Movie.CurrentFrame); - S9xMessage (S9X_INFO, S9X_MOVIE_INFO, Movie.FrameDisplayString); + if(!Movie.RecordedThisSession) + { + // stop movie; it reached the end + change_state(MOVIE_STATE_NONE); + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_END); + return; + } + else + { + // if user has been recording this movie since the last time it started playing, + // they probably don't want the movie to end now during playback, + // so switch back to recording when it reaches the end + change_state(MOVIE_STATE_RECORD); + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RECORD); + fseek(Movie.File, Movie.ControllerDataOffset+(Movie.BytesPerSample * (Movie.CurrentSample+1)), SEEK_SET); + Settings.Paused = true; // also pause so it doesn't keep going unless they want it to + goto movieUpdateStart; + } + } + else + { + if(addFrame) + S9xUpdateFrameCounter(); + else if(SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + + read_frame_controller_data(addFrame); + ++Movie.CurrentSample; + if(addFrame) + ++Movie.CurrentFrame; } - read_frame_controller_data(); - ++Movie.CurrentFrame; } break; - case MOVIE_STATE_RECORD: + case MOVIE_STATE_RECORD: { - if(Movie.FrameDisplay) - { - sprintf(Movie.FrameDisplayString, "Recording frame: %d", Movie.CurrentFrame); - S9xMessage (S9X_INFO, S9X_MOVIE_INFO, Movie.FrameDisplayString); - } + if(addFrame) + S9xUpdateFrameCounter(); + else if(SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + write_frame_controller_data(); - ++Movie.CurrentFrame; - Movie.MaxFrame=Movie.CurrentFrame; - fwrite((Movie.InputBufferPtr - Movie.BytesPerFrame), 1, Movie.BytesPerFrame, Movie.File); + Movie.MaxSample = ++Movie.CurrentSample; + if(addFrame) + Movie.MaxFrame = ++Movie.CurrentFrame; + fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + assert(!ferror(Movie.File)); + + Movie.RecordedThisSession = true; } break; default: + if(addFrame) + S9xUpdateFrameCounter(); break; } } @@ -641,6 +1223,8 @@ void S9xMovieStop (bool8 suppress_message) int S9xMovieGetInfo (const char* filename, struct MovieInfo* info) { + flush_movie(); + FILE* fd; int result; SMovie local_movie; @@ -650,13 +1234,22 @@ int S9xMovieGetInfo (const char* filename, struct MovieInfo* info) if(!(fd=fopen(filename, "rb"))) return FILE_NOT_FOUND; - if((result=(read_movie_header(fd, &local_movie)))!=SUCCESS) + result = read_movie_header(fd, &local_movie); + + // we can still get this basic info from older, unsupported movies (v1 movies) + info->TimeCreated=(time_t)local_movie.MovieId; + info->RerecordCount=local_movie.RerecordCount; + info->LengthFrames=local_movie.MaxFrame; + info->Version=local_movie.Version; + + if(result!=SUCCESS) return result; - info->TimeCreated=(time_t)local_movie.MovieId; - info->LengthFrames=local_movie.MaxFrame; - info->RerecordCount=local_movie.RerecordCount; + info->LengthSamples=local_movie.MaxSample; + info->PortType[0]=local_movie.PortType[0]; + info->PortType[1]=local_movie.PortType[1]; info->Opts=local_movie.Opts; + info->SyncFlags=local_movie.SyncFlags; info->ControllersMask=local_movie.ControllersMask; if(local_movie.SaveStateOffset > SMV_HEADER_SIZE) @@ -664,7 +1257,9 @@ int S9xMovieGetInfo (const char* filename, struct MovieInfo* info) uint8 meta_buf[MOVIE_MAX_METADATA * sizeof(uint16)]; int i; - metadata_length=((int)local_movie.SaveStateOffset-SMV_HEADER_SIZE)/sizeof(uint16); + int curRomInfoSize = (local_movie.SyncFlags & MOVIE_SYNC_HASROMINFO) != 0 ? SMV_EXTRAROMINFO_SIZE : 0; + + metadata_length=((int)local_movie.SaveStateOffset-SMV_HEADER_SIZE-curRomInfoSize)/sizeof(uint16); metadata_length=(metadata_length>=MOVIE_MAX_METADATA) ? MOVIE_MAX_METADATA-1 : metadata_length; metadata_length=(int)fread(meta_buf, sizeof(uint16), metadata_length, fd); @@ -680,6 +1275,11 @@ int S9xMovieGetInfo (const char* filename, struct MovieInfo* info) info->Metadata[0]='\0'; } + read_movie_extrarominfo(fd, &local_movie); + + info->ROMCRC32=local_movie.ROMCRC32; + strncpy(info->ROMName,local_movie.ROMName,23); + fclose(fd); if(access(filename, W_OK)) @@ -692,6 +1292,19 @@ bool8 S9xMovieActive () { return (Movie.State!=MOVIE_STATE_NONE); } +bool8 S9xMoviePlaying () +{ + return (Movie.State==MOVIE_STATE_PLAY); +} +bool8 S9xMovieRecording () +{ + return (Movie.State==MOVIE_STATE_RECORD); +} + +uint8 S9xMovieControllers () +{ + return Movie.ControllersMask; +} bool8 S9xMovieReadOnly () { @@ -725,13 +1338,22 @@ uint32 S9xMovieGetFrameCounter () return Movie.CurrentFrame; } +void S9xMovieToggleRecState() +{ + Movie.ReadOnly=!Movie.ReadOnly; + + if (Movie.ReadOnly) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read-only."); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read+write."); +} + void S9xMovieToggleFrameDisplay () { - Movie.FrameDisplay = !Movie.FrameDisplay; - if(!Movie.FrameDisplay) - { - GFX.InfoStringTimeout = 1; - } + GFX.FrameDisplay = !GFX.FrameDisplay; + // updating the frame counter string here won't work, because it may or may not be 1 too high now + extern void S9xReRefresh(); + S9xReRefresh(); } void S9xMovieFreeze (uint8** buf, uint32* size) @@ -746,8 +1368,8 @@ void S9xMovieFreeze (uint8** buf, uint32* size) *size = 0; // compute size needed for the buffer - uint32 size_needed = 4*3; // room for MovieId, CurrentFrame, and MaxFrame - size_needed += (uint32)(Movie.BytesPerFrame * (Movie.MaxFrame+1)); + uint32 size_needed = sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample); + size_needed += (uint32)(Movie.BytesPerSample * (Movie.MaxSample+1)); *buf=new uint8[size_needed]; *size=size_needed; @@ -760,76 +1382,92 @@ void S9xMovieFreeze (uint8** buf, uint32* size) Write32(Movie.MovieId, ptr); Write32(Movie.CurrentFrame, ptr); Write32(Movie.MaxFrame, ptr); + Write32(Movie.CurrentSample, ptr); + Write32(Movie.MaxSample, ptr); - memcpy(ptr, Movie.InputBuffer, Movie.BytesPerFrame * (Movie.MaxFrame+1)); + memcpy(ptr, Movie.InputBuffer, Movie.BytesPerSample * (Movie.MaxSample+1)); } -bool8 S9xMovieUnfreeze (const uint8* buf, uint32 size) +int S9xMovieUnfreeze (const uint8* buf, uint32 size) { // sanity check if(!S9xMovieActive()) { - return false; + return FILE_NOT_FOUND; } const uint8* ptr = buf; - if(size < 4*3) + if(size < sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample) ) { - return false; + return WRONG_FORMAT; } uint32 movie_id = Read32(ptr); uint32 current_frame = Read32(ptr); uint32 max_frame = Read32(ptr); - uint32 space_needed = (Movie.BytesPerFrame * (max_frame+1)); + uint32 current_sample = Read32(ptr); + uint32 max_sample = Read32(ptr); + uint32 space_needed = (Movie.BytesPerSample * (max_sample+1)); - if(movie_id != Movie.MovieId || - current_frame > max_frame || - space_needed > size) + if(current_frame > max_frame || + current_sample > max_sample || + space_needed > size) { - return false; + return WRONG_MOVIE_SNAPSHOT; } + if(movie_id != Movie.MovieId) + if(Settings.WrongMovieStateProtection) + if(max_frame < Movie.MaxFrame || max_sample < Movie.MaxSample || + memcmp(Movie.InputBuffer, ptr, space_needed)) + return WRONG_MOVIE_SNAPSHOT; + if(!Movie.ReadOnly) { // here, we are going to take the input data from the savestate // and make it the input data for the current movie, then continue // writing new input data at the currentframe pointer change_state(MOVIE_STATE_RECORD); - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RERECORD); +// S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RERECORD); Movie.CurrentFrame = current_frame; Movie.MaxFrame = max_frame; + Movie.CurrentSample = current_sample; + Movie.MaxSample = max_sample; ++Movie.RerecordCount; + // when re-recording, update the sync info in the movie to the new settings as of the last re-record. + store_movie_settings(); + reserve_buffer_space(space_needed); memcpy(Movie.InputBuffer, ptr, space_needed); flush_movie(); - fseek(Movie.File, Movie.ControllerDataOffset+(Movie.BytesPerFrame * (Movie.CurrentFrame+1)), SEEK_SET); + fseek(Movie.File, Movie.ControllerDataOffset+(Movie.BytesPerSample * (Movie.CurrentSample+1)), SEEK_SET); } else { // here, we are going to keep the input data from the movie file // and simply rewind to the currentframe pointer - // this will cause a desync if the savestate is not in sync + // this will cause a desync if the savestate is not in sync // <-- NOT ANYMORE // with the on-disk recording data, but it's easily solved // by loading another savestate or playing the movie from the beginning - // and older savestate might have a currentframe pointer past - // the end of the input data, so check for that here - if(current_frame > Movie.MaxFrame) + // don't allow loading a state inconsistent with the current movie + if(current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || + memcmp(Movie.InputBuffer, ptr, space_needed)) { - return false; + return SNAPSHOT_INCONSISTENT; } change_state(MOVIE_STATE_PLAY); - S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REWIND); +// S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REWIND); Movie.CurrentFrame = current_frame; + Movie.CurrentSample = current_sample; } - Movie.InputBufferPtr = Movie.InputBuffer + (Movie.BytesPerFrame * Movie.CurrentFrame); - read_frame_controller_data(); + Movie.InputBufferPtr = Movie.InputBuffer + (Movie.BytesPerSample * (Movie.CurrentSample)); + read_frame_controller_data(true); - return true; + return SUCCESS; } diff --git a/source/snes9x/movie.h b/source/snes9x/unused/movie.h similarity index 83% rename from source/snes9x/movie.h rename to source/snes9x/unused/movie.h index 4f4d47a..efc14ca 100644 --- a/source/snes9x/movie.h +++ b/source/snes9x/unused/movie.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + // Input recording/playback code // (c) Copyright 2004 blip @@ -161,8 +180,18 @@ #define MOVIE_OPT_FROM_SNAPSHOT 0 #define MOVIE_OPT_FROM_RESET (1<<0) #define MOVIE_OPT_PAL (1<<1) +#define MOVIE_OPT_NOSAVEDATA (1<<2) #define MOVIE_MAX_METADATA 512 +#define MOVIE_SYNC_DATA_EXISTS 0x01 +#define MOVIE_SYNC_OBSOLETE 0x02 +#define MOVIE_SYNC_LEFTRIGHT 0x04 +#define MOVIE_SYNC_VOLUMEENVX 0x08 +#define MOVIE_SYNC_FAKEMUTE 0x10 +#define MOVIE_SYNC_SYNCSOUND 0x20 +#define MOVIE_SYNC_HASROMINFO 0x40 +#define MOVIE_SYNC_NOCPUSHUTDOWN 0x80 + START_EXTERN_C struct MovieInfo { @@ -173,6 +202,14 @@ struct MovieInfo uint8 Opts; uint8 ControllersMask; bool8 ReadOnly; + uint8 SyncFlags; + + uint32 ROMCRC32; + char ROMName [23]; + + uint32 LengthSamples; + uint8 PortType[2]; + uint32 Version; }; // methods used by the user-interface code @@ -180,23 +217,30 @@ int S9xMovieOpen (const char* filename, bool8 read_only); int S9xMovieCreate (const char* filename, uint8 controllers_mask, uint8 opts, const wchar_t* metadata, int metadata_length); int S9xMovieGetInfo (const char* filename, struct MovieInfo* info); void S9xMovieStop (bool8 suppress_message); +void S9xMovieToggleRecState (); void S9xMovieToggleFrameDisplay (); const char *S9xChooseMovieFilename(bool8 read_only); // methods used by the emulation void S9xMovieInit (); -void S9xMovieUpdate (); +void S9xMovieShutdown (); +void S9xMovieUpdate (bool addFrame=true); +void S9xMovieUpdateOnReset (); //bool8 S9xMovieRewind (uint32 at_frame); void S9xMovieFreeze (uint8** buf, uint32* size); -bool8 S9xMovieUnfreeze (const uint8* buf, uint32 size); +int S9xMovieUnfreeze (const uint8* buf, uint32 size); +void S9xUpdateFrameCounter (int offset=0); // accessor functions bool8 S9xMovieActive (); +bool8 S9xMoviePlaying (); +bool8 S9xMovieRecording (); // the following accessors return 0/false if !S9xMovieActive() bool8 S9xMovieReadOnly (); uint32 S9xMovieGetId (); uint32 S9xMovieGetLength (); uint32 S9xMovieGetFrameCounter (); +uint8 S9xMovieControllers (); END_EXTERN_C diff --git a/source/snes9x/unused/netplay.cpp b/source/snes9x/unused/netplay.cpp index a015f5b..1283c40 100644 --- a/source/snes9x/unused/netplay.cpp +++ b/source/snes9x/unused/netplay.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,7 +159,14 @@ **********************************************************************************/ + + #ifdef NETPLAY_SUPPORT +#ifdef _DEBUG + #define NP_DEBUG 1 +#endif + +#define NP_DEBUG 3 // FF-FIXME #include #include @@ -150,33 +174,31 @@ #include #include -#ifndef __WIN32__ -#include -#include -#include -#include -#endif +#ifdef __WIN32__ + #include + #include + #include "win32/wsnes9x.h" -#if defined (__WIN32__) -#include -#include - -#define ioctl ioctlsocket -#define close closesocket -#define read(a,b,c) recv(a, b, c, 0) -#define write(a,b,c) send(a, b, c, 0) + #define ioctl ioctlsocket + #define close closesocket + #define read(a,b,c) recv(a, b, c, 0) + #define write(a,b,c) send(a, b, c, 0) #else + #include + #include + #include + #include -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include -#ifdef __SVR4 -#include -#endif + #ifdef __SVR4 + #include + #endif #endif #ifdef USE_THREADS @@ -201,6 +223,8 @@ void S9xNPGetFreezeFile (uint32 len); unsigned long START = 0; +bool8 S9xNPConnect (); + bool8 S9xNPConnectToServer (const char *hostname, int port, const char *rom_name) { @@ -234,9 +258,11 @@ bool8 S9xNPConnectToServer (const char *hostname, int port, NetPlay.ReplyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); _beginthread (S9xNPClientLoop, 0, NULL); -#endif return (TRUE); +#endif + + return S9xNPConnect(); } bool8 S9xNPConnect () @@ -244,7 +270,7 @@ bool8 S9xNPConnect () struct sockaddr_in address; struct hostent *hostinfo; unsigned int addr; - + address.sin_family = AF_INET; address.sin_port = htons (NetPlay.Port); #ifdef NP_DEBUG @@ -331,7 +357,7 @@ on the remote machine on this port?"); WRITE_LONG (ptr, len); ptr += 4; #ifdef __WIN32__ - uint32 ft = Settings.FrameTime * 1000; + uint32 ft = Settings.FrameTime; WRITE_LONG (ptr, ft); #else @@ -356,8 +382,8 @@ on the remote machine on this port?"); uint8 header [7]; - if (!S9xNPGetData (NetPlay.Socket, header, 7) || - header [0] != NP_SERV_MAGIC || header [1] != 0 || + if (!S9xNPGetData (NetPlay.Socket, header, 7) || + header [0] != NP_SERV_MAGIC || header [1] != 0 || (header [2] & 0x1f) != NP_SERV_HELLO) { S9xNPSetError ("Error in 'HELLO' reply packet received from server."); @@ -412,14 +438,14 @@ version of the protocol. Disconnecting."); Settings.NetPlay = TRUE; S9xNPResetJoypadReadPos (); NetPlay.ServerSequenceNum = 1; - + #ifdef NP_DEBUG printf ("CLIENT: Sending 'READY' to server @%ld...\n", S9xGetMilliTime () - START); #endif S9xNPSetAction ("Sending 'READY' to the server..."); - return (S9xNPSendReady ((header [2] & 0x80) ? - NP_CLNT_WAITING_FOR_ROM_IMAGE : + return (S9xNPSendReady ((header [2] & 0x80) ? + NP_CLNT_WAITING_FOR_ROM_IMAGE : NP_CLNT_READY)); } @@ -488,7 +514,7 @@ void S9xNPClientLoop (void *) } else { - if (!NetPlay.Waiting4EmulationThread && + if (!NetPlay.Waiting4EmulationThread && prev == (int) NetPlay.MaxBehindFrameCount) { NetPlay.Waiting4EmulationThread = TRUE; @@ -510,6 +536,45 @@ void S9xNPClientLoop (void *) } #endif +bool8 S9xNPCheckForHeartBeat (uint32 time_msec) +{ + fd_set read_fds; + struct timeval timeout; + int res; + int i; + + int max_fd = NetPlay.Socket; + + FD_ZERO (&read_fds); + FD_SET (NetPlay.Socket, &read_fds); + + timeout.tv_sec = 0; + timeout.tv_usec = time_msec * 1000; + res = select (max_fd + 1, &read_fds, NULL, NULL, &timeout); + + i = (res > 0 && FD_ISSET(NetPlay.Socket, &read_fds)); + +#if defined(NP_DEBUG) && NP_DEBUG >= 4 + printf ("CLIENT: S9xCheckForHeartBeat %s @%ld\n", (i?"successful":"still waiting"), S9xGetMilliTime () - START); +#endif + + return i; +} + +bool8 S9xNPWaitForHeartBeatDelay (uint32 time_msec) +{ + if (!S9xNPCheckForHeartBeat(time_msec)) + return FALSE; + + if (!S9xNPWaitForHeartBeat()) + { + S9xNPDisconnect(); + return FALSE; + } + + return TRUE; +} + bool8 S9xNPWaitForHeartBeat () { uint8 header [3 + 4 + 4 * 5]; @@ -531,7 +596,7 @@ bool8 S9xNPWaitForHeartBeat () } else NetPlay.ServerSequenceNum++; - + if ((header [2] & 0x1f) == NP_SERV_JOYPAD) { // Top 2 bits + 1 of opcode is joypad data count. @@ -548,15 +613,18 @@ bool8 S9xNPWaitForHeartBeat () } NetPlay.Frame [NetPlay.JoypadWriteInd] = READ_LONG (&header [3]); - for (int i = 0; i < num; i++) - { - NetPlay.Joypads [NetPlay.JoypadWriteInd][i] = - READ_LONG (&header [3 + 4 + i * sizeof (uint32)]); - } - NetPlay.Paused = (header [2] & 0x20) != 0; + int i; + + for (i = 0; i < num; i++) + NetPlay.Joypads [NetPlay.JoypadWriteInd][i] = READ_LONG (&header [3 + 4 + i * sizeof (uint32)]); + + for (i = 0; i < NP_MAX_CLIENTS; i++) + NetPlay.JoypadsReady [NetPlay.JoypadWriteInd][i] = TRUE; + + NetPlay.Paused = (header [2] & 0x20) != 0; NetPlay.JoypadWriteInd = (NetPlay.JoypadWriteInd + 1) % NP_JOYPAD_HIST_SIZE; - + if (NetPlay.JoypadWriteInd != (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE) { //printf ("(%d)", (NetPlay.JoypadWriteInd - NetPlay.JoypadReadInd) % NP_JOYPAD_HIST_SIZE); fflush (stdout); @@ -581,6 +649,10 @@ bool8 S9xNPWaitForHeartBeat () break; case NP_SERV_PAUSE: NetPlay.Paused = (header [2] & 0x20) != 0; + if (NetPlay.Paused) + S9xNPSetWarning("CLIENT: Server has paused."); + else + S9xNPSetWarning("CLIENT: Server has resumed."); break; case NP_SERV_LOAD_ROM: #ifdef NP_DEBUG @@ -633,7 +705,7 @@ bool8 S9xNPLoadROMDialog (const char *rom_name) NetPlay.Answer = FALSE; #ifdef __WIN32__ - ResetEvent (NetPlay.ReplyEvent); + ResetEvent (NetPlay.ReplyEvent); #ifdef NP_DEBUG printf ("CLIENT: Asking GUI thread to open ROM load dialog...\n"); @@ -658,7 +730,7 @@ bool8 S9xNPLoadROMDialog (const char *rom_name) bool8 S9xNPLoadROM (uint32 len) { uint8 *data = new uint8 [len]; - + S9xNPSetAction ("Receiving ROM name..."); if (!S9xNPGetData (NetPlay.Socket, data, len)) { @@ -667,7 +739,7 @@ bool8 S9xNPLoadROM (uint32 len) S9xNPDisconnect (); return (FALSE); } - + S9xNPSetAction ("Opening LoadROM dialog..."); if (!S9xNPLoadROMDialog ((char *) data)) { @@ -695,14 +767,14 @@ bool8 S9xNPGetROMImage (uint32 len) #ifdef NP_DEBUG printf ("CLIENT: Hi-ROM: %s, Size: %04x\n", rom_info [0] ? "Y" : "N", CalculatedSize); #endif - if (CalculatedSize + 5 >= len || + if (CalculatedSize + 5 >= len || CalculatedSize >= CMemory::MAX_ROM_SIZE) { S9xNPSetError ("Size error in ROM image data received from server."); S9xNPDisconnect (); return (FALSE); } - + Memory.HiROM = rom_info [0]; Memory.LoROM = !Memory.HiROM; Memory.HeaderCount = 0; @@ -716,7 +788,7 @@ bool8 S9xNPGetROMImage (uint32 len) if (!S9xNPGetData (NetPlay.Socket, Memory.ROM, Memory.CalculatedSize)) { S9xNPSetError ("Error while receiving ROM image from server."); - Settings.StopEmulation = TRUE; + Settings.StopEmulation = TRUE; S9xNPDisconnect (); return (FALSE); } @@ -733,7 +805,7 @@ bool8 S9xNPGetROMImage (uint32 len) Settings.StopEmulation = TRUE; return (FALSE); } - Memory.InitROM (FALSE); + Memory.InitROM (); S9xReset (); S9xNPResetJoypadReadPos (); Settings.StopEmulation = FALSE; @@ -741,7 +813,7 @@ bool8 S9xNPGetROMImage (uint32 len) #ifdef __WIN32__ PostMessage (GUI.hWnd, WM_NULL, 0, 0); #endif - + return (TRUE); } @@ -754,11 +826,12 @@ void S9xNPGetSRAMData (uint32 len) return; } S9xNPSetAction ("Receiving S-RAM data..."); - if (len > 0 && !S9xNPGetData (NetPlay.Socket, ::SRAM, len)) + if (len > 0 && !S9xNPGetData (NetPlay.Socket, Memory.SRAM, len)) { S9xNPSetError ("Error while receiving S-RAM data from server."); S9xNPDisconnect (); } + S9xNPSetAction ("", TRUE); } void S9xNPGetFreezeFile (uint32 len) @@ -789,13 +862,14 @@ void S9xNPGetFreezeFile (uint32 len) delete data; return; } + S9xNPSetAction ("", TRUE); //FIXME: Setting umask here wouldn't hurt. FILE *file; #ifdef HAVE_MKSTEMP int fd; char fname[] = "/tmp/snes9x_fztmpXXXXXX"; - if ((fd = mkstemp(fname)) < 0) + if ((fd = mkstemp(fname)) >= 0) { if ((file = fdopen (fd, "wb"))) #else @@ -808,11 +882,23 @@ void S9xNPGetFreezeFile (uint32 len) if (fwrite (data, 1, len, file) == len) { fclose(file); +#ifndef __WIN32__ + /* We need .s96 extension, else .s96 is addded by unix code */ + char buf[PATH_MAX +1 ]; + + strncpy(buf, fname, PATH_MAX); + strcat(buf, ".s96"); + + rename(fname, buf); + + if (!S9xUnfreezeGame (buf)) +#else if (!S9xUnfreezeGame (fname)) +#endif S9xNPSetError ("Unable to load freeze file just received."); } else { S9xNPSetError ("Failed to write to temporary freeze file."); - fclose (file); + fclose(file); } } else S9xNPSetError ("Failed to create temporary freeze file."); @@ -824,8 +910,18 @@ void S9xNPGetFreezeFile (uint32 len) uint32 S9xNPGetJoypad (int which1) { - if (Settings.NetPlay && which1 < 5) - return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]); + if (Settings.NetPlay && which1 < 8) + { +#ifdef NP_DEBUG + if(!NetPlay.JoypadsReady [NetPlay.JoypadReadInd][which1]) + { + S9xNPSetWarning ("Missing input from server!"); + } +#endif + NetPlay.JoypadsReady [NetPlay.JoypadReadInd][which1] = FALSE; + + return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]); + } return (0); } @@ -861,6 +957,8 @@ void S9xNPResetJoypadReadPos () NetPlay.JoypadReadInd = NP_JOYPAD_HIST_SIZE - 1; for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++) memset ((void *) &NetPlay.Joypads [h], 0, sizeof (NetPlay.Joypads [0])); + for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++) + memset ((void *) &NetPlay.JoypadsReady [h], 0, sizeof (NetPlay.JoypadsReady [0])); } bool8 S9xNPSendJoypadUpdate (uint32 joypad) @@ -914,7 +1012,7 @@ bool8 S9xNPSendData (int socket, const uint8 *data, int length) int sent = write (socket, (char *) ptr, num_bytes); if (sent < 0) { - if (errno == EINTR + if (errno == EINTR #ifdef EAGAIN || errno == EAGAIN #endif @@ -1009,12 +1107,12 @@ bool8 S9xNPGetData (int socket, uint8 *data, int length) { NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length); #ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete, + PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete, NetPlay.PercentageComplete); Sleep (0); #endif } - + } while (len > 0); return (TRUE); @@ -1039,11 +1137,11 @@ bool8 S9xNPInitialise () if (WSAStartup (MAKEWORD (1, 0), &data) != 0) { S9xNPSetError ("Call to init Windows sockets failed. Do you have WinSock2 installed?"); - return (FALSE); + return (FALSE); } } #endif - return (TRUE); + return (TRUE); } void S9xNPDiscardHeartbeats () @@ -1068,6 +1166,9 @@ void S9xNPDiscardHeartbeats () void S9xNPSetAction (const char *action, bool8 force) { +#ifdef NP_DEBUG + printf ("NPSetAction: %s, forced = %d %ld\n", action, force, S9xGetMilliTime () - START); +#endif if (force || !Settings.NetPlayServer) { strncpy (NetPlay.ActionMsg, action, NP_MAX_ACTION_LEN - 1); @@ -1081,9 +1182,13 @@ void S9xNPSetAction (const char *action, bool8 force) void S9xNPSetError (const char *error) { +#if defined(NP_DEBUG) && NP_DEBUG == 2 + printf("ERROR: %s\n", error); + fflush (stdout); +#endif strncpy (NetPlay.ErrorMsg, error, NP_MAX_ACTION_LEN - 1); NetPlay.ErrorMsg [NP_MAX_ACTION_LEN - 1] = 0; -#ifdef __WIN32 +#ifdef __WIN32__ PostMessage (GUI.hWnd, WM_USER + 1, 0, 0); Sleep (0); #endif @@ -1091,6 +1196,10 @@ void S9xNPSetError (const char *error) void S9xNPSetWarning (const char *warning) { +#if defined(NP_DEBUG) && NP_DEBUG == 3 + printf("Warning: %s\n", warning); + fflush (stdout); +#endif strncpy (NetPlay.WarningMsg, warning, NP_MAX_ACTION_LEN - 1); NetPlay.WarningMsg [NP_MAX_ACTION_LEN - 1] = 0; #ifdef __WIN32__ diff --git a/source/snes9x/unused/netplay.h b/source/snes9x/unused/netplay.h index bfede8b..686e414 100644 --- a/source/snes9x/unused/netplay.h +++ b/source/snes9x/unused/netplay.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,6 +159,8 @@ **********************************************************************************/ + + #ifndef _NETPLAY_H_ #define _NETPLAY_H_ @@ -166,7 +185,7 @@ #define NP_JOYPAD_HIST_SIZE 120 #define NP_DEFAULT_PORT 6096 -#define NP_MAX_CLIENTS 5 +#define NP_MAX_CLIENTS 8 #define NP_SERV_MAGIC 'S' #define NP_CLNT_MAGIC 'C' @@ -238,7 +257,7 @@ struct SNPServer uint32 FrameTime; uint32 FrameCount; char ROMName [30]; - uint32 Joypads [5]; + uint32 Joypads [NP_MAX_CLIENTS]; bool8 ClientPaused; uint32 Paused; bool8 SendROMImageOnConnect; @@ -275,6 +294,7 @@ struct SNetPlay uint32 FrameCount; uint32 MaxFrameSkip; uint32 MaxBehindFrameCount; + bool8 JoypadsReady [NP_JOYPAD_HIST_SIZE][NP_MAX_CLIENTS]; char ActionMsg [NP_MAX_ACTION_LEN]; char ErrorMsg [NP_MAX_ACTION_LEN]; char WarningMsg [NP_MAX_ACTION_LEN]; @@ -304,6 +324,8 @@ extern "C" struct SNetPlay NetPlay; bool8 S9xNPConnectToServer (const char *server_name, int port, const char *rom_name); bool8 S9xNPWaitForHeartBeat (); +bool8 S9xNPWaitForHeartBeatDelay (uint32 time_msec = 0); +bool8 S9xNPCheckForHeartBeat (uint32 time_msec = 0); uint32 S9xNPGetJoypad (int which1); bool8 S9xNPSendJoypadUpdate (uint32 joypad); void S9xNPDisconnect (); diff --git a/source/snes9x/unused/offsets.cpp b/source/snes9x/unused/offsets.cpp new file mode 100644 index 0000000..021c0fe --- /dev/null +++ b/source/snes9x/unused/offsets.cpp @@ -0,0 +1,481 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + + +#include "snes9x.h" +#include "65c816.h" +#include "memmap.h" +#include "ppu.h" +#include "apu.h" +#include "cpuexec.h" +#include "sa1.h" + +#ifndef S9xSTREAM +#define S9xSTREAM stdout +#endif + +#define OFFSET(N,F) \ +fprintf (S9xSTREAM, "#define " #N " CPU + %d\n", (int) &((struct SCPUState *) 0)->F); +#define OFFSET2(N,F) \ +fprintf (S9xSTREAM, "#define " #N " Registers + %d\n", (int) &((struct SRegisters *) 0)->F); +#define OFFSET3(F) \ +fprintf (S9xSTREAM, "#define " #F " Memory + %d\n", (int) &((class CMemory *) 0)->F); +#define OFFSET4(N,F) \ +fprintf (S9xSTREAM, "#define " #N " APU + %d\n", (int) &((struct SAPU *) 0)->F); +#define OFFSET5(N,F) \ +fprintf (S9xSTREAM, "#define " #N " IAPU + %d\n", (int) &((struct SIAPU *) 0)->F); +#define OFFSET6(N,F) \ +fprintf (S9xSTREAM, "#define " #N " ICPU + %d\n", (int) &((struct SICPU *) 0)->F); +#define OFFSET7(N,F) \ +fprintf (S9xSTREAM, "#define " #N " Settings + %d\n", (int) &((struct SSettings *) 0)->F); +#define OFFSET8(N, F) \ +fprintf (S9xSTREAM, "#define " #N " APURegisters + %d\n", (int) &((struct SAPURegisters *) 0)->F); + +#define OFFSET9(N, F) \ +fprintf (S9xSTREAM, "#define " #N " PPU + %d\n", (int) &((struct SPPU *) 0)->F); +#define OFFSET10(N, F) \ +fprintf (S9xSTREAM, "#define " #N " IPPU + %d\n", (int) &((struct InternalPPU *) 0)->F); +#define OFFSET11(N, F) \ +fprintf (S9xSTREAM, "#define " #N " SA1 + %d\n", (int) &((struct SSA1 *) 0)->F); +#define OFFSET12(N, F) \ +fprintf (S9xSTREAM, "#define " #N " SA1Registers + %d\n", (int) &((struct SSA1Registers *) 0)->F); + +int main (int /*argc*/, char ** /*argv*/) +{ + OFFSET(Flags,Flags) + OFFSET(BranchSkip,BranchSkip) + OFFSET(NMIActive,NMIActive) + OFFSET(IRQActive,IRQActive) + OFFSET(WaitingForInterrupt,WaitingForInterrupt) + OFFSET(InDMA,InDMA) + OFFSET(InWRAM_DMA,InWRAM_DMA) + OFFSET(WhichEvent,WhichEvent) + OFFSET(PCBase,PCBase) + OFFSET(PBPCAtOpcodeStart,PBPCAtOpcodeStart) + OFFSET(WaitAddress,WaitAddress) + OFFSET(WaitCounter,WaitCounter) + OFFSET(Cycles,Cycles) + OFFSET(NextEvent,NextEvent) + OFFSET(V_Counter,V_Counter) + OFFSET(MemSpeed,MemSpeed) + OFFSET(MemSpeedx2,MemSpeedx2) + OFFSET(FastROMSpeed,FastROMSpeed) + OFFSET(AutoSaveTimer,AutoSaveTimer) + OFFSET(SRAMModified,SRAMModified) + OFFSET(BRKTriggered,BRKTriggered) + OFFSET(TriedInterleavedMode2,TriedInterleavedMode2) + + OFFSET2(DB,DB) + OFFSET2(PP,P.W) + OFFSET2(PL,P.W) + fprintf (S9xSTREAM, "#define PH PL + 1\n"); + OFFSET2(AA,A.W) + OFFSET2(AL,A.W) + fprintf (S9xSTREAM, "#define AH AL + 1\n"); + OFFSET2(DD,D.W) + OFFSET2(DL,D.W) + fprintf (S9xSTREAM, "#define DH DL + 1\n"); + OFFSET2(SS,S.W) + OFFSET2(SL,S.W) + fprintf (S9xSTREAM, "#define SH SL + 1\n"); + OFFSET2(XX,X.W) + OFFSET2(XL,X.W) + fprintf (S9xSTREAM, "#define XH XL + 1\n"); + OFFSET2(YY,Y.W) + OFFSET2(YL,Y.W) + fprintf (S9xSTREAM, "#define YH YL + 1\n"); + OFFSET2(PCR,PC.W.xPC) + OFFSET2(PB,PC.B.xPB) + + OFFSET3(RAM) + OFFSET3(ROM) + OFFSET3(VRAM) + OFFSET3(SRAM) + OFFSET3(BWRAM) + OFFSET3(FillRAM) + OFFSET3(C4RAM) + OFFSET3(HiROM) + OFFSET3(LoROM) + OFFSET3(SRAMMask) + OFFSET3(SRAMSize) + OFFSET3(Map) + OFFSET3(WriteMap) + OFFSET3(MemorySpeed) + OFFSET3(BlockIsRAM) + OFFSET3(BlockIsROM) + OFFSET3(ROMFilename) + + OFFSET5(APUPCS,PC) + OFFSET5(APURAM,RAM) + OFFSET5(APUExecuting,APUExecuting) + OFFSET5(APUDirectPage,DirectPage) + OFFSET5(APUBit,Bit) + OFFSET5(APUAddress,Address) + OFFSET5(APUWaitAddress1,WaitAddress1) + OFFSET5(APUWaitAddress2,WaitAddress2) + OFFSET5(APUWaitCounter,WaitCounter) + OFFSET5(APUShadowRAM,ShadowRAM) + OFFSET5(APUCachedSamples,CachedSamples) + OFFSET5(APU_Carry,_Carry) + OFFSET5(APU_Zero,_Zero) + OFFSET5(APU_Overflow,_Overflow) + OFFSET5(APUTimerErrorCounter,TimerErrorCounter) + OFFSET5(NextAPUTimerPos,NextAPUTimerPos) + + OFFSET4(APUCycles,Cycles) + OFFSET4(APUShowROM,ShowROM) + OFFSET4(APUFlags,Flags) + OFFSET4(APUKeyedChannels,KeyedChannels) + OFFSET4(APUOutPorts,OutPorts) + OFFSET4(APUDSP,DSP) + OFFSET4(APUExtraRAM,ExtraRAM) + OFFSET4(APUTimer,Timer) + OFFSET4(APUTimerTarget,TimerTarget) + OFFSET4(APUTimerEnabled,TimerEnabled) + OFFSET4(TimerValueWritten,TimerValueWritten) + + OFFSET6(CPUSpeed,Speed) + OFFSET6(CPUOpcodes,S9xOpcodes) + OFFSET6(_Carry,_Carry) + OFFSET6(_Zero,_Zero) + OFFSET6(_Negative,_Negative) + OFFSET6(_Overflow,_Overflow) + OFFSET6(ShiftedDB,ShiftedDB) + OFFSET6(ShiftedPB,ShiftedPB) + OFFSET6(CPUExecuting,CPUExecuting) + OFFSET6(Scanline,Scanline) + OFFSET6(Frame,Frame) + + OFFSET7(APUEnabled,APUEnabled) + OFFSET7(Shutdown,Shutdown) + OFFSET7(SoundSkipMethod,SoundSkipMethod) + OFFSET7(HDMATimingHack,HDMATimingHack) + OFFSET7(DisableIRQ,DisableIRQ) + OFFSET7(Paused,Paused) + OFFSET7(PAL,PAL) + OFFSET7(SoundSync,SoundSync) + OFFSET7(SA1Enabled,SA1) + OFFSET7(SuperFXEnabled,SuperFX) + + OFFSET8(ApuP,P) + OFFSET8(ApuYA,YA.W) + OFFSET8(ApuA,YA.B.A) + OFFSET8(ApuY,YA.B.Y) + OFFSET8(ApuX,X) + OFFSET8(ApuS,S) + OFFSET8(ApuPC,PC) + OFFSET8(APUPCR,PC) + + OFFSET9(BGMode,BGMode) + OFFSET9(BG3Priority,BG3Priority) + OFFSET9(Brightness,Brightness) + OFFSET9(GHight,VMA.High) + OFFSET9(GInc,VMA.Increment) + OFFSET9(GAddress,VMA.Address) + OFFSET9(GMask1,VMA.Mask1) + OFFSET9(GFullGraphicCount,VMA.FullGraphicCount) + OFFSET9(GShift,VMA.Shift) + OFFSET9(CGFLIP,CGFLIP) + OFFSET9(CGDATA,CGDATA) + OFFSET9(FirstSprite,FirstSprite) + OFFSET9(LastSprite,LastSprite) + OFFSET9(OBJ,OBJ) + OFFSET9(OAMPriorityRotation,OAMPriorityRotation) + OFFSET9(OAMAddr,OAMAddr) + OFFSET9(OAMFlip,OAMFlip) + OFFSET9(OAMTileAddress,OAMTileAddress) + OFFSET9(IRQVBeamPos,IRQVBeamPos) + OFFSET9(IRQHBeamPos,IRQHBeamPos) + OFFSET9(VBeamPosLatched,VBeamPosLatched) + OFFSET9(HBeamPosLatched,HBeamPosLatched) + OFFSET9(HBeamFlip,HBeamFlip) + OFFSET9(VBeamFlip,VBeamFlip) + OFFSET9(HVBeamCounterLatched,HVBeamCounterLatched) + OFFSET9(MatrixA,MatrixA) + OFFSET9(MatrixB,MatrixB) + OFFSET9(MatrixC,MatrixC) + OFFSET9(MatrixD,MatrixD) + OFFSET9(CentreX,CentreX) + OFFSET9(CentreY,CentreY) + OFFSET9(CGADD,CGADD) + OFFSET9(FixedColourGreen,FixedColourGreen) + OFFSET9(FixedColourRed,FixedColourRed) + OFFSET9(FixedColourBlue,FixedColourBlue) + OFFSET9(SavedOAMAddr,SavedOAMAddr) + OFFSET9(ScreenHeight,ScreenHeight) + OFFSET9(WRAM,WRAM) + OFFSET9(BG_Forced,BG_Forced) + OFFSET9(ForcedBlanking,ForcedBlanking) + OFFSET9(OBJThroughMain,OBJThroughMain) + OFFSET9(OBJThroughSub,OBJThroughSub) + OFFSET9(OBJSizeSelect,OBJSizeSelect) + OFFSET9(OBJNameBase,OBJNameBase) + OFFSET9(OAMReadFlip,OAMReadFlip) + OFFSET9(OAMData,OAMData) + OFFSET9(VTimerEnabled,VTimerEnabled) + OFFSET9(HTimerEnabled,HTimerEnabled) + OFFSET9(HTimerPosition,HTimerPosition) + OFFSET9(Mosaic,Mosaic) + OFFSET9(BGMosaic,BGMosaic) + OFFSET9(Mode7HFlip,Mode7HFlip) + OFFSET9(Mode7VFlip,Mode7VFlip) + OFFSET9(Mode7Repeat,Mode7Repeat) + OFFSET9(Window1Left,Window1Left) + OFFSET9(Window1Right,Window1Right) + OFFSET9(Window2Left,Window2Left) + OFFSET9(Window2Right,Window2Right) + OFFSET9(ClipWindowOverlapLogic,ClipWindowOverlapLogic) + OFFSET9(ClipWindow1Enable,ClipWindow1Enable) + OFFSET9(ClipWindow2Enable,ClipWindow2Enable) + OFFSET9(ClipWindow1Inside,ClipWindow1Inside) + OFFSET9(ClipWindow2Inside,ClipWindow2Inside) + OFFSET9(RecomputeClipWindows,RecomputeClipWindows) + OFFSET9(CGFLIPRead,CGFLIPRead) + OFFSET9(OBJNameSelect,OBJNameSelect) + OFFSET9(Need16x8Mulitply,Need16x8Mulitply) + OFFSET9(RangeTimeOver,RangeTimeOver) + + OFFSET10(ColorsChanged,ColorsChanged) + OFFSET10(HDMA,HDMA) + OFFSET10(HDMAStarted,HDMAStarted) + OFFSET10(MaxBrightness,MaxBrightness) + OFFSET10(LatchedBlanking,LatchedBlanking) + OFFSET10(OBJChanged,OBJChanged) + OFFSET10(RenderThisFrame,RenderThisFrame) + OFFSET10(SkippedFrames,SkippedFrames) + OFFSET10(FrameSkip,FrameSkip) + OFFSET10(TileCache,TileCache) + OFFSET10(TileCached,TileCached) +#ifdef CORRECT_VRAM_READS + OFFSET10(VRAMReadBuffer,VRAMReadBuffer) +#else + OFFSET10(FirstVRAMRead,FirstVRAMRead) +#endif + OFFSET10(Interlace,Interlace) + OFFSET10(DoubleWidthPixels,DoubleWidthPixels) + OFFSET10(RenderedScreenHeight,RenderedScreenHeight) + OFFSET10(RenderedScreenWidth,RenderedScreenWidth) + OFFSET10(Red,Red) + OFFSET10(Green,Green) + OFFSET10(Blue,Blue) + OFFSET10(XB,XB) + OFFSET10(ScreenColors,ScreenColors) + OFFSET10(PreviousLine,PreviousLine) + OFFSET10(CurrentLine,CurrentLine) + OFFSET10(Clip,Clip) + + OFFSET11(SA1Opcodes,S9xOpcodes) + OFFSET11(SA1_Carry,_Carry) + OFFSET11(SA1_Zero,_Zero) + OFFSET11(SA1_Negative,_Negative) + OFFSET11(SA1_Overflow,_Overflow) + OFFSET11(SA1CPUExecuting,CPUExecuting) + OFFSET11(SA1ShiftedPB,ShiftedPB) + OFFSET11(SA1ShiftedDB,ShiftedDB) + OFFSET11(SA1Flags,Flags) + OFFSET11(SA1Executing,Executing) + OFFSET11(SA1NMIActive,NMIActive) + OFFSET11(SA1IRQActive,IRQActive) + OFFSET11(SA1WaitingForInterrupt,WaitingForInterrupt) + OFFSET11(SA1PCBase,PCBase) + OFFSET11(SA1PBPCAtOpcodeStart,PBPCAtOpcodeStart) + OFFSET11(SA1WaitAddress,WaitAddress) + OFFSET11(SA1WaitCounter,WaitCounter) + OFFSET11(SA1WaitByteAddress1,WaitByteAddress1) + OFFSET11(SA1WaitByteAddress2,WaitByteAddress2) + OFFSET11(SA1BWRAM,BWRAM) + OFFSET11(SA1Map,Map) + OFFSET11(SA1WriteMap,WriteMap) + OFFSET11(SA1op1,op1) + OFFSET11(SA1op2,op2) + OFFSET11(SA1arithmetic_op,arithmetic_op) + OFFSET11(SA1sum,sum) + OFFSET11(SA1overflow,overflow) + OFFSET11(VirtualBitmapFormat,VirtualBitmapFormat) + OFFSET11(SA1_in_char_dma,in_char_dma) + OFFSET11(SA1variable_bit_pos,variable_bit_pos) + + OFFSET12(SA1DB,DB) + OFFSET12(SA1PP,P.W) + OFFSET12(SA1PL,P.W) + fprintf (S9xSTREAM, "#define SA1PH SA1PL + 1\n"); + OFFSET12(SA1AA,A.W) + OFFSET12(SA1AL,A.W) + fprintf (S9xSTREAM, "#define SA1AH SA1AL + 1\n"); + OFFSET12(SA1DD,D.W) + OFFSET12(SA1DL,D.W) + fprintf (S9xSTREAM, "#define SA1DH SA1DL + 1\n"); + OFFSET12(SA1SS,S.W) + OFFSET12(SA1SL,S.W) + fprintf (S9xSTREAM, "#define SA1SH SA1SL + 1\n"); + OFFSET12(SA1XX,X.W) + OFFSET12(SA1XL,X.W) + fprintf (S9xSTREAM, "#define SA1XH SA1XL + 1\n"); + OFFSET12(SA1YY,Y.W) + OFFSET12(SA1YL,Y.W) + fprintf (S9xSTREAM, "#define SA1YH SA1YL + 1\n"); + OFFSET12(SA1PB,PC.B.xPB) + OFFSET12(SA1PCR,PC.W.xPC) + + return (0); +} + diff --git a/source/snes9x/unused/reader.cpp b/source/snes9x/unused/reader.cpp index 3712fa4..540fa20 100644 --- a/source/snes9x/unused/reader.cpp +++ b/source/snes9x/unused/reader.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + // Abstract the details of reading from zip files versus FILE *'s. #include "reader.h" @@ -165,9 +184,9 @@ char *Reader::getline(void){ } std::string Reader::getline(bool &eof){ - char buf[100]; + char buf[1024]; std::string ret; - + eof=false; ret.clear(); do { @@ -221,7 +240,7 @@ int unzReader::get_char(){ if(numbytes<=0) return (EOF); head=buffer; } - + c=*head; head++; numbytes--; diff --git a/source/snes9x/unused/reader.h b/source/snes9x/unused/reader.h index 4e26009..302139e 100644 --- a/source/snes9x/unused/reader.h +++ b/source/snes9x/unused/reader.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + // Abstract the details of reading from zip files versus FILE *'s. #ifndef _READER_H_ @@ -174,7 +193,7 @@ class fReader : public Reader { }; #ifdef UNZIP_SUPPORT -#include "unzip.h" +#include "unzip/unzip.h" #define unz_BUFFSIZ 1024 diff --git a/source/snes9x/unused/screenshot.cpp b/source/snes9x/unused/screenshot.cpp index e285bf2..6999edb 100644 --- a/source/snes9x/unused/screenshot.cpp +++ b/source/snes9x/unused/screenshot.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -143,6 +160,8 @@ + + #ifdef HAVE_CONFIG_H #include #endif @@ -167,7 +186,10 @@ #include "ppu.h" #include "screenshot.h" -bool8 S9xDoScreenshot(int width, int height){ +#define ShowFailure() S9xSetInfoString("Failed to take screenshot.") + +bool8 S9xDoScreenshot(int width, int height) +{ #ifdef HAVE_LIBPNG FILE *fp; png_structp png_ptr; @@ -176,10 +198,11 @@ bool8 S9xDoScreenshot(int width, int height){ int imgwidth; int imgheight; const char *fname=S9xGetFilenameInc(".png", SCREENSHOT_DIR); - + Settings.TakeScreenshot=FALSE; if((fp=fopen(fname, "wb"))==NULL){ + ShowFailure(); perror("Screenshot failed"); return FALSE; } @@ -188,6 +211,7 @@ bool8 S9xDoScreenshot(int width, int height){ if(!png_ptr){ fclose(fp); unlink(fname); + ShowFailure(); return FALSE; } info_ptr=png_create_info_struct(png_ptr); @@ -195,6 +219,7 @@ bool8 S9xDoScreenshot(int width, int height){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); unlink(fname); + ShowFailure(); return FALSE; } @@ -203,6 +228,7 @@ bool8 S9xDoScreenshot(int width, int height){ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); unlink(fname); + ShowFailure(); return FALSE; } @@ -215,7 +241,7 @@ bool8 S9xDoScreenshot(int width, int height){ if(width<=256) imgwidth=width<<1; if(height<=SNES_HEIGHT_EXTENDED) imgheight=height<<1; } - + png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, @@ -229,7 +255,7 @@ bool8 S9xDoScreenshot(int width, int height){ png_set_shift(png_ptr, &sig_bit); png_write_info(png_ptr, info_ptr); - + png_set_packing(png_ptr); png_byte *row_pointer=new png_byte [png_get_rowbytes(png_ptr, info_ptr)]; @@ -254,12 +280,20 @@ bool8 S9xDoScreenshot(int width, int height){ } delete [] row_pointer; - + png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); fprintf(stderr, "%s saved.\n", fname); + + { + static char str [64]; + sprintf(str, "Saved screenshot %s", fname + strlen(fname)-7); + str[strlen(str)-3] = '\0'; + S9xSetInfoString(str); + } + return TRUE; #else Settings.TakeScreenshot=FALSE; diff --git a/source/snes9x/unused/server.cpp b/source/snes9x/unused/server.cpp index 275fe20..43a5639 100644 --- a/source/snes9x/unused/server.cpp +++ b/source/snes9x/unused/server.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -142,44 +159,48 @@ **********************************************************************************/ + + #ifdef NETPLAY_SUPPORT +#ifdef _DEBUG + #define NP_DEBUG 1 +#endif + #include #include #include #include #include #ifdef HAVE_STRINGS_H -#include -#endif - -#ifndef __WIN32__ -#include -#include + #include #endif #ifdef __WIN32__ -#include -#include -#define ioctl ioctlsocket -#define close closesocket -#define read(a,b,c) recv(a, b, c, 0) -#define write(a,b,c) send(a, b, c, 0) -#define gettimeofday(a,b) S9xGetTimeOfDay (a) -#define exit(a) _endthread() -void S9xGetTimeOfDay (struct timeval *n); + #include + #include + #include "win32/wsnes9x.h" + #define ioctl ioctlsocket + #define close closesocket + #define read(a,b,c) recv(a, b, c, 0) + #define write(a,b,c) send(a, b, c, 0) + #define gettimeofday(a,b) S9xGetTimeOfDay (a) + #define exit(a) _endthread() + void S9xGetTimeOfDay (struct timeval *n); #else + #include + #include -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include -#ifdef __SVR4 -#include -#endif + #ifdef __SVR4 + #include + #endif #endif // !__WIN32__ @@ -188,7 +209,11 @@ void S9xGetTimeOfDay (struct timeval *n); #include "memmap.h" #include "snapshot.h" +#ifdef __WIN32__ #define NP_ONE_CLIENT 1 +#else +#define NP_ONE_CLIENT 0 +#endif struct SNPServer NPServer; @@ -222,10 +247,10 @@ void S9xNPShutdownClient (int c, bool8 report_error = FALSE) #endif if (report_error) { - sprintf (NetPlay.ErrorMsg, + sprintf (NetPlay.ErrorMsg, "Player %d on '%s' has disconnected.", c + 1, NPServer.Clients [c].HostName); - S9xNPSetError (NetPlay.ErrorMsg); + S9xNPSetWarning (NetPlay.ErrorMsg); } if (NPServer.Clients [c].HostName) @@ -311,7 +336,7 @@ static bool8 S9xNPSSendData (int fd, const uint8 *data, int length) if (chunk < 1024) chunk = 1024; - + do { int num_bytes = len; @@ -326,7 +351,7 @@ static bool8 S9xNPSSendData (int fd, const uint8 *data, int length) if (sent < 0) { - if (errno == EINTR + if (errno == EINTR #ifdef EAGAIN || errno == EAGAIN #endif @@ -376,18 +401,18 @@ void S9xNPSendHeartBeat () if (n >= 0) { bool8 Paused = NPServer.Paused != 0; - + NPServer.FrameCount++; *ptr++ = NP_SERV_MAGIC; *ptr++ = 0; // Individual client sequence number will get placed here *ptr++ = NP_SERV_JOYPAD | (n << 6) | ((Paused != 0) << 5); - + WRITE_LONG (ptr, NPServer.FrameCount); len += 4; ptr += 4; int i; - + for (i = 0; i <= n; i++) { WRITE_LONG (ptr, NPServer.Joypads [i]); @@ -438,15 +463,15 @@ void S9xNPProcessClient (int c) { #ifdef NP_DEBUG printf ("SERVER: Messages lost from '%s', expected %d, got %d\n", - NPServer.Clients [c].HostName ? - NPServer.Clients [c].HostName : "Unknown", + NPServer.Clients [c].HostName ? + NPServer.Clients [c].HostName : "Unknown", NPServer.Clients [c].ReceiveSequenceNum, header [1]); #endif - sprintf (NetPlay.WarningMsg, + sprintf (NetPlay.WarningMsg, "SERVER: Messages lost from '%s', expected %d, got %d\n", - NPServer.Clients [c].HostName ? - NPServer.Clients [c].HostName : "Unknown", + NPServer.Clients [c].HostName ? + NPServer.Clients [c].HostName : "Unknown", NPServer.Clients [c].ReceiveSequenceNum, header [1]); NPServer.Clients [c].ReceiveSequenceNum = header [1] + 1; @@ -499,7 +524,7 @@ void S9xNPProcessClient (int c) *ptr++ = NP_SERV_MAGIC; *ptr++ = NPServer.Clients [c].SendSequenceNum++; - if (NPServer.SendROMImageOnConnect && + if (NPServer.SendROMImageOnConnect && NPServer.NumClients > NP_ONE_CLIENT) *ptr++ = NP_SERV_HELLO | 0x80; else @@ -545,7 +570,7 @@ void S9xNPProcessClient (int c) S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); } else - S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); + S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); break; case NP_CLNT_RECEIVED_ROM_IMAGE: @@ -564,7 +589,7 @@ void S9xNPProcessClient (int c) S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); } else - S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); + S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); break; @@ -587,7 +612,7 @@ void S9xNPProcessClient (int c) { NPServer.Clients [c].Paused = FALSE; NPServer.Clients [c].Ready = TRUE; - + S9xNPRecomputePause (); break; } @@ -602,14 +627,19 @@ void S9xNPProcessClient (int c) if (!NPServer.SendROMImageOnConnect) { S9xNPWaitForEmulationToComplete (); - + if (NPServer.SyncByReset) { S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); } else +#ifdef __WIN32__ S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); +#else + /* We need to resync all clients on new player connect as we don't have a 'reference game' */ + S9xNPServerAddTask (NP_SERVER_SYNC_ALL, (void *) c); +#endif } } else @@ -643,14 +673,14 @@ void S9xNPAcceptClient (int Listen, bool8 block) struct hostent *host; int new_fd; int i; - + #ifdef NP_DEBUG printf ("SERVER: attempting to accept new client connection @%ld\n", S9xGetMilliTime () - START); #endif S9xNPSetAction ("SERVER: Attempting to accept client connection...", TRUE); memset (&remote_address, 0, sizeof (remote_address)); ACCEPT_SIZE_T len = sizeof (remote_address); - + new_fd = accept (Listen, (struct sockaddr *)&remote_address, &len); S9xNPSetAction ("Setting socket options...", TRUE); @@ -762,9 +792,9 @@ static bool8 S9xNPServerInit (int port) S9xNPSetError ("NetPlay Server: Can't create listening socket."); return (FALSE); } - + val = 1; - setsockopt (NPServer.Socket, SOL_SOCKET, SO_REUSEADDR, + setsockopt (NPServer.Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof (val)); memset (&address, 0, sizeof (address)); @@ -796,14 +826,32 @@ static bool8 S9xNPServerInit (int port) return (TRUE); } +void S9xNPSendServerPause (bool8 paused) +{ +#ifdef NP_DEBUG + printf ("SERVER: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START); +#endif + uint8 pause [7]; + uint8 *ptr = pause; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = 0; + *ptr++ = NP_SERV_PAUSE | (paused ? 0x20 : 0); + WRITE_LONG (ptr, NPServer.FrameCount); + S9xNPSendToAllClients (pause, 7); +} + void S9xNPServerLoop (void *) { #ifdef __WIN32__ BOOL success = FALSE; #else bool8 success = FALSE; + static struct timeval next1 = {0, 0}; + struct timeval now; #endif + int pausedState = -1, newPausedState = -1; + while (server_continue) { fd_set read_fds; @@ -812,16 +860,27 @@ void S9xNPServerLoop (void *) int i; int max_fd = NPServer.Socket; - + #ifdef __WIN32__ Sleep (0); #endif - if (success && !Settings.Paused && !Settings.StopEmulation && + if (success && !(Settings.Paused && !Settings.FrameAdvance) && !Settings.StopEmulation && !Settings.ForcedPause && !NPServer.Paused) { S9xNPSendHeartBeat (); + newPausedState = 0; } + else + { + newPausedState = 1; + } + + if(pausedState != newPausedState) + { + pausedState = newPausedState; +// S9xNPSendServerPause(pausedState); // XXX: doesn't seem to work yet... + } do { @@ -836,11 +895,11 @@ void S9xNPServerLoop (void *) max_fd = NPServer.Clients [i].Socket; } } - + timeout.tv_sec = 0; timeout.tv_usec = 1000; res = select (max_fd + 1, &read_fds, NULL, NULL, &timeout); - + if (res > 0) { if (FD_ISSET (NPServer.Socket, &read_fds)) @@ -848,7 +907,7 @@ void S9xNPServerLoop (void *) for (i = 0; i < NP_MAX_CLIENTS; i++) { - if (NPServer.Clients [i].Connected && + if (NPServer.Clients [i].Connected && FD_ISSET (NPServer.Clients [i].Socket, &read_fds)) { S9xNPProcessClient (i); @@ -859,6 +918,35 @@ void S9xNPServerLoop (void *) #ifdef __WIN32__ success = WaitForSingleObject (GUI.ServerTimerSemaphore, 200) == WAIT_OBJECT_0; +#else + while (gettimeofday (&now, NULL) < 0) ; + + /* If there is no known "next" frame, initialize it now */ + if (next1.tv_sec == 0) { next1 = now; ++next1.tv_usec; } + + success=FALSE; + + if (timercmp(&next1, &now, >)) + { + /* If we're ahead of time, sleep a while */ + unsigned timeleft = + (next1.tv_sec - now.tv_sec) * 1000000 + + next1.tv_usec - now.tv_usec; + usleep(timeleft<(200*1000)?timeleft:(200*1000)); + } + + if (!timercmp(&next1, &now, >)) + { + + /* Calculate the timestamp of the next frame. */ + next1.tv_usec += Settings.FrameTime; + if (next1.tv_usec >= 1000000) + { + next1.tv_sec += next1.tv_usec / 1000000; + next1.tv_usec %= 1000000; + } + success=TRUE; + } #endif while (NPServer.TaskHead != NPServer.TaskTail) @@ -908,6 +996,7 @@ void S9xNPServerLoop (void *) WRITE_LONG (ptr, NPServer.FrameCount); S9xNPSendToAllClients (reset, 7); } + S9xNPSetAction ("", TRUE); break; case NP_SERVER_SEND_SRAM: NPServer.Clients [(pint) task_data].Ready = FALSE; @@ -946,8 +1035,9 @@ bool8 S9xNPStartServer (int port) server_continue = TRUE; if (S9xNPServerInit (port)) #ifdef __WIN32__ - return (_beginthread (S9xNPServerLoop, 0, &p) != ~0); + return (_beginthread (S9xNPServerLoop, 0, &p) != (uintptr_t)(~0)); #else + S9xNPServerLoop(NULL); return (TRUE); #endif @@ -965,11 +1055,7 @@ void S9xNPStopServer () for (int i = 0; i < NP_MAX_CLIENTS; i++) { if (NPServer.Clients [i].Connected) - { - close (NPServer.Clients [i].Socket); - NPServer.Clients [i].Connected = FALSE; - NPServer.Clients [i].SaidHello = FALSE; - } + S9xNPShutdownClient(i, FALSE); } } @@ -977,7 +1063,7 @@ void S9xNPStopServer () void S9xGetTimeOfDay (struct timeval *n) { unsigned long t = S9xGetMilliTime (); - + n->tv_sec = t / 1000; n->tv_usec = (t % 1000) * 1000; } @@ -1015,7 +1101,7 @@ bool8 S9xNPSendROMImageToClient (int c) uint8 header [7 + 1 + 4]; uint8 *ptr = header; - int len = sizeof (header) + Memory.CalculatedSize + + int len = sizeof (header) + Memory.CalculatedSize + strlen (Memory.ROMFilename) + 1; *ptr++ = NP_SERV_MAGIC; *ptr++ = NPServer.Clients [c].SendSequenceNum++; @@ -1047,6 +1133,7 @@ void S9xNPSyncClient (int client) { #ifdef HAVE_MKSTEMP char fname[] = "/tmp/snes9x_fztmpXXXXXX"; + int fd=-1; #else char fname [L_tmpnam]; #endif @@ -1055,7 +1142,7 @@ void S9xNPSyncClient (int client) S9xNPSetAction ("SERVER: Freezing game...", TRUE); #ifdef HAVE_MKSTEMP - if ( (mkstemp(fname) < 0) && S9xFreezeGame(fname) ) + if ( ((fd=mkstemp(fname)) >= 0) && S9xFreezeGame(fname) ) #else if ( tmpnam(fname) && S9xFreezeGame(fname) ) #endif @@ -1090,6 +1177,10 @@ void S9xNPSyncClient (int client) } remove (fname); } +#ifdef HAVE_MKSTEMP + if (fd != -1) + close(fd); +#endif } bool8 S9xNPLoadFreezeFile (const char *fname, uint8 *&data, uint32 &len) @@ -1134,6 +1225,7 @@ void S9xNPSendFreezeFile (int c, uint8 *data, uint32 len) { S9xNPShutdownClient (c, TRUE); } + S9xNPSetAction ("", TRUE); } void S9xNPRecomputePause () @@ -1222,7 +1314,7 @@ void S9xNPSendSRAMToClient (int c) if (SRAMSize > 0x10000) SRAMSize = 0x10000; int len = 7 + SRAMSize; - + sprintf (NetPlay.ActionMsg, "SERVER: Sending S-RAM to player %d...", c + 1); S9xNPSetAction (NetPlay.ActionMsg, TRUE); @@ -1231,11 +1323,11 @@ void S9xNPSendSRAMToClient (int c) *ptr++ = NPServer.Clients [c].SendSequenceNum++; *ptr++ = NP_SERV_SRAM_DATA; WRITE_LONG (ptr, len); - if (!S9xNPSSendData (NPServer.Clients [c].Socket, + if (!S9xNPSSendData (NPServer.Clients [c].Socket, sram, sizeof (sram)) || (len > 7 && !S9xNPSSendData (NPServer.Clients [c].Socket, - ::SRAM, len - 7))) + Memory.SRAM, len - 7))) { S9xNPShutdownClient (c, TRUE); } @@ -1280,8 +1372,8 @@ void S9xNPWaitForEmulationToComplete () #endif while (!NetPlay.PendingWait4Sync && NetPlay.Connected && - !Settings.ForcedPause && !Settings.StopEmulation && - !Settings.Paused) + !Settings.ForcedPause && !Settings.StopEmulation && + !(Settings.Paused && !Settings.FrameAdvance)) { #ifdef __WIN32__ Sleep (40); @@ -1294,7 +1386,7 @@ void S9xNPWaitForEmulationToComplete () void S9xNPServerQueueSyncAll () { - if (Settings.NetPlay && Settings.NetPlayServer && + if (Settings.NetPlay && Settings.NetPlayServer && NPServer.NumClients > NP_ONE_CLIENT) { S9xNPNoClientReady (); @@ -1305,7 +1397,7 @@ void S9xNPServerQueueSyncAll () void S9xNPServerQueueSendingROMImage () { - if (Settings.NetPlay && Settings.NetPlayServer && + if (Settings.NetPlay && Settings.NetPlayServer && NPServer.NumClients > NP_ONE_CLIENT) { S9xNPNoClientReady (); @@ -1316,19 +1408,19 @@ void S9xNPServerQueueSendingROMImage () void S9xNPServerQueueSendingFreezeFile (const char *filename) { - if (Settings.NetPlay && Settings.NetPlayServer && + if (Settings.NetPlay && Settings.NetPlayServer && NPServer.NumClients > NP_ONE_CLIENT) { S9xNPNoClientReady (); S9xNPDiscardHeartbeats (); - S9xNPServerAddTask (NP_SERVER_SEND_FREEZE_FILE_ALL, + S9xNPServerAddTask (NP_SERVER_SEND_FREEZE_FILE_ALL, (void *) strdup (filename)); } } void S9xNPServerQueueSendingLoadROMRequest (const char *filename) { - if (Settings.NetPlay && Settings.NetPlayServer && + if (Settings.NetPlay && Settings.NetPlayServer && NPServer.NumClients > NP_ONE_CLIENT) { S9xNPNoClientReady (); diff --git a/source/snes9x/unused/snaporig.cpp b/source/snes9x/unused/snaporig.cpp index fd6c126..bb07192 100644 --- a/source/snes9x/unused/snaporig.cpp +++ b/source/snes9x/unused/snaporig.cpp @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #include #ifdef HAVE_STRINGS_H #include @@ -201,7 +220,7 @@ static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) char buffer [20]; int len = 0; int rem = 0; - + if (READ_STREAM (buffer, 11, snap) != 11 || strncmp (buffer, key, 4) != 0 || (len = atoi (&buffer [4])) == 0) @@ -221,7 +240,7 @@ static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) READ_STREAM (junk, rem, snap); delete[] junk; } - + return (SUCCESS); } @@ -400,7 +419,7 @@ static int ReadOrigSnapshot (STREAM snap) for (i = 0; i < 8; i++) { - DMA[i].TransferDirection = OrigDMA[i].TransferDirection; + DMA[i].ReverseTransfer = OrigDMA[i].ReverseTransfer; DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; DMA[i].TransferMode = OrigDMA[i].TransferMode; @@ -420,7 +439,7 @@ static int ReadOrigSnapshot (STREAM snap) return (result); if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) return (result); - if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS) + if ((result = ReadBlock ("SRA:", Memory.SRAM, 0x10000, snap)) != SUCCESS) return (result); if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) return (result); @@ -441,7 +460,7 @@ static int ReadOrigSnapshot (STREAM snap) SoundData.master_volume_left = OrigSoundData.master_volume_left; SoundData.master_volume_right = OrigSoundData.master_volume_right; SoundData.echo_volume_left = OrigSoundData.echo_volume_left; - SoundData.echo_volume_right = OrigSoundData.echo_volume_right; + SoundData.echo_volume_right = OrigSoundData.echo_volume_right; SoundData.echo_enable = OrigSoundData.echo_enable; SoundData.echo_feedback = OrigSoundData.echo_feedback; SoundData.echo_ptr = OrigSoundData.echo_ptr; diff --git a/source/snes9x/unused/snaporig.h b/source/snes9x/unused/snaporig.h index c75147b..139f979 100644 --- a/source/snes9x/unused/snaporig.h +++ b/source/snes9x/unused/snaporig.h @@ -1,7 +1,7 @@ /********************************************************************************** Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), Jerremy Koot (jkoot@snes9x.com) (c) Copyright 2002 - 2004 Matthew Kendora @@ -12,12 +12,16 @@ (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) - (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Kris Bleakley (codeviolation@hotmail.com), - Nach (n-a-c-h@users.sourceforge.net), and + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), zones (kasumitokoduck@yahoo.com) + (c) Copyright 2006 - 2007 nitsuja + + BS-X C emulator code (c) Copyright 2005 - 2006 Dreamer Nom, zones @@ -110,17 +114,30 @@ 2xSaI filter (c) Copyright 1999 - 2001 Derek Liauw Kie Fa - HQ2x filter + HQ2x, HQ3x, HQ4x filters (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + Specific ports contains the works of other authors. See headers in individual files. + Snes9x homepage: http://www.snes9x.com Permission to use, copy, modify and/or distribute Snes9x in both binary - and source form, for non-commercial purposes, is hereby granted without - fee, providing that this license information and copyright notice appear + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear with all copies and any derived work. This software is provided 'as-is', without any express or implied @@ -141,6 +158,8 @@ Nintendo Co., Limited and its subsidiary companies. **********************************************************************************/ + + #ifndef _SNAPORIG_H_ #define _SNAPORIG_H_ @@ -160,7 +179,7 @@ struct SOrigCPUState{ bool8 NMIActive; bool8 IRQActive; bool8 WaitingForInterrupt; - bool8 InDMA; + bool8 InDMAorHDMA; uint8 WhichEvent; uint8 *PC; uint8 *PCBase; @@ -312,7 +331,7 @@ struct SOrigPPU { } BG [4]; bool8 CGFLIP; - uint16 CGDATA [256]; + uint16 CGDATA [256]; uint8 FirstSprite; uint8 LastSprite; struct SOrigOBJ OBJ [129]; @@ -385,7 +404,7 @@ struct SOrigPPU { }; struct SOrigDMA { - bool8 TransferDirection; + bool8 ReverseTransfer; bool8 AAddressFixed; bool8 AAddressDecrement; uint8 TransferMode; diff --git a/source/snes9x/unused/snes9x_default_config.cfg b/source/snes9x/unused/snes9x_default_config.cfg new file mode 100644 index 0000000..aaf168f --- /dev/null +++ b/source/snes9x/unused/snes9x_default_config.cfg @@ -0,0 +1,81 @@ +#--------------------------- +# Snes9x Configuration file +#--------------------------- + +[CPU] +Cycles = +DisableIRQ = + +[ROM] +PAL = +NTSC = +HiROM = +LoROM = +Header = +Interleaved = +Interleaved2 = +InterleaveGD24 = +SuperFX = +DSP1 = +Cheat = +Patch = +BS = +Filename = + +[Sound] +APUEnabled = +Sync = +Stereo = +SixteenBitSound = +AltDecode = +BufferSize = +Echo = +FixFrequency = +Interpolate = +MasterVolume = +Rate = +SoundSkip = +ReverseStereo = +EnvelopeHeightReading = +FakeMuteFix = +SampleCaching = +Mute = + +[Display] +GraphicWindows = +Mode7Interpolate = +HiRes = +Transparency = +MessagesInImage = +FrameRate = +DisplayInput = +DisplayFrameCount = + +[Settings] +DisableHDMA = +TurboMode = +StretchScreenshots = +BGLayeringHack = +PALFrameTime = +NTSCFrameTime = +FrameTime = +FrameSkip = +AutoMaxSkipFramesAtOnce = +TurboFrameSkip = +AutoSaveDelay = +SpeedHacks = + +[Controls] +MP5Master = +MouseMaster = +SuperscopeMaster = +JustifierMaster = +Port1 = +Port2 = +Mouse1Crosshair = +Mouse2Crosshair = +SuperscopeCrosshair = +Justifier1Crosshair = +Justifier2Crosshair = +Joystick = +AllowLeftRight = diff --git a/source/snes9x/unused/sound.cpp b/source/snes9x/unused/sound.cpp new file mode 100644 index 0000000..de39655 --- /dev/null +++ b/source/snes9x/unused/sound.cpp @@ -0,0 +1,356 @@ +/********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2007 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com) + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley, + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001-2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight, + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound DSP emulator code is derived from SNEeSe and OpenSPC: + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2007 zones + + + Specific ports contains the works of other authors. See headers in + individual files. + + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and/or distribute Snes9x in both binary + and source form, for non-commercial purposes, is hereby granted without + fee, providing that this license information and copyright notice appear + with all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +**********************************************************************************/ + + + +#ifndef __WIN32__ + +#include +#include +#include +#include +#include +#include +#include + +#define EQ == +#define MINBUFFLEN 10000 + +#include +#include +#include +#include +#include + +#include "snes9x.h" +#include "soundux.h" + +extern SoundStatus so; + +extern int AudioOpen(unsigned long freq, unsigned long bufsize, unsigned long bitrate, unsigned long stereo); +extern void AudioClose(void); + +extern int OpenPrelude(ULONG Type, ULONG DefaultFreq, ULONG MinBuffSize); +extern void ClosePrelude(void); + +extern int SoundSignal; +unsigned long DoubleBuffer; +//extern struct AHISampleInfo Sample0; +//extern struct AHISampleInfo Sample1; +//extern unsigned long BufferSize; + +struct Library *AHIPPCBase; +struct Library *AHIBase; +struct MsgPort *AHImp=NULL; +struct AHIRequest *AHIio=NULL; +BYTE AHIDevice=-1; + +struct AHIData *AHIData; + +unsigned long Frequency = 0; +//unsigned long BufferSize = 0; +unsigned long BitRate = 0; +unsigned long Stereo = 0; +//unsigned long AHIError = 9; + +BYTE InternSignal=-1; + +int mixsamples; +extern int prelude; + +#define REALSIZE (BitRate*Stereo) + +struct AHIAudioModeRequester *req=NULL; +struct AHIAudioCtrl *actrl=NULL; + +ULONG BufferLen=NULL; + + +/* this really should be dynamically allocated... */ +#undef MAX_BUFFER_SIZE +#define MAX_BUFFER_SIZE 65536 +#define MIN_BUFFER_SIZE 65536 + +#define MODE_MONO 0 +#define MODE_STEREO 1 + +#define QUAL_8BIT 8 +#define QUAL_16BIT 16 + + +int test=0; +int test2=0; + +int AudioOpen(unsigned long freq, unsigned long minbufsize, unsigned long bitrate, unsigned long stereo) +{ + ULONG Type; + + Frequency = freq; + + so.playback_rate = Frequency; + + if(stereo) so.stereo = TRUE; + else so.stereo = FALSE; + + switch(bitrate) + { + case 8: + so.sixteen_bit = FALSE; + BitRate=1; + if(stereo) + { + Stereo=2; + Type = AHIST_S8S; + } + else + { + Stereo=1; + Type = AHIST_M8S; + } + + break; + + default: //defaulting to 16bit, because it means it won't crash atleast + case QUAL_16BIT: + so.sixteen_bit = TRUE; + BitRate=2; + if(stereo) + { + Stereo=2; + Type = AHIST_S16S; + } + else + { + Stereo=1; + Type = AHIST_M16S; + } + break; + } + + if(prelude) prelude = OpenPrelude(Type, freq, minbufsize); + + + if(prelude) return 1; else printf("Defaulting to AHI...\n"); + + /* only 1 channel right? */ + /* NOTE: The buffersize will not always be what you requested + * it finds the minimun AHI requires and then rounds it up to + * nearest 32 bytes. Check AHIData->BufferSize or Samples[n].something_Length + */ + if(AHIData = OpenAHI(1, Type, AHI_INVALID_ID, AHI_DEFAULT_FREQ, 0, minbufsize)) + { + printf("AHI opened\n"); + printf("BuffSize %d\n", AHIData->BufferSize); + } + else + { + printf("AHI failed to open: %d\n", AHIData); + return 0; + } + + so.buffer_size = AHIData->BufferSize; // in bytes + if (so.buffer_size > MAX_BUFFER_SIZE) so.buffer_size = MAX_BUFFER_SIZE; + + /* Lots of useful fields in the AHIData struct, have a look */ + AHIBase = AHIData->AHIBase; + actrl = AHIData->AudioCtrl; + Frequency = AHIData->MixingFreq; + + printf("signal %ld\n", AHIData->SoundFuncSignal); + + Wait(AHIData->SoundFuncSignal); + + /* I don't think it should start playing until there is something + * In the buffer, however to set off the SoundFunc it should + * probably go through the buffer at least once, just silently. + */ + AHI_SetFreq(0, Frequency, actrl, AHISF_IMM); + + Wait(AHIData->SoundFuncSignal); + + AHI_SetVol(0, 0x10000, 0x8000, actrl, AHISF_IMM); + + mixsamples=AHIData->BufferSamples; + + SoundSignal = AHIData->SoundFuncSignal; + + return 1; +} + +void AudioClose( void ) +{ + if(prelude) ClosePrelude(); + else ;//CloseAHI(AHIData); +} + + +#include + +extern int main(int argc, char **argv); + +void wbmain(struct WBStartup * argmsg) +{ + char argv[1][]={"WarpSNES"}; + int argc=1; + main(argc,(char **)argv); +} + + +#endif diff --git a/source/snes9x/unused/xenofarm.sh b/source/snes9x/unused/xenofarm.sh new file mode 100644 index 0000000..90f2254 --- /dev/null +++ b/source/snes9x/unused/xenofarm.sh @@ -0,0 +1,113 @@ +#! /bin/sh + +# This script is part of the automated Xenofarm testing testing. For +# more information about Xenofarm see http://www.lysator.liu.se/xenofarm/ + +# $Id: xenofarm.sh,v 1.6 2003/11/09 14:02:39 pbortas Exp $ +# This file scripts the xenofarm actions and creates a result package +# to send back. + +#FIXME: snes9x doesn't really need MAKE_FLAGS. Clean out later. + +BUILDDIR=. +#OS=`uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` +#BUILDDIR=build/$(OS) +MAKE=${MAKE-make} +PATH=$PATH:/usr/ccs/bin +export PATH + +log() { + echo $1 | tee -a build/xenofarm/mainlog.txt +} + +log_start() { + log "BEGIN $1" + TZ=GMT date >> build/xenofarm/mainlog.txt +} + +log_end() { + LASTERR=$1 + if [ "$1" = "0" ] ; then + log "PASS" + else + log "FAIL" + fi + TZ=GMT date >> build/xenofarm/mainlog.txt +} + +xenofarm_build() { + log_start compile + "`pwd`/configure" >> build/xenofarm/compilelog.txt 2>&1 && + $MAKE $MAKE_FLAGS >> build/xenofarm/compilelog.txt 2>&1 + log_end $? + [ $LASTERR = 0 ] || return 1 +} + +xenofarm_post_build() { + log_start verify + $MAKE $MAKE_FLAGS verify > build/xenofarm/verifylog.txt 2>&1 + log_end $? + [ $LASTERR = 0 ] || return 1 + + log_start binrelease + $MAKE $MAKE_FLAGS bin-release > build/xenofarm/binreleaselog.txt 2>&1 + log_end $? + [ $LASTERR = 0 ] || return 1 +} + +fail_builddir() { + echo "FATAL: Failed to create build directory!" + exit 1 +} + +# main code + +test -d build || mkdir build 2>&1 && +rm -rf build/xenofarm 2>&1 && +mkdir build/xenofarm 2>&1 || fail_builddir + +LC_CTYPE=C +export LC_CTYPE +log "FORMAT 2" + +log_start build +xenofarm_build +log_end $? + +if [ $LASTERR = 0 ]; then + log_start post_build + xenofarm_post_build + log_end $? + else : +fi + +log_start response_assembly + # Basic stuff + cp ../buildid.txt build/xenofarm/ + # Configuration + cp "$BUILDDIR/config.info" build/xenofarm/configinfo.txt 2>/dev/null || /bin/true + ( + cd "$BUILDDIR" + test -f config.log && cat config.log + for f in `find . -name config.log -type f`; do + echo + echo '###################################################' + echo '##' `dirname "$f"` + echo + cat "$f" + done + ) > build/xenofarm/configlogs.txt + cp "$BUILDDIR/config.cache" build/xenofarm/configcache.txt 2>/dev/null || /bin/true; + # Core files + find . -name "core" -exec \ + gdb --batch --nx --command=bin/xenofarm_gdb_cmd "$BUILDDIR/pike" {} >> \ + build/xenofarm/_core.txt ";" + find . -name "*.core" -exec \ + gdb --batch --nx --command=bin/xenofarm_gdb_cmd "$BUILDDIR/pike" {} >> \ + build/xenofarm/_core.txt ";" + find . -name "core.*" -exec \ + gdb --batch --nx --command=bin/xenofarm_gdb_cmd "$BUILDDIR/pike" {} >> \ + build/xenofarm/_core.txt ";" +log_end $? + +log "END" diff --git a/source/snes9x/unused/xenofarm_gdb_cmd b/source/snes9x/unused/xenofarm_gdb_cmd new file mode 100644 index 0000000..43b471d --- /dev/null +++ b/source/snes9x/unused/xenofarm_gdb_cmd @@ -0,0 +1,14 @@ +echo \nActive threads\n +info threads +echo \nBacktrace\n +bt +echo \nSource code for frame 0\n +list +echo \nDisassembly of frame 0\n +disassemble +echo \nSource code for frame 1\n +up +list +echo \nDisassembly of frame 1\n +disassemble +echo \nEnd of core inspection\n\n\n\n