From 0f6e8c372178a14c3345a4efa2bd54ad9d910102 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 7 May 2011 18:35:11 +0200 Subject: [PATCH 001/130] Win32: fix netplay connect --- win32/wsnes9x.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index d7d81f12..6bf7c357 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -1431,7 +1431,7 @@ LRESULT CALLBACK WinProc( unsigned int i; //bool showFPS; #ifdef NETPLAY_SUPPORT - char hostname [100]; + TCHAR hostname [100]; #endif switch (uMsg) { @@ -1866,7 +1866,7 @@ LRESULT CALLBACK WinProc( S9xSetPause (PAUSE_NETPLAY_CONNECT); - if (!S9xNPConnectToServer (hostname, Settings.Port, + if (!S9xNPConnectToServer (_tToChar(hostname), Settings.Port, Memory.ROMName)) { S9xClearPause (PAUSE_NETPLAY_CONNECT); From f505626dda44c327d5a62c52cdf18b91c99b92a5 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 7 May 2011 22:24:37 +0200 Subject: [PATCH 002/130] Win32: remove sync options from movie dialog; fix KEYUP handling for modifier keys; send CUSTKEYUP for background keypresses --- movie.h | 2 -- win32/rsrc/snes9x.rc | 74 +++++++++++++++++++------------------------- win32/wlanguage.h | 2 -- win32/wsnes9x.cpp | 34 +++++++------------- 4 files changed, 43 insertions(+), 69 deletions(-) diff --git a/movie.h b/movie.h index 508ad307..cf55b5a2 100644 --- a/movie.h +++ b/movie.h @@ -185,10 +185,8 @@ #define MOVIE_OPT_NOSAVEDATA (1 << 2) #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 #define MOVIE_MAX_METADATA 512 diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index d8288504..2a0ff7cd 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -364,13 +364,13 @@ BEGIN RTEXT "Description",IDC_STATIC,7,103,70,12,SS_CENTERIMAGE END -IDD_OPENMOVIE DIALOGEX 0, 0, 304, 223 +IDD_OPENMOVIE DIALOGEX 0, 0, 304, 166 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Play Movie" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - DEFPUSHBUTTON "OK",IDOK,187,200,50,14 - PUSHBUTTON "Cancel",IDCANCEL,246,200,50,14 + DEFPUSHBUTTON "OK",IDOK,187,149,50,14 + PUSHBUTTON "Cancel",IDCANCEL,246,149,50,14 EDITTEXT IDC_MOVIE_PATH,7,18,230,13,ES_AUTOHSCROLL LTEXT "Movie File",IDC_STATIC,7,7,33,8 PUSHBUTTON "&Browse...",IDC_BROWSE_MOVIE,248,17,48,14 @@ -382,54 +382,45 @@ BEGIN LTEXT "LENGTH",IDC_MOVIE_LENGTH,71,64,81,8 LTEXT "FRAMES",IDC_MOVIE_FRAMES,71,73,81,8 LTEXT "RERECORD",IDC_MOVIE_RERECORD,71,82,81,8 - LTEXT "Author Info:",IDC_LABEL_MOVIEINFOBOX,30,99,38,8 + LTEXT "Author Info:",IDC_LABEL_MOVIEINFOBOX,30,123,38,8 CONTROL "Open Read-Only",IDC_READONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,7,69,10 - LTEXT "Static",IDC_MOVIE_METADATA,70,99,226,21,WS_BORDER - GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,7,133,77,61 - CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_GROUP | WS_TABSTOP,11,169,70,10 - CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_TABSTOP,11,154,72,10 - CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,142,45,10 - CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,162,45,10 - CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,152,45,10 - CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,172,45,10 - CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,183,45,10 - GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,89,133,69,61 - GROUPBOX "Emulator Sync Settings",IDC_LABEL_SYNCSETTINGS,163,133,133,61 - CONTROL "Allow Left+Right / Up+Down",IDC_ALLOWLEFTRIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,153,118,11 - CONTROL "Sync samples with sound CPU",IDC_SYNC_TO_SOUND_CPU, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,166,117,10 - LTEXT " ",IDC_LOADEDFROMMOVIE,169,124,127,8 + LTEXT "Static",IDC_MOVIE_METADATA,70,123,226,21,WS_BORDER + GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,204,54,95,41 + CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_GROUP | WS_TABSTOP,208,76,70,10 + CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_TABSTOP,208,64,72,10 + CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,18,106,45,10 + CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,116,106,45,10 + CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,67,106,45,10 + CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,165,106,45,10 + CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,214,106,45,10 + GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,12,95,272,25 LTEXT "Movie's ROM: CRC32=Unknown, Name=Unknown",IDC_MOVIEROMINFO,8,35,1024,8 LTEXT "Current ROM: CRC32=Unknown, Name=Unknown",IDC_CURRENTROMINFO,9,43,287,9 - LTEXT " ",IDC_PLAYWARN,10,203,167,15 + LTEXT " ",IDC_PLAYWARN,10,149,167,15 END -IDD_CREATEMOVIE DIALOGEX 0, 0, 303, 150 +IDD_CREATEMOVIE DIALOGEX 0, 0, 303, 118 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Record Movie" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,187,129,50,14 - PUSHBUTTON "Cancel",IDCANCEL,246,129,50,14 + DEFPUSHBUTTON "OK",IDOK,187,96,50,14 + PUSHBUTTON "Cancel",IDCANCEL,246,96,50,14 EDITTEXT IDC_MOVIE_PATH,7,18,230,13,ES_AUTOHSCROLL LTEXT "Movie File",IDC_STATIC,7,7,33,8 PUSHBUTTON "&Browse...",IDC_BROWSE_MOVIE,248,17,48,14 - GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,7,38,77,61 - CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,65,70,10 - CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,52,72,10 - CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,47,45,10 - CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,67,45,10 - CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,57,45,10 - CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,77,45,10 - CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,87,45,10 - GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,89,38,69,61 - EDITTEXT IDC_MOVIE_METADATA,67,105,229,14,ES_AUTOHSCROLL - LTEXT "Author Info:",IDC_STATIC,18,108,43,8,0,WS_EX_RIGHT - GROUPBOX "Emulator Sync Settings",IDC_LABEL_SYNCSETTINGS,163,38,133,61 - CONTROL "Allow Left+Right / Up+Down",IDC_ALLOWLEFTRIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,62,118,10 - CONTROL "Sync samples with sound CPU",IDC_SYNC_TO_SOUND_CPU, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,75,117,10 - CONTROL "Clear SRAM",IDC_CLEARSRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,83,70,10 + GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,7,50,77,61 + CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,77,70,10 + CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,64,72,10 + CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,59,45,10 + CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,79,45,10 + CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,69,45,10 + CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,89,45,10 + CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,99,45,10 + GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,97,50,69,61 + EDITTEXT IDC_MOVIE_METADATA,67,34,229,14,ES_AUTOHSCROLL + LTEXT "Author Info:",IDC_STATIC,18,37,43,8,0,WS_EX_RIGHT + CONTROL "Clear SRAM",IDC_CLEARSRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,95,70,10 END IDD_KEYCUSTOM DIALOGEX 0, 0, 349, 203 @@ -654,12 +645,11 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 297 TOPMARGIN, 7 - BOTTOMMARGIN, 219 + BOTTOMMARGIN, 162 HORZGUIDE, 31 HORZGUIDE, 55 HORZGUIDE, 120 HORZGUIDE, 133 - HORZGUIDE, 191 END IDD_CREATEMOVIE, DIALOG @@ -667,7 +657,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 296 TOPMARGIN, 7 - BOTTOMMARGIN, 143 + BOTTOMMARGIN, 111 HORZGUIDE, 31 HORZGUIDE, 38 HORZGUIDE, 99 diff --git a/win32/wlanguage.h b/win32/wlanguage.h index b840e6fb..e50402dd 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -272,7 +272,6 @@ #define HOTKEYS_LABEL_2_5 TEXT("Sprites Layer") #define HOTKEYS_LABEL_2_6 TEXT("Clipping Windows") #define HOTKEYS_LABEL_2_7 TEXT("Transparency") -#define HOTKEYS_LABEL_2_8 TEXT("HDMA Emulation") #define HOTKEYS_LABEL_2_10 TEXT("Switch Controllers") #define HOTKEYS_LABEL_2_11 TEXT("Joypad Swap") #define HOTKEYS_LABEL_2_12 TEXT("Reset Game") @@ -396,7 +395,6 @@ #define WINPROC_TURBOMODE_ON "Fast-Forward Activated" #define WINPROC_TURBOMODE_OFF "Fast-Forward Deactivated" #define WINPROC_TURBOMODE_TEXT "Fast-Forward" -#define WINPROC_HDMA_TEXT "HDMA emulation" #define WINPROC_BG1 "BG#1" //Background Layers #define WINPROC_BG2 "BG#2" #define WINPROC_BG3 "BG#3" diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 6bf7c357..0aff572f 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -1454,11 +1454,11 @@ LRESULT CALLBACK WinProc( case WM_CUSTKEYUP: { int modifiers = 0; - if(GetAsyncKeyState(VK_MENU)) + if(GetAsyncKeyState(VK_MENU) || wParam == VK_MENU) modifiers |= CUSTKEY_ALT_MASK; - if(GetAsyncKeyState(VK_CONTROL)) + if(GetAsyncKeyState(VK_CONTROL)|| wParam == VK_CONTROL) modifiers |= CUSTKEY_CTRL_MASK; - if(GetAsyncKeyState(VK_SHIFT)) + if(GetAsyncKeyState(VK_SHIFT)|| wParam == VK_SHIFT) modifiers |= CUSTKEY_SHIFT_MASK; if(wParam == CustomKeys.FastForward.key @@ -2687,7 +2687,11 @@ VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWO PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, (WPARAM)(i),(LPARAM)(NULL)); } else - joyState[i] = 0; + if(joyState[i]) + { + joyState[i] = 0; + PostMessage(GUI.hWnd, WM_CUSTKEYUP, (WPARAM)(i),(LPARAM)(NULL)); + } } counter++; } @@ -7765,7 +7769,8 @@ static void set_hotkeyinfo(HWND hDlg) SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.BGL5.key,CustomKeys.BGL5.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.ClippingWindows.key,CustomKeys.ClippingWindows.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.Transparency.key,CustomKeys.Transparency.modifiers); -// SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.HDMA.key,CustomKeys.HDMA.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,0,0); + SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,0,0); SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.SwitchControllers.key,CustomKeys.SwitchControllers.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.JoypadSwap.key,CustomKeys.JoypadSwap.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ResetGame.key,CustomKeys.ResetGame.modifiers); @@ -7829,7 +7834,7 @@ static void set_hotkeyinfo(HWND hDlg) SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_2_5); SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_2_6); SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_2_7); - SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_2_8); + SetDlgItemText(hDlg,IDC_LABEL_HK8,INPUTCONFIG_LABEL_UNUSED); SetDlgItemText(hDlg,IDC_LABEL_HK9,INPUTCONFIG_LABEL_UNUSED); SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_2_10); SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_2_11); @@ -10188,8 +10193,6 @@ static void set_movieinfo(const TCHAR* path, HWND hDlg) // if(m.SyncFlags & MOVIE_SYNC_DATA_EXISTS) { - SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, (m.SyncFlags & MOVIE_SYNC_LEFTRIGHT)!=0 ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); - SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK, (m.SyncFlags & MOVIE_SYNC_SYNCSOUND)!=0 ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); // SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), _T(MOVIE_LABEL_SYNC_DATA_FROM_MOVIE)); } @@ -10330,10 +10333,6 @@ INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch(LOWORD(wParam)) { - case IDC_ALLOWLEFTRIGHT: - case IDC_SYNC_TO_SOUND_CPU: - SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), TEXT("")); - break; case IDC_BROWSE_MOVIE: { OPENFILENAME ofn; @@ -10389,8 +10388,6 @@ INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_MOVIE_PATH, op->Path, MAX_PATH); SetCurrentDirectory(movieDirectory); } - Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT); - Settings.SoundSync = IsDlgButtonChecked(hDlg, IDC_SYNC_TO_SOUND_CPU); EndDialog(hDlg, 1); return true; @@ -10458,10 +10455,6 @@ INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), filename); } - SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, Settings.UpAndDown ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); - SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK, Settings.SoundSync ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); - SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), _T("")); - //EnableWindow(GetDlgItem(hDlg, IDC_SYNC_TO_SOUND_CPU), Settings.SoundDriver<1||Settings.SoundDriver>3); // can't sync sound to CPU unless using "Snes9x DirectSound" driver SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK, (WPARAM)(GUI.MovieStartFromReset ? BST_CHECKED : BST_UNCHECKED), 0); @@ -10540,12 +10533,7 @@ INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara else GUI.MovieStartFromReset = FALSE; - Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT); - Settings.SoundSync = IsDlgButtonChecked(hDlg, IDC_SYNC_TO_SOUND_CPU); - op->SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; - if(Settings.UpAndDown) op->SyncFlags |= MOVIE_SYNC_LEFTRIGHT; - if(Settings.SoundSync) op->SyncFlags |= MOVIE_SYNC_SYNCSOUND; if(IsDlgButtonChecked(hDlg, IDC_CLEARSRAM) && IsDlgButtonChecked(hDlg, IDC_RECORD_RESET) && existsSRAM()) { From 2c3b9f1f63b93e789c759d5a48f5b3a92c5eb978 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 7 May 2011 23:16:10 +0200 Subject: [PATCH 003/130] Win32: react to WM_DISPLAYCHANGE (hopefully without crashing) --- win32/win32_display.cpp | 1 - win32/wsnes9x.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index 8fb317cc..2809347b 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -256,7 +256,6 @@ bool WinDisplayReset(void) if(S9xDisplayOutput->Initialize(GUI.hWnd)) { S9xGraphicsDeinit(); S9xSetWinPixelFormat (); - S9xInitUpdate(); S9xGraphicsInit(); return true; } else { diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 0aff572f..77577590 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -2342,9 +2342,9 @@ LRESULT CALLBACK WinProc( S9xClearPause(PAUSE_MENU); break; case WM_DISPLAYCHANGE: - if (!GUI.FullScreen) + if (!GUI.FullScreen && !(Settings.ForcedPause & PAUSE_TOGGLE_FULL_SCREEN)) { - //WinDisplayReset(); + WinDisplayReset(); } break; case WM_MOUSEMOVE: From a4f56c08e7d71083eccfdbdd6de908b6c6ca1579 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 8 May 2011 01:41:33 +0200 Subject: [PATCH 004/130] Win32: merge BackgroundKeyGamekeys and BackgroundKeyHotkeys, add menu item --- win32/rsrc/resource.h | 3 ++- win32/rsrc/snes9x.rc | 2 ++ win32/wconfig.cpp | 3 +-- win32/win32.cpp | 2 +- win32/wsnes9x.cpp | 17 +++++++++++++---- win32/wsnes9x.h | 2 +- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index ca767abd..90d5997f 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -485,13 +485,14 @@ #define ID_WINDOW_SIZE_3X 40171 #define ID_WINDOW_SIZE_4X 40172 #define ID_DEBUG_APU_TRACE 40173 +#define ID_EMULATION_BACKGROUNDINPUT 40174 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 151 -#define _APS_NEXT_COMMAND_VALUE 40174 +#define _APS_NEXT_COMMAND_VALUE 40175 #define _APS_NEXT_CONTROL_VALUE 3018 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 2a0ff7cd..aad02cb6 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -842,6 +842,8 @@ BEGIN MENUITEM "&Input Configuration...\tAlt+F7", 40022 MENUITEM "&Customize Hotkeys...\tAlt+F9", ID_OPTIONS_KEYCUSTOM MENUITEM SEPARATOR + MENUITEM "Enable Background Input", ID_EMULATION_BACKGROUNDINPUT + MENUITEM SEPARATOR MENUITEM "Use SNES Joypad(s)", IDM_SNES_JOYPAD MENUITEM "Use SNES Mouse", IDM_MOUSE_TOGGLE MENUITEM "Use Super Scope", IDM_SCOPE_TOGGLE diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index 407e697f..fab84361 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -997,11 +997,10 @@ void WinRegisterConfigItems() #undef ADDT3 #undef ADDTN #undef ADD2T2 - AddBool2C("Joypads:Background", GUI.BackgroundKeyGamekeys, true, "on to detect game keypresses while window is inactive, if PauseWhenInactive = FALSE."); + AddBool2C("Input:Background", GUI.BackgroundInput, false, "on to detect game keypresses and hotkeys while window is inactive, if PauseWhenInactive = FALSE."); #undef CATEGORY #define CATEGORY "Controls\\Win\\Hotkeys" AddBool2C("Handler:Joystick", GUI.JoystickHotkeys, true, "on to detect game controller buttons assigned to hotkeys. May impact performance."); - AddBool2C("Handler:Background", GUI.BackgroundKeyHotkeys, false, "on to detect keyboard hotkeys when in the background. May impact performance and decrease responsiveness."); #define ADD(x) AddVKey("Key:" #x , CustomKeys.x.key, CustomKeys.x.key); AddVKMod("Mods:" #x, CustomKeys.x.modifiers, CustomKeys.x.modifiers) #define ADDN(x,n2) AddVKey("Key:" #n2, CustomKeys.x.key, CustomKeys.x.key); AddVKMod("Mods:" #n2, CustomKeys.x.modifiers, CustomKeys.x.modifiers) ADD(SpeedUp); ADD(SpeedDown); ADD(Pause); ADD(FrameAdvance); diff --git a/win32/win32.cpp b/win32/win32.cpp index bcdc5c5e..aba6d171 100644 --- a/win32/win32.cpp +++ b/win32/win32.cpp @@ -641,7 +641,7 @@ bool S9xGetState (WORD KeyIdent) if(KeyIdent == 0 || KeyIdent == VK_ESCAPE) // if it's the 'disabled' key, it's never pressed return true; - if(!GUI.BackgroundKeyGamekeys && GUI.hWnd != GetActiveWindow()) + if(!GUI.BackgroundInput && GUI.hWnd != GetForegroundWindow()) return true; if (KeyIdent & 0x8000) // if it's a joystick 'key': diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 77577590..7d871b06 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -277,7 +277,7 @@ INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); HRESULT CALLBACK EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext); -INT_PTR CALLBACK test(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); #define NOTKNOWN "Unknown Company " #define HEADER_SIZE 512 @@ -1440,7 +1440,7 @@ LRESULT CALLBACK WinProc( DragAcceptFiles(hWnd, TRUE); return 0; case WM_KEYDOWN: - if(GUI.BackgroundKeyHotkeys) + if(GUI.BackgroundInput && !GUI.InactivePause) break; case WM_CUSTKEYDOWN: case WM_SYSKEYDOWN: @@ -1754,6 +1754,12 @@ LRESULT CALLBACK WinProc( RestoreSNESDisplay (); break; + case ID_EMULATION_BACKGROUNDINPUT: + GUI.BackgroundInput = !GUI.BackgroundInput; + if(!GUI.hHotkeyTimer) + GUI.hHotkeyTimer = timeSetEvent (32, 0, (LPTIMECALLBACK)HotkeyTimer, 0, TIME_PERIODIC); + break; + case ID_FILE_LOADMULTICART: { #ifdef NETPLAY_SUPPORT @@ -2669,7 +2675,7 @@ VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWO } counter++; } - if(GUI.BackgroundKeyHotkeys) + if(GUI.BackgroundInput && !GUI.InactivePause) { static int counter = 0; static uint32 joyState [256]; @@ -3270,7 +3276,7 @@ int WINAPI WinMain( Settings.StopEmulation = TRUE; GUI.hFrameTimer = timeSetEvent (20, 0, (LPTIMECALLBACK)FrameTimer, 0, TIME_PERIODIC); - if(GUI.JoystickHotkeys || GUI.BackgroundKeyHotkeys) + if(GUI.JoystickHotkeys || GUI.BackgroundInput) GUI.hHotkeyTimer = timeSetEvent (32, 0, (LPTIMECALLBACK)HotkeyTimer, 0, TIME_PERIODIC); else GUI.hHotkeyTimer = 0; @@ -3792,6 +3798,9 @@ static void CheckMenuStates () mii.fState = (GUI.SoundChannelEnable & (1 << 7)) ? MFS_CHECKED : MFS_UNCHECKED; SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL8, FALSE, &mii); + mii.fState = GUI.BackgroundInput ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_EMULATION_BACKGROUNDINPUT, FALSE, &mii); + UINT validFlag; enum controllers controller[2]; int8 ids[4]; diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index e99aacb3..3e6df53c 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -353,7 +353,7 @@ struct sGUI { int ControllerOption; int ValidControllerOptions; int SoundChannelEnable; - bool BackgroundKeyHotkeys, BackgroundKeyGamekeys; + bool BackgroundInput; bool JoystickHotkeys; bool MovieClearSRAM; bool MovieStartFromReset; From 54d8e77a96aa542dc2e66b31d0757ccca2564237 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 8 May 2011 03:39:25 +0200 Subject: [PATCH 005/130] Win32: add config option to disable OpenGL PBO usage --- win32/COpenGL.cpp | 3 +++ win32/wconfig.cpp | 1 + win32/wsnes9x.cpp | 2 +- win32/wsnes9x.h | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 4775cbca..4d85f558 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -604,6 +604,9 @@ void COpenGL::EnumModes(std::vector *modeVector) bool COpenGL::LoadPBOFunctions() { + if(GUI.OGLdisablePBOs) + return false; + if(pboFunctionsLoaded) return true; diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index fab84361..2d202535 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -868,6 +868,7 @@ void WinRegisterConfigItems() AddBoolC("ShaderEnabled", GUI.shaderEnabled, false, "true to use pixel shader (if supported by output method)"); AddStringC("Direct3D:D3DShader", GUI.D3DshaderFileName, MAX_PATH, "", "shader filename for Direct3D mode (HLSL effect file or CG shader"); AddStringC("OpenGL:OGLShader", GUI.OGLshaderFileName, MAX_PATH, "", "shader filename for OpenGL mode (bsnes-style XML shader or CG shader)"); + AddBoolC("OpenGL:DisablePBOs", GUI.OGLdisablePBOs, false, "do not use PBOs in OpenGL mode, even if the video card supports them"); AddBoolC("ExtendHeight", GUI.HeightExtend, false, "true to display an extra 15 pixels at the bottom, which few games use. Also increases AVI output size from 256x224 to 256x240."); AddBoolC("AlwaysCenterImage", GUI.AlwaysCenterImage,false, "true to center the image even if larger than window"); AddIntC("Window:Width", GUI.window_size.right, 512, "256=1x, 512=2x, 768=3x, 1024=4x, etc. (usually)"); diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 7d871b06..05da512b 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -4834,7 +4834,7 @@ INT_PTR CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) case 14:strcat(romtext, "Unknown region 14");break; default:strcat(romtext, "Unknown region 15");break; } - SendDlgItemMessageA(hDlg, IDC_ROM_DATA, WM_SETTEXT, 0, (LPARAM)romtext); + SendDlgItemMessage(hDlg, IDC_ROM_DATA, WM_SETTEXT, 0, (LPARAM)((TCHAR *)_tFromChar(romtext))); break; } case WM_CTLCOLORSTATIC: diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 3e6df53c..c533c305 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -320,6 +320,8 @@ struct sGUI { TCHAR D3DshaderFileName[MAX_PATH]; TCHAR OGLshaderFileName[MAX_PATH]; + bool OGLdisablePBOs; + bool IgnoreNextMouseMove; RECT window_size; bool window_maximized; From acfe6a53cc3fc433c282dacb93d283807f80e602 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 11 May 2011 21:39:06 +0200 Subject: [PATCH 006/130] Win32: add frame counter to cg shader vars (Themaister) --- win32/CDirect3D.cpp | 6 ++++++ win32/CDirect3D.h | 1 + win32/COpenGL.cpp | 11 +++++++++++ win32/COpenGL.h | 2 ++ win32/cgFunctions.cpp | 3 +++ win32/cgFunctions.h | 2 ++ 6 files changed, 25 insertions(+) diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index 28a6743e..b7d81afb 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -221,6 +221,7 @@ CDirect3D::CDirect3D() shaderTimer = 1.0f; shaderTimeStart = 0; shaderTimeElapsed = 0; + frameCount = 0; cgContext = NULL; cgVertexProgram = cgFragmentProgram = NULL; cgAvailable = false; @@ -649,11 +650,13 @@ void CDirect3D::SetShaderVars() D3DXVECTOR2 videoSize; D3DXVECTOR2 textureSize; D3DXVECTOR2 outputSize; + float frameCnt; videoSize.x = (float)afterRenderWidth; videoSize.y = (float)afterRenderHeight; textureSize.x = textureSize.y = (float)quadTextureSize; outputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; outputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; + frameCnt = (float)++frameCount; #define setProgramUniform(program,varname,floats)\ {\ @@ -665,10 +668,13 @@ void CDirect3D::SetShaderVars() setProgramUniform(cgFragmentProgram,"IN.video_size",&videoSize); setProgramUniform(cgFragmentProgram,"IN.texture_size",&textureSize); setProgramUniform(cgFragmentProgram,"IN.output_size",&outputSize); + setProgramUniform(cgFragmentProgram,"IN.frame_count",&frameCnt); setProgramUniform(cgVertexProgram,"IN.video_size",&videoSize); setProgramUniform(cgVertexProgram,"IN.texture_size",&textureSize); setProgramUniform(cgVertexProgram,"IN.output_size",&outputSize); + setProgramUniform(cgVertexProgram,"IN.frame_count",&frameCnt); + } } diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 92b1a9ae..f4707b61 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -230,6 +230,7 @@ private: float shaderTimer; int shaderTimeStart; int shaderTimeElapsed; + int frameCount; bool BlankTexture(LPDIRECT3DTEXTURE9 texture); void CreateDrawSurface(); diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 4d85f558..66597c79 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -210,6 +210,7 @@ COpenGL::COpenGL(void) cgContext = NULL; cgVertexProgram = cgFragmentProgram = NULL; cgAvailable = false; + frameCount = 0; } COpenGL::~COpenGL(void) @@ -452,6 +453,7 @@ void COpenGL::Render(SSurface Src) float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; + float frameCnt = (float)++frameCount; if(shader_type == OGL_SHADER_GLSL) { location = glGetUniformLocation (shaderProgram, "rubyInputSize"); @@ -474,12 +476,21 @@ void COpenGL::Render(SSurface Src) cgGLSetParameter2fv(cgp,floats);\ }\ +#define setProgram1f(program,varname,val)\ +{\ + CGparameter cgp = cgGetNamedParameter(program, varname);\ + if(cgp)\ + cgGLSetParameter1f(cgp,val);\ +}\ + setProgram2fv(cgFragmentProgram,"IN.video_size",inputSize); setProgram2fv(cgFragmentProgram,"IN.texture_size",textureSize); setProgram2fv(cgFragmentProgram,"IN.output_size",outputSize); + setProgram1f(cgFragmentProgram,"IN.frame_count",frameCnt); setProgram2fv(cgVertexProgram,"IN.video_size",inputSize); setProgram2fv(cgVertexProgram,"IN.texture_size",textureSize); setProgram2fv(cgVertexProgram,"IN.output_size",outputSize); + setProgram1f(cgVertexProgram,"IN.frame_count",frameCnt); } } diff --git a/win32/COpenGL.h b/win32/COpenGL.h index 4837d9bf..cd10f85b 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -202,6 +202,8 @@ private: GLfloat texcoords[8]; unsigned char * noPboBuffer; + int frameCount; + bool initDone; bool fullscreen; unsigned int quadTextureSize; diff --git a/win32/cgFunctions.cpp b/win32/cgFunctions.cpp index 2c88931d..7229f3e1 100644 --- a/win32/cgFunctions.cpp +++ b/win32/cgFunctions.cpp @@ -204,6 +204,7 @@ CGD3DSU cgD3D9SetUniform = NULL; //cggl.dll CGGLSSMP cgGLSetStateMatrixParameter = NULL; CGGLSP2FV cgGLSetParameter2fv = NULL; +CGGLSP1F cgGLSetParameter1f = NULL; CGGLGLP cgGLGetLatestProfile = NULL; CGGLEP cgGLEnableProfile = NULL; CGGLDP cgGLDisableProfile = NULL; @@ -248,6 +249,7 @@ bool loadCgFunctions() //cggl.dll cgGLSetStateMatrixParameter = (CGGLSSMP)GetProcAddress(hCgGLDll,"cgGLSetStateMatrixParameter"); cgGLSetParameter2fv = (CGGLSP2FV)GetProcAddress(hCgGLDll,"cgGLSetParameter2fv"); + cgGLSetParameter1f = (CGGLSP1F)GetProcAddress(hCgGLDll,"cgGLSetParameter1f"); cgGLGetLatestProfile = (CGGLGLP)GetProcAddress(hCgGLDll,"cgGLGetLatestProfile"); cgGLEnableProfile = (CGGLEP)GetProcAddress(hCgGLDll,"cgGLEnableProfile"); cgGLDisableProfile = (CGGLDP)GetProcAddress(hCgGLDll,"cgGLDisableProfile"); @@ -277,6 +279,7 @@ bool loadCgFunctions() //cggl.dll !cgGLSetStateMatrixParameter || !cgGLSetParameter2fv || + !cgGLSetParameter1f || !cgGLGetLatestProfile || !cgGLEnableProfile || !cgGLDisableProfile || diff --git a/win32/cgFunctions.h b/win32/cgFunctions.h index 2d7ea3ac..324eca32 100644 --- a/win32/cgFunctions.h +++ b/win32/cgFunctions.h @@ -227,6 +227,8 @@ extern CGD3DSU cgD3D9SetUniform; //cggl.dll typedef CGGL_API void (CGGLENTRY *CGGLSSMP)(CGparameter param, CGGLenum matrix, CGGLenum transform); extern CGGLSSMP cgGLSetStateMatrixParameter; +typedef CGGL_API void (CGGLENTRY *CGGLSP1F)(CGparameter param, float x); +extern CGGLSP1F cgGLSetParameter1f; typedef CGGL_API void (CGGLENTRY *CGGLSP2FV)(CGparameter param, const float *v); extern CGGLSP2FV cgGLSetParameter2fv; typedef CGGL_API CGprofile (CGGLENTRY *CGGLGLP)(CGGLenum profile_type); From a13d50916d98fec7f69b98d250022c2d0a1278e1 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 13 May 2011 09:46:43 +0200 Subject: [PATCH 007/130] Win32: update cg matrix parameter on setviewport (d3d) --- win32/CDirect3D.cpp | 39 +++++++++++++++++++++------------------ win32/CDirect3D.h | 2 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index b7d81afb..5f5b3f49 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -423,23 +423,6 @@ bool CDirect3D::SetShaderCG(const TCHAR *file) if(cgVertexProgram) { hr = cgD3D9LoadProgram(cgVertexProgram,true,0); hr = cgD3D9BindProgram(cgVertexProgram); - - D3DXMATRIX matWorld; - D3DXMATRIX matView; - D3DXMATRIX matProj; - D3DXMATRIX mvp; - - pDevice->GetTransform(D3DTS_WORLD,&matWorld); - pDevice->GetTransform(D3DTS_VIEW,&matView); - pDevice->GetTransform(D3DTS_PROJECTION,&matProj); - - mvp = matWorld * matView * matProj; - D3DXMatrixTranspose(&mvp,&mvp); - - CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); - - if(cgpModelViewProj) - cgD3D9SetUniformMatrix(cgpModelViewProj,&mvp); } if(cgFragmentProgram) { hr = cgD3D9LoadProgram(cgFragmentProgram,false,0); @@ -605,7 +588,7 @@ bool CDirect3D::SetShaderHLSL(const TCHAR *file) return true; } -void CDirect3D::SetShaderVars() +void CDirect3D::SetShaderVars(bool setMatrix) { if(shader_type == D3D_SHADER_HLSL) { D3DXVECTOR4 rubyTextureSize; @@ -675,6 +658,24 @@ void CDirect3D::SetShaderVars() setProgramUniform(cgVertexProgram,"IN.output_size",&outputSize); setProgramUniform(cgVertexProgram,"IN.frame_count",&frameCnt); + if(setMatrix) { + D3DXMATRIX matWorld; + D3DXMATRIX matView; + D3DXMATRIX matProj; + D3DXMATRIX mvp; + + pDevice->GetTransform(D3DTS_WORLD,&matWorld); + pDevice->GetTransform(D3DTS_VIEW,&matView); + pDevice->GetTransform(D3DTS_PROJECTION,&matProj); + + mvp = matWorld * matView * matProj; + D3DXMatrixTranspose(&mvp,&mvp); + + CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + + if(cgpModelViewProj) + cgD3D9SetUniformMatrix(cgpModelViewProj,&mvp); + } } } @@ -896,6 +897,8 @@ void CDirect3D::SetViewport() pDevice->SetTransform(D3DTS_VIEW,&matIdentity); pDevice->SetTransform(D3DTS_PROJECTION,&matProjection); + SetShaderVars(true); + RECT drawRect = CalculateDisplayRect(afterRenderWidth,afterRenderHeight,dPresentParams.BackBufferWidth,dPresentParams.BackBufferHeight); D3DVIEWPORT9 viewport; viewport.X = drawRect.left; diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index f4707b61..54cd9e00 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -239,7 +239,7 @@ private: void SetViewport(); void SetupVertices(); bool ResetDevice(); - void SetShaderVars(); + void SetShaderVars(bool setMatrix = false); bool SetShader(const TCHAR *file); bool SetShaderHLSL(const TCHAR *file); void checkForCgError(const char *situation); From 2872a711275e4a96ae3490814544c999ddd6a03b Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 13 May 2011 10:02:12 +0200 Subject: [PATCH 008/130] Win32: fix cheat dialog value entry --- win32/wsnes9x.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 05da512b..9e5136f6 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -8741,8 +8741,8 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { uint32 j, k; long index; - TCHAR buffer[4]; - TCHAR buffer2[4]; + char buffer[4]; + char buffer2[4]; POINT point; switch(HIWORD(wParam)) { @@ -8758,18 +8758,18 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) index = SendMessageA((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16))); k=0; - for(j=0; j=TEXT('0') && buffer[j]<=TEXT('9')) || (buffer[j]>=TEXT('A') && buffer[j]<=TEXT('F')) || buffer[j]==TEXT('$')) + if( (buffer[j]>='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F') || buffer[j]=='$') { buffer2[k]=buffer[j]; k++; } else index --; } - buffer2[k]=TEXT('\0'); + buffer2[k]='\0'; - if(has_sel&&!new_sel&&0!=lstrlen(buffer2)) + if(has_sel&&!new_sel&&0!=strlen(buffer2)) SetDlgItemTextA(hDlg, IDC_CHEAT_CODE, ""); if(new_sel!=0) @@ -8780,7 +8780,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) SendMessageA((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index); SendMessageA(GetDlgItem(hDlg, IDC_CHEAT_ADDRESS), WM_GETTEXT, 7,(LPARAM)buffer); - if(lstrlen(buffer2)!=0 && lstrlen(buffer) !=0) + if(strlen(buffer2)!=0 && strlen(buffer) !=0) { if(has_sel) EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true); From 3e84a2eaf4616e1917cfd53140af2b6c5198007c Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 9 Jun 2011 19:15:57 +0200 Subject: [PATCH 009/130] Win32: remove legacy extentions from valid.ext --- win32/wsnes9x.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 9e5136f6..68be3edd 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -6783,10 +6783,8 @@ void MakeExtFile(void) out.open("Valid.Ext"); out<<"N" < Date: Sun, 12 Jun 2011 01:25:22 -0500 Subject: [PATCH 010/130] Add byuu's SMP and DSP files to tree. --- apu/apu.cpp | 6 + apu/bapu/dsp/SPC_DSP.cpp | 1072 ++++++++++++++++ apu/bapu/dsp/SPC_DSP.h | 319 +++++ apu/bapu/dsp/blargg_common.h | 186 +++ apu/bapu/dsp/blargg_config.h | 24 + apu/bapu/dsp/blargg_endian.h | 185 +++ apu/bapu/dsp/blargg_source.h | 100 ++ apu/bapu/dsp/dsp.cpp | 61 + apu/bapu/dsp/dsp.hpp | 26 + apu/bapu/dsp/serialization.cpp | 31 + apu/bapu/smp/algorithms.cpp | 122 ++ apu/bapu/smp/core.cpp | 105 ++ apu/bapu/smp/core/cc.sh | 1 + apu/bapu/smp/core/generate.cpp | 154 +++ apu/bapu/smp/core/op_misc.b | 163 +++ apu/bapu/smp/core/op_misc.cpp | 346 +++++ apu/bapu/smp/core/op_mov.b | 217 ++++ apu/bapu/smp/core/op_mov.cpp | 389 ++++++ apu/bapu/smp/core/op_pc.b | 179 +++ apu/bapu/smp/core/op_pc.cpp | 603 +++++++++ apu/bapu/smp/core/op_read.b | 205 +++ apu/bapu/smp/core/op_read.cpp | 744 +++++++++++ apu/bapu/smp/core/op_rmw.b | 74 ++ apu/bapu/smp/core/op_rmw.cpp | 262 ++++ apu/bapu/smp/core/opcycle_misc.cpp | 696 +++++++++++ apu/bapu/smp/core/opcycle_mov.cpp | 806 ++++++++++++ apu/bapu/smp/core/opcycle_pc.cpp | 1347 ++++++++++++++++++++ apu/bapu/smp/core/opcycle_read.cpp | 1599 ++++++++++++++++++++++++ apu/bapu/smp/core/opcycle_rmw.cpp | 550 ++++++++ apu/bapu/smp/debugger/debugger.cpp | 75 ++ apu/bapu/smp/debugger/debugger.hpp | 27 + apu/bapu/smp/debugger/disassembler.cpp | 304 +++++ apu/bapu/smp/iplrom.cpp | 44 + apu/bapu/smp/memory.cpp | 130 ++ apu/bapu/smp/smp.cpp | 154 +++ apu/bapu/smp/smp.hpp | 124 ++ apu/bapu/smp/timing.cpp | 26 + apu/bapu/snes/snes.hpp | 45 + gtk/Makefile.am | 10 +- gtk/src/gtk_s9xwindow.cpp | 4 - 40 files changed, 11509 insertions(+), 6 deletions(-) create mode 100755 apu/bapu/dsp/SPC_DSP.cpp create mode 100755 apu/bapu/dsp/SPC_DSP.h create mode 100755 apu/bapu/dsp/blargg_common.h create mode 100755 apu/bapu/dsp/blargg_config.h create mode 100755 apu/bapu/dsp/blargg_endian.h create mode 100755 apu/bapu/dsp/blargg_source.h create mode 100755 apu/bapu/dsp/dsp.cpp create mode 100755 apu/bapu/dsp/dsp.hpp create mode 100755 apu/bapu/dsp/serialization.cpp create mode 100755 apu/bapu/smp/algorithms.cpp create mode 100755 apu/bapu/smp/core.cpp create mode 100755 apu/bapu/smp/core/cc.sh create mode 100755 apu/bapu/smp/core/generate.cpp create mode 100755 apu/bapu/smp/core/op_misc.b create mode 100755 apu/bapu/smp/core/op_misc.cpp create mode 100755 apu/bapu/smp/core/op_mov.b create mode 100755 apu/bapu/smp/core/op_mov.cpp create mode 100755 apu/bapu/smp/core/op_pc.b create mode 100755 apu/bapu/smp/core/op_pc.cpp create mode 100755 apu/bapu/smp/core/op_read.b create mode 100755 apu/bapu/smp/core/op_read.cpp create mode 100755 apu/bapu/smp/core/op_rmw.b create mode 100755 apu/bapu/smp/core/op_rmw.cpp create mode 100755 apu/bapu/smp/core/opcycle_misc.cpp create mode 100755 apu/bapu/smp/core/opcycle_mov.cpp create mode 100755 apu/bapu/smp/core/opcycle_pc.cpp create mode 100755 apu/bapu/smp/core/opcycle_read.cpp create mode 100755 apu/bapu/smp/core/opcycle_rmw.cpp create mode 100755 apu/bapu/smp/debugger/debugger.cpp create mode 100755 apu/bapu/smp/debugger/debugger.hpp create mode 100755 apu/bapu/smp/debugger/disassembler.cpp create mode 100755 apu/bapu/smp/iplrom.cpp create mode 100755 apu/bapu/smp/memory.cpp create mode 100755 apu/bapu/smp/smp.cpp create mode 100755 apu/bapu/smp/smp.hpp create mode 100755 apu/bapu/smp/timing.cpp create mode 100755 apu/bapu/snes/snes.hpp diff --git a/apu/apu.cpp b/apu/apu.cpp index f6e24456..47f03b6b 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -183,6 +183,7 @@ #include "display.h" #include "linear_resampler.h" #include "hermite_resampler.h" +#include "snes/snes.hpp" #define APU_DEFAULT_INPUT_RATE 32000 #define APU_MINIMUM_SAMPLE_COUNT 512 @@ -195,6 +196,11 @@ SNES_SPC *spc_core = NULL; +namespace SNES +{ + CPU cpu; +} + static uint8 APUROM[64] = { 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp new file mode 100755 index 00000000..e6ba49ed --- /dev/null +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -0,0 +1,1072 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_DSP.h" + +#include "blargg_endian.h" +#include + +/* Copyright (C) 2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +#if INT_MAX < 0x7FFFFFFF + #error "Requires that int type have at least 32 bits" +#endif + +// TODO: add to blargg_endian.h +#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) +#define GET_LE16A( addr ) GET_LE16( addr ) +#define SET_LE16A( addr, data ) SET_LE16( addr, data ) + +static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = +{ + 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, + 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, + 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, + 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, + 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, + 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF, + 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, + 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF +}; + +// if ( io < -32768 ) io = -32768; +// if ( io > 32767 ) io = 32767; +#define CLAMP16( io )\ +{\ + if ( (int16_t) io != io )\ + io = (io >> 31) ^ 0x7FFF;\ +} + +// Access global DSP register +#define REG(n) m.regs [r_##n] + +// Access voice DSP register +#define VREG(r,n) r [v_##n] + +#define WRITE_SAMPLES( l, r, out ) \ +{\ + out [0] = l;\ + out [1] = r;\ + out += 2;\ + if ( out >= m.out_end )\ + {\ + check( out == m.out_end );\ + check( m.out_end != &m.extra [extra_size] || \ + (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ + out = m.extra;\ + m.out_end = &m.extra [extra_size];\ + }\ +}\ + +void SPC_DSP::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // must be even + if ( !out ) + { + out = m.extra; + size = extra_size; + } + m.out_begin = out; + m.out = out; + m.out_end = out + size; +} + +// Volume registers and efb are signed! Easy to forget int8_t cast. +// Prefixes are to avoid accidental use of locals with same names. + +// Gaussian interpolation + +static short const gauss [512] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, + 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, + 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, + 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, + 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, + 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, + 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, + 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, + 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, + 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, + 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, + 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, + 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, + 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, + 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, + 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, + 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, +1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, +1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, +1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, +1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, +1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, +1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, +1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, +}; + +inline int SPC_DSP::interpolate( voice_t const* v ) +{ + // Make pointers into gaussian based on fractional position between samples + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = gauss + 255 - offset; + short const* rev = gauss + offset; // mirror left half of gaussian + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (fwd [ 0] * in [0]) >> 11; + out += (fwd [256] * in [1]) >> 11; + out += (rev [256] * in [2]) >> 11; + out = (int16_t) out; + out += (rev [ 0] * in [3]) >> 11; + + CLAMP16( out ); + out &= ~1; + return out; +} + + +//// Counters + +int const simple_counter_range = 2048 * 5 * 3; // 30720 + +static unsigned const counter_rates [32] = +{ + simple_counter_range + 1, // never fires + 2048, 1536, + 1280, 1024, 768, + 640, 512, 384, + 320, 256, 192, + 160, 128, 96, + 80, 64, 48, + 40, 32, 24, + 20, 16, 12, + 10, 8, 6, + 5, 4, 3, + 2, + 1 +}; + +static unsigned const counter_offsets [32] = +{ + 1, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 0, + 0 +}; + +inline void SPC_DSP::init_counter() +{ + m.counter = 0; +} + +inline void SPC_DSP::run_counters() +{ + if ( --m.counter < 0 ) + m.counter = simple_counter_range - 1; +} + +inline unsigned SPC_DSP::read_counter( int rate ) +{ + return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; +} + + +//// Envelope + +inline void SPC_DSP::run_envelope( voice_t* const v ) +{ + int env = v->env; + if ( v->env_mode == env_release ) // 60% + { + if ( (env -= 0x8) < 0 ) + env = 0; + v->env = env; + } + else + { + int rate; + int env_data = VREG(v->regs,adsr1); + if ( m.t_adsr0 & 0x80 ) // 99% ADSR + { + if ( v->env_mode >= env_decay ) // 99% + { + env--; + env -= env >> 8; + rate = env_data & 0x1F; + if ( v->env_mode == env_decay ) // 1% + rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; + } + else // env_attack + { + rate = (m.t_adsr0 & 0x0F) * 2 + 1; + env += rate < 31 ? 0x20 : 0x400; + } + } + else // GAIN + { + int mode; + env_data = VREG(v->regs,gain); + mode = env_data >> 5; + if ( mode < 4 ) // direct + { + env = env_data * 0x10; + rate = 31; + } + else + { + rate = env_data & 0x1F; + if ( mode == 4 ) // 4: linear decrease + { + env -= 0x20; + } + else if ( mode < 6 ) // 5: exponential decrease + { + env--; + env -= env >> 8; + } + else // 6,7: linear increase + { + env += 0x20; + if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) + env += 0x8 - 0x20; // 7: two-slope linear increase + } + } + } + + // Sustain level + if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) + v->env_mode = env_sustain; + + v->hidden_env = env; + + // unsigned cast because linear decrease going negative also triggers this + if ( (unsigned) env > 0x7FF ) + { + env = (env < 0 ? 0 : 0x7FF); + if ( v->env_mode == env_attack ) + v->env_mode = env_decay; + } + + if ( !read_counter( rate ) ) + v->env = env; // nothing else is controlled by the counter + } +} + + +//// BRR Decoding + +inline void SPC_DSP::decode_brr( voice_t* v ) +{ + // Arrange the four input nybbles in 0xABCD order for easy decoding + int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; + + int const header = m.t_brr_header; + + // Write to next four samples in circular buffer + int* pos = &v->buf [v->buf_pos]; + int* end; + if ( (v->buf_pos += 4) >= brr_buf_size ) + v->buf_pos = 0; + + // Decode four samples + for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) + { + // Extract nybble and sign-extend + int s = (int16_t) nybbles >> 12; + + // Shift sample based on header + int const shift = header >> 4; + s = (s << shift) >> 1; + if ( shift >= 0xD ) // handle invalid range + s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) + + // Apply IIR filter (8 is the most commonly used) + int const filter = header & 0x0C; + int const p1 = pos [brr_buf_size - 1]; + int const p2 = pos [brr_buf_size - 2] >> 1; + if ( filter >= 8 ) + { + s += p1; + s -= p2; + if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 + { + s += p2 >> 4; + s += (p1 * -3) >> 6; + } + else // s += p1 * 0.8984375 - p2 * 0.40625 + { + s += (p1 * -13) >> 7; + s += (p2 * 3) >> 4; + } + } + else if ( filter ) // s += p1 * 0.46875 + { + s += p1 >> 1; + s += (-p1) >> 5; + } + + // Adjust and write sample + CLAMP16( s ); + s = (int16_t) (s * 2); + pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around + } +} + + +//// Misc + +#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() + +MISC_CLOCK( 27 ) +{ + m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON +} +MISC_CLOCK( 28 ) +{ + m.t_non = REG(non); + m.t_eon = REG(eon); + m.t_dir = REG(dir); +} +MISC_CLOCK( 29 ) +{ + if ( (m.every_other_sample ^= 1) != 0 ) + m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read +} +MISC_CLOCK( 30 ) +{ + if ( m.every_other_sample ) + { + m.kon = m.new_kon; + m.t_koff = REG(koff) | m.mute_mask; + } + + run_counters(); + + // Noise + if ( !read_counter( REG(flg) & 0x1F ) ) + { + int feedback = (m.noise << 13) ^ (m.noise << 14); + m.noise = (feedback & 0x4000) ^ (m.noise >> 1); + } +} + + +//// Voices + +#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) + +inline VOICE_CLOCK( V1 ) +{ + m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; + m.t_srcn = VREG(v->regs,srcn); +} +inline VOICE_CLOCK( V2 ) +{ + // Read sample pointer (ignored if not needed) + uint8_t const* entry = &m.ram [m.t_dir_addr]; + if ( !v->kon_delay ) + entry += 2; + m.t_brr_next_addr = GET_LE16A( entry ); + + m.t_adsr0 = VREG(v->regs,adsr0); + + // Read pitch, spread over two clocks + m.t_pitch = VREG(v->regs,pitchl); +} +inline VOICE_CLOCK( V3a ) +{ + m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; +} +inline VOICE_CLOCK( V3b ) +{ + // Read BRR header and byte + m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; + m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking +} +VOICE_CLOCK( V3c ) +{ + // Pitch modulation using previous voice's output + if ( m.t_pmon & v->vbit ) + m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; + + if ( v->kon_delay ) + { + // Get ready to start BRR decoding on next sample + if ( v->kon_delay == 5 ) + { + v->brr_addr = m.t_brr_next_addr; + v->brr_offset = 1; + v->buf_pos = 0; + m.t_brr_header = 0; // header is ignored on this sample + m.kon_check = true; + + if (take_spc_snapshot) + { + take_spc_snapshot = 0; + if (spc_snapshot_callback) + spc_snapshot_callback(); + } + } + + // Envelope is never run during KON + v->env = 0; + v->hidden_env = 0; + + // Disable BRR decoding until last three samples + v->interp_pos = 0; + if ( --v->kon_delay & 3 ) + v->interp_pos = 0x4000; + + // Pitch is never added during KON + m.t_pitch = 0; + } + + // Gaussian interpolation + { + int output = interpolate( v ); + + // Noise + if ( m.t_non & v->vbit ) + output = (int16_t) (m.noise * 2); + + // Apply envelope + m.t_output = (output * v->env) >> 11 & ~1; + v->t_envx_out = (uint8_t) (v->env >> 4); + } + + // Immediate silence due to end of sample or soft reset + if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) + { + v->env_mode = env_release; + v->env = 0; + } + + if ( m.every_other_sample ) + { + // KOFF + if ( m.t_koff & v->vbit ) + v->env_mode = env_release; + + // KON + if ( m.kon & v->vbit ) + { + v->kon_delay = 5; + v->env_mode = env_attack; + } + } + + // Run envelope for next sample + if ( !v->kon_delay ) + run_envelope( v ); +} + +inline void SPC_DSP::voice_output( voice_t const* v, int ch ) +{ + // Apply left/right volume + int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; + amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); + + // Add to output total + m.t_main_out [ch] += amp; + CLAMP16( m.t_main_out [ch] ); + + // Optionally add to echo total + if ( m.t_eon & v->vbit ) + { + m.t_echo_out [ch] += amp; + CLAMP16( m.t_echo_out [ch] ); + } +} +VOICE_CLOCK( V4 ) +{ + // Decode BRR + m.t_looped = 0; + if ( v->interp_pos >= 0x4000 ) + { + decode_brr( v ); + + if ( (v->brr_offset += 2) >= brr_block_size ) + { + // Start decoding next BRR block + assert( v->brr_offset == brr_block_size ); + v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; + if ( m.t_brr_header & 1 ) + { + v->brr_addr = m.t_brr_next_addr; + m.t_looped = v->vbit; + } + v->brr_offset = 1; + } + } + + // Apply pitch + v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; + + // Keep from getting too far ahead (when using pitch modulation) + if ( v->interp_pos > 0x7FFF ) + v->interp_pos = 0x7FFF; + + // Output left + voice_output( v, 0 ); +} +inline VOICE_CLOCK( V5 ) +{ + // Output right + voice_output( v, 1 ); + + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier + int endx_buf = REG(endx) | m.t_looped; + + // Clear bit in ENDX if KON just began + if ( v->kon_delay == 5 ) + endx_buf &= ~v->vbit; + m.endx_buf = (uint8_t) endx_buf; +} +inline VOICE_CLOCK( V6 ) +{ + (void) v; // avoid compiler warning about unused v + m.outx_buf = (uint8_t) (m.t_output >> 8); +} +inline VOICE_CLOCK( V7 ) +{ + // Update ENDX + REG(endx) = m.endx_buf; + + m.envx_buf = v->t_envx_out; +} +inline VOICE_CLOCK( V8 ) +{ + // Update OUTX + VREG(v->regs,outx) = m.outx_buf; +} +inline VOICE_CLOCK( V9 ) +{ + // Update ENVX + VREG(v->regs,envx) = m.envx_buf; +} + +// Most voices do all these in one clock, so make a handy composite +inline VOICE_CLOCK( V3 ) +{ + voice_V3a( v ); + voice_V3b( v ); + voice_V3c( v ); +} + +// Common combinations of voice steps on different voices. This greatly reduces +// code size and allows everything to be inlined in these functions. +VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } +VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } +VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } + + +//// Echo + +// Current echo buffer pointer for left/right channel +#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) + +// Sample in echo history buffer, where 0 is the oldest +#define ECHO_FIR( i ) (m.echo_hist_pos [i]) + +// Calculate FIR point for left/right channel +#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) + +#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() + +inline void SPC_DSP::echo_read( int ch ) +{ + int s; + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); + else + s = GET_LE16SA( ECHO_PTR( ch ) ); + // second copy simplifies wrap-around handling + ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; +} + +ECHO_CLOCK( 22 ) +{ + // History + if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) + m.echo_hist_pos = m.echo_hist; + + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; + echo_read( 0 ); + + // FIR (using l and r temporaries below helps compiler optimize) + int l = CALC_FIR( 0, 0 ); + int r = CALC_FIR( 0, 1 ); + + m.t_echo_in [0] = l; + m.t_echo_in [1] = r; +} +ECHO_CLOCK( 23 ) +{ + int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); + int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; + + echo_read( 1 ); +} +ECHO_CLOCK( 24 ) +{ + int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); + int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; +} +ECHO_CLOCK( 25 ) +{ + int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); + int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); + + l = (int16_t) l; + r = (int16_t) r; + + l += (int16_t) CALC_FIR( 7, 0 ); + r += (int16_t) CALC_FIR( 7, 1 ); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_in [0] = l & ~1; + m.t_echo_in [1] = r & ~1; +} +inline int SPC_DSP::echo_output( int ch ) +{ + int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + + (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); + CLAMP16( out ); + return out; +} +ECHO_CLOCK( 26 ) +{ + // Left output volumes + // (save sample for next clock so we can output both together) + m.t_main_out [0] = echo_output( 0 ); + + // Echo feedback + int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); + int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_out [0] = l & ~1; + m.t_echo_out [1] = r & ~1; +} +ECHO_CLOCK( 27 ) +{ + // Output + int l = m.t_main_out [0]; + int r = echo_output( 1 ); + m.t_main_out [0] = 0; + m.t_main_out [1] = 0; + + // TODO: global muting isn't this simple (turns DAC on and off + // or something, causing small ~37-sample pulse when first muted) + if ( REG(flg) & 0x40 ) + { + l = 0; + r = 0; + } + + // Output sample to DAC + #ifdef SPC_DSP_OUT_HOOK + SPC_DSP_OUT_HOOK( l, r ); + #else + sample_t* out = m.out; + WRITE_SAMPLES( l, r, out ); + m.out = out; + #endif +} +ECHO_CLOCK( 28 ) +{ + m.t_echo_enabled = REG(flg); +} +inline void SPC_DSP::echo_write( int ch ) +{ + if ( !(m.t_echo_enabled & 0x20) ) + { + if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) + SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); + else + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); + } + + m.t_echo_out [ch] = 0; +} +ECHO_CLOCK( 29 ) +{ + m.t_esa = REG(esa); + + if ( !m.echo_offset ) + m.echo_length = (REG(edl) & 0x0F) * 0x800; + + m.echo_offset += 4; + if ( m.echo_offset >= m.echo_length ) + m.echo_offset = 0; + + // Write left echo + echo_write( 0 ); + + m.t_echo_enabled = REG(flg); +} +ECHO_CLOCK( 30 ) +{ + // Write right echo + echo_write( 1 ); +} + + +//// Timing + +// Execute clock for a particular voice +#define V( clock, voice ) voice_##clock( &m.voices [voice] ); + +/* The most common sequence of clocks uses composite operations +for efficiency. For example, the following are equivalent to the +individual steps on the right: + +V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) +V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) +V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ + +// Voice 0 1 2 3 4 5 6 7 +#define GEN_DSP_TIMING \ +PHASE( 0) V(V5,0)V(V2,1)\ +PHASE( 1) V(V6,0)V(V3,1)\ +PHASE( 2) V(V7_V4_V1,0)\ +PHASE( 3) V(V8_V5_V2,0)\ +PHASE( 4) V(V9_V6_V3,0)\ +PHASE( 5) V(V7_V4_V1,1)\ +PHASE( 6) V(V8_V5_V2,1)\ +PHASE( 7) V(V9_V6_V3,1)\ +PHASE( 8) V(V7_V4_V1,2)\ +PHASE( 9) V(V8_V5_V2,2)\ +PHASE(10) V(V9_V6_V3,2)\ +PHASE(11) V(V7_V4_V1,3)\ +PHASE(12) V(V8_V5_V2,3)\ +PHASE(13) V(V9_V6_V3,3)\ +PHASE(14) V(V7_V4_V1,4)\ +PHASE(15) V(V8_V5_V2,4)\ +PHASE(16) V(V9_V6_V3,4)\ +PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ +PHASE(18) V(V8_V5_V2,5)\ +PHASE(19) V(V9_V6_V3,5)\ +PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ +PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ +PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ +PHASE(23) V(V7,7) echo_23();\ +PHASE(24) V(V8,7) echo_24();\ +PHASE(25) V(V3b,0) V(V9,7) echo_25();\ +PHASE(26) echo_26();\ +PHASE(27) misc_27(); echo_27();\ +PHASE(28) misc_28(); echo_28();\ +PHASE(29) misc_29(); echo_29();\ +PHASE(30) misc_30();V(V3c,0) echo_30();\ +PHASE(31) V(V4,0) V(V1,2)\ + +#if !SPC_DSP_CUSTOM_RUN + +void SPC_DSP::run( int clocks_remain ) +{ + require( clocks_remain > 0 ); + + int const phase = m.phase; + m.phase = (phase + clocks_remain) & 31; + switch ( phase ) + { + loop: + + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: + GEN_DSP_TIMING + #undef PHASE + + if ( --clocks_remain ) + goto loop; + } +} + +#endif + + +//// Setup + +void SPC_DSP::init( void* ram_64k ) +{ + m.ram = (uint8_t*) ram_64k; + mute_voices( 0 ); + disable_surround( false ); + set_output( 0, 0 ); + reset(); + + stereo_switch = 0xffff; + take_spc_snapshot = 0; + spc_snapshot_callback = 0; + + #ifndef NDEBUG + // be sure this sign-extends + assert( (int16_t) 0x8000 == -0x8000 ); + + // be sure right shift preserves sign + assert( (-1 >> 1) == -1 ); + + // check clamp macro + int i; + i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); + i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); + + blargg_verify_byte_order(); + #endif +} + +void SPC_DSP::soft_reset_common() +{ + require( m.ram ); // init() must have been called already + + m.noise = 0x4000; + m.echo_hist_pos = m.echo_hist; + m.every_other_sample = 1; + m.echo_offset = 0; + m.phase = 0; + + init_counter(); + + for (int i = 0; i < voice_count; i++) + m.voices[i].voice_number = i; +} + +void SPC_DSP::soft_reset() +{ + REG(flg) = 0xE0; + soft_reset_common(); +} + +void SPC_DSP::load( uint8_t const regs [register_count] ) +{ + memcpy( m.regs, regs, sizeof m.regs ); + memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); + + // Internal state + for ( int i = voice_count; --i >= 0; ) + { + voice_t* v = &m.voices [i]; + v->brr_offset = 1; + v->vbit = 1 << i; + v->regs = &m.regs [i * 0x10]; + } + m.new_kon = REG(kon); + m.t_dir = REG(dir); + m.t_esa = REG(esa); + + soft_reset_common(); +} + +void SPC_DSP::reset() { load( initial_regs ); } + + +//// State save/load + +#if !SPC_NO_COPY_STATE_FUNCS + +void SPC_State_Copier::copy( void* state, size_t size ) +{ + func( buf, state, size ); +} + +int SPC_State_Copier::copy_int( int state, int size ) +{ + BOOST::uint8_t s [2]; + SET_LE16( s, state ); + func( buf, &s, size ); + return GET_LE16( s ); +} + +void SPC_State_Copier::skip( int count ) +{ + if ( count > 0 ) + { + char temp [64]; + memset( temp, 0, sizeof temp ); + do + { + int n = sizeof temp; + if ( n > count ) + n = count; + count -= n; + func( buf, temp, n ); + } + while ( count ); + } +} + +void SPC_State_Copier::extra() +{ + int n = 0; + SPC_State_Copier& copier = *this; + SPC_COPY( uint8_t, n ); + skip( n ); +} + +void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // DSP registers + copier.copy( m.regs, register_count ); + + // Internal state + + // Voices + int i; + for ( i = 0; i < voice_count; i++ ) + { + voice_t* v = &m.voices [i]; + + // BRR buffer + int i; + for ( i = 0; i < brr_buf_size; i++ ) + { + int s = v->buf [i]; + SPC_COPY( int16_t, s ); + v->buf [i] = v->buf [i + brr_buf_size] = s; + } + + SPC_COPY( uint16_t, v->interp_pos ); + SPC_COPY( uint16_t, v->brr_addr ); + SPC_COPY( uint16_t, v->env ); + SPC_COPY( int16_t, v->hidden_env ); + SPC_COPY( uint8_t, v->buf_pos ); + SPC_COPY( uint8_t, v->brr_offset ); + SPC_COPY( uint8_t, v->kon_delay ); + { + int m = v->env_mode; + SPC_COPY( uint8_t, m ); + v->env_mode = (enum env_mode_t) m; + } + SPC_COPY( uint8_t, v->t_envx_out ); + + copier.extra(); + } + + // Echo history + for ( i = 0; i < echo_hist_size; i++ ) + { + int j; + for ( j = 0; j < 2; j++ ) + { + int s = m.echo_hist_pos [i] [j]; + SPC_COPY( int16_t, s ); + m.echo_hist [i] [j] = s; // write back at offset 0 + } + } + m.echo_hist_pos = m.echo_hist; + memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); + + // Misc + SPC_COPY( uint8_t, m.every_other_sample ); + SPC_COPY( uint8_t, m.kon ); + + SPC_COPY( uint16_t, m.noise ); + SPC_COPY( uint16_t, m.counter ); + SPC_COPY( uint16_t, m.echo_offset ); + SPC_COPY( uint16_t, m.echo_length ); + SPC_COPY( uint8_t, m.phase ); + + SPC_COPY( uint8_t, m.new_kon ); + SPC_COPY( uint8_t, m.endx_buf ); + SPC_COPY( uint8_t, m.envx_buf ); + SPC_COPY( uint8_t, m.outx_buf ); + + SPC_COPY( uint8_t, m.t_pmon ); + SPC_COPY( uint8_t, m.t_non ); + SPC_COPY( uint8_t, m.t_eon ); + SPC_COPY( uint8_t, m.t_dir ); + SPC_COPY( uint8_t, m.t_koff ); + + SPC_COPY( uint16_t, m.t_brr_next_addr ); + SPC_COPY( uint8_t, m.t_adsr0 ); + SPC_COPY( uint8_t, m.t_brr_header ); + SPC_COPY( uint8_t, m.t_brr_byte ); + SPC_COPY( uint8_t, m.t_srcn ); + SPC_COPY( uint8_t, m.t_esa ); + SPC_COPY( uint8_t, m.t_echo_enabled ); + + SPC_COPY( int16_t, m.t_main_out [0] ); + SPC_COPY( int16_t, m.t_main_out [1] ); + SPC_COPY( int16_t, m.t_echo_out [0] ); + SPC_COPY( int16_t, m.t_echo_out [1] ); + SPC_COPY( int16_t, m.t_echo_in [0] ); + SPC_COPY( int16_t, m.t_echo_in [1] ); + + SPC_COPY( uint16_t, m.t_dir_addr ); + SPC_COPY( uint16_t, m.t_pitch ); + SPC_COPY( int16_t, m.t_output ); + SPC_COPY( uint16_t, m.t_echo_ptr ); + SPC_COPY( uint8_t, m.t_looped ); + + copier.extra(); +} +#endif + + +//// Snes9x Accessor + +void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) +{ + spc_snapshot_callback = callback; +} + +void SPC_DSP::dump_spc_snapshot( void ) +{ + take_spc_snapshot = 1; +} + +void SPC_DSP::set_stereo_switch( int value ) +{ + stereo_switch = value; +} + +SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) +{ + return m.voices[ch].regs[addr]; +} + +int SPC_DSP::envx_value( int ch ) +{ + return m.voices[ch].env; +} diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h new file mode 100755 index 00000000..61d05ab5 --- /dev/null +++ b/apu/bapu/dsp/SPC_DSP.h @@ -0,0 +1,319 @@ +// Highly accurate SNES SPC-700 DSP emulator + +// snes_spc 0.9.0 +#ifndef SPC_DSP_H +#define SPC_DSP_H + +#include "blargg_common.h" + +extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } + +class SPC_DSP { +public: + typedef BOOST::uint8_t uint8_t; + +// Setup + + // Initializes DSP and has it use the 64K RAM provided + void init( void* ram_64k ); + + // Sets destination for output samples. If out is NULL or out_size is 0, + // doesn't generate any. + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since it was last set, always + // a multiple of 2. Undefined if more samples were generated than + // output buffer could hold. + int sample_count() const; + +// Emulation + + // Resets DSP to power-on state + void reset(); + + // Emulates pressing reset switch on SNES + void soft_reset(); + + // Reads/writes DSP registers. For accuracy, you must first call run() + // to catch the DSP up to present. + int read ( int addr ) const; + void write( int addr, int data ); + + // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks + // a pair of samples is be generated. + void run( int clock_count ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + +// State + + // Resets DSP and uses supplied values to initialize registers + enum { register_count = 128 }; + void load( uint8_t const regs [register_count] ); + + // Saves/loads exact emulator state + enum { state_size = 640 }; // maximum space needed when saving + typedef dsp_copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Returns non-zero if new key-on events occurred since last call + bool check_kon(); + +// Snes9x Accessor + + int stereo_switch; + int take_spc_snapshot; + int rom_enabled; // mirror + uint8_t *rom, *hi_ram; // mirror + void (*spc_snapshot_callback) (void); + + void set_spc_snapshot_callback( void (*callback) (void) ); + void dump_spc_snapshot( void ); + void set_stereo_switch( int ); + uint8_t reg_value( int, int ); + int envx_value( int ); + +// DSP register addresses + + // Global registers + enum { + r_mvoll = 0x0C, r_mvolr = 0x1C, + r_evoll = 0x2C, r_evolr = 0x3C, + r_kon = 0x4C, r_koff = 0x5C, + r_flg = 0x6C, r_endx = 0x7C, + r_efb = 0x0D, r_pmon = 0x2D, + r_non = 0x3D, r_eon = 0x4D, + r_dir = 0x5D, r_esa = 0x6D, + r_edl = 0x7D, + r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F + }; + + // Voice registers + enum { + v_voll = 0x00, v_volr = 0x01, + v_pitchl = 0x02, v_pitchh = 0x03, + v_srcn = 0x04, v_adsr0 = 0x05, + v_adsr1 = 0x06, v_gain = 0x07, + v_envx = 0x08, v_outx = 0x09 + }; + +public: + enum { extra_size = 16 }; + sample_t* extra() { return m.extra; } + sample_t const* out_pos() const { return m.out; } + void disable_surround( bool ) { } // not supported +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::int8_t int8_t; + typedef BOOST::int16_t int16_t; + + enum { echo_hist_size = 8 }; + + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; + enum { brr_buf_size = 12 }; + struct voice_t + { + int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) + int buf_pos; // place in buffer where next samples will be decoded + int interp_pos; // relative fractional position in sample (0x1000 = 1.0) + int brr_addr; // address of current BRR block + int brr_offset; // current decoding offset in BRR block + uint8_t* regs; // pointer to voice's DSP registers + int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. + int kon_delay; // KON delay/current setup phase + env_mode_t env_mode; + int env; // current envelope level + int hidden_env; // used by GAIN mode 7, very obscure quirk + uint8_t t_envx_out; + int voice_number; + }; +private: + enum { brr_block_size = 9 }; + + struct state_t + { + uint8_t regs [register_count]; + + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) + int echo_hist [echo_hist_size * 2] [2]; + int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] + + int every_other_sample; // toggles every sample + int kon; // KON value when last checked + int noise; + int counter; + int echo_offset; // offset from ESA in echo buffer + int echo_length; // number of bytes that echo_offset will stop at + int phase; // next clock cycle to run (0-31) + bool kon_check; // set when a new KON occurs + + // Hidden registers also written to when main register is written to + int new_kon; + uint8_t endx_buf; + uint8_t envx_buf; + uint8_t outx_buf; + + // Temporary state between clocks + + // read once per sample + int t_pmon; + int t_non; + int t_eon; + int t_dir; + int t_koff; + + // read a few clocks ahead then used + int t_brr_next_addr; + int t_adsr0; + int t_brr_header; + int t_brr_byte; + int t_srcn; + int t_esa; + int t_echo_enabled; + + // internal state that is recalculated every sample + int t_dir_addr; + int t_pitch; + int t_output; + int t_looped; + int t_echo_ptr; + + // left/right sums + int t_main_out [2]; + int t_echo_out [2]; + int t_echo_in [2]; + + voice_t voices [voice_count]; + + // non-emulation state + uint8_t* ram; // 64K shared RAM between DSP and SMP + int mute_mask; + sample_t* out; + sample_t* out_end; + sample_t* out_begin; + sample_t extra [extra_size]; + }; + state_t m; + + void init_counter(); + void run_counters(); + unsigned read_counter( int rate ); + + int interpolate( voice_t const* v ); + void run_envelope( voice_t* const v ); + void decode_brr( voice_t* v ); + + void misc_27(); + void misc_28(); + void misc_29(); + void misc_30(); + + void voice_output( voice_t const* v, int ch ); + void voice_V1( voice_t* const ); + void voice_V2( voice_t* const ); + void voice_V3( voice_t* const ); + void voice_V3a( voice_t* const ); + void voice_V3b( voice_t* const ); + void voice_V3c( voice_t* const ); + void voice_V4( voice_t* const ); + void voice_V5( voice_t* const ); + void voice_V6( voice_t* const ); + void voice_V7( voice_t* const ); + void voice_V8( voice_t* const ); + void voice_V9( voice_t* const ); + void voice_V7_V4_V1( voice_t* const ); + void voice_V8_V5_V2( voice_t* const ); + void voice_V9_V6_V3( voice_t* const ); + + void echo_read( int ch ); + int echo_output( int ch ); + void echo_write( int ch ); + void echo_22(); + void echo_23(); + void echo_24(); + void echo_25(); + void echo_26(); + void echo_27(); + void echo_28(); + void echo_29(); + void echo_30(); + + void soft_reset_common(); +}; + +#include + +inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } + +inline int SPC_DSP::read( int addr ) const +{ + assert( (unsigned) addr < register_count ); + return m.regs [addr]; +} + +inline void SPC_DSP::write( int addr, int data ) +{ + assert( (unsigned) addr < register_count ); + + m.regs [addr] = (uint8_t) data; + switch ( addr & 0x0F ) + { + case v_envx: + m.envx_buf = (uint8_t) data; + break; + + case v_outx: + m.outx_buf = (uint8_t) data; + break; + + case 0x0C: + if ( addr == r_kon ) + m.new_kon = (uint8_t) data; + + if ( addr == r_endx ) // always cleared, regardless of data written + { + m.endx_buf = 0; + m.regs [r_endx] = 0; + } + break; + } +} + +inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } + +inline bool SPC_DSP::check_kon() +{ + bool old = m.kon_check; + m.kon_check = 0; + return old; +} + +#if !SPC_NO_COPY_STATE_FUNCS + +class SPC_State_Copier { + SPC_DSP::copy_func_t func; + unsigned char** buf; +public: + SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } + void copy( void* state, size_t size ); + int copy_int( int state, int size ); + void skip( int count ); + void extra(); +}; + +#define SPC_COPY( type, state )\ +{\ + state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ + assert( (BOOST::type) state == state );\ +} + +#endif + +#endif diff --git a/apu/bapu/dsp/blargg_common.h b/apu/bapu/dsp/blargg_common.h new file mode 100755 index 00000000..75edff39 --- /dev/null +++ b/apu/bapu/dsp/blargg_common.h @@ -0,0 +1,186 @@ +// Sets up common environment for Shay Green's libraries. +// To change configuration options, modify blargg_config.h, not this file. + +// snes_spc 0.9.0 +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +#include +#include +#include +#include + +#undef BLARGG_COMMON_H +// allow blargg_config.h to #include blargg_common.h +#include "blargg_config.h" +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if defined (__GNUC__) || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + +// STATIC_CAST(T,expr): Used in place of static_cast (expr) +#ifndef STATIC_CAST + #define STATIC_CAST(T,expr) ((T) (expr)) +#endif + +// blargg_err_t (0 on success, otherwise error string) +#ifndef blargg_err_t + typedef const char* blargg_err_t; +#endif + +// blargg_vector - very lightweight vector of POD types (no constructor/destructor) +template +class blargg_vector { + T* begin_; + size_t size_; +public: + blargg_vector() : begin_( 0 ), size_( 0 ) { } + ~blargg_vector() { free( begin_ ); } + size_t size() const { return size_; } + T* begin() const { return begin_; } + T* end() const { return begin_ + size_; } + blargg_err_t resize( size_t n ) + { + // TODO: blargg_common.cpp to hold this as an outline function, ugh + void* p = realloc( begin_, n * sizeof (T) ); + if ( p ) + begin_ = (T*) p; + else if ( n > size_ ) // realloc failure only a problem if expanding + return "Out of memory"; + size_ = n; + return 0; + } + void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } + T& operator [] ( size_t n ) const + { + assert( n <= size_ ); // <= to allow past-the-end value + return begin_ [n]; + } +}; + +#ifndef BLARGG_DISABLE_NOTHROW + // throw spec mandatory in ISO C++ if operator new can return NULL + #if __cplusplus >= 199711 || defined (__GNUC__) + #define BLARGG_THROWS( spec ) throw spec + #else + #define BLARGG_THROWS( spec ) + #endif + #define BLARGG_DISABLE_NOTHROW \ + void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ + void operator delete ( void* p ) { free( p ); } + #define BLARGG_NEW new +#else + #include + #define BLARGG_NEW new (std::nothrow) +#endif + +// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) +#define BLARGG_4CHAR( a, b, c, d ) \ + ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) + +// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. +#ifndef BOOST_STATIC_ASSERT + #ifdef _MSC_VER + // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) + #else + // Some other compilers fail when declaring same function multiple times in class, + // so differentiate them by line + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) + #endif +#endif + +// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, +// compiler is assumed to support bool. If undefined, availability is determined. +#ifndef BLARGG_COMPILER_HAS_BOOL + #if defined (__MWERKS__) + #if !__option(bool) + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (_MSC_VER) + #if _MSC_VER < 1100 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (__GNUC__) + // supports bool + #elif __cplusplus < 199711 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif +#endif +#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL + // If you get errors here, modify your blargg_config.h file + typedef int bool; + const bool true = 1; + const bool false = 0; +#endif + +// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough + +#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF + typedef long blargg_long; +#else + typedef int blargg_long; +#endif + +#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF + typedef unsigned long blargg_ulong; +#else + typedef unsigned blargg_ulong; +#endif + +// BOOST::int8_t etc. + +// HAVE_STDINT_H: If defined, use for int8_t etc. +#if defined (HAVE_STDINT_H) + #include + #define BOOST + +// HAVE_INTTYPES_H: If defined, use for int8_t etc. +#elif defined (HAVE_INTTYPES_H) + #include + #define BOOST + +#else + struct BOOST + { + #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F + typedef signed char int8_t; + typedef unsigned char uint8_t; + #else + // No suitable 8-bit type available + typedef struct see_blargg_common_h int8_t; + typedef struct see_blargg_common_h uint8_t; + #endif + + #if USHRT_MAX == 0xFFFF + typedef short int16_t; + typedef unsigned short uint16_t; + #else + // No suitable 16-bit type available + typedef struct see_blargg_common_h int16_t; + typedef struct see_blargg_common_h uint16_t; + #endif + + #if ULONG_MAX == 0xFFFFFFFF + typedef long int32_t; + typedef unsigned long uint32_t; + #elif UINT_MAX == 0xFFFFFFFF + typedef int int32_t; + typedef unsigned int uint32_t; + #else + // No suitable 32-bit type available + typedef struct see_blargg_common_h int32_t; + typedef struct see_blargg_common_h uint32_t; + #endif + }; +#endif + +#endif +#endif diff --git a/apu/bapu/dsp/blargg_config.h b/apu/bapu/dsp/blargg_config.h new file mode 100755 index 00000000..d85d2663 --- /dev/null +++ b/apu/bapu/dsp/blargg_config.h @@ -0,0 +1,24 @@ +// snes_spc 0.9.0 user configuration file. Don't replace when updating library. + +// snes_spc 0.9.0 +#ifndef BLARGG_CONFIG_H +#define BLARGG_CONFIG_H + +// Uncomment to disable debugging checks +#define NDEBUG 1 + +// Uncomment to enable platform-specific (and possibly non-portable) optimizations +//#define BLARGG_NONPORTABLE 1 + +// Uncomment if automatic byte-order determination doesn't work +//#define BLARGG_BIG_ENDIAN 1 + +// Uncomment if you get errors in the bool section of blargg_common.h +//#define BLARGG_COMPILER_HAS_BOOL 1 + +// Use standard config.h if present +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#endif diff --git a/apu/bapu/dsp/blargg_endian.h b/apu/bapu/dsp/blargg_endian.h new file mode 100755 index 00000000..f2daca64 --- /dev/null +++ b/apu/bapu/dsp/blargg_endian.h @@ -0,0 +1,185 @@ +// CPU Byte Order Utilities + +// snes_spc 0.9.0 +#ifndef BLARGG_ENDIAN +#define BLARGG_ENDIAN + +#include "blargg_common.h" + +// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) +#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ + defined (__x86_64__) || defined (__ia64__) || defined (__i386__) + #define BLARGG_CPU_X86 1 + #define BLARGG_CPU_CISC 1 +#endif + +#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) + #define BLARGG_CPU_POWERPC 1 + #define BLARGG_CPU_RISC 1 +#endif + +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only +// one may be #defined to 1. Only needed if something actually depends on byte order. +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) +#ifdef __GLIBC__ + // GCC handles this for us + #include + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BLARGG_LITTLE_ENDIAN 1 + #elif __BYTE_ORDER == __BIG_ENDIAN + #define BLARGG_BIG_ENDIAN 1 + #endif +#else + +#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ + (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) + #define BLARGG_LITTLE_ENDIAN 1 +#endif + +#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ + defined (__sparc__) || BLARGG_CPU_POWERPC || \ + (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) + #define BLARGG_BIG_ENDIAN 1 +#elif !defined (__mips__) + // No endian specified; assume little-endian, since it's most common + #define BLARGG_LITTLE_ENDIAN 1 +#endif +#endif +#endif + +#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN + #undef BLARGG_LITTLE_ENDIAN + #undef BLARGG_BIG_ENDIAN +#endif + +inline void blargg_verify_byte_order() +{ + #ifndef NDEBUG + #if BLARGG_BIG_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i == 0 ); + #elif BLARGG_LITTLE_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i != 0 ); + #endif + #endif +} + +inline unsigned get_le16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [1] << 8 | + (unsigned) ((unsigned char const*) p) [0]; +} + +inline unsigned get_be16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [0] << 8 | + (unsigned) ((unsigned char const*) p) [1]; +} + +inline blargg_ulong get_le32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | + (blargg_ulong) ((unsigned char const*) p) [2] << 16 | + (blargg_ulong) ((unsigned char const*) p) [1] << 8 | + (blargg_ulong) ((unsigned char const*) p) [0]; +} + +inline blargg_ulong get_be32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | + (blargg_ulong) ((unsigned char const*) p) [1] << 16 | + (blargg_ulong) ((unsigned char const*) p) [2] << 8 | + (blargg_ulong) ((unsigned char const*) p) [3]; +} + +inline void set_le16( void* p, unsigned n ) +{ + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be16( void* p, unsigned n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) n; +} + +inline void set_le32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [0] = (unsigned char) n; + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); +} + +inline void set_be32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [3] = (unsigned char) n; + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); +} + +#if BLARGG_NONPORTABLE + // Optimized implementation if byte order is known + #if BLARGG_LITTLE_ENDIAN + #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + #elif BLARGG_BIG_ENDIAN + #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + + #if BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + #if defined (__MWERKS__) + #define GET_LE16( addr ) (__lhbrx( addr, 0 )) + #define GET_LE32( addr ) (__lwbrx( addr, 0 )) + #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) + #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) + #elif defined (__GNUC__) + #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) + #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) + #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #endif + #endif + #endif +#endif + +#ifndef GET_LE16 + #define GET_LE16( addr ) get_le16( addr ) + #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) + #define SET_LE32( addr, data ) set_le32( addr, data ) +#endif + +#ifndef GET_BE16 + #define GET_BE16( addr ) get_be16( addr ) + #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) + #define SET_BE32( addr, data ) set_be32( addr, data ) +#endif + +// auto-selecting versions + +inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } +inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } +inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } +inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } +inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } +inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } +inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } +inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } + +#endif diff --git a/apu/bapu/dsp/blargg_source.h b/apu/bapu/dsp/blargg_source.h new file mode 100755 index 00000000..5e45c4fb --- /dev/null +++ b/apu/bapu/dsp/blargg_source.h @@ -0,0 +1,100 @@ +/* Included at the beginning of library source files, after all other #include lines. +Sets up helpful macros and services used in my source code. They don't need +module an annoying module prefix on their names since they are defined after +all other #include lines. */ + +// snes_spc 0.9.0 +#ifndef BLARGG_SOURCE_H +#define BLARGG_SOURCE_H + +// If debugging is enabled, abort program if expr is false. Meant for checking +// internal state and consistency. A failed assertion indicates a bug in the module. +// void assert( bool expr ); +#include + +// If debugging is enabled and expr is false, abort program. Meant for checking +// caller-supplied parameters and operations that are outside the control of the +// module. A failed requirement indicates a bug outside the module. +// void require( bool expr ); +#undef require +#define require( expr ) assert( expr ) + +// Like printf() except output goes to debug log file. Might be defined to do +// nothing (not even evaluate its arguments). +// void dprintf( const char* format, ... ); +static inline void blargg_dprintf_( const char*, ... ) { } +#undef dprintf +#define dprintf (1) ? (void) 0 : blargg_dprintf_ + +// If enabled, evaluate expr and if false, make debug log entry with source file +// and line. Meant for finding situations that should be examined further, but that +// don't indicate a problem. In all cases, execution continues normally. +#undef check +#define check( expr ) ((void) 0) + +// If expr yields error string, return it from current function, otherwise continue. +#undef RETURN_ERR +#define RETURN_ERR( expr ) do { \ + blargg_err_t blargg_return_err_ = (expr); \ + if ( blargg_return_err_ ) return blargg_return_err_; \ + } while ( 0 ) + +// If ptr is 0, return out of memory error string. +#undef CHECK_ALLOC +#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) + +// Avoid any macros which evaluate their arguments multiple times +#undef min +#undef max + +#define DEF_MIN_MAX( type ) \ + static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ + static inline type max( type x, type y ) { if ( y < x ) return x; return y; } + +DEF_MIN_MAX( int ) +DEF_MIN_MAX( unsigned ) +DEF_MIN_MAX( long ) +DEF_MIN_MAX( unsigned long ) +DEF_MIN_MAX( float ) +DEF_MIN_MAX( double ) + +#undef DEF_MIN_MAX + +/* +// using const references generates crappy code, and I am currenly only using these +// for built-in types, so they take arguments by value + +// TODO: remove +inline int min( int x, int y ) +template +inline T min( T x, T y ) +{ + if ( x < y ) + return x; + return y; +} + +template +inline T max( T x, T y ) +{ + if ( x < y ) + return y; + return x; +} +*/ + +// TODO: good idea? bad idea? +#undef byte +#define byte byte_ +typedef unsigned char byte; + +// deprecated +#define BLARGG_CHECK_ALLOC CHECK_ALLOC +#define BLARGG_RETURN_ERR RETURN_ERR + +// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check +#ifdef BLARGG_SOURCE_BEGIN + #include BLARGG_SOURCE_BEGIN +#endif + +#endif diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp new file mode 100755 index 00000000..f82bd824 --- /dev/null +++ b/apu/bapu/dsp/dsp.cpp @@ -0,0 +1,61 @@ +#include + +#define DSP_CPP +namespace SNES { + +DSP dsp; + +#include "SPC_DSP.cpp" + +void DSP::step(unsigned clocks) { + clock += clocks; +} + +void DSP::synchronize_smp() { + while(clock >= 0) smp.enter(); +} + +void DSP::enter() { + spc_dsp.run(1); + step(24); + +/* signed count = spc_dsp.sample_count(); + if(count > 0) { + for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); + spc_dsp.set_output(samplebuffer, 8192); + } */ +} + +uint8 DSP::read(uint8 addr) { + return spc_dsp.read(addr); +} + +void DSP::write(uint8 addr, uint8 data) { + spc_dsp.write(addr, data); +} + +void DSP::power() { + spc_dsp.init(smp.apuram); + spc_dsp.reset(); + spc_dsp.set_output(samplebuffer, 8192); +} + +void DSP::reset() { + spc_dsp.soft_reset(); + spc_dsp.set_output(samplebuffer, 8192); +} + +void DSP::channel_enable(unsigned channel, bool enable) { + channel_enabled[channel & 7] = enable; + unsigned mask = 0; + for(unsigned i = 0; i < 8; i++) { + if(channel_enabled[i] == false) mask |= 1 << i; + } + spc_dsp.mute_voices(mask); +} + +DSP::DSP() { + for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; +} + +} diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp new file mode 100755 index 00000000..634c6da4 --- /dev/null +++ b/apu/bapu/dsp/dsp.hpp @@ -0,0 +1,26 @@ +#include "SPC_DSP.h" + +class DSP : public Processor { +public: + enum { Threaded = false }; + alwaysinline void step(unsigned clocks); + alwaysinline void synchronize_smp(); + + uint8 read(uint8 addr); + void write(uint8 addr, uint8 data); + + void enter(); + void power(); + void reset(); + + void channel_enable(unsigned channel, bool enable); + + DSP(); + +private: + SPC_DSP spc_dsp; + int16 samplebuffer[8192]; + bool channel_enabled[8]; +}; + +extern DSP dsp; diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp new file mode 100755 index 00000000..0565a1b5 --- /dev/null +++ b/apu/bapu/dsp/serialization.cpp @@ -0,0 +1,31 @@ +#ifdef DSP_CPP + +static void dsp_state_save(unsigned char **out, void *in, size_t size) { + memcpy(*out, in, size); + *out += size; +} + +static void dsp_state_load(unsigned char **in, void *out, size_t size) { + memcpy(out, *in, size); + *in += size; +} + +void DSP::serialize(serializer &s) { + Processor::serialize(s); + s.array(samplebuffer); + + unsigned char state[SPC_DSP::state_size]; + unsigned char *p = state; + memset(&state, 0, SPC_DSP::state_size); + if(s.mode() == serializer::Save) { + spc_dsp.copy_state(&p, dsp_state_save); + s.array(state); + } else if(s.mode() == serializer::Load) { + s.array(state); + spc_dsp.copy_state(&p, dsp_state_load); + } else { + s.array(state); + } +} + +#endif diff --git a/apu/bapu/smp/algorithms.cpp b/apu/bapu/smp/algorithms.cpp new file mode 100755 index 00000000..a55369fb --- /dev/null +++ b/apu/bapu/smp/algorithms.cpp @@ -0,0 +1,122 @@ +uint8 SMP::op_adc(uint8 x, uint8 y) { + int r = x + y + regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = ~(x ^ y) & (x ^ r) & 0x80; + regs.p.h = (x ^ y ^ r) & 0x10; + regs.p.z = (uint8)r == 0; + regs.p.c = r > 0xff; + return r; +} + +uint16 SMP::op_addw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 0; + r = op_adc(x, y); + r |= op_adc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMP::op_and(uint8 x, uint8 y) { + x &= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_cmp(uint8 x, uint8 y) { + int r = x - y; + regs.p.n = r & 0x80; + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint16 SMP::op_cmpw(uint16 x, uint16 y) { + int r = x - y; + regs.p.n = r & 0x8000; + regs.p.z = (uint16)r == 0; + regs.p.c = r >= 0; + return x; +} + +uint8 SMP::op_eor(uint8 x, uint8 y) { + x ^= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_or(uint8 x, uint8 y) { + x |= y; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_sbc(uint8 x, uint8 y) { + int r = x - y - !regs.p.c; + regs.p.n = r & 0x80; + regs.p.v = (x ^ y) & (x ^ r) & 0x80; + regs.p.h = !((x ^ y ^ r) & 0x10); + regs.p.z = (uint8)r == 0; + regs.p.c = r >= 0; + return r; +} + +uint16 SMP::op_subw(uint16 x, uint16 y) { + uint16 r; + regs.p.c = 1; + r = op_sbc(x, y); + r |= op_sbc(x >> 8, y >> 8) << 8; + regs.p.z = r == 0; + return r; +} + +uint8 SMP::op_inc(uint8 x) { + x++; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_dec(uint8 x) { + x--; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_asl(uint8 x) { + regs.p.c = x & 0x80; + x <<= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_lsr(uint8 x) { + regs.p.c = x & 0x01; + x >>= 1; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_rol(uint8 x) { + unsigned carry = (unsigned)regs.p.c; + regs.p.c = x & 0x80; + x = (x << 1) | carry; + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} + +uint8 SMP::op_ror(uint8 x) { + unsigned carry = (unsigned)regs.p.c << 7; + regs.p.c = x & 0x01; + x = carry | (x >> 1); + regs.p.n = x & 0x80; + regs.p.z = x == 0; + return x; +} diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp new file mode 100755 index 00000000..6e0a29b2 --- /dev/null +++ b/apu/bapu/smp/core.cpp @@ -0,0 +1,105 @@ +void SMP::tick() { + timer0.tick(); + timer1.tick(); + timer2.tick(); + + clock += cycle_step_cpu; + dsp.clock -= 24; + synchronize_dsp(); +} + +void SMP::op_io() { + #if defined(CYCLE_ACCURATE) + tick(); + #endif +} + +uint8 SMP::op_read(uint16 addr) { + #if defined(CYCLE_ACCURATE) + tick(); + #endif + if((addr & 0xfff0) == 0x00f0) return mmio_read(addr); + if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f]; + return apuram[addr]; +} + +void SMP::op_write(uint16 addr, uint8 data) { + #if defined(CYCLE_ACCURATE) + tick(); + #endif + if((addr & 0xfff0) == 0x00f0) mmio_write(addr, data); + apuram[addr] = data; //all writes go to RAM, even MMIO writes +} + +void SMP::op_step() { + #define op_readpc() op_read(regs.pc++) + #define op_readdp(addr) op_read((regs.p.p << 8) + addr) + #define op_writedp(addr, data) op_write((regs.p.p << 8) + addr, data) + #define op_readaddr(addr) op_read(addr) + #define op_writeaddr(addr, data) op_write(addr, data) + #define op_readstack() op_read(0x0100 | ++regs.sp) + #define op_writestack(data) op_write(0x0100 | regs.sp--, data) + static unsigned rd, wr, dp, sp, ya, bit; + + #if defined(CYCLE_ACCURATE) + + if(opcode_cycle == 0) { + opcode_number = op_readpc(); + opcode_cycle++; + } else switch(opcode_number) { + #include "core/opcycle_misc.cpp" + #include "core/opcycle_mov.cpp" + #include "core/opcycle_pc.cpp" + #include "core/opcycle_read.cpp" + #include "core/opcycle_rmw.cpp" + } + + #else + + unsigned opcode = op_readpc(); + switch(opcode) { + #include "core/op_misc.cpp" + #include "core/op_mov.cpp" + #include "core/op_pc.cpp" + #include "core/op_read.cpp" + #include "core/op_rmw.cpp" + } + + //TODO: untaken branches should consume less cycles + + timer0.tick(cycle_count_table[opcode]); + timer1.tick(cycle_count_table[opcode]); + timer2.tick(cycle_count_table[opcode]); + + clock += cycle_table_cpu[opcode]; + dsp.clock -= cycle_table_dsp[opcode]; + synchronize_dsp(); + + #endif +} + +const unsigned SMP::cycle_count_table[256] = { + #define c 12 +//0 1 2 3 4 5 6 7 8 9 A B C D E F + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,6,8, //0 + 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,4,6, //1 + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,4,7,4, //2 + 4,8,4,7, 4,5,5,6, 5,5,6,5, 2,2,3,8, //3 + + 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,6,6, //4 + 4,8,4,7, 4,5,5,6, 5,5,4,5, 2,2,4,3, //5 + 2,8,4,7, 3,4,3,6, 2,6,4,4, 5,4,7,5, //6 + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,6, //7 + + 2,8,4,7, 3,4,3,6, 2,6,5,4, 5,2,4,5, //8 + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,c,5, //9 + 3,8,4,7, 3,4,3,6, 2,6,4,4, 5,2,4,4, //A + 4,8,4,7, 4,5,5,6, 5,5,5,5, 2,2,3,4, //B + + 3,8,4,7, 4,5,4,7, 2,5,6,4, 5,2,4,9, //C + 4,8,4,7, 5,6,6,7, 4,5,5,5, 2,2,8,3, //D + 2,8,4,7, 3,4,3,6, 2,4,5,3, 4,3,4,1, //E + 4,8,4,7, 4,5,5,6, 3,4,5,4, 2,2,6,1, //F + + #undef c +}; diff --git a/apu/bapu/smp/core/cc.sh b/apu/bapu/smp/core/cc.sh new file mode 100755 index 00000000..937b7139 --- /dev/null +++ b/apu/bapu/smp/core/cc.sh @@ -0,0 +1 @@ +g++-4.5 -std=gnu++0x -I../../../.. -o generate generate.cpp diff --git a/apu/bapu/smp/core/generate.cpp b/apu/bapu/smp/core/generate.cpp new file mode 100755 index 00000000..77ab3ed2 --- /dev/null +++ b/apu/bapu/smp/core/generate.cpp @@ -0,0 +1,154 @@ +#include +#include +#include +using namespace nall; + +static bool cycle_accurate; + +struct opcode_t { + string name; + lstring args; + unsigned opcode; +}; + +void generate(const char *sourceFilename, const char *targetFilename) { + file fp; + fp.open(targetFilename, file::mode::write); + + string filedata; + filedata.readfile(sourceFilename); + filedata.replace("\r", ""); + + lstring block; + block.split("\n\n", filedata); + + foreach(data, block) { + lstring lines; + lines.split("\n", data); + + linear_vector array; + + unsigned sourceStart = 0; + foreach(line, lines, currentLine) { + line.transform("()", "``"); + lstring part; + part.split("`", line); + lstring arguments; + arguments.split(", ", part[1]); + + opcode_t opcode; + opcode.name = part[0]; + opcode.args = arguments; + opcode.opcode = hex(arguments[0]); + array.append(opcode); + + line.rtrim<1>(","); + if(line.endswith(" {")) { + line.rtrim<1>("{ "); + sourceStart = currentLine + 1; + break; + } + } + + if(cycle_accurate == false) { + foreach(opcode, array) { + fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); + + for(unsigned n = sourceStart; n < lines.size(); n++) { + if(lines[n] == "}") break; + + string output; + + if(lines[n].beginswith(" ")) { + output = lines[n]; + } else { + lstring part; + part.split<1>(":", lines[n]); + output = { " ", part[1] }; + } + + output.replace("$1", opcode.args[1]); + output.replace("$2", opcode.args[2]); + output.replace("$3", opcode.args[3]); + output.replace("$4", opcode.args[4]); + output.replace("$5", opcode.args[5]); + output.replace("$6", opcode.args[6]); + output.replace("$7", opcode.args[7]); + output.replace("$8", opcode.args[8]); + output.replace("end;", "break;"); + + fp.print(output, "\n"); + } + + fp.print(" break;\n"); + fp.print("}\n\n"); + } + } else { + foreach(opcode, array) { + fp.print("case 0x", hex<2>(opcode.opcode), ": {\n"); + fp.print(" switch(opcode_cycle++) {\n"); + + for(unsigned n = sourceStart; n < lines.size(); n++) { + if(lines[n] == "}") break; + + bool nextLineEndsCycle = false; + if(lines[n + 1] == "}") nextLineEndsCycle = true; + if(lines[n + 1].beginswith(" ") == false) nextLineEndsCycle = true; + + string output; + + if(lines[n].beginswith(" ")) { + output = { " ", lines[n] }; + } else { + lstring part; + part.split<1>(":", lines[n]); + fp.print(" case ", (unsigned)decimal(part[0]), ":\n"); + output = { " ", part[1] }; + } + + output.replace("$1", opcode.args[1]); + output.replace("$2", opcode.args[2]); + output.replace("$3", opcode.args[3]); + output.replace("$4", opcode.args[4]); + output.replace("$5", opcode.args[5]); + output.replace("$6", opcode.args[6]); + output.replace("$7", opcode.args[7]); + output.replace("$8", opcode.args[8]); + output.replace("end;", "{ opcode_cycle = 0; break; }"); + + fp.print(output, "\n"); + if(nextLineEndsCycle) { + if(lines[n + 1].beginswith("}")) { + fp.print(" opcode_cycle = 0;\n"); + } + fp.print(" break;\n"); + } + } + + fp.print(" }\n"); + fp.print(" break;\n"); + fp.print("}\n\n"); + } + } + } + + fp.close(); +} + +int main() { + cycle_accurate = false; + generate("op_misc.b", "op_misc.cpp"); + generate("op_mov.b", "op_mov.cpp" ); + generate("op_pc.b", "op_pc.cpp" ); + generate("op_read.b", "op_read.cpp"); + generate("op_rmw.b", "op_rmw.cpp" ); + + cycle_accurate = true; + generate("op_misc.b", "opcycle_misc.cpp"); + generate("op_mov.b", "opcycle_mov.cpp" ); + generate("op_pc.b", "opcycle_pc.cpp" ); + generate("op_read.b", "opcycle_read.cpp"); + generate("op_rmw.b", "opcycle_rmw.cpp" ); + + return 0; +} diff --git a/apu/bapu/smp/core/op_misc.b b/apu/bapu/smp/core/op_misc.b new file mode 100755 index 00000000..fb258650 --- /dev/null +++ b/apu/bapu/smp/core/op_misc.b @@ -0,0 +1,163 @@ +nop(0x00) { +1:op_io(); +} + +sleep(0xef), +stop(0xff) { +1:op_io(); +2:op_io(); + regs.pc--; +} + +xcn(0x9f) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +daa(0xdf) { +1:op_io(); +2:op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +das(0xbe) { +1:op_io(); +2:op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +clrc(0x60, regs.p.c = 0), +clrp(0x20, regs.p.p = 0), +setc(0x80, regs.p.c = 1), +setp(0x40, regs.p.p = 1) { +1:op_io(); + $1; +} + +clrv(0xe0) { +1:op_io(); + regs.p.v = 0; + regs.p.h = 0; +} + +notc(0xed) { +1:op_io(); +2:op_io(); + regs.p.c = !regs.p.c; +} + +ei(0xa0, 1), +di(0xc0, 0) { +1:op_io(); +2:op_io(); + regs.p.i = $1; +} + +set0_dp(0x02, rd |= 0x01), +clr0_dp(0x12, rd &= ~0x01), +set1_dp(0x22, rd |= 0x02), +clr1_dp(0x32, rd &= ~0x02), +set2_dp(0x42, rd |= 0x04), +clr2_dp(0x52, rd &= ~0x04), +set3_dp(0x62, rd |= 0x08), +clr3_dp(0x72, rd &= ~0x08), +set4_dp(0x82, rd |= 0x10), +clr4_dp(0x92, rd &= ~0x10), +set5_dp(0xa2, rd |= 0x20), +clr5_dp(0xb2, rd &= ~0x20), +set6_dp(0xc2, rd |= 0x40), +clr6_dp(0xd2, rd &= ~0x40), +set7_dp(0xe2, rd |= 0x80), +clr7_dp(0xf2, rd &= ~0x80) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:$1; + op_writedp(dp, rd); +} + +push_a(0x2d, a), +push_x(0x4d, x), +push_y(0x6d, y), +push_p(0x0d, p) { +1:op_io(); +2:op_io(); +3:op_writestack(regs.$1); +} + +pop_a(0xae, a), +pop_x(0xce, x), +pop_y(0xee, y), +pop_p(0x8e, p) { +1:op_io(); +2:op_io(); +3:regs.$1 = op_readstack(); +} + +mul_ya(0xcf) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); +} + +div_ya_x(0x9e) { +1:op_io(); +2:op_io(); +3:op_io(); +4:op_io(); +5:op_io(); +6:op_io(); +7:op_io(); +8:op_io(); +9:op_io(); +10:op_io(); +11:op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} diff --git a/apu/bapu/smp/core/op_misc.cpp b/apu/bapu/smp/core/op_misc.cpp new file mode 100755 index 00000000..9a6a062d --- /dev/null +++ b/apu/bapu/smp/core/op_misc.cpp @@ -0,0 +1,346 @@ +case 0x00: { + op_io(); + break; +} + +case 0xef: { + op_io(); + op_io(); + regs.pc--; + break; +} + +case 0xff: { + op_io(); + op_io(); + regs.pc--; + break; +} + +case 0x9f: { + op_io(); + op_io(); + op_io(); + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdf: { + op_io(); + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xbe: { + op_io(); + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x60: { + op_io(); + regs.p.c = 0; + break; +} + +case 0x20: { + op_io(); + regs.p.p = 0; + break; +} + +case 0x80: { + op_io(); + regs.p.c = 1; + break; +} + +case 0x40: { + op_io(); + regs.p.p = 1; + break; +} + +case 0xe0: { + op_io(); + regs.p.v = 0; + regs.p.h = 0; + break; +} + +case 0xed: { + op_io(); + op_io(); + regs.p.c = !regs.p.c; + break; +} + +case 0xa0: { + op_io(); + op_io(); + regs.p.i = 1; + break; +} + +case 0xc0: { + op_io(); + op_io(); + regs.p.i = 0; + break; +} + +case 0x02: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + break; +} + +case 0x12: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + break; +} + +case 0x22: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + break; +} + +case 0x32: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + break; +} + +case 0x42: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + break; +} + +case 0x52: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + break; +} + +case 0x62: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + break; +} + +case 0x72: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + break; +} + +case 0x82: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + break; +} + +case 0x92: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + break; +} + +case 0xa2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + break; +} + +case 0xb2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + break; +} + +case 0xc2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + break; +} + +case 0xd2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + break; +} + +case 0xe2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + break; +} + +case 0xf2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + break; +} + +case 0x2d: { + op_io(); + op_io(); + op_writestack(regs.a); + break; +} + +case 0x4d: { + op_io(); + op_io(); + op_writestack(regs.x); + break; +} + +case 0x6d: { + op_io(); + op_io(); + op_writestack(regs.y); + break; +} + +case 0x0d: { + op_io(); + op_io(); + op_writestack(regs.p); + break; +} + +case 0xae: { + op_io(); + op_io(); + regs.a = op_readstack(); + break; +} + +case 0xce: { + op_io(); + op_io(); + regs.x = op_readstack(); + break; +} + +case 0xee: { + op_io(); + op_io(); + regs.y = op_readstack(); + break; +} + +case 0x8e: { + op_io(); + op_io(); + regs.p = op_readstack(); + break; +} + +case 0xcf: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9e: { + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + diff --git a/apu/bapu/smp/core/op_mov.b b/apu/bapu/smp/core/op_mov.b new file mode 100755 index 00000000..dee821af --- /dev/null +++ b/apu/bapu/smp/core/op_mov.b @@ -0,0 +1,217 @@ +mov_a_x(0x7d, a, x), +mov_a_y(0xdd, a, y), +mov_x_a(0x5d, x, a), +mov_y_a(0xfd, y, a), +mov_x_sp(0x9d, x, sp) { +1:op_io(); + regs.$1 = regs.$2; + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_sp_x(0xbd, sp, x) { +1:op_io(); + regs.$1 = regs.$2; +} + +mov_a_const(0xe8, a), +mov_x_const(0xcd, x), +mov_y_const(0x8d, y) { +1:regs.$1 = op_readpc(); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_ix(0xe6) { +1:op_io(); +2:regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_ixinc(0xbf) { +1:op_io(); +2:regs.a = op_readdp(regs.x++); +3:op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_dp(0xe4, a), +mov_x_dp(0xf8, x), +mov_y_dp(0xeb, y) { +1:sp = op_readpc(); +2:regs.$1 = op_readdp(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_dpx(0xf4, a, x), +mov_x_dpy(0xf9, x, y), +mov_y_dpx(0xfb, y, x) { +1:sp = op_readpc(); +2:op_io(); +3:regs.$1 = op_readdp(sp + regs.$2); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addr(0xe5, a), +mov_x_addr(0xe9, x), +mov_y_addr(0xec, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:regs.$1 = op_readaddr(sp); + regs.p.n = !!(regs.$1 & 0x80); + regs.p.z = (regs.$1 == 0); +} + +mov_a_addrx(0xf5, x), +mov_a_addry(0xf6, y) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:op_io(); +4:regs.a = op_readaddr(sp + regs.$1); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpx(0xe7) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_a_idpy(0xf7) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); +} + +mov_dp_dp(0xfa) { +1:sp = op_readpc(); +2:rd = op_readdp(sp); +3:dp = op_readpc(); +4:op_writedp(dp, rd); +} + +mov_dp_const(0x8f) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:op_readdp(dp); +4:op_writedp(dp, rd); +} + +mov_ix_a(0xc6) { +1:op_io(); +2:op_readdp(regs.x); +3:op_writedp(regs.x, regs.a); +} + +mov_ixinc_a(0xaf) { +1:op_io(); +2:op_io(); +3:op_writedp(regs.x++, regs.a); +} + +mov_dp_a(0xc4, a), +mov_dp_x(0xd8, x), +mov_dp_y(0xcb, y) { +1:dp = op_readpc(); +2:op_readdp(dp); +3:op_writedp(dp, regs.$1); +} + +mov_dpx_a(0xd4, x, a), +mov_dpy_x(0xd9, y, x), +mov_dpx_y(0xdb, x, y) { +1:dp = op_readpc(); +2:op_io(); + dp += regs.$1; +3:op_readdp(dp); +4:op_writedp(dp, regs.$2); +} + +mov_addr_a(0xc5, a), +mov_addr_x(0xc9, x), +mov_addr_y(0xcc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_readaddr(dp); +4:op_writeaddr(dp, regs.$1); +} + +mov_addrx_a(0xd5, x), +mov_addry_a(0xd6, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); + dp += regs.$1; +4:op_readaddr(dp); +5:op_writeaddr(dp, regs.a); +} + +mov_idpx_a(0xc7) { +1:sp = op_readpc(); +2:op_io(); + sp += regs.x; +3:dp = op_readdp(sp); +4:dp |= op_readdp(sp + 1) << 8; +5:op_readaddr(dp); +6:op_writeaddr(dp, regs.a); +} + +mov_idpy_a(0xd7) { +1:sp = op_readpc(); +2:dp = op_readdp(sp); +3:dp |= op_readdp(sp + 1) << 8; +4:op_io(); + dp += regs.y; +5:op_readaddr(dp); +6:op_writeaddr(dp, regs.a); +} + +movw_ya_dp(0xba) { +1:sp = op_readpc(); +2:regs.a = op_readdp(sp); +3:op_io(); +4:regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); +} + +movw_dp_ya(0xda) { +1:dp = op_readpc(); +2:op_readdp(dp); +3:op_writedp(dp, regs.a); +4:op_writedp(dp + 1, regs.y); +} + +mov1_c_bit(0xaa) { +1:sp = op_readpc(); +2:sp |= op_readpc() << 8; +3:bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); +} + +mov1_bit_c(0xca) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); +4:op_io(); +5:op_writeaddr(dp, rd); +} diff --git a/apu/bapu/smp/core/op_mov.cpp b/apu/bapu/smp/core/op_mov.cpp new file mode 100755 index 00000000..f3079423 --- /dev/null +++ b/apu/bapu/smp/core/op_mov.cpp @@ -0,0 +1,389 @@ +case 0x7d: { + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdd: { + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x5d: { + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfd: { + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9d: { + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xbd: { + op_io(); + regs.sp = regs.x; + break; +} + +case 0xe8: { + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xcd: { + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0x8d: { + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe6: { + op_io(); + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xbf: { + op_io(); + regs.a = op_readdp(regs.x++); + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe4: { + sp = op_readpc(); + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf8: { + sp = op_readpc(); + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xeb: { + sp = op_readpc(); + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xf4: { + sp = op_readpc(); + op_io(); + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf9: { + sp = op_readpc(); + op_io(); + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfb: { + sp = op_readpc(); + op_io(); + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe9: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xec: { + sp = op_readpc(); + sp |= op_readpc() << 8; + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xf5: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf6: { + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xe7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xf7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xfa: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + op_writedp(dp, rd); + break; +} + +case 0x8f: { + rd = op_readpc(); + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, rd); + break; +} + +case 0xc6: { + op_io(); + op_readdp(regs.x); + op_writedp(regs.x, regs.a); + break; +} + +case 0xaf: { + op_io(); + op_io(); + op_writedp(regs.x++, regs.a); + break; +} + +case 0xc4: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.a); + break; +} + +case 0xd8: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.x); + break; +} + +case 0xcb: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.y); + break; +} + +case 0xd4: { + dp = op_readpc(); + op_io(); + dp += regs.x; + op_readdp(dp); + op_writedp(dp, regs.a); + break; +} + +case 0xd9: { + dp = op_readpc(); + op_io(); + dp += regs.y; + op_readdp(dp); + op_writedp(dp, regs.x); + break; +} + +case 0xdb: { + dp = op_readpc(); + op_io(); + dp += regs.x; + op_readdp(dp); + op_writedp(dp, regs.y); + break; +} + +case 0xc5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xc9: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.x); + break; +} + +case 0xcc: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.y); + break; +} + +case 0xd5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xd6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.y; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xc7: { + sp = op_readpc(); + op_io(); + sp += regs.x; + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xd7: { + sp = op_readpc(); + dp = op_readdp(sp); + dp |= op_readdp(sp + 1) << 8; + op_io(); + dp += regs.y; + op_readaddr(dp); + op_writeaddr(dp, regs.a); + break; +} + +case 0xba: { + sp = op_readpc(); + regs.a = op_readdp(sp); + op_io(); + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + break; +} + +case 0xda: { + dp = op_readpc(); + op_readdp(dp); + op_writedp(dp, regs.a); + op_writedp(dp + 1, regs.y); + break; +} + +case 0xaa: { + sp = op_readpc(); + sp |= op_readpc() << 8; + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + break; +} + +case 0xca: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + op_io(); + op_writeaddr(dp, rd); + break; +} + diff --git a/apu/bapu/smp/core/op_pc.b b/apu/bapu/smp/core/op_pc.b new file mode 100755 index 00000000..affaf844 --- /dev/null +++ b/apu/bapu/smp/core/op_pc.b @@ -0,0 +1,179 @@ +bra(0x2f, 0), +beq(0xf0, !regs.p.z), +bne(0xd0, regs.p.z), +bcs(0xb0, !regs.p.c), +bcc(0x90, regs.p.c), +bvs(0x70, !regs.p.v), +bvc(0x50, regs.p.v), +bmi(0x30, !regs.p.n), +bpl(0x10, regs.p.n) { +1:rd = op_readpc(); + if($1)end; +2:op_io(); +3:op_io(); + regs.pc += (int8)rd; +} + +bbs0(0x03, 0x01, !=), +bbc0(0x13, 0x01, ==), +bbs1(0x23, 0x02, !=), +bbc1(0x33, 0x02, ==), +bbs2(0x43, 0x04, !=), +bbc2(0x53, 0x04, ==), +bbs3(0x63, 0x08, !=), +bbc3(0x73, 0x08, ==), +bbs4(0x83, 0x10, !=), +bbc4(0x93, 0x10, ==), +bbs5(0xa3, 0x20, !=), +bbc5(0xb3, 0x20, ==), +bbs6(0xc3, 0x40, !=), +bbc6(0xd3, 0x40, ==), +bbs7(0xe3, 0x80, !=), +bbc7(0xf3, 0x80, ==) { +1:dp = op_readpc(); +2:sp = op_readdp(dp); +3:rd = op_readpc(); +4:op_io(); + if((sp & $1) $2 $1)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dp(0x2e) { +1:dp = op_readpc(); +2:sp = op_readdp(dp); +3:rd = op_readpc(); +4:op_io(); + if(regs.a == sp)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +cbne_dpx(0xde) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp + regs.x); +4:rd = op_readpc(); +5:op_io(); + if(regs.a == sp)end; +6:op_io(); +7:op_io(); + regs.pc += (int8)rd; +} + +dbnz_dp(0x6e) { +1:dp = op_readpc(); +2:wr = op_readdp(dp); +3:op_writedp(dp, --wr); +4:rd = op_readpc(); + if(wr == 0x00)end; +5:op_io(); +6:op_io(); + regs.pc += (int8)rd; +} + +dbnz_y(0xfe) { +1:rd = op_readpc(); +2:op_io(); + regs.y--; +3:op_io(); + if(regs.y == 0x00)end; +4:op_io(); +5:op_io(); + regs.pc += (int8)rd; +} + +jmp_addr(0x5f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; + regs.pc = rd; +} + +jmp_iaddrx(0x1f) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); + dp += regs.x; +4:rd = op_readaddr(dp); +5:rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; +} + +call(0x3f) { +1:rd = op_readpc(); +2:rd |= op_readpc() << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +pcall(0x4f) { +1:rd = op_readpc(); +2:op_io(); +3:op_io(); +4:op_writestack(regs.pc >> 8); +5:op_writestack(regs.pc); + regs.pc = 0xff00 | rd; +} + +tcall_0(0x01, 0), +tcall_1(0x11, 1), +tcall_2(0x21, 2), +tcall_3(0x31, 3), +tcall_4(0x41, 4), +tcall_5(0x51, 5), +tcall_6(0x61, 6), +tcall_7(0x71, 7), +tcall_8(0x81, 8), +tcall_9(0x91, 9), +tcall_10(0xa1, 10), +tcall_11(0xb1, 11), +tcall_12(0xc1, 12), +tcall_13(0xd1, 13), +tcall_14(0xe1, 14), +tcall_15(0xf1, 15) { +1:dp = 0xffde - ($1 << 1); + rd = op_readaddr(dp); +2:rd |= op_readaddr(dp + 1) << 8; +3:op_io(); +4:op_io(); +5:op_io(); +6:op_writestack(regs.pc >> 8); +7:op_writestack(regs.pc); + regs.pc = rd; +} + +brk(0x0f) { +1:rd = op_readaddr(0xffde); +2:rd |= op_readaddr(0xffdf) << 8; +3:op_io(); +4:op_io(); +5:op_writestack(regs.pc >> 8); +6:op_writestack(regs.pc); +7:op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; +} + +ret(0x6f) { +1:rd = op_readstack(); +2:rd |= op_readstack() << 8; +3:op_io(); +4:op_io(); + regs.pc = rd; +} + +reti(0x7f) { +1:regs.p = op_readstack(); +2:rd = op_readstack(); +3:rd |= op_readstack() << 8; +4:op_io(); +5:op_io(); + regs.pc = rd; +} diff --git a/apu/bapu/smp/core/op_pc.cpp b/apu/bapu/smp/core/op_pc.cpp new file mode 100755 index 00000000..763a033e --- /dev/null +++ b/apu/bapu/smp/core/op_pc.cpp @@ -0,0 +1,603 @@ +case 0x2f: { + rd = op_readpc(); + if(0)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xf0: { + rd = op_readpc(); + if(!regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xd0: { + rd = op_readpc(); + if(regs.p.z)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xb0: { + rd = op_readpc(); + if(!regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x90: { + rd = op_readpc(); + if(regs.p.c)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x70: { + rd = op_readpc(); + if(!regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x50: { + rd = op_readpc(); + if(regs.p.v)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x30: { + rd = op_readpc(); + if(!regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x10: { + rd = op_readpc(); + if(regs.p.n)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x03: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x13: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x23: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x33: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x43: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x53: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x63: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x73: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x83: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x93: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xa3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xb3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xc3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xd3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xe3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xf3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x2e: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xde: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x6e: { + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0xfe: { + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00)break; + op_io(); + op_io(); + regs.pc += (int8)rd; + break; +} + +case 0x5f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + break; +} + +case 0x1f: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + break; +} + +case 0x3f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x4f: { + rd = op_readpc(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + break; +} + +case 0x01: { + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x11: { + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x21: { + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x31: { + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x41: { + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x51: { + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x61: { + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x71: { + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x81: { + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x91: { + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xa1: { + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xb1: { + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xc1: { + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xd1: { + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xe1: { + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xf1: { + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(); + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x0f: { + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(); + op_io(); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + break; +} + +case 0x6f: { + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; + break; +} + +case 0x7f: { + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(); + op_io(); + regs.pc = rd; + break; +} + diff --git a/apu/bapu/smp/core/op_read.b b/apu/bapu/smp/core/op_read.b new file mode 100755 index 00000000..fd2f9d82 --- /dev/null +++ b/apu/bapu/smp/core/op_read.b @@ -0,0 +1,205 @@ +adc_a_const(0x88, adc, a), +and_a_const(0x28, and, a), +cmp_a_const(0x68, cmp, a), +cmp_x_const(0xc8, cmp, x), +cmp_y_const(0xad, cmp, y), +eor_a_const(0x48, eor, a), +or_a_const(0x08, or, a), +sbc_a_const(0xa8, sbc, a) { +1:rd = op_readpc(); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_ix(0x86, adc), +and_a_ix(0x26, and), +cmp_a_ix(0x66, cmp), +eor_a_ix(0x46, eor), +or_a_ix(0x06, or), +sbc_a_ix(0xa6, sbc) { +1:op_io(); +2:rd = op_readdp(regs.x); + regs.a = op_$1(regs.a, rd); +} + +adc_a_dp(0x84, adc, a), +and_a_dp(0x24, and, a), +cmp_a_dp(0x64, cmp, a), +cmp_x_dp(0x3e, cmp, x), +cmp_y_dp(0x7e, cmp, y), +eor_a_dp(0x44, eor, a), +or_a_dp(0x04, or, a), +sbc_a_dp(0xa4, sbc, a) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_dpx(0x94, adc), +and_a_dpx(0x34, and), +cmp_a_dpx(0x74, cmp), +eor_a_dpx(0x54, eor), +or_a_dpx(0x14, or), +sbc_a_dpx(0xb4, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); + regs.a = op_$1(regs.a, rd); +} + +adc_a_addr(0x85, adc, a), +and_a_addr(0x25, and, a), +cmp_a_addr(0x65, cmp, a), +cmp_x_addr(0x1e, cmp, x), +cmp_y_addr(0x5e, cmp, y), +eor_a_addr(0x45, eor, a), +or_a_addr(0x05, or, a), +sbc_a_addr(0xa5, sbc, a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); + regs.$2 = op_$1(regs.$2, rd); +} + +adc_a_addrx(0x95, adc, x), +adc_a_addry(0x96, adc, y), +and_a_addrx(0x35, and, x), +and_a_addry(0x36, and, y), +cmp_a_addrx(0x75, cmp, x), +cmp_a_addry(0x76, cmp, y), +eor_a_addrx(0x55, eor, x), +eor_a_addry(0x56, eor, y), +or_a_addrx(0x15, or, x), +or_a_addry(0x16, or, y), +sbc_a_addrx(0xb5, sbc, x), +sbc_a_addry(0xb6, sbc, y) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:op_io(); +4:rd = op_readaddr(dp + regs.$2); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpx(0x87, adc), +and_a_idpx(0x27, and), +cmp_a_idpx(0x67, cmp), +eor_a_idpx(0x47, eor), +or_a_idpx(0x07, or), +sbc_a_idpx(0xa7, sbc) { +1:dp = op_readpc() + regs.x; +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp); + regs.a = op_$1(regs.a, rd); +} + +adc_a_idpy(0x97, adc), +and_a_idpy(0x37, and), +cmp_a_idpy(0x77, cmp), +eor_a_idpy(0x57, eor), +or_a_idpy(0x17, or), +sbc_a_idpy(0xb7, sbc) { +1:dp = op_readpc(); +2:op_io(); +3:sp = op_readdp(dp); +4:sp |= op_readdp(dp + 1) << 8; +5:rd = op_readaddr(sp + regs.y); + regs.a = op_$1(regs.a, rd); +} + +adc_ix_iy(0x99, adc, 1), +and_ix_iy(0x39, and, 1), +cmp_ix_iy(0x79, cmp, 0), +eor_ix_iy(0x59, eor, 1), +or_ix_iy(0x19, or, 1), +sbc_ix_iy(0xb9, sbc, 1) { +1:op_io(); +2:rd = op_readdp(regs.y); +3:wr = op_readdp(regs.x); + wr = op_$1(wr, rd); +4:($2) ? op_writedp(regs.x, wr) : op_io(); +} + +adc_dp_dp(0x89, adc, 1), +and_dp_dp(0x29, and, 1), +cmp_dp_dp(0x69, cmp, 0), +eor_dp_dp(0x49, eor, 1), +or_dp_dp(0x09, or, 1), +sbc_dp_dp(0xa9, sbc, 1) { +1:sp = op_readpc(); +2:rd = op_readdp(sp); +3:dp = op_readpc(); +4:wr = op_readdp(dp); +5:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +adc_dp_const(0x98, adc, 1), +and_dp_const(0x38, and, 1), +cmp_dp_const(0x78, cmp, 0), +eor_dp_const(0x58, eor, 1), +or_dp_const(0x18, or, 1), +sbc_dp_const(0xb8, sbc, 1) { +1:rd = op_readpc(); +2:dp = op_readpc(); +3:wr = op_readdp(dp); +4:wr = op_$1(wr, rd); + ($2) ? op_writedp(dp, wr) : op_io(); +} + +addw_ya_dp(0x7a, addw), +subw_ya_dp(0x9a, subw) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:op_io(); +4:rd |= op_readdp(dp + 1) << 8; + regs.ya = op_$1(regs.ya, rd); +} + +cmpw_ya_dp(0x5a) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); +} + +and1_bit(0x4a, !!), +and1_notbit(0x6a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & $1(rd & (1 << bit)); +} + +eor1_bit(0x8a) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); +} + +not1_bit(0xea) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); +4:op_writeaddr(dp, rd); +} + +or1_bit(0x0a, !!), +or1_notbit(0x2a, !) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); +4:op_io(); + regs.p.c = regs.p.c | $1(rd & (1 << bit)); +} diff --git a/apu/bapu/smp/core/op_read.cpp b/apu/bapu/smp/core/op_read.cpp new file mode 100755 index 00000000..2a16a3c8 --- /dev/null +++ b/apu/bapu/smp/core/op_read.cpp @@ -0,0 +1,744 @@ +case 0x88: { + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x28: { + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x68: { + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0xc8: { + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0xad: { + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x48: { + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x08: { + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa8: { + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x86: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x26: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x66: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x46: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x06: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa6: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x84: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x24: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x64: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x3e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x7e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x44: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x04: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa4: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x94: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x34: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x74: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x54: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x14: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb4: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x85: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x25: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x65: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x1e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x5e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x45: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x05: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x95: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x96: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x35: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x36: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x75: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x76: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x55: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x56: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x15: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0x16: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0xb6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x87: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x27: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x67: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x47: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x07: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x97: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x37: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x77: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x57: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x17: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x99: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x39: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x79: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x59: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x19: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0xb9: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x89: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x29: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x69: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x49: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x09: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xa9: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x98: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x38: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x78: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x58: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x18: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xb8: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x7a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + break; +} + +case 0x9a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + break; +} + +case 0x5a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + break; +} + +case 0x4a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + break; +} + +case 0x6a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + break; +} + +case 0x8a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + break; +} + +case 0xea: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + break; +} + +case 0x0a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + break; +} + +case 0x2a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + break; +} + diff --git a/apu/bapu/smp/core/op_rmw.b b/apu/bapu/smp/core/op_rmw.b new file mode 100755 index 00000000..425574e8 --- /dev/null +++ b/apu/bapu/smp/core/op_rmw.b @@ -0,0 +1,74 @@ +inc_a(0xbc, inc, a), +inc_x(0x3d, inc, x), +inc_y(0xfc, inc, y), +dec_a(0x9c, dec, a), +dec_x(0x1d, dec, x), +dec_y(0xdc, dec, y), +asl_a(0x1c, asl, a), +lsr_a(0x5c, lsr, a), +rol_a(0x3c, rol, a), +ror_a(0x7c, ror, a) { +1:op_io(); + regs.$2 = op_$1(regs.$2); +} + +inc_dp(0xab, inc), +dec_dp(0x8b, dec), +asl_dp(0x0b, asl), +lsr_dp(0x4b, lsr), +rol_dp(0x2b, rol), +ror_dp(0x6b, ror) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); +3:rd = op_$1(rd); + op_writedp(dp, rd); +} + +inc_dpx(0xbb, inc), +dec_dpx(0x9b, dec), +asl_dpx(0x1b, asl), +lsr_dpx(0x5b, lsr), +rol_dpx(0x3b, rol), +ror_dpx(0x7b, ror) { +1:dp = op_readpc(); +2:op_io(); +3:rd = op_readdp(dp + regs.x); +4:rd = op_$1(rd); + op_writedp(dp + regs.x, rd); +} + +inc_addr(0xac, inc), +dec_addr(0x8c, dec), +asl_addr(0x0c, asl), +lsr_addr(0x4c, lsr), +rol_addr(0x2c, rol), +ror_addr(0x6c, ror) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); +4:rd = op_$1(rd); + op_writeaddr(dp, rd); +} + +tset_addr_a(0x0e, |), +tclr_addr_a(0x4e, &~) { +1:dp = op_readpc(); +2:dp |= op_readpc() << 8; +3:rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); +4:op_readaddr(dp); +5:op_writeaddr(dp, rd $1 regs.a); +} + +incw_dp(0x3a, ++), +decw_dp(0x1a, --) { +1:dp = op_readpc(); +2:rd = op_readdp(dp); + rd$1; +3:op_writedp(dp++, rd); +4:rd += op_readdp(dp) << 8; +5:op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); +} diff --git a/apu/bapu/smp/core/op_rmw.cpp b/apu/bapu/smp/core/op_rmw.cpp new file mode 100755 index 00000000..f89ecacf --- /dev/null +++ b/apu/bapu/smp/core/op_rmw.cpp @@ -0,0 +1,262 @@ +case 0xbc: { + op_io(); + regs.a = op_inc(regs.a); + break; +} + +case 0x3d: { + op_io(); + regs.x = op_inc(regs.x); + break; +} + +case 0xfc: { + op_io(); + regs.y = op_inc(regs.y); + break; +} + +case 0x9c: { + op_io(); + regs.a = op_dec(regs.a); + break; +} + +case 0x1d: { + op_io(); + regs.x = op_dec(regs.x); + break; +} + +case 0xdc: { + op_io(); + regs.y = op_dec(regs.y); + break; +} + +case 0x1c: { + op_io(); + regs.a = op_asl(regs.a); + break; +} + +case 0x5c: { + op_io(); + regs.a = op_lsr(regs.a); + break; +} + +case 0x3c: { + op_io(); + regs.a = op_rol(regs.a); + break; +} + +case 0x7c: { + op_io(); + regs.a = op_ror(regs.a); + break; +} + +case 0xab: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + break; +} + +case 0x8b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + break; +} + +case 0x0b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + break; +} + +case 0x4b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + break; +} + +case 0x2b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + break; +} + +case 0x6b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + break; +} + +case 0xbb: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x9b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x1b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x5b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x3b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x7b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0xac: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x8c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x4c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x2c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x6c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + break; +} + +case 0x4e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + break; +} + +case 0x3a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + +case 0x1a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp new file mode 100755 index 00000000..963f9fc2 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -0,0 +1,696 @@ +case 0x00: { + switch(opcode_cycle++) { + case 1: + op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xef: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } + break; +} + +case 0xff: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } + break; +} + +case 0x9f: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbe: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x60: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x20: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x80: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0x40: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe0: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0xed: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.c = !regs.p.c; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa0: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 1; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc0: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x02: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x12: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x22: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x32: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x42: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x52: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x62: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x72: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x82: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x92: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf2: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0d: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.p); + opcode_cycle = 0; + break; + } + break; +} + +case 0xae: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xce: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xee: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8e: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.p = op_readstack(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9e: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + break; + case 9: + op_io(); + break; + case 10: + op_io(); + break; + case 11: + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp new file mode 100755 index 00000000..635c7ca5 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -0,0 +1,806 @@ +case 0x7d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbd: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe8: { + switch(opcode_cycle++) { + case 1: + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcd: { + switch(opcode_cycle++) { + case 1: + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8d: { + switch(opcode_cycle++) { + case 1: + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x++); + break; + case 3: + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe4: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf8: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xeb: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf4: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfb: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe5: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xec: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf5: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf6: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfa: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_readdp(regs.x); + break; + case 3: + op_writedp(regs.x, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaf: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writedp(regs.x++, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd8: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.x; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd9: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.y; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + dp += regs.x; + break; + case 3: + op_readdp(dp); + break; + case 4: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc9: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcc: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd6: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.y; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc7: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + op_io(); + sp += regs.x; + break; + case 3: + dp = op_readdp(sp); + break; + case 4: + dp |= op_readdp(sp + 1) << 8; + break; + case 5: + op_readaddr(dp); + break; + case 6: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd7: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + break; + case 4: + op_io(); + dp += regs.y; + break; + case 5: + op_readaddr(dp); + break; + case 6: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xba: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + break; + case 3: + op_io(); + break; + case 4: + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xda: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + break; + case 4: + op_writedp(dp + 1, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaa: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xca: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + break; + case 4: + op_io(); + break; + case 5: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp new file mode 100755 index 00000000..1cdda647 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -0,0 +1,1347 @@ +case 0x2f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb0: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x90: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x70: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x50: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x30: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x10: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x03: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x13: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x23: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x33: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x43: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x53: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x63: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x73: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x83: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x93: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf3: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x2e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xde: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp + regs.x); + break; + case 4: + rd = op_readpc(); + break; + case 5: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 6: + op_io(); + break; + case 7: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x6e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + wr = op_readdp(dp); + break; + case 3: + op_writedp(dp, --wr); + break; + case 4: + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xfe: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + regs.y--; + break; + case 3: + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x5f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x1f: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + rd = op_readaddr(dp); + break; + case 5: + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x3f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x4f: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_writestack(regs.pc >> 8); + break; + case 5: + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x01: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x11: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x21: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x31: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x41: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x51: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x61: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x71: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x81: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x91: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xa1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xb1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xc1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xd1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xe1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0xf1: { + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x0f: { + switch(opcode_cycle++) { + case 1: + rd = op_readaddr(0xffde); + break; + case 2: + rd |= op_readaddr(0xffdf) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_writestack(regs.pc >> 8); + break; + case 6: + op_writestack(regs.pc); + break; + case 7: + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; + break; + } + break; +} + +case 0x6f: { + switch(opcode_cycle++) { + case 1: + rd = op_readstack(); + break; + case 2: + rd |= op_readstack() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + +case 0x7f: { + switch(opcode_cycle++) { + case 1: + regs.p = op_readstack(); + break; + case 2: + rd = op_readstack(); + break; + case 3: + rd |= op_readstack() << 8; + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp new file mode 100755 index 00000000..6c19f3a9 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -0,0 +1,1599 @@ +case 0x88: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x28: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x68: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xad: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x48: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x08: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x86: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x26: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x66: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x46: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x06: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa6: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x84: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x24: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x64: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x44: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x04: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x94: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x34: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x74: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x54: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x14: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb4: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x85: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x25: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x65: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x45: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x05: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x95: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x96: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x35: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x36: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x75: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x76: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x55: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x56: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x15: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x16: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb5: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb6: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x87: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x27: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x67: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x47: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x07: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x97: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x37: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x77: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x57: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x17: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb7: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x99: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x39: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x79: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + break; + case 4: + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x59: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x19: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb9: { + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x89: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x29: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x69: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x49: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x09: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xa9: { + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x98: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x38: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x78: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x58: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x18: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0xb8: { + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xea: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + break; + case 4: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp new file mode 100755 index 00000000..eca62f02 --- /dev/null +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -0,0 +1,550 @@ +case 0xbc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1d: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdc: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7c: { + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_ror(regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xab: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbb: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x9b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x5b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x7b: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xac: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x2c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x6c: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x0e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x4e: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0x3a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd++; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0x1a: { + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd--; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/debugger/debugger.cpp b/apu/bapu/smp/debugger/debugger.cpp new file mode 100755 index 00000000..9546c118 --- /dev/null +++ b/apu/bapu/smp/debugger/debugger.cpp @@ -0,0 +1,75 @@ +#ifdef SMP_CPP + +void SMPDebugger::op_step() { + bool break_event = false; + + usage[regs.pc] |= UsageExec; + opcode_pc = regs.pc; + + opcode_edge = true; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00); + if(step_event && step_event() == true) { + debugger.break_event = Debugger::BreakEvent::SMPStep; + scheduler.exit(Scheduler::ExitReason::DebuggerEvent); + } + opcode_edge = false; + + SMP::op_step(); + synchronize_cpu(); +} + +uint8 SMPDebugger::op_read(uint16 addr) { + uint8 data = SMP::op_read(addr); + usage[addr] |= UsageRead; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Read, addr, data); + return data; +} + +void SMPDebugger::op_write(uint16 addr, uint8 data) { + SMP::op_write(addr, data); + usage[addr] |= UsageWrite; + usage[addr] &= ~UsageExec; + debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Write, addr, data); +} + +SMPDebugger::SMPDebugger() { + usage = new uint8[1 << 16](); + opcode_pc = 0xffc0; + opcode_edge = false; +} + +SMPDebugger::~SMPDebugger() { + delete[] usage; +} + +bool SMPDebugger::property(unsigned id, string &name, string &value) { + unsigned n = 0; + + #define item(name_, value_) \ + if(id == n++) { \ + name = name_; \ + value = value_; \ + return true; \ + } + + //$00f0 + item("$00f0", ""); + item("Clock Speed", (unsigned)status.clock_speed); + item("Timers Enable", status.timers_enable); + item("RAM Disable", status.ram_disable); + item("RAM Writable", status.ram_writable); + item("Timers Disable", status.timers_disable); + + //$00f1 + item("$00f1", ""); + item("IPLROM Enable", status.iplrom_enable); + + //$00f2 + item("$00f2", ""); + item("DSP Address", string("0x", hex<2>(status.dsp_addr))); + + #undef item + return false; +} + +#endif diff --git a/apu/bapu/smp/debugger/debugger.hpp b/apu/bapu/smp/debugger/debugger.hpp new file mode 100755 index 00000000..811aa4c6 --- /dev/null +++ b/apu/bapu/smp/debugger/debugger.hpp @@ -0,0 +1,27 @@ +class SMPDebugger : public SMP, public ChipDebugger { +public: + bool property(unsigned id, string &name, string &value); + + function step_event; + + enum Usage { + UsageRead = 0x80, + UsageWrite = 0x40, + UsageExec = 0x20, + }; + uint8 *usage; + uint16 opcode_pc; + bool opcode_edge; + + void op_step(); + uint8 op_read(uint16 addr); + void op_write(uint16 addr, uint8 data); + + SMPDebugger(); + ~SMPDebugger(); + + //disassembler + void disassemble_opcode(char *output, uint16 addr); + inline uint8 disassemble_read(uint16 addr); + inline uint16 relb(int8 offset, int op_len); +}; diff --git a/apu/bapu/smp/debugger/disassembler.cpp b/apu/bapu/smp/debugger/disassembler.cpp new file mode 100755 index 00000000..fb76ae92 --- /dev/null +++ b/apu/bapu/smp/debugger/disassembler.cpp @@ -0,0 +1,304 @@ +uint8 SMP::disassemble_read(uint16 addr) { + if(addr >= 0xffc0) return smp.iplrom[addr & 0x3f]; + return smp.apuram[addr]; +} + +uint16 SMP::relb(int8 offset, int op_len) { + uint16 pc = regs.pc + op_len; + return pc + offset; +} + +void SMP::disassemble_opcode(char *output, uint16 addr) { + char *s, t[512]; + uint8 op, op0, op1; + uint16 opw, opdp0, opdp1; + s = output; + + sprintf(s, "..%.4x ", addr); + + op = disassemble_read(addr + 0); + op0 = disassemble_read(addr + 1); + op1 = disassemble_read(addr + 2); + opw = (op0) | (op1 << 8); + opdp0 = ((unsigned)regs.p.p << 8) + op0; + opdp1 = ((unsigned)regs.p.p << 8) + op1; + + strcpy(t, " "); + + switch(op) { + case 0x00: sprintf(t, "nop"); break; + case 0x01: sprintf(t, "tcall 0"); break; + case 0x02: sprintf(t, "set0 $%.3x", opdp0); break; + case 0x03: sprintf(t, "bbs0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x04: sprintf(t, "or a,$%.3x", opdp0); break; + case 0x05: sprintf(t, "or a,$%.4x", opw); break; + case 0x06: sprintf(t, "or a,(x)"); break; + case 0x07: sprintf(t, "or a,($%.3x+x)", opdp0); break; + case 0x08: sprintf(t, "or a,#$%.2x", op0); break; + case 0x09: sprintf(t, "or $%.3x,$%.3x", opdp1, opdp0); break; + case 0x0a: sprintf(t, "or1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x0b: sprintf(t, "asl $%.3x", opdp0); break; + case 0x0c: sprintf(t, "asl $%.4x", opw); break; + case 0x0d: sprintf(t, "push p"); break; + case 0x0e: sprintf(t, "tset $%.4x,a", opw); break; + case 0x0f: sprintf(t, "brk"); break; + case 0x10: sprintf(t, "bpl $%.4x", relb(op0, 2)); break; + case 0x11: sprintf(t, "tcall 1"); break; + case 0x12: sprintf(t, "clr0 $%.3x", opdp0); break; + case 0x13: sprintf(t, "bbc0 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x14: sprintf(t, "or a,$%.3x+x", opdp0); break; + case 0x15: sprintf(t, "or a,$%.4x+x", opw); break; + case 0x16: sprintf(t, "or a,$%.4x+y", opw); break; + case 0x17: sprintf(t, "or a,($%.3x)+y", opdp0); break; + case 0x18: sprintf(t, "or $%.3x,#$%.2x", opdp1, op0); break; + case 0x19: sprintf(t, "or (x),(y)"); break; + case 0x1a: sprintf(t, "decw $%.3x", opdp0); break; + case 0x1b: sprintf(t, "asl $%.3x+x", opdp0); break; + case 0x1c: sprintf(t, "asl a"); break; + case 0x1d: sprintf(t, "dec x"); break; + case 0x1e: sprintf(t, "cmp x,$%.4x", opw); break; + case 0x1f: sprintf(t, "jmp ($%.4x+x)", opw); break; + case 0x20: sprintf(t, "clrp"); break; + case 0x21: sprintf(t, "tcall 2"); break; + case 0x22: sprintf(t, "set1 $%.3x", opdp0); break; + case 0x23: sprintf(t, "bbs1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x24: sprintf(t, "and a,$%.3x", opdp0); break; + case 0x25: sprintf(t, "and a,$%.4x", opw); break; + case 0x26: sprintf(t, "and a,(x)"); break; + case 0x27: sprintf(t, "and a,($%.3x+x)", opdp0); break; + case 0x28: sprintf(t, "and a,#$%.2x", op0); break; + case 0x29: sprintf(t, "and $%.3x,$%.3x", opdp1, opdp0); break; + case 0x2a: sprintf(t, "or1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x2b: sprintf(t, "rol $%.3x", opdp0); break; + case 0x2c: sprintf(t, "rol $%.4x", opw); break; + case 0x2d: sprintf(t, "push a"); break; + case 0x2e: sprintf(t, "cbne $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x2f: sprintf(t, "bra $%.4x", relb(op0, 2)); break; + case 0x30: sprintf(t, "bmi $%.4x", relb(op0, 2)); break; + case 0x31: sprintf(t, "tcall 3"); break; + case 0x32: sprintf(t, "clr1 $%.3x", opdp0); break; + case 0x33: sprintf(t, "bbc1 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x34: sprintf(t, "and a,$%.3x+x", opdp0); break; + case 0x35: sprintf(t, "and a,$%.4x+x", opw); break; + case 0x36: sprintf(t, "and a,$%.4x+y", opw); break; + case 0x37: sprintf(t, "and a,($%.3x)+y", opdp0); break; + case 0x38: sprintf(t, "and $%.3x,#$%.2x", opdp1, op0); break; + case 0x39: sprintf(t, "and (x),(y)"); break; + case 0x3a: sprintf(t, "incw $%.3x", opdp0); break; + case 0x3b: sprintf(t, "rol $%.3x+x", opdp0); break; + case 0x3c: sprintf(t, "rol a"); break; + case 0x3d: sprintf(t, "inc x"); break; + case 0x3e: sprintf(t, "cmp x,$%.3x", opdp0); break; + case 0x3f: sprintf(t, "call $%.4x", opw); break; + case 0x40: sprintf(t, "setp"); break; + case 0x41: sprintf(t, "tcall 4"); break; + case 0x42: sprintf(t, "set2 $%.3x", opdp0); break; + case 0x43: sprintf(t, "bbs2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x44: sprintf(t, "eor a,$%.3x", opdp0); break; + case 0x45: sprintf(t, "eor a,$%.4x", opw); break; + case 0x46: sprintf(t, "eor a,(x)"); break; + case 0x47: sprintf(t, "eor a,($%.3x+x)", opdp0); break; + case 0x48: sprintf(t, "eor a,#$%.2x", op0); break; + case 0x49: sprintf(t, "eor $%.3x,$%.3x", opdp1, opdp0); break; + case 0x4a: sprintf(t, "and1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x4b: sprintf(t, "lsr $%.3x", opdp0); break; + case 0x4c: sprintf(t, "lsr $%.4x", opw); break; + case 0x4d: sprintf(t, "push x"); break; + case 0x4e: sprintf(t, "tclr $%.4x,a", opw); break; + case 0x4f: sprintf(t, "pcall $ff%.2x", op0); break; + case 0x50: sprintf(t, "bvc $%.4x", relb(op0, 2)); break; + case 0x51: sprintf(t, "tcall 5"); break; + case 0x52: sprintf(t, "clr2 $%.3x", opdp0); break; + case 0x53: sprintf(t, "bbc2 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x54: sprintf(t, "eor a,$%.3x+x", opdp0); break; + case 0x55: sprintf(t, "eor a,$%.4x+x", opw); break; + case 0x56: sprintf(t, "eor a,$%.4x+y", opw); break; + case 0x57: sprintf(t, "eor a,($%.3x)+y", opdp0); break; + case 0x58: sprintf(t, "eor $%.3x,#$%.2x", opdp1, op0); break; + case 0x59: sprintf(t, "eor (x),(y)"); break; + case 0x5a: sprintf(t, "cmpw ya,$%.3x", opdp0); break; + case 0x5b: sprintf(t, "lsr $%.3x+x", opdp0); break; + case 0x5c: sprintf(t, "lsr a"); break; + case 0x5d: sprintf(t, "mov x,a"); break; + case 0x5e: sprintf(t, "cmp y,$%.4x", opw); break; + case 0x5f: sprintf(t, "jmp $%.4x", opw); break; + case 0x60: sprintf(t, "clrc"); break; + case 0x61: sprintf(t, "tcall 6"); break; + case 0x62: sprintf(t, "set3 $%.3x", opdp0); break; + case 0x63: sprintf(t, "bbs3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x64: sprintf(t, "cmp a,$%.3x", opdp0); break; + case 0x65: sprintf(t, "cmp a,$%.4x", opw); break; + case 0x66: sprintf(t, "cmp a,(x)"); break; + case 0x67: sprintf(t, "cmp a,($%.3x+x)", opdp0); break; + case 0x68: sprintf(t, "cmp a,#$%.2x", op0); break; + case 0x69: sprintf(t, "cmp $%.3x,$%.3x", opdp1, opdp0); break; + case 0x6a: sprintf(t, "and1 c,!$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x6b: sprintf(t, "ror $%.3x", opdp0); break; + case 0x6c: sprintf(t, "ror $%.4x", opw); break; + case 0x6d: sprintf(t, "push y"); break; + case 0x6e: sprintf(t, "dbnz $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x6f: sprintf(t, "ret"); break; + case 0x70: sprintf(t, "bvs $%.4x", relb(op0, 2)); break; + case 0x71: sprintf(t, "tcall 7"); break; + case 0x72: sprintf(t, "clr3 $%.3x", opdp0); break; + case 0x73: sprintf(t, "bbc3 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x74: sprintf(t, "cmp a,$%.3x+x", opdp0); break; + case 0x75: sprintf(t, "cmp a,$%.4x+x", opw); break; + case 0x76: sprintf(t, "cmp a,$%.4x+y", opw); break; + case 0x77: sprintf(t, "cmp a,($%.3x)+y", opdp0); break; + case 0x78: sprintf(t, "cmp $%.3x,#$%.2x", opdp1, op0); break; + case 0x79: sprintf(t, "cmp (x),(y)"); break; + case 0x7a: sprintf(t, "addw ya,$%.3x", opdp0); break; + case 0x7b: sprintf(t, "ror $%.3x+x", opdp0); break; + case 0x7c: sprintf(t, "ror a"); break; + case 0x7d: sprintf(t, "mov a,x"); break; + case 0x7e: sprintf(t, "cmp y,$%.3x", opdp0); break; + case 0x7f: sprintf(t, "reti"); break; + case 0x80: sprintf(t, "setc"); break; + case 0x81: sprintf(t, "tcall 8"); break; + case 0x82: sprintf(t, "set4 $%.3x", opdp0); break; + case 0x83: sprintf(t, "bbs4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x84: sprintf(t, "adc a,$%.3x", opdp0); break; + case 0x85: sprintf(t, "adc a,$%.4x", opw); break; + case 0x86: sprintf(t, "adc a,(x)"); break; + case 0x87: sprintf(t, "adc a,($%.3x+x)", opdp0); break; + case 0x88: sprintf(t, "adc a,#$%.2x", op0); break; + case 0x89: sprintf(t, "adc $%.3x,$%.3x", opdp1, opdp0); break; + case 0x8a: sprintf(t, "eor1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0x8b: sprintf(t, "dec $%.3x", opdp0); break; + case 0x8c: sprintf(t, "dec $%.4x", opw); break; + case 0x8d: sprintf(t, "mov y,#$%.2x", op0); break; + case 0x8e: sprintf(t, "pop p"); break; + case 0x8f: sprintf(t, "mov $%.3x,#$%.2x", opdp1, op0); break; + case 0x90: sprintf(t, "bcc $%.4x", relb(op0, 2)); break; + case 0x91: sprintf(t, "tcall 9"); break; + case 0x92: sprintf(t, "clr4 $%.3x", opdp0); break; + case 0x93: sprintf(t, "bbc4 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0x94: sprintf(t, "adc a,$%.3x+x", opdp0); break; + case 0x95: sprintf(t, "adc a,$%.4x+x", opw); break; + case 0x96: sprintf(t, "adc a,$%.4x+y", opw); break; + case 0x97: sprintf(t, "adc a,($%.3x)+y", opdp0); break; + case 0x98: sprintf(t, "adc $%.3x,#$%.2x", opdp1, op0); break; + case 0x99: sprintf(t, "adc (x),(y)"); break; + case 0x9a: sprintf(t, "subw ya,$%.3x", opdp0); break; + case 0x9b: sprintf(t, "dec $%.3x+x", opdp0); break; + case 0x9c: sprintf(t, "dec a"); break; + case 0x9d: sprintf(t, "mov x,sp"); break; + case 0x9e: sprintf(t, "div ya,x"); break; + case 0x9f: sprintf(t, "xcn a"); break; + case 0xa0: sprintf(t, "ei"); break; + case 0xa1: sprintf(t, "tcall 10"); break; + case 0xa2: sprintf(t, "set5 $%.3x", opdp0); break; + case 0xa3: sprintf(t, "bbs5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xa4: sprintf(t, "sbc a,$%.3x", opdp0); break; + case 0xa5: sprintf(t, "sbc a,$%.4x", opw); break; + case 0xa6: sprintf(t, "sbc a,(x)"); break; + case 0xa7: sprintf(t, "sbc a,($%.3x+x)", opdp0); break; + case 0xa8: sprintf(t, "sbc a,#$%.2x", op0); break; + case 0xa9: sprintf(t, "sbc $%.3x,$%.3x", opdp1, opdp0); break; + case 0xaa: sprintf(t, "mov1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xab: sprintf(t, "inc $%.3x", opdp0); break; + case 0xac: sprintf(t, "inc $%.4x", opw); break; + case 0xad: sprintf(t, "cmp y,#$%.2x", op0); break; + case 0xae: sprintf(t, "pop a"); break; + case 0xaf: sprintf(t, "mov (x)+,a"); break; + case 0xb0: sprintf(t, "bcs $%.4x", relb(op0, 2)); break; + case 0xb1: sprintf(t, "tcall 11"); break; + case 0xb2: sprintf(t, "clr5 $%.3x", opdp0); break; + case 0xb3: sprintf(t, "bbc5 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xb4: sprintf(t, "sbc a,$%.3x+x", opdp0); break; + case 0xb5: sprintf(t, "sbc a,$%.4x+x", opw); break; + case 0xb6: sprintf(t, "sbc a,$%.4x+y", opw); break; + case 0xb7: sprintf(t, "sbc a,($%.3x)+y", opdp0); break; + case 0xb8: sprintf(t, "sbc $%.3x,#$%.2x", opdp1, op0); break; + case 0xb9: sprintf(t, "sbc (x),(y)"); break; + case 0xba: sprintf(t, "movw ya,$%.3x", opdp0); break; + case 0xbb: sprintf(t, "inc $%.3x+x", opdp0); break; + case 0xbc: sprintf(t, "inc a"); break; + case 0xbd: sprintf(t, "mov sp,x"); break; + case 0xbe: sprintf(t, "das a"); break; + case 0xbf: sprintf(t, "mov a,(x)+"); break; + case 0xc0: sprintf(t, "di"); break; + case 0xc1: sprintf(t, "tcall 12"); break; + case 0xc2: sprintf(t, "set6 $%.3x", opdp0); break; + case 0xc3: sprintf(t, "bbs6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xc4: sprintf(t, "mov $%.3x,a", opdp0); break; + case 0xc5: sprintf(t, "mov $%.4x,a", opw); break; + case 0xc6: sprintf(t, "mov (x),a"); break; + case 0xc7: sprintf(t, "mov ($%.3x+x),a", opdp0); break; + case 0xc8: sprintf(t, "cmp x,#$%.2x", op0); break; + case 0xc9: sprintf(t, "mov $%.4x,x", opw); break; + case 0xca: sprintf(t, "mov1 $%.4x:%d,c", opw & 0x1fff, opw >> 13); break; + case 0xcb: sprintf(t, "mov $%.3x,y", opdp0); break; + case 0xcc: sprintf(t, "mov $%.4x,y", opw); break; + case 0xcd: sprintf(t, "mov x,#$%.2x", op0); break; + case 0xce: sprintf(t, "pop x"); break; + case 0xcf: sprintf(t, "mul ya"); break; + case 0xd0: sprintf(t, "bne $%.4x", relb(op0, 2)); break; + case 0xd1: sprintf(t, "tcall 13"); break; + case 0xd2: sprintf(t, "clr6 $%.3x", opdp0); break; + case 0xd3: sprintf(t, "bbc6 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xd4: sprintf(t, "mov $%.3x+x,a", opdp0); break; + case 0xd5: sprintf(t, "mov $%.4x+x,a", opw); break; + case 0xd6: sprintf(t, "mov $%.4x+y,a", opw); break; + case 0xd7: sprintf(t, "mov ($%.3x)+y,a", opdp0); break; + case 0xd8: sprintf(t, "mov $%.3x,x", opdp0); break; + case 0xd9: sprintf(t, "mov $%.3x+y,x", opdp0); break; + case 0xda: sprintf(t, "movw $%.3x,ya", opdp0); break; + case 0xdb: sprintf(t, "mov $%.3x+x,y", opdp0); break; + case 0xdc: sprintf(t, "dec y"); break; + case 0xdd: sprintf(t, "mov a,y"); break; + case 0xde: sprintf(t, "cbne $%.3x+x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xdf: sprintf(t, "daa a"); break; + case 0xe0: sprintf(t, "clrv"); break; + case 0xe1: sprintf(t, "tcall 14"); break; + case 0xe2: sprintf(t, "set7 $%.3x", opdp0); break; + case 0xe3: sprintf(t, "bbs7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xe4: sprintf(t, "mov a,$%.3x", opdp0); break; + case 0xe5: sprintf(t, "mov a,$%.4x", opw); break; + case 0xe6: sprintf(t, "mov a,(x)"); break; + case 0xe7: sprintf(t, "mov a,($%.3x+x)", opdp0); break; + case 0xe8: sprintf(t, "mov a,#$%.2x", op0); break; + case 0xe9: sprintf(t, "mov x,$%.4x", opw); break; + case 0xea: sprintf(t, "not1 c,$%.4x:%d", opw & 0x1fff, opw >> 13); break; + case 0xeb: sprintf(t, "mov y,$%.3x", opdp0); break; + case 0xec: sprintf(t, "mov y,$%.4x", opw); break; + case 0xed: sprintf(t, "notc"); break; + case 0xee: sprintf(t, "pop y"); break; + case 0xef: sprintf(t, "sleep"); break; + case 0xf0: sprintf(t, "beq $%.4x", relb(op0, 2)); break; + case 0xf1: sprintf(t, "tcall 15"); break; + case 0xf2: sprintf(t, "clr7 $%.3x", opdp0); break; + case 0xf3: sprintf(t, "bbc7 $%.3x,$%.4x", opdp0, relb(op1, 3)); break; + case 0xf4: sprintf(t, "mov a,$%.3x+x", opdp0); break; + case 0xf5: sprintf(t, "mov a,$%.4x+x", opw); break; + case 0xf6: sprintf(t, "mov a,$%.4x+y", opw); break; + case 0xf7: sprintf(t, "mov a,($%.3x)+y", opdp0); break; + case 0xf8: sprintf(t, "mov x,$%.3x", opdp0); break; + case 0xf9: sprintf(t, "mov x,$%.3x+y", opdp0); break; + case 0xfa: sprintf(t, "mov $%.3x,$%.3x", opdp1, opdp0); break; + case 0xfb: sprintf(t, "mov y,$%.3x+x", opdp0); break; + case 0xfc: sprintf(t, "inc y"); break; + case 0xfd: sprintf(t, "mov y,a"); break; + case 0xfe: sprintf(t, "dbnz y,$%.4x", relb(op0, 2)); break; + case 0xff: sprintf(t, "stop"); break; + } + + t[strlen(t)] = ' '; + strcat(s, t); + + sprintf(t, "A:%.2x X:%.2x Y:%.2x SP:01%.2x YA:%.4x ", + regs.a, regs.x, regs.y, regs.sp, (uint16)regs.ya); + strcat(s, t); + + sprintf(t, "%c%c%c%c%c%c%c%c", + regs.p.n ? 'N' : 'n', + regs.p.v ? 'V' : 'v', + regs.p.p ? 'P' : 'p', + regs.p.b ? 'B' : 'b', + regs.p.h ? 'H' : 'h', + regs.p.i ? 'I' : 'i', + regs.p.z ? 'Z' : 'z', + regs.p.c ? 'C' : 'c'); + strcat(s, t); +} diff --git a/apu/bapu/smp/iplrom.cpp b/apu/bapu/smp/iplrom.cpp new file mode 100755 index 00000000..a2ade89d --- /dev/null +++ b/apu/bapu/smp/iplrom.cpp @@ -0,0 +1,44 @@ +#ifdef SMP_CPP + +//this is the IPLROM for the S-SMP coprocessor. +//the S-SMP does not allow writing to the IPLROM. +//all writes are instead mapped to the extended +//RAM region, accessible when $f1.d7 is clear. + +const uint8 SMP::iplrom[64] = { +/*ffc0*/ 0xcd, 0xef, //mov x,#$ef +/*ffc2*/ 0xbd, //mov sp,x +/*ffc3*/ 0xe8, 0x00, //mov a,#$00 +/*ffc5*/ 0xc6, //mov (x),a +/*ffc6*/ 0x1d, //dec x +/*ffc7*/ 0xd0, 0xfc, //bne $ffc5 +/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov $f4,#$aa +/*ffcc*/ 0x8f, 0xbb, 0xf5, //mov $f5,#$bb +/*ffcf*/ 0x78, 0xcc, 0xf4, //cmp $f4,#$cc +/*ffd2*/ 0xd0, 0xfb, //bne $ffcf +/*ffd4*/ 0x2f, 0x19, //bra $ffef +/*ffd6*/ 0xeb, 0xf4, //mov y,$f4 +/*ffd8*/ 0xd0, 0xfc, //bne $ffd6 +/*ffda*/ 0x7e, 0xf4, //cmp y,$f4 +/*ffdc*/ 0xd0, 0x0b, //bne $ffe9 +/*ffde*/ 0xe4, 0xf5, //mov a,$f5 +/*ffe0*/ 0xcb, 0xf4, //mov $f4,y +/*ffe2*/ 0xd7, 0x00, //mov ($00)+y,a +/*ffe4*/ 0xfc, //inc y +/*ffe5*/ 0xd0, 0xf3, //bne $ffda +/*ffe7*/ 0xab, 0x01, //inc $01 +/*ffe9*/ 0x10, 0xef, //bpl $ffda +/*ffeb*/ 0x7e, 0xf4, //cmp y,$f4 +/*ffed*/ 0x10, 0xeb, //bpl $ffda +/*ffef*/ 0xba, 0xf6, //movw ya,$f6 +/*fff1*/ 0xda, 0x00, //movw $00,ya +/*fff3*/ 0xba, 0xf4, //movw ya,$f4 +/*fff5*/ 0xc4, 0xf4, //mov $f4,a +/*fff7*/ 0xdd, //mov a,y +/*fff8*/ 0x5d, //mov x,a +/*fff9*/ 0xd0, 0xdb, //bne $ffd6 +/*fffb*/ 0x1f, 0x00, 0x00, //jmp ($0000+x) +/*fffe*/ 0xc0, 0xff //reset vector location ($ffc0) +}; + +#endif diff --git a/apu/bapu/smp/memory.cpp b/apu/bapu/smp/memory.cpp new file mode 100755 index 00000000..aecba720 --- /dev/null +++ b/apu/bapu/smp/memory.cpp @@ -0,0 +1,130 @@ +unsigned SMP::port_read(unsigned addr) { + return apuram[0xf4 + (addr & 3)]; +} + +void SMP::port_write(unsigned addr, unsigned data) { + apuram[0xf4 + (addr & 3)] = data; +} + +unsigned SMP::mmio_read(unsigned addr) { + switch(addr) { + + case 0xf2: + return status.dsp_addr; + + case 0xf3: + return dsp.read(status.dsp_addr & 0x7f); + + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + synchronize_cpu(); + return cpu.port_read(addr); + + case 0xf8: + return status.ram00f8; + + case 0xf9: + return status.ram00f9; + + case 0xfd: { + unsigned result = timer0.stage3_ticks & 15; + timer0.stage3_ticks = 0; + return result; + } + + case 0xfe: { + unsigned result = timer1.stage3_ticks & 15; + timer1.stage3_ticks = 0; + return result; + } + + case 0xff: { + unsigned result = timer2.stage3_ticks & 15; + timer2.stage3_ticks = 0; + return result; + } + + } + + return 0x00; +} + +void SMP::mmio_write(unsigned addr, unsigned data) { + switch(addr) { + + case 0xf1: + status.iplrom_enable = data & 0x80; + + if(data & 0x30) { + synchronize_cpu(); + if(data & 0x20) { + cpu.port_write(3, 0x00); + cpu.port_write(2, 0x00); + } + if(data & 0x10) { + cpu.port_write(1, 0x00); + cpu.port_write(0, 0x00); + } + } + + if(timer2.enable == false && (data & 0x04)) { + timer2.stage2_ticks = 0; + timer2.stage3_ticks = 0; + } + timer2.enable = data & 0x04; + + if(timer1.enable == false && (data & 0x02)) { + timer1.stage2_ticks = 0; + timer1.stage3_ticks = 0; + } + timer1.enable = data & 0x02; + + if(timer0.enable == false && (data & 0x01)) { + timer0.stage2_ticks = 0; + timer0.stage3_ticks = 0; + } + timer0.enable = data & 0x01; + + break; + + case 0xf2: + status.dsp_addr = data; + break; + + case 0xf3: + if(status.dsp_addr & 0x80) break; + dsp.write(status.dsp_addr, data); + break; + + case 0xf4: + case 0xf5: + case 0xf6: + case 0xf7: + synchronize_cpu(); + port_write(addr, data); + break; + + case 0xf8: + status.ram00f8 = data; + break; + + case 0xf9: + status.ram00f9 = data; + break; + + case 0xfa: + timer0.target = data; + break; + + case 0xfb: + timer1.target = data; + break; + + case 0xfc: + timer2.target = data; + break; + + } +} diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp new file mode 100755 index 00000000..ba26d0b4 --- /dev/null +++ b/apu/bapu/smp/smp.cpp @@ -0,0 +1,154 @@ +#define CYCLE_ACCURATE + +#include + +#define SMP_CPP +namespace SNES { + +#if defined(DEBUGGER) + #include "debugger/debugger.cpp" + #include "debugger/disassembler.cpp" + SMPDebugger smp; +#else + SMP smp; +#endif + +#include "algorithms.cpp" +#include "core.cpp" +#include "iplrom.cpp" +#include "memory.cpp" +#include "timing.cpp" + +void SMP::synchronize_cpu() { + if(CPU::Threaded == true) { + //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); + } else { + while(clock >= 0) cpu.enter(); + } +} + +void SMP::synchronize_dsp() { + if(DSP::Threaded == true) { + //if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); + } else { + while(dsp.clock < 0) dsp.enter(); + } +} + +void SMP::enter() { + while(clock < 0) op_step(); +} + +void SMP::power() { +#ifdef BSNES + Processor::frequency = system.apu_frequency(); +#else + Processor::frequency = 1025600; +#endif + + Processor::clock = 0; + + timer0.target = 0; + timer1.target = 0; + timer2.target = 0; + + for(unsigned n = 0; n < 256; n++) { + cycle_table_dsp[n] = (cycle_count_table[n] * 24); + cycle_table_cpu[n] = (cycle_count_table[n] * 24) * cpu.frequency; + } + + cycle_step_cpu = 24 * cpu.frequency; + + reset(); +} + +void SMP::reset() { + for(unsigned n = 0x0000; n <= 0xffff; n++) apuram[n] = 0x00; + + opcode_number = 0; + opcode_cycle = 0; + + regs.pc = 0xffc0; + regs.sp = 0xef; + regs.a = 0x00; + regs.x = 0x00; + regs.y = 0x00; + regs.p = 0x02; + + //$00f1 + status.iplrom_enable = true; + + //$00f2 + status.dsp_addr = 0x00; + + //$00f8,$00f9 + status.ram00f8 = 0x00; + status.ram00f9 = 0x00; + + //timers + timer0.enable = timer1.enable = timer2.enable = false; + timer0.stage1_ticks = timer1.stage1_ticks = timer2.stage1_ticks = 0; + timer0.stage2_ticks = timer1.stage2_ticks = timer2.stage2_ticks = 0; + timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0; +} + +#ifdef BSNES +void SMP::serialize(serializer &s) { + Processor::serialize(s); + + s.array(apuram, 64 * 1024); + + s.integer(opcode_number); + s.integer(opcode_cycle); + + s.integer(regs.pc); + s.integer(regs.sp); + s.integer(regs.a); + s.integer(regs.x); + s.integer(regs.y); + + s.integer(regs.p.n); + s.integer(regs.p.v); + s.integer(regs.p.p); + s.integer(regs.p.b); + s.integer(regs.p.h); + s.integer(regs.p.i); + s.integer(regs.p.z); + s.integer(regs.p.c); + + s.integer(status.iplrom_enable); + + s.integer(status.dsp_addr); + + s.integer(status.ram00f8); + s.integer(status.ram00f9); + + s.integer(timer0.enable); + s.integer(timer0.target); + s.integer(timer0.stage1_ticks); + s.integer(timer0.stage2_ticks); + s.integer(timer0.stage3_ticks); + + s.integer(timer1.enable); + s.integer(timer1.target); + s.integer(timer1.stage1_ticks); + s.integer(timer1.stage2_ticks); + s.integer(timer1.stage3_ticks); + + s.integer(timer2.enable); + s.integer(timer2.target); + + s.integer(timer2.stage1_ticks); + s.integer(timer2.stage2_ticks); + s.integer(timer2.stage3_ticks); +} +#endif + +SMP::SMP() { + apuram = new uint8[64 * 1024]; +} + +SMP::~SMP() { +} + +} diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp new file mode 100755 index 00000000..be52f77a --- /dev/null +++ b/apu/bapu/smp/smp.hpp @@ -0,0 +1,124 @@ +class SMP : public Processor { +public: + static const uint8 iplrom[64]; + uint8 *apuram; + + enum { Threaded = false }; + alwaysinline void synchronize_cpu(); + alwaysinline void synchronize_dsp(); + + unsigned port_read(unsigned port); + void port_write(unsigned port, unsigned data); + + unsigned mmio_read(unsigned addr); + void mmio_write(unsigned addr, unsigned data); + + void enter(); + void power(); + void reset(); + +#ifdef BSNES + void serialize(serializer&); +#endif + SMP(); + ~SMP(); + +//private: + struct Flags { + bool n, v, p, b, h, i, z, c; + + alwaysinline operator unsigned() const { + return (n << 7) | (v << 6) | (p << 5) | (b << 4) + | (h << 3) | (i << 2) | (z << 1) | (c << 0); + }; + + alwaysinline unsigned operator=(unsigned data) { + n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; + h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; + return *this; + } + + alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } + alwaysinline unsigned operator^=(unsigned data) { return operator=(operator unsigned() ^ data); } + alwaysinline unsigned operator&=(unsigned data) { return operator=(operator unsigned() & data); } + }; + + unsigned opcode_number; + unsigned opcode_cycle; + + struct Regs { + uint16 pc; + uint8 sp; + union { + uint16 ya; +#ifndef __BIG_ENDIAN__ + struct { uint8 a, y; }; +#else + struct { uint8 y, a; }; +#endif + }; + uint8 x; + Flags p; + } regs; + + struct Status { + //$00f1 + bool iplrom_enable; + + //$00f2 + unsigned dsp_addr; + + //$00f8,$00f9 + unsigned ram00f8; + unsigned ram00f9; + } status; + + template + struct Timer { + bool enable; + uint8 target; + uint8 stage1_ticks; + uint8 stage2_ticks; + uint8 stage3_ticks; + + void tick(); + void tick(unsigned clocks); + }; + + Timer<128> timer0; + Timer<128> timer1; + Timer< 16> timer2; + + void tick(); + alwaysinline void op_io(); + debugvirtual alwaysinline uint8 op_read(uint16 addr); + debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); + debugvirtual alwaysinline void op_step(); + static const unsigned cycle_count_table[256]; + uint64 cycle_table_cpu[256]; + unsigned cycle_table_dsp[256]; + uint64 cycle_step_cpu; + + uint8 op_adc (uint8 x, uint8 y); + uint16 op_addw(uint16 x, uint16 y); + uint8 op_and (uint8 x, uint8 y); + uint8 op_cmp (uint8 x, uint8 y); + uint16 op_cmpw(uint16 x, uint16 y); + uint8 op_eor (uint8 x, uint8 y); + uint8 op_inc (uint8 x); + uint8 op_dec (uint8 x); + uint8 op_or (uint8 x, uint8 y); + uint8 op_sbc (uint8 x, uint8 y); + uint16 op_subw(uint16 x, uint16 y); + uint8 op_asl (uint8 x); + uint8 op_lsr (uint8 x); + uint8 op_rol (uint8 x); + uint8 op_ror (uint8 x); +}; + +#if defined(DEBUGGER) + #include "debugger/debugger.hpp" + extern SMPDebugger smp; +#else + extern SMP smp; +#endif diff --git a/apu/bapu/smp/timing.cpp b/apu/bapu/smp/timing.cpp new file mode 100755 index 00000000..d278f6f4 --- /dev/null +++ b/apu/bapu/smp/timing.cpp @@ -0,0 +1,26 @@ +template +void SMP::Timer::tick() { + if(++stage1_ticks < cycle_frequency) return; + + stage1_ticks = 0; + if(enable == false) return; + + if(++stage2_ticks != target) return; + + stage2_ticks = 0; + stage3_ticks = (stage3_ticks + 1) & 15; +} + +template +void SMP::Timer::tick(unsigned clocks) { + stage1_ticks += clocks; + if(stage1_ticks < cycle_frequency) return; + + stage1_ticks -= cycle_frequency; + if(enable == false) return; + + if(++stage2_ticks != target) return; + + stage2_ticks = 0; + stage3_ticks = (stage3_ticks + 1) & 15; +} diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp new file mode 100755 index 00000000..47b687ff --- /dev/null +++ b/apu/bapu/snes/snes.hpp @@ -0,0 +1,45 @@ +#ifndef __SNES_HPP +#define __SNES_HPP + +#include "snes9x.h" + +#define alwaysinline inline +#define debugvirtual + +namespace SNES +{ + +struct Processor +{ + unsigned frequency; + int64 clock; +}; + +class CPU +{ +public: + enum { Threaded = false }; + int frequency; + + void enter () + { + } + + void port_write (uint8 port, uint8 data) + { + } + + uint8 port_read (uint8 port) + { + return 0; + } +}; + +extern CPU cpu; + +#include "smp/smp.hpp" +#include "dsp/dsp.hpp" + +} /* namespace SNES */ + +#endif diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 14d99899..4ec45d06 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -8,7 +8,7 @@ snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti endif noinst_LIBRARIES = -INCLUDES = -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" +INCLUDES = -I../apu/bapu -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" CLEANFILES = \ src/gtk_snes9x_ui.cpp \ @@ -123,8 +123,14 @@ snes9x_gtk_SOURCES += \ ../apu/SNES_SPC.cpp \ ../apu/SNES_SPC_misc.cpp \ ../apu/SNES_SPC_state.cpp \ - ../apu/SPC_DSP.cpp \ ../apu/SPC_Filter.cpp + +# Byuu's APU +snes9x_gtk_SOURCES += \ + ../apu/bapu/dsp/dsp.cpp \ + ../apu/bapu/dsp/serialization.cpp \ + ../apu/bapu/dsp/SPC_DSP.cpp \ + ../apu/bapu/smp/smp.cpp # DSP snes9x_gtk_SOURCES += \ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index f7713978..f58d934f 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -221,7 +221,6 @@ event_motion_notify (GtkWidget *widget, gpointer user_data) { Snes9xWindow *window = (Snes9xWindow *) user_data; - int c_width, c_height; if (!window->config->rom_loaded || window->last_width <= 0 || @@ -230,9 +229,6 @@ event_motion_notify (GtkWidget *widget, return FALSE; } - c_width = window->get_width (); - c_height = window->get_height (); - window->mouse_loc_x = (uint16) ((int) (event->x) - window->mouse_region_x) * 256 / (window->mouse_region_width <= 0 ? 1 : window->mouse_region_width); From 10a521e39c64ed51580e0421f49e5079c173d536 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 18 Jun 2011 05:31:44 -0500 Subject: [PATCH 011/130] byuu APU now being used. Nothing works yet. Sync is broken, but the new SMP will handle ratios now. Save states need to be redone without serializer. No SPC dumping. --- apu/SNES_SPC.cpp | 564 ------------------ apu/SNES_SPC.h | 316 ----------- apu/SNES_SPC_misc.cpp | 855 ---------------------------- apu/SNES_SPC_state.cpp | 142 ----- apu/SPC_CPU.h | 1228 ---------------------------------------- apu/SPC_DSP.cpp | 1072 ----------------------------------- apu/SPC_DSP.h | 319 ----------- apu/SPC_Filter.cpp | 68 --- apu/SPC_Filter.h | 47 -- apu/apu.cpp | 101 ++-- apu/apu.h | 3 - apu/bapu/dsp/dsp.cpp | 8 - apu/bapu/dsp/dsp.hpp | 4 +- apu/bapu/smp/smp.cpp | 2 - apu/bapu/snes/snes.hpp | 2 + apu/blargg_common.h | 186 ------ apu/blargg_config.h | 24 - apu/blargg_endian.h | 185 ------ apu/blargg_source.h | 100 ---- apu/license.txt | 504 ----------------- apu/linear_resampler.h | 115 ---- gtk/Makefile.am | 6 +- snapshot.cpp | 14 +- 23 files changed, 46 insertions(+), 5819 deletions(-) delete mode 100644 apu/SNES_SPC.cpp delete mode 100644 apu/SNES_SPC.h delete mode 100644 apu/SNES_SPC_misc.cpp delete mode 100644 apu/SNES_SPC_state.cpp delete mode 100644 apu/SPC_CPU.h delete mode 100644 apu/SPC_DSP.cpp delete mode 100644 apu/SPC_DSP.h delete mode 100644 apu/SPC_Filter.cpp delete mode 100644 apu/SPC_Filter.h delete mode 100644 apu/blargg_common.h delete mode 100644 apu/blargg_config.h delete mode 100644 apu/blargg_endian.h delete mode 100644 apu/blargg_source.h delete mode 100644 apu/license.txt delete mode 100644 apu/linear_resampler.h diff --git a/apu/SNES_SPC.cpp b/apu/SNES_SPC.cpp deleted file mode 100644 index 567b7ddc..00000000 --- a/apu/SNES_SPC.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// Core SPC emulation: CPU, timers, SMP registers, memory - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - -// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which -// do crazy echo buffer accesses. -#ifndef SPC_MORE_ACCURACY - #define SPC_MORE_ACCURACY 0 -#endif - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - - -//// Timers - -#if SPC_DISABLE_TEMPO - #define TIMER_DIV( t, n ) ((n) >> t->prescaler) - #define TIMER_MUL( t, n ) ((n) << t->prescaler) -#else - #define TIMER_DIV( t, n ) ((n) / t->prescaler) - #define TIMER_MUL( t, n ) ((n) * t->prescaler) -#endif - -SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time ) -{ - int elapsed = TIMER_DIV( t, time - t->next_time ) + 1; - t->next_time += TIMER_MUL( t, elapsed ); - - if ( t->enabled ) - { - int remain = IF_0_THEN_256( t->period - t->divider ); - int divider = t->divider + elapsed; - int over = elapsed - remain; - if ( over >= 0 ) - { - int n = over / t->period; - t->counter = (t->counter + 1 + n) & 0x0F; - divider = over - n * t->period; - } - t->divider = (uint8_t) divider; - } - return t; -} - -inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time ) -{ - if ( time >= t->next_time ) - t = run_timer_( t, time ); - return t; -} - - -//// ROM - -void SNES_SPC::enable_rom( int enable ) -{ - if ( m.rom_enabled != enable ) - { - m.rom_enabled = dsp.rom_enabled = enable; - if ( enable ) - memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram ); - memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size ); - // TODO: ROM can still get overwritten when DSP writes to echo buffer - } -} - - -//// DSP - -#if SPC_LESS_ACCURATE - int const max_reg_time = 29; - - signed char const SNES_SPC::reg_times_ [256] = - { - -1, 0,-11,-10,-15,-11, -2, -2, 4, 3, 14, 14, 26, 26, 14, 22, - 2, 3, 0, 1,-12, 0, 1, 1, 7, 6, 14, 14, 27, 14, 14, 23, - 5, 6, 3, 4, -1, 3, 4, 4, 10, 9, 14, 14, 26, -5, 14, 23, - 8, 9, 6, 7, 2, 6, 7, 7, 13, 12, 14, 14, 27, -4, 14, 24, - 11, 12, 9, 10, 5, 9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24, - 14, 15, 12, 13, 8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24, - 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25, - 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25, - - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - }; - - #define RUN_DSP( time, offset ) \ - int count = (time) - (offset) - m.dsp_time;\ - if ( count >= 0 )\ - {\ - int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\ - m.dsp_time += clock_count;\ - dsp.run( clock_count );\ - } -#else - #define RUN_DSP( time, offset ) \ - {\ - int count = (time) - m.dsp_time;\ - if ( !SPC_MORE_ACCURACY || count )\ - {\ - assert( count > 0 );\ - m.dsp_time = (time);\ - dsp.run( count );\ - }\ - } -#endif - -int SNES_SPC::dsp_read( rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] ); - - int result = dsp.read( REGS [r_dspaddr] & 0x7F ); - - #ifdef SPC_DSP_READ_HOOK - SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result ); - #endif - - return result; -} - -inline void SNES_SPC::dsp_write( int data, rel_time_t time ) -{ - RUN_DSP( time, reg_times [REGS [r_dspaddr]] ) - #if SPC_LESS_ACCURATE - else if ( m.dsp_time == skipping_time ) - { - int r = REGS [r_dspaddr]; - if ( r == SPC_DSP::r_kon ) - m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff ); - - if ( r == SPC_DSP::r_koff ) - { - m.skipped_koff |= data; - m.skipped_kon &= ~data; - } - } - #endif - - #ifdef SPC_DSP_WRITE_HOOK - SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data ); - #endif - - if ( REGS [r_dspaddr] <= 0x7F ) - dsp.write( REGS [r_dspaddr], data ); - else if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to DSP register > $7F\n" ); -} - - -//// Memory access extras - -#if SPC_MORE_ACCURACY - #define MEM_ACCESS( time, addr ) \ - {\ - if ( time >= m.dsp_time )\ - {\ - RUN_DSP( time, max_reg_time );\ - }\ - } -#elif !defined (NDEBUG) - // Debug-only check for read/write within echo buffer, since this might result in - // inaccurate emulation due to the DSP not being caught up to the present. - - bool SNES_SPC::check_echo_access( int addr ) - { - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int start = 0x100 * dsp.read( SPC_DSP::r_esa ); - int size = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - int end = start + (size ? size : 4); - if ( start <= addr && addr < end ) - { - if ( !m.echo_accessed ) - { - m.echo_accessed = 1; - return true; - } - } - } - return false; - } - - #define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) ); -#else - #define MEM_ACCESS( time, addr ) -#endif - - -//// CPU write - -#if SPC_MORE_ACCURACY -static unsigned char const glitch_probs [3] [256] = -{ - 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, - 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, - 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, - 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, - 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, - 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, - 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, - 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, - 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, - 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, - 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, - 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, - 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, - 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, - 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, - 0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, - - 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, - 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, - 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, - 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, - 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, - 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, - 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, - 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, - 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, - 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, - 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, - 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, - 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, - 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, - 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, - 0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, - - 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, - 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, - 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, - 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, - 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, - 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, - 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, - 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, - 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, - 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, - 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, - 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, - 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, - 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, - 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, - 0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, -}; -#endif - -// divided into multiple functions to keep rarely-used functionality separate -// so often-used functionality can be optimized better by compiler - -// If write isn't preceded by read, data has this added to it -int const no_read_before_write = 0x2000; - -void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) -{ - switch ( addr ) - { - case r_t0target: - case r_t1target: - case r_t2target: { - Timer* t = &m.timers [addr - r_t0target]; - int period = IF_0_THEN_256( data ); - if ( t->period != period ) - { - t = run_timer( t, time ); - #if SPC_MORE_ACCURACY - // Insane behavior when target is written just after counter is - // clocked and counter matches new period and new period isn't 1, 2, 4, or 8 - if ( t->divider == (period & 0xFF) && - t->next_time == time + TIMER_MUL( t, 1 ) && - ((period - 1) | ~0x0F) & period ) - { - //dprintf( "SPC pathological timer target write\n" ); - - // If the period is 3, 5, or 9, there's a probability this behavior won't occur, - // based on the previous period - int prob = 0xFF; - int old_period = t->period & 0xFF; - if ( period == 3 ) prob = glitch_probs [0] [old_period]; - if ( period == 5 ) prob = glitch_probs [1] [old_period]; - if ( period == 9 ) prob = glitch_probs [2] [old_period]; - - // The glitch suppresses incrementing of one of the counter bits, based on - // the lowest set bit in the new period - int b = 1; - while ( !(period & b) ) - b <<= 1; - - if ( (rand() >> 4 & 0xFF) <= prob ) - t->divider = (t->divider - b) & 0xFF; - } - #endif - t->period = period; - } - break; - } - - case r_t0out: - case r_t1out: - case r_t2out: - if ( !SPC_MORE_ACCURACY ) - dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); - - if ( data < no_read_before_write / 2 ) - run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; - break; - - // Registers that act like RAM - case 0x8: - case 0x9: - REGS_IN [addr] = (uint8_t) data; - break; - - case r_test: - if ( (uint8_t) data != 0x0A ) - dprintf( "SPC wrote to test register\n" ); - break; - - case r_control: - // port clears - if ( data & 0x10 ) - { - REGS_IN [r_cpuio0] = 0; - REGS_IN [r_cpuio1] = 0; - } - if ( data & 0x20 ) - { - REGS_IN [r_cpuio2] = 0; - REGS_IN [r_cpuio3] = 0; - } - - // timers - { - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - int enabled = data >> i & 1; - if ( t->enabled != enabled ) - { - t = run_timer( t, time ); - t->enabled = enabled; - if ( enabled ) - { - t->divider = 0; - t->counter = 0; - } - } - } - } - enable_rom( data & 0x80 ); - break; - } -} - -void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr ) -{ - if ( addr == r_dspdata ) // 99% - dsp_write( data, time ); - else - cpu_write_smp_reg_( data, time, addr ); -} - -void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time ) -{ - if ( i < rom_size ) - { - m.hi_ram [i] = (uint8_t) data; - if ( m.rom_enabled ) - RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM - } - else - { - assert( *(&(RAM [0]) + i + rom_addr) == (uint8_t) data ); - *(&(RAM [0]) + i + rom_addr) = cpu_pad_fill; // restore overwritten padding - cpu_write( data, i + rom_addr - 0x10000, time ); - } -} - -int const bits_in_int = CHAR_BIT * sizeof (int); - -void SNES_SPC::cpu_write( int data, int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - RAM [addr] = (uint8_t) data; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 64% - { - // $F0-$FF - if ( reg < reg_count ) // 87% - { - REGS [reg] = (uint8_t) data; - - // Ports - #ifdef SPC_PORT_WRITE_HOOK - if ( (unsigned) (reg - r_cpuio0) < port_count ) - SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0), - (uint8_t) data, ®S [r_cpuio0] ); - #endif - - // Registers other than $F2 and $F4-$F7 - //if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) - // TODO: this is a bit on the fragile side - if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36% - cpu_write_smp_reg( data, time, reg ); - } - // High mem/address wrap-around - else - { - reg -= rom_addr - 0xF0; - if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around - cpu_write_high( data, reg, time ); - } - } -} - - -//// CPU read - -inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time ) -{ - int result = REGS_IN [reg]; - reg -= r_dspaddr; - // DSP addr and data - if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3 - { - result = REGS [r_dspaddr]; - if ( (unsigned) reg == 1 ) - result = dsp_read( time ); // 0xF3 - } - return result; -} - -int SNES_SPC::cpu_read( int addr, rel_time_t time ) -{ - MEM_ACCESS( time, addr ) - - // RAM - int result = RAM [addr]; - int reg = addr - 0xF0; - if ( reg >= 0 ) // 40% - { - reg -= 0x10; - if ( (unsigned) reg >= 0xFF00 ) // 21% - { - reg += 0x10 - r_t0out; - - // Timers - if ( (unsigned) reg < timer_count ) // 90% - { - Timer* t = &m.timers [reg]; - if ( time >= t->next_time ) - t = run_timer_( t, time ); - result = t->counter; - t->counter = 0; - } - // Other registers - else if ( reg < 0 ) // 10% - { - result = cpu_read_smp_reg( reg + r_t0out, time ); - } - else // 1% - { - assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 ); - result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time ); - } - } - } - - return result; -} - - -//// Run - -// Prefix and suffix for CPU emulator function -#define SPC_CPU_RUN_FUNC \ -BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ -{\ - rel_time_t rel_time = m.spc_time - end_time;\ - /*assert( rel_time <= 0 );*/\ - m.spc_time = end_time;\ - m.dsp_time += rel_time;\ - m.timers [0].next_time += rel_time;\ - m.timers [1].next_time += rel_time;\ - m.timers [2].next_time += rel_time; - -#define SPC_CPU_RUN_FUNC_END \ - m.spc_time += rel_time;\ - m.dsp_time -= rel_time;\ - m.timers [0].next_time -= rel_time;\ - m.timers [1].next_time -= rel_time;\ - m.timers [2].next_time -= rel_time;\ - /*assert( m.spc_time >= end_time );*/\ - return ®S [r_cpuio0];\ -} - -int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks - -void SNES_SPC::end_frame( time_t end_time ) -{ - // Catch CPU up to as close to end as possible. If final instruction - // would exceed end, does NOT execute it and leaves m.spc_time < end. - if ( end_time > m.spc_time ) - run_until_( end_time ); - - m.spc_time -= end_time; - m.extra_clocks += end_time; - - // Greatest number of clocks early that emulation can stop early due to - // not being able to execute current instruction without going over - // allowed time. - assert( -cpu_lag_max <= m.spc_time && m.spc_time <= cpu_lag_max ); - - // Catch timers up to CPU - for ( int i = 0; i < timer_count; i++ ) - run_timer( &m.timers [i], 0 ); - - // Catch DSP up to CPU - if ( m.dsp_time < 0 ) - { - RUN_DSP( 0, max_reg_time ); - } - - // Save any extra samples beyond what should be generated - if ( m.buf_begin ) - save_extra(); -} - -// Inclusion here allows static memory access functions and better optimization -#include "SPC_CPU.h" diff --git a/apu/SNES_SPC.h b/apu/SNES_SPC.h deleted file mode 100644 index baf90063..00000000 --- a/apu/SNES_SPC.h +++ /dev/null @@ -1,316 +0,0 @@ -// SNES SPC-700 APU emulator - -// snes_spc 0.9.0 -#ifndef SNES_SPC_H -#define SNES_SPC_H - -#include "SPC_DSP.h" -#include "blargg_endian.h" - -#ifdef DEBUGGER -#include "snes9x.h" -#include "display.h" -#include "debug.h" -#endif - -struct SNES_SPC { -public: - typedef BOOST::uint8_t uint8_t; - - // Must be called once before using - blargg_err_t init(); - - // Sample pairs generated per second - enum { sample_rate = 32000 }; - -// Emulator use - - // Sets IPL ROM data. Library does not include ROM data. Most SPC music files - // don't need ROM, but a full emulator must provide this. - enum { rom_size = 0x40 }; - void init_rom( uint8_t const rom [rom_size] ); - - // Sets destination for output samples - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since last set - int sample_count() const; - - // Resets SPC to power-on state. This resets your output buffer, so you must - // call set_output() after this. - void reset(); - - // Emulates pressing reset switch on SNES. This resets your output buffer, so - // you must call set_output() after this. - void soft_reset(); - - // 1024000 SPC clocks per second, sample pair every 32 clocks - typedef int time_t; - enum { clock_rate = 1024000 }; - enum { clocks_per_sample = 32 }; - - // Emulated port read/write at specified time - enum { port_count = 4 }; - int read_port ( time_t, int port ); - void write_port( time_t, int port, int data ); - - // Runs SPC to end_time and starts a new time frame at 0 - void end_frame( time_t end_time ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - - // If true, prevents channels and global volumes from being phase-negated. - // Only supported by fast DSP. - void disable_surround( bool disable = true ); - - // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. - enum { tempo_unit = 0x100 }; - void set_tempo( int ); - -// SPC music files - - // Loads SPC data into emulator - enum { spc_min_file_size = 0x10180 }; - enum { spc_file_size = 0x10200 }; - blargg_err_t load_spc( void const* in, long size ); - - // Clears echo region. Useful after loading an SPC as many have garbage in echo. - void clear_echo(); - - // Plays for count samples and write samples to out. Discards samples if out - // is NULL. Count must be a multiple of 2 since output is stereo. - blargg_err_t play( int count, sample_t* out ); - - // Skips count samples. Several times faster than play() when using fast DSP. - blargg_err_t skip( int count ); - -// State save/load (only available with accurate DSP) - -#if !SPC_NO_COPY_STATE_FUNCS - // Saves/loads state - enum { state_size = 68 * 1024L }; // maximum space needed when saving - typedef SPC_DSP::copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Writes minimal header to spc_out - static void init_header( void* spc_out ); - - // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. - // Does not set up SPC header; use init_header() for that. - void save_spc( void* spc_out ); - - // Returns true if new key-on events occurred since last check. Useful for - // trimming silence while saving an SPC. - bool check_kon(); -#endif - -//// Snes9x Accessor - - void spc_allow_time_overflow( bool ); - - void dsp_set_spc_snapshot_callback( void (*callback) (void) ); - void dsp_dump_spc_snapshot( void ); - void dsp_set_stereo_switch( int ); - uint8_t dsp_reg_value( int, int ); - int dsp_envx_value( int ); - -//// Snes9x Debugger - -#ifdef DEBUGGER - void debug_toggle_trace( void ); - bool debug_is_enabled( void ); - void debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); - void debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int ); - void debug_io_print( char * ); -#endif - -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::uint16_t uint16_t; - - // Time relative to m_spc_time. Speeds up code a bit by eliminating need to - // constantly add m_spc_time to time from CPU. CPU uses time that ends at - // 0 to eliminate reloading end time every instruction. It pays off. - typedef int rel_time_t; - - struct Timer - { - rel_time_t next_time; // time of next event - int prescaler; - int period; - int divider; - int enabled; - int counter; - }; - enum { reg_count = 0x10 }; - enum { timer_count = 3 }; - enum { extra_size = SPC_DSP::extra_size }; - - enum { signature_size = 35 }; - -private: - SPC_DSP dsp; - - #if SPC_LESS_ACCURATE - static signed char const reg_times_ [256]; - signed char reg_times [256]; - #endif - - struct state_t - { - Timer timers [timer_count]; - - uint8_t smp_regs [2] [reg_count]; - - struct - { - int pc; - int a; - int x; - int y; - int psw; - int sp; - } cpu_regs; - - rel_time_t dsp_time; - time_t spc_time; - bool echo_accessed; - - int tempo; - int skipped_kon; - int skipped_koff; - const char* cpu_error; - - int extra_clocks; - sample_t* buf_begin; - sample_t const* buf_end; - sample_t* extra_pos; - sample_t extra_buf [extra_size]; - - int rom_enabled; - uint8_t rom [rom_size]; - uint8_t hi_ram [rom_size]; - - unsigned char cycle_table [256]; - - struct - { - // padding to neutralize address overflow - union { - uint8_t padding1 [0x100]; - uint16_t align; // makes compiler align data for 16-bit access - } padding1 [1]; - uint8_t ram [0x10000]; - uint8_t padding2 [0x100]; - } ram; - }; - state_t m; - - enum { rom_addr = 0xFFC0 }; - - enum { skipping_time = 127 }; - - // Value that padding should be filled with - enum { cpu_pad_fill = 0xFF }; - - enum { - r_test = 0x0, r_control = 0x1, - r_dspaddr = 0x2, r_dspdata = 0x3, - r_cpuio0 = 0x4, r_cpuio1 = 0x5, - r_cpuio2 = 0x6, r_cpuio3 = 0x7, - r_f8 = 0x8, r_f9 = 0x9, - r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC, - r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF - }; - - void timers_loaded(); - void enable_rom( int enable ); - void reset_buf(); - void save_extra(); - void load_regs( uint8_t const in [reg_count] ); - void ram_loaded(); - void regs_loaded(); - void reset_time_regs(); - void reset_common( int timer_counter_init ); - - Timer* run_timer_ ( Timer* t, rel_time_t ); - Timer* run_timer ( Timer* t, rel_time_t ); - int dsp_read ( rel_time_t ); - void dsp_write ( int data, rel_time_t ); - void cpu_write_smp_reg_( int data, rel_time_t, int addr ); - void cpu_write_smp_reg ( int data, rel_time_t, int addr ); - void cpu_write_high ( int data, int i, rel_time_t ); - void cpu_write ( int data, int addr, rel_time_t ); - int cpu_read_smp_reg ( int i, rel_time_t ); - int cpu_read ( int addr, rel_time_t ); - unsigned CPU_mem_bit ( uint8_t const* pc, rel_time_t ); - - bool check_echo_access ( int addr ); - uint8_t* run_until_( time_t end_time ); - - struct spc_file_t - { - char signature [signature_size]; - uint8_t has_id666; - uint8_t version; - uint8_t pcl, pch; - uint8_t a; - uint8_t x; - uint8_t y; - uint8_t psw; - uint8_t sp; - char text [212]; - uint8_t ram [0x10000]; - uint8_t dsp [128]; - uint8_t unused [0x40]; - uint8_t ipl_rom [0x40]; - }; - - static char const signature [signature_size + 1]; - - void save_regs( uint8_t out [reg_count] ); - -// Snes9x timing hack - bool allow_time_overflow; -// Snes9x debugger -#ifdef DEBUGGER - FILE *apu_trace; - bool debug_trace; -#endif -}; - -#include - -inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; } - -inline int SNES_SPC::read_port( time_t t, int port ) -{ - assert( (unsigned) port < port_count ); - return run_until_( t ) [port]; -} - -inline void SNES_SPC::write_port( time_t t, int port, int data ) -{ - assert( (unsigned) port < port_count ); - run_until_( t ) [0x10 + port] = data; - m.ram.ram [0xF4 + port] = data; -} - -inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); } - -inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); } - -#if !SPC_NO_COPY_STATE_FUNCS -inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } -#endif - -inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; } - -#endif diff --git a/apu/SNES_SPC_misc.cpp b/apu/SNES_SPC_misc.cpp deleted file mode 100644 index 078120d2..00000000 --- a/apu/SNES_SPC_misc.cpp +++ /dev/null @@ -1,855 +0,0 @@ -// SPC emulation support: init, sample buffering, reset, SPC loading - -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SNES_SPC.h" - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -// (n ? n : 256) -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) - - -//// Init - -blargg_err_t SNES_SPC::init() -{ - memset( &m, 0, sizeof m ); - dsp.init( RAM ); - - m.tempo = tempo_unit; - - // Most SPC music doesn't need ROM, and almost all the rest only rely - // on these two bytes - m.rom [0x3E] = 0xFF; - m.rom [0x3F] = 0xC0; - - static unsigned char const cycle_table [128] = - {// 01 23 45 67 89 AB CD EF - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1 - 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2 - 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4 - 0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5 - 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7 - 0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8 - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9 - 0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A - 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B - 0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C - 0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D - 0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E - 0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F - }; - - // unpack cycle table - for ( int i = 0; i < 128; i++ ) - { - int n = cycle_table [i]; - m.cycle_table [i * 2 + 0] = n >> 4; - m.cycle_table [i * 2 + 1] = n & 0x0F; - } - - allow_time_overflow = false; - - dsp.rom = m.rom; - dsp.hi_ram = m.hi_ram; - -#ifdef DEBUGGER - apu_trace = NULL; - debug_trace = false; -#endif - - #if SPC_LESS_ACCURATE - memcpy( reg_times, reg_times_, sizeof reg_times ); - #endif - - reset(); - return 0; -} - -void SNES_SPC::init_rom( uint8_t const in [rom_size] ) -{ - memcpy( m.rom, in, sizeof m.rom ); -} - -void SNES_SPC::set_tempo( int t ) -{ - m.tempo = t; - int const timer2_shift = 4; // 64 kHz - int const other_shift = 3; // 8 kHz - - #if SPC_DISABLE_TEMPO - m.timers [2].prescaler = timer2_shift; - m.timers [1].prescaler = timer2_shift + other_shift; - m.timers [0].prescaler = timer2_shift + other_shift; - #else - if ( !t ) - t = 1; - int const timer2_rate = 1 << timer2_shift; - int rate = (timer2_rate * tempo_unit + (t >> 1)) / t; - if ( rate < timer2_rate / 4 ) - rate = timer2_rate / 4; // max 4x tempo - m.timers [2].prescaler = rate; - m.timers [1].prescaler = rate << other_shift; - m.timers [0].prescaler = rate << other_shift; - #endif -} - -// Timer registers have been loaded. Applies these to the timers. Does not -// reset timer prescalers or dividers. -void SNES_SPC::timers_loaded() -{ - int i; - for ( i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - t->counter = REGS_IN [r_t0out + i] & 0x0F; - } - - set_tempo( m.tempo ); -} - -// Loads registers from unified 16-byte format -void SNES_SPC::load_regs( uint8_t const in [reg_count] ) -{ - memcpy( REGS, in, reg_count ); - memcpy( REGS_IN, REGS, reg_count ); - - // These always read back as 0 - REGS_IN [r_test ] = 0; - REGS_IN [r_control ] = 0; - REGS_IN [r_t0target] = 0; - REGS_IN [r_t1target] = 0; - REGS_IN [r_t2target] = 0; -} - -// RAM was just loaded from SPC, with $F0-$FF containing SMP registers -// and timer counts. Copies these to proper registers. -void SNES_SPC::ram_loaded() -{ - m.rom_enabled = dsp.rom_enabled = 0; - load_regs( &RAM [0xF0] ); - - // Put STOP instruction around memory to catch PC underflow/overflow - memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 ); - memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 ); -} - -// Registers were just loaded. Applies these new values. -void SNES_SPC::regs_loaded() -{ - enable_rom( REGS [r_control] & 0x80 ); - timers_loaded(); -} - -void SNES_SPC::reset_time_regs() -{ - m.cpu_error = 0; - m.echo_accessed = 0; - m.spc_time = 0; - m.dsp_time = 0; - #if SPC_LESS_ACCURATE - m.dsp_time = clocks_per_sample + 1; - #endif - - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->next_time = 1; - t->divider = 0; - } - - regs_loaded(); - - m.extra_clocks = 0; - reset_buf(); -} - -void SNES_SPC::reset_common( int timer_counter_init ) -{ - int i; - for ( i = 0; i < timer_count; i++ ) - REGS_IN [r_t0out + i] = timer_counter_init; - - // Run IPL ROM - memset( &m.cpu_regs, 0, sizeof m.cpu_regs ); - m.cpu_regs.pc = rom_addr; - - REGS [r_test ] = 0x0A; - REGS [r_control] = 0xB0; // ROM enabled, clear ports - for ( i = 0; i < port_count; i++ ) - REGS_IN [r_cpuio0 + i] = 0; - - reset_time_regs(); -} - -void SNES_SPC::soft_reset() -{ - reset_common( 0 ); - dsp.soft_reset(); -} - -void SNES_SPC::reset() -{ - m.cpu_regs.pc = 0xFFC0; - m.cpu_regs.a = 0x00; - m.cpu_regs.x = 0x00; - m.cpu_regs.y = 0x00; - m.cpu_regs.psw = 0x02; - m.cpu_regs.sp = 0xEF; - memset( RAM, 0x00, 0x10000 ); - ram_loaded(); - reset_common( 0x0F ); - dsp.reset(); -} - -char const SNES_SPC::signature [signature_size + 1] = - "SNES-SPC700 Sound File Data v0.30\x1A\x1A"; - -blargg_err_t SNES_SPC::load_spc( void const* data, long size ) -{ - spc_file_t const* const spc = (spc_file_t const*) data; - - // be sure compiler didn't insert any padding into fle_t - assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); - - // Check signature and file size - if ( size < signature_size || memcmp( spc, signature, 27 ) ) - return "Not an SPC file"; - - if ( size < spc_min_file_size ) - return "Corrupt SPC file"; - - // CPU registers - m.cpu_regs.pc = spc->pch * 0x100 + spc->pcl; - m.cpu_regs.a = spc->a; - m.cpu_regs.x = spc->x; - m.cpu_regs.y = spc->y; - m.cpu_regs.psw = spc->psw; - m.cpu_regs.sp = spc->sp; - - // RAM and registers - memcpy( RAM, spc->ram, 0x10000 ); - ram_loaded(); - - // DSP registers - dsp.load( spc->dsp ); - - reset_time_regs(); - - return 0; -} - -void SNES_SPC::clear_echo() -{ - if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) - { - int addr = 0x100 * dsp.read( SPC_DSP::r_esa ); - int end = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); - if ( end > 0x10000 ) - end = 0x10000; - memset( &RAM [addr], 0xFF, end - addr ); - } -} - - -//// Sample output - -void SNES_SPC::reset_buf() -{ - // Start with half extra buffer of silence - sample_t* out = m.extra_buf; - while ( out < &m.extra_buf [extra_size / 2] ) - *out++ = 0; - - m.extra_pos = out; - m.buf_begin = 0; - - dsp.set_output( 0, 0 ); -} - -void SNES_SPC::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // size must be even - - m.extra_clocks &= clocks_per_sample - 1; - if ( out ) - { - sample_t const* out_end = out + size; - m.buf_begin = out; - m.buf_end = out_end; - - // Copy extra to output - sample_t const* in = m.extra_buf; - while ( in < m.extra_pos && out < out_end ) - *out++ = *in++; - - // Handle output being full already - if ( out >= out_end ) - { - // Have DSP write to remaining extra space - out = dsp.extra(); - out_end = &dsp.extra() [extra_size]; - - // Copy any remaining extra samples as if DSP wrote them - while ( in < m.extra_pos ) - *out++ = *in++; - assert( out <= out_end ); - } - - dsp.set_output( out, out_end - out ); - } - else - { - reset_buf(); - } -} - -void SNES_SPC::save_extra() -{ - // Get end pointers - sample_t const* main_end = m.buf_end; // end of data written to buf - sample_t const* dsp_end = dsp.out_pos(); // end of data written to dsp.extra() - if ( m.buf_begin <= dsp_end && dsp_end <= main_end ) - { - main_end = dsp_end; - dsp_end = dsp.extra(); // nothing in DSP's extra - } - - // Copy any extra samples at these ends into extra_buf - sample_t* out = m.extra_buf; - sample_t const* in; - for ( in = m.buf_begin + sample_count(); in < main_end; in++ ) - *out++ = *in; - for ( in = dsp.extra(); in < dsp_end ; in++ ) - *out++ = *in; - - m.extra_pos = out; - assert( out <= &m.extra_buf [extra_size] ); -} - -blargg_err_t SNES_SPC::play( int count, sample_t* out ) -{ - require( (count & 1) == 0 ); // must be even - if ( count ) - { - set_output( out, count ); - end_frame( count * (clocks_per_sample / 2) ); - } - - const char* err = m.cpu_error; - m.cpu_error = 0; - return err; -} - -blargg_err_t SNES_SPC::skip( int count ) -{ - #if SPC_LESS_ACCURATE - if ( count > 2 * sample_rate * 2 ) - { - set_output( 0, 0 ); - - // Skip a multiple of 4 samples - time_t end = count; - count = (count & 3) + 1 * sample_rate * 2; - end = (end - count) * (clocks_per_sample / 2); - - m.skipped_kon = 0; - m.skipped_koff = 0; - - // Preserve DSP and timer synchronization - // TODO: verify that this really preserves it - int old_dsp_time = m.dsp_time + m.spc_time; - m.dsp_time = end - m.spc_time + skipping_time; - end_frame( end ); - m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; - - dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); - dsp.write( SPC_DSP::r_kon , m.skipped_kon ); - clear_echo(); - } - #endif - - return play( count, 0 ); -} - -//// Snes9x Accessor - -void SNES_SPC::dsp_set_spc_snapshot_callback( void (*callback) (void) ) -{ - dsp.set_spc_snapshot_callback( callback ); -} - -void SNES_SPC::dsp_dump_spc_snapshot( void ) -{ - dsp.dump_spc_snapshot(); -} - -void SNES_SPC::dsp_set_stereo_switch( int value ) -{ - dsp.set_stereo_switch( value ); -} - -SNES_SPC::uint8_t SNES_SPC::dsp_reg_value( int ch, int addr ) -{ - return dsp.reg_value( ch, addr ); -} - -int SNES_SPC::dsp_envx_value( int ch ) -{ - return dsp.envx_value( ch ); -} - -//// Snes9x debugger - -#ifdef DEBUGGER - -void SNES_SPC::debug_toggle_trace( void ) -{ - debug_trace = !debug_trace; - - if (debug_trace) - { - printf("APU tracing enabled.\n"); - ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "wb") - } - else - { - printf("APU tracing disabled.\n"); - fclose(apu_trace); - apu_trace = NULL; - } -} - -bool SNES_SPC::debug_is_enabled( void ) { return debug_trace; } - -void SNES_SPC::debug_do_trace( int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) -{ - char msg[512]; - - ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "a") - - debug_op_print(msg, a, x, y, pc, sp, psw, c, nz, dp); - fprintf(apu_trace, "%s ", msg); - debug_io_print(msg); - fprintf(apu_trace, "%s ", msg); - S9xPrintHVPosition(msg); - fprintf(apu_trace, "%s\n", msg); -} - -void SNES_SPC::debug_op_print( char *buffer, int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp ) -{ - static char mnemonics[256][20] = - { - "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" - }; - - static int modes[256] = - { - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 7, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 0, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 4, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 0, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 5, 2, - 2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 2, 2, 2, - 7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 3, 0, 2, 2, 7, 2 - }; - - static int modesToBytes[] = - { - 2, 3, 1, 3, 3, 3, 3, 2 - }; - - int const n80 = 0x80; // nz - int const p20 = 0x20; // dp - int const z02 = 0x02; // nz - int const c01 = 0x01; // c - - #define GET_PC() (pc - ram) - #define GET_SP() (sp - 0x101 - ram) - #define GET_PSW( out )\ - {\ - out = psw & ~(n80 | p20 | z02 | c01);\ - out |= c >> 8 & c01;\ - out |= dp >> 3 & p20;\ - out |= ((nz >> 4) | nz) & n80;\ - if ( !(uint8_t) nz ) out |= z02;\ - } - - uint8_t const *ram = RAM; - - int addr; - int tsp, tpsw; - uint8_t d0, d1, d2; - - addr = GET_PC(); - tsp = GET_SP(); - GET_PSW(tpsw); - - d0 = *pc; - d1 = (addr < 0xffff) ? *(pc + 1) : 0; - d2 = (addr < 0xfffe) ? *(pc + 2) : 0; - - int mode = modes[d0]; - int bytes = modesToBytes[mode]; - char mnem[100]; - - switch (bytes) - { - case 1: - sprintf(buffer, "%04X %02X ", addr, d0); - break; - - case 2: - sprintf(buffer, "%04X %02X %02X ", addr, d0, d1); - break; - - case 3: - sprintf(buffer, "%04X %02X %02X %02X ", addr, d0, d1, d2); - break; - } - - switch (mode) - { - case 0: - sprintf(mnem, mnemonics[d0], d1); - break; - - case 1: - sprintf(mnem, mnemonics[d0], d1 + (d2 << 8)); - break; - - case 2: - strcpy (mnem, mnemonics[d0]); - break; - - case 3: - sprintf(mnem, mnemonics[d0], d2, d1); - break; - - case 4: - sprintf(mnem, mnemonics[d0], d2, d1); - break; - - case 5: - sprintf(mnem, mnemonics[d0], d1, addr + 3 + (int8_t) d2); - break; - - case 6: - sprintf(mnem, mnemonics[d0], (d1 + (d2 << 8)) & 0x1fff, d2 >> 5); - break; - - case 7: - sprintf(mnem, mnemonics[d0], addr + 2 + (int8_t) d1); - break; - } - - sprintf(buffer, "%s %-20s A:%02X X:%02X Y:%02X S:%02X P:%c%c%c%c%c%c%c%c ROM:%d", - buffer, mnem, a, x, y, tsp, - (tpsw & 0x80) ? 'N' : 'n', - (tpsw & 0x40) ? 'V' : 'v', - (tpsw & 0x20) ? 'P' : 'p', - (tpsw & 0x10) ? 'B' : 'b', - (tpsw & 0x08) ? 'H' : 'h', - (tpsw & 0x04) ? 'I' : 'i', - (tpsw & 0x02) ? 'Z' : 'z', - (tpsw & 0x01) ? 'C' : 'c', - m.rom_enabled ? 1 : 0); -} - -void SNES_SPC::debug_io_print( char *buffer ) -{ - sprintf(buffer, "i/o %02X/%02X %02X/%02X %02X/%02X %02X/%02X", - m.smp_regs[1][r_cpuio0], m.smp_regs[0][r_cpuio0], - m.smp_regs[1][r_cpuio1], m.smp_regs[0][r_cpuio1], - m.smp_regs[1][r_cpuio2], m.smp_regs[0][r_cpuio2], - m.smp_regs[1][r_cpuio3], m.smp_regs[0][r_cpuio3]); -} - -#endif diff --git a/apu/SNES_SPC_state.cpp b/apu/SNES_SPC_state.cpp deleted file mode 100644 index 3d9d3f3a..00000000 --- a/apu/SNES_SPC_state.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// SPC emulation state save/load: copy_state(), save_spc() -// Separate file to avoid linking in unless needed - -// snes_spc 0.9.0. http://www.slack.net/‾ant/ - -#include "SNES_SPC.h" - -#if !SPC_NO_COPY_STATE_FUNCS - -#include - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include -#include "blargg_source.h" - -#define RAM (m.ram.ram) -#define REGS (m.smp_regs [0]) -#define REGS_IN (m.smp_regs [1]) - -void SNES_SPC::save_regs( uint8_t out [reg_count] ) -{ - // Use current timer counter values - for ( int i = 0; i < timer_count; i++ ) - out [r_t0out + i] = m.timers [i].counter; - - // Last written values - memcpy( out, REGS, r_t0out ); -} - -void SNES_SPC::init_header( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - spc->has_id666 = 26; // has none - spc->version = 30; - memcpy( spc, signature, sizeof spc->signature ); - memset( spc->text, 0, sizeof spc->text ); -} - -void SNES_SPC::save_spc( void* spc_out ) -{ - spc_file_t* const spc = (spc_file_t*) spc_out; - - // CPU - spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); - spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); - spc->a = m.cpu_regs.a; - spc->x = m.cpu_regs.x; - spc->y = m.cpu_regs.y; - spc->psw = m.cpu_regs.psw; - spc->sp = m.cpu_regs.sp; - - // RAM, ROM - memcpy( spc->ram, RAM, sizeof spc->ram ); - if ( m.rom_enabled ) - memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); - memset( spc->unused, 0, sizeof spc->unused ); - memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); - - // SMP registers - save_regs( &spc->ram [0xF0] ); - int i; - for ( i = 0; i < port_count; i++ ) - spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; - - // DSP registers - for ( i = 0; i < SPC_DSP::register_count; i++ ) - spc->dsp [i] = dsp.read( i ); -} - -#undef IF_0_THEN_256 -#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) -void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // Make state data more readable by putting 64K RAM, 16 SMP registers, - // then DSP (with its 128 registers) first - - // RAM - enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below - copier.copy( RAM, 0x10000 ); - - { - // SMP registers - uint8_t regs [reg_count]; - uint8_t regs_in [reg_count]; - - memcpy( regs, REGS, reg_count ); - memcpy( regs_in, REGS_IN, reg_count ); - - copier.copy( regs, sizeof regs ); - copier.copy( regs_in, sizeof regs_in ); - - memcpy( REGS, regs, reg_count); - memcpy( REGS_IN, regs_in, reg_count ); - - enable_rom( REGS [r_control] & 0x80 ); - } - - // CPU registers - SPC_COPY( uint16_t, m.cpu_regs.pc ); - SPC_COPY( uint8_t, m.cpu_regs.a ); - SPC_COPY( uint8_t, m.cpu_regs.x ); - SPC_COPY( uint8_t, m.cpu_regs.y ); - SPC_COPY( uint8_t, m.cpu_regs.psw ); - SPC_COPY( uint8_t, m.cpu_regs.sp ); - copier.extra(); - - SPC_COPY( int16_t, m.spc_time ); - SPC_COPY( int16_t, m.dsp_time ); - - // DSP - dsp.copy_state( io, copy ); - - // Timers - for ( int i = 0; i < timer_count; i++ ) - { - Timer* t = &m.timers [i]; - t->period = IF_0_THEN_256( REGS [r_t0target + i] ); - t->enabled = REGS [r_control] >> i & 1; - SPC_COPY( int16_t, t->next_time ); - SPC_COPY( uint8_t, t->divider ); - SPC_COPY( uint8_t, t->counter ); - copier.extra(); - } - - set_tempo( m.tempo ); - - copier.extra(); -} -#endif diff --git a/apu/SPC_CPU.h b/apu/SPC_CPU.h deleted file mode 100644 index 67fee8da..00000000 --- a/apu/SPC_CPU.h +++ /dev/null @@ -1,1228 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -/* Copyright (C) 2004-2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -//// Memory access - -#if SPC_MORE_ACCURACY - #define SUSPICIOUS_OPCODE( name ) ((void) 0) -#else - #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) -#endif - -#define CPU_READ( time, offset, addr )\ - cpu_read( addr, time + offset ) - -#define CPU_WRITE( time, offset, addr, data )\ - cpu_write( data, addr, time + offset ) - -#if SPC_MORE_ACCURACY - #define CPU_READ_TIMER( time, offset, addr, out )\ - { out = CPU_READ( time, offset, addr ); } - -#else - // timers are by far the most common thing read from dp - #define CPU_READ_TIMER( time, offset, addr_, out )\ - {\ - rel_time_t adj_time = time + offset;\ - int dp_addr = addr_;\ - int ti = dp_addr - (r_t0out + 0xF0);\ - if ( (unsigned) ti < timer_count )\ - {\ - Timer* t = &m.timers [ti];\ - if ( adj_time >= t->next_time )\ - t = run_timer_( t, adj_time );\ - out = t->counter;\ - t->counter = 0;\ - }\ - else\ - {\ - out = ram [dp_addr];\ - int i = dp_addr - 0xF0;\ - if ( (unsigned) i < 0x10 )\ - out = cpu_read_smp_reg( i, adj_time );\ - }\ - } -#endif - -#define TIME_ADJ( n ) (n) - -#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) -#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) -#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) - -#define DP_ADDR( addr ) (dp + (addr)) - -#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) -#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) -#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) - -#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) - -#define SET_PC( n ) (pc = ram + (n)) -#define GET_PC() (pc - ram) -#define READ_PC( pc ) (*(pc)) -#define READ_PC16( pc ) GET_LE16( pc ) - -// TODO: remove non-wrapping versions? -#define SPC_NO_SP_WRAPAROUND 0 - -#define SET_SP( v ) (sp = ram + 0x101 + (v)) -#define GET_SP() (sp - 0x101 - ram) - -#if SPC_NO_SP_WRAPAROUND -#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) -#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) -#define POP( out ) (void) ((out) = *sp++) - -#else -#define PUSH16( data )\ -{\ - int addr = (sp -= 2) - ram;\ - if ( addr > 0x100 )\ - {\ - SET_LE16( sp, data );\ - }\ - else\ - {\ - ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ - sp [1] = (uint8_t) (data >> 8);\ - sp += 0x100;\ - }\ -} - -#define PUSH( data )\ -{\ - *--sp = (uint8_t) (data);\ - if ( sp - ram == 0x100 )\ - sp += 0x100;\ -} - -#define POP( out )\ -{\ - out = *sp++;\ - if ( sp - ram == 0x201 )\ - {\ - out = sp [-0x101];\ - sp -= 0x100;\ - }\ -} - -#endif - -#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) - -unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) -{ - unsigned addr = READ_PC16( pc ); - unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); - return t << 8 & 0x100; -} - -//// Status flag handling - -// Hex value in name to clarify code and bit shifting. -// Flag stored in indicated variable during emulation -int const n80 = 0x80; // nz -int const v40 = 0x40; // psw -int const p20 = 0x20; // dp -int const b10 = 0x10; // psw -int const h08 = 0x08; // psw -int const i04 = 0x04; // psw -int const z02 = 0x02; // nz -int const c01 = 0x01; // c - -int const nz_neg_mask = 0x880; // either bit set indicates N flag set - -#define GET_PSW( out )\ -{\ - out = psw & ~(n80 | p20 | z02 | c01);\ - out |= c >> 8 & c01;\ - out |= dp >> 3 & p20;\ - out |= ((nz >> 4) | nz) & n80;\ - if ( !(uint8_t) nz ) out |= z02;\ -} - -#define SET_PSW( in )\ -{\ - psw = in;\ - c = in << 8;\ - dp = in << 3 & 0x100;\ - nz = (in << 4 & 0x800) | (~in & z02);\ -} - -SPC_CPU_RUN_FUNC -{ - uint8_t* const ram = RAM; - int a = m.cpu_regs.a; - int x = m.cpu_regs.x; - int y = m.cpu_regs.y; - uint8_t const* pc; - uint8_t* sp; - int psw; - int c; - int nz; - int dp; - - SET_PC( m.cpu_regs.pc ); - SET_SP( m.cpu_regs.sp ); - SET_PSW( m.cpu_regs.psw ); - - goto loop; - - - // Main loop - -cbranch_taken_loop: - pc += *(BOOST::int8_t const*) pc; -inc_pc_loop: - pc++; -loop: -{ - unsigned opcode; - unsigned data; - - check( (unsigned) a < 0x100 ); - check( (unsigned) x < 0x100 ); - check( (unsigned) y < 0x100 ); - - opcode = *pc; - if (allow_time_overflow && rel_time >= 0 ) - goto stop; - if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow) - goto out_of_time; - - #ifdef SPC_CPU_OPCODE_HOOK - SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); - #endif - /* - //SUB_CASE_COUNTER( 1 ); - #define PROFILE_TIMER_LOOP( op, addr, len )\ - if ( opcode == op )\ - {\ - int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ - pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ - SUB_CASE_COUNTER( op && cond );\ - } - - PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); - PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); - PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); - */ - -#ifdef DEBUGGER - if (debug_trace) - debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp); -#endif - - - // TODO: if PC is at end of memory, this will get wrong operand (very obscure) - data = *++pc; - switch ( opcode ) - { - -// Common instructions - -#define BRANCH( cond )\ -{\ - pc++;\ - pc += (BOOST::int8_t) data;\ - if ( cond )\ - goto loop;\ - pc -= (BOOST::int8_t) data;\ - rel_time -= 2;\ - goto loop;\ -} - - case 0xF0: // BEQ - BRANCH( !(uint8_t) nz ) // 89% taken - - case 0xD0: // BNE - BRANCH( (uint8_t) nz ) - - case 0x3F:{// CALL - int old_addr = GET_PC() + 2; - SET_PC( READ_PC16( pc ) ); - PUSH16( old_addr ); - goto loop; - } - - case 0x6F:// RET - #if SPC_NO_SP_WRAPAROUND - { - SET_PC( GET_LE16( sp ) ); - sp += 2; - } - #else - { - int addr = sp - ram; - SET_PC( GET_LE16( sp ) ); - sp += 2; - if ( addr < 0x1FF ) - goto loop; - - SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); - sp -= 0x100; - } - #endif - goto loop; - - case 0xE4: // MOV a,dp - ++pc; - // 80% from timer - READ_DP_TIMER( 0, data, a = nz ); - goto loop; - - case 0xFA:{// MOV dp,dp - int temp; - READ_DP_TIMER( -2, data, temp ); - data = temp + no_read_before_write ; - } - // fall through - case 0x8F:{// MOV dp,#imm - int temp = READ_PC( pc + 1 ); - pc += 2; - - #if !SPC_MORE_ACCURACY - { - int i = dp + temp; - ram [i] = (uint8_t) data; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 76% - { - REGS [i] = (uint8_t) data; - - // Registers other than $F2 and $F4-$F7 - //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) - if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% - cpu_write_smp_reg( data, rel_time, i ); - } - } - #else - WRITE_DP( 0, temp, data ); - #endif - goto loop; - } - - case 0xC4: // MOV dp,a - ++pc; - #if !SPC_MORE_ACCURACY - { - int i = dp + data; - ram [i] = (uint8_t) a; - i -= 0xF0; - if ( (unsigned) i < 0x10 ) // 39% - { - unsigned sel = i - 2; - REGS [i] = (uint8_t) a; - - if ( sel == 1 ) // 51% $F3 - dsp_write( a, rel_time ); - else if ( sel > 1 ) // 1% not $F2 or $F3 - cpu_write_smp_reg_( a, rel_time, i ); - } - } - #else - WRITE_DP( 0, data, a ); - #endif - goto loop; - -#define CASE( n ) case n: - -// Define common address modes based on opcode for immediate mode. Execution -// ends with data set to the address of the operand. -#define ADDR_MODES_( op )\ - CASE( op - 0x02 ) /* (X) */\ - data = x + dp;\ - pc--;\ - goto end_##op;\ - CASE( op + 0x0F ) /* (dp)+Y */\ - data = READ_PROG16( data + dp ) + y;\ - goto end_##op;\ - CASE( op - 0x01 ) /* (dp+X) */\ - data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ - goto end_##op;\ - CASE( op + 0x0E ) /* abs+Y */\ - data += y;\ - goto abs_##op;\ - CASE( op + 0x0D ) /* abs+X */\ - data += x;\ - CASE( op - 0x03 ) /* abs */\ - abs_##op:\ - data += 0x100 * READ_PC( ++pc );\ - goto end_##op;\ - CASE( op + 0x0C ) /* dp+X */\ - data = (uint8_t) (data + x); - -#define ADDR_MODES_NO_DP( op )\ - ADDR_MODES_( op )\ - data += dp;\ - end_##op: - -#define ADDR_MODES( op )\ - ADDR_MODES_( op )\ - CASE( op - 0x04 ) /* dp */\ - data += dp;\ - end_##op: - -// 1. 8-bit Data Transmission Commands. Group I - - ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr - a = nz = READ( 0, data ); - goto inc_pc_loop; - - case 0xBF:{// MOV A,(X)+ - int temp = x + dp; - x = (uint8_t) (x + 1); - a = nz = READ( -1, temp ); - goto loop; - } - - case 0xE8: // MOV A,imm - a = data; - nz = data; - goto inc_pc_loop; - - case 0xF9: // MOV X,dp+Y - data = (uint8_t) (data + y); - case 0xF8: // MOV X,dp - READ_DP_TIMER( 0, data, x = nz ); - goto inc_pc_loop; - - case 0xE9: // MOV X,abs - data = READ_PC16( pc ); - ++pc; - data = READ( 0, data ); - case 0xCD: // MOV X,imm - x = data; - nz = data; - goto inc_pc_loop; - - case 0xFB: // MOV Y,dp+X - data = (uint8_t) (data + x); - case 0xEB: // MOV Y,dp - // 70% from timer - pc++; - READ_DP_TIMER( 0, data, y = nz ); - goto loop; - - case 0xEC:{// MOV Y,abs - int temp = READ_PC16( pc ); - pc += 2; - READ_TIMER( 0, temp, y = nz ); - //y = nz = READ( 0, temp ); - goto loop; - } - - case 0x8D: // MOV Y,imm - y = data; - nz = data; - goto inc_pc_loop; - -// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 - - ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A - WRITE( 0, data, a ); - goto inc_pc_loop; - - { - int temp; - case 0xCC: // MOV abs,Y - temp = y; - goto mov_abs_temp; - case 0xC9: // MOV abs,X - temp = x; - mov_abs_temp: - WRITE( 0, READ_PC16( pc ), temp ); - pc += 2; - goto loop; - } - - case 0xD9: // MOV dp+Y,X - data = (uint8_t) (data + y); - case 0xD8: // MOV dp,X - WRITE( 0, data + dp, x ); - goto inc_pc_loop; - - case 0xDB: // MOV dp+X,Y - data = (uint8_t) (data + x); - case 0xCB: // MOV dp,Y - WRITE( 0, data + dp, y ); - goto inc_pc_loop; - -// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. - - case 0x7D: // MOV A,X - a = x; - nz = x; - goto loop; - - case 0xDD: // MOV A,Y - a = y; - nz = y; - goto loop; - - case 0x5D: // MOV X,A - x = a; - nz = a; - goto loop; - - case 0xFD: // MOV Y,A - y = a; - nz = a; - goto loop; - - case 0x9D: // MOV X,SP - x = nz = GET_SP(); - goto loop; - - case 0xBD: // MOV SP,X - SET_SP( x ); - goto loop; - - //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) - - case 0xAF: // MOV (X)+,A - WRITE_DP( 0, x, a + no_read_before_write ); - x++; - goto loop; - -// 5. 8-BIT LOGIC OPERATION COMMANDS - -#define LOGICAL_OP( op, func )\ - ADDR_MODES( op ) /* addr */\ - data = READ( 0, data );\ - case op: /* imm */\ - nz = a func##= data;\ - goto inc_pc_loop;\ - { unsigned addr;\ - case op + 0x11: /* X,Y */\ - data = READ_DP( -2, y );\ - addr = x + dp;\ - goto addr_##op;\ - case op + 0x01: /* dp,dp */\ - data = READ_DP( -3, data );\ - case op + 0x10:{/*dp,imm*/\ - uint8_t const* addr2 = pc + 1;\ - pc += 2;\ - addr = READ_PC( addr2 ) + dp;\ - }\ - addr_##op:\ - nz = data func READ( -1, addr );\ - WRITE( 0, addr, nz );\ - goto loop;\ - } - - LOGICAL_OP( 0x28, & ); // AND - - LOGICAL_OP( 0x08, | ); // OR - - LOGICAL_OP( 0x48, ^ ); // EOR - -// 4. 8-BIT ARITHMETIC OPERATION COMMANDS - - ADDR_MODES( 0x68 ) // CMP addr - data = READ( 0, data ); - case 0x68: // CMP imm - nz = a - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x79: // CMP (X),(Y) - data = READ_DP( -2, y ); - nz = READ_DP( -1, x ) - data; - c = ~nz; - nz &= 0xFF; - goto loop; - - case 0x69: // CMP dp,dp - data = READ_DP( -3, data ); - case 0x78: // CMP dp,imm - nz = READ_DP( -1, READ_PC( ++pc ) ) - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x3E: // CMP X,dp - data += dp; - goto cmp_x_addr; - case 0x1E: // CMP X,abs - data = READ_PC16( pc ); - pc++; - cmp_x_addr: - data = READ( 0, data ); - case 0xC8: // CMP X,imm - nz = x - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - case 0x7E: // CMP Y,dp - data += dp; - goto cmp_y_addr; - case 0x5E: // CMP Y,abs - data = READ_PC16( pc ); - pc++; - cmp_y_addr: - data = READ( 0, data ); - case 0xAD: // CMP Y,imm - nz = y - data; - c = ~nz; - nz &= 0xFF; - goto inc_pc_loop; - - { - int addr; - case 0xB9: // SBC (x),(y) - case 0x99: // ADC (x),(y) - pc--; // compensate for inc later - data = READ_DP( -2, y ); - addr = x + dp; - goto adc_addr; - case 0xA9: // SBC dp,dp - case 0x89: // ADC dp,dp - data = READ_DP( -3, data ); - case 0xB8: // SBC dp,imm - case 0x98: // ADC dp,imm - addr = READ_PC( ++pc ) + dp; - adc_addr: - nz = READ( -1, addr ); - goto adc_data; - -// catch ADC and SBC together, then decode later based on operand -#undef CASE -#define CASE( n ) case n: case (n) + 0x20: - ADDR_MODES( 0x88 ) // ADC/SBC addr - data = READ( 0, data ); - case 0xA8: // SBC imm - case 0x88: // ADC imm - addr = -1; // A - nz = a; - adc_data: { - int flags; - if ( opcode >= 0xA0 ) // SBC - data ^= 0xFF; - - flags = data ^ nz; - nz += data + (c >> 8 & 1); - flags ^= nz; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = nz; - if ( addr < 0 ) - { - a = (uint8_t) nz; - goto inc_pc_loop; - } - WRITE( 0, addr, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - } - - } - -// 6. ADDITION & SUBTRACTION COMMANDS - -#define INC_DEC_REG( reg, op )\ - nz = reg op;\ - reg = (uint8_t) nz;\ - goto loop; - - case 0xBC: INC_DEC_REG( a, + 1 ) // INC A - case 0x3D: INC_DEC_REG( x, + 1 ) // INC X - case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y - - case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A - case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X - case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y - - case 0x9B: // DEC dp+X - case 0xBB: // INC dp+X - data = (uint8_t) (data + x); - case 0x8B: // DEC dp - case 0xAB: // INC dp - data += dp; - goto inc_abs; - case 0x8C: // DEC abs - case 0xAC: // INC abs - data = READ_PC16( pc ); - pc++; - inc_abs: - nz = (opcode >> 4 & 2) - 1; - nz += READ( -1, data ); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - -// 7. SHIFT, ROTATION COMMANDS - - case 0x5C: // LSR A - c = 0; - case 0x7C:{// ROR A - nz = (c >> 1 & 0x80) | (a >> 1); - c = a << 8; - a = nz; - goto loop; - } - - case 0x1C: // ASL A - c = 0; - case 0x3C:{// ROL A - int temp = c >> 8 & 1; - c = a << 1; - nz = c | temp; - a = (uint8_t) nz; - goto loop; - } - - case 0x0B: // ASL dp - c = 0; - data += dp; - goto rol_mem; - case 0x1B: // ASL dp+X - c = 0; - case 0x3B: // ROL dp+X - data = (uint8_t) (data + x); - case 0x2B: // ROL dp - data += dp; - goto rol_mem; - case 0x0C: // ASL abs - c = 0; - case 0x2C: // ROL abs - data = READ_PC16( pc ); - pc++; - rol_mem: - nz = c >> 8 & 1; - nz |= (c = READ( -1, data ) << 1); - WRITE( 0, data, /*(uint8_t)*/ nz ); - goto inc_pc_loop; - - case 0x4B: // LSR dp - c = 0; - data += dp; - goto ror_mem; - case 0x5B: // LSR dp+X - c = 0; - case 0x7B: // ROR dp+X - data = (uint8_t) (data + x); - case 0x6B: // ROR dp - data += dp; - goto ror_mem; - case 0x4C: // LSR abs - c = 0; - case 0x6C: // ROR abs - data = READ_PC16( pc ); - pc++; - ror_mem: { - int temp = READ( -1, data ); - nz = (c >> 1 & 0x80) | (temp >> 1); - c = temp << 8; - WRITE( 0, data, nz ); - goto inc_pc_loop; - } - - case 0x9F: // XCN - nz = a = (a >> 4) | (uint8_t) (a << 4); - goto loop; - -// 8. 16-BIT TRANSMISION COMMANDS - - case 0xBA: // MOVW YA,dp - a = READ_DP( -2, data ); - nz = (a & 0x7F) | (a >> 1); - y = READ_DP( 0, (uint8_t) (data + 1) ); - nz |= y; - goto inc_pc_loop; - - case 0xDA: // MOVW dp,YA - WRITE_DP( -1, data, a ); - WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); - goto inc_pc_loop; - -// 9. 16-BIT OPERATION COMMANDS - - case 0x3A: // INCW dp - case 0x1A:{// DECW dp - int temp; - // low byte - data += dp; - temp = READ( -3, data ); - temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW - nz = ((temp >> 1) | temp) & 0x7F; - WRITE( -2, data, /*(uint8_t)*/ temp ); - - // high byte - data = (uint8_t) (data + 1) + dp; - temp = (uint8_t) ((temp >> 8) + READ( -1, data )); - nz |= temp; - WRITE( 0, data, temp ); - - goto inc_pc_loop; - } - - case 0x7A: // ADDW YA,dp - case 0x9A:{// SUBW YA,dp - int lo = READ_DP( -2, data ); - int hi = READ_DP( 0, (uint8_t) (data + 1) ); - int result; - int flags; - - if ( opcode == 0x9A ) // SUBW - { - lo = (lo ^ 0xFF) + 1; - hi ^= 0xFF; - } - - lo += a; - result = y + hi + (lo >> 8); - flags = hi ^ y ^ result; - - psw = (psw & ~(v40 | h08)) | - (flags >> 1 & h08) | - ((flags + 0x80) >> 2 & v40); - c = result; - a = (uint8_t) lo; - result = (uint8_t) result; - y = result; - nz = (((lo >> 1) | lo) & 0x7F) | result; - - goto inc_pc_loop; - } - - case 0x5A: { // CMPW YA,dp - int temp = a - READ_DP( -1, data ); - nz = ((temp >> 1) | temp) & 0x7F; - temp = y + (temp >> 8); - temp -= READ_DP( 0, (uint8_t) (data + 1) ); - nz |= temp; - c = ~temp; - nz &= 0xFF; - goto inc_pc_loop; - } - -// 10. MULTIPLICATION & DIVISON COMMANDS - - case 0xCF: { // MUL YA - unsigned temp = y * a; - a = (uint8_t) temp; - nz = ((temp >> 1) | temp) & 0x7F; - y = temp >> 8; - nz |= y; - goto loop; - } - - case 0x9E: // DIV YA,X - { - unsigned ya = y * 0x100 + a; - - psw &= ~(h08 | v40); - - if ( y >= x ) - psw |= v40; - - if ( (y & 15) >= (x & 15) ) - psw |= h08; - - if ( y < x * 2 ) - { - a = ya / x; - y = ya - a * x; - } - else - { - a = 255 - (ya - x * 0x200) / (256 - x); - y = x + (ya - x * 0x200) % (256 - x); - } - - nz = (uint8_t) a; - a = (uint8_t) a; - - goto loop; - } - -// 11. DECIMAL COMPENSATION COMMANDS - - case 0xDF: // DAA - SUSPICIOUS_OPCODE( "DAA" ); - if ( a > 0x99 || c & 0x100 ) - { - a += 0x60; - c = 0x100; - } - - if ( (a & 0x0F) > 9 || psw & h08 ) - a += 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - - case 0xBE: // DAS - SUSPICIOUS_OPCODE( "DAS" ); - if ( a > 0x99 || !(c & 0x100) ) - { - a -= 0x60; - c = 0; - } - - if ( (a & 0x0F) > 9 || !(psw & h08) ) - a -= 0x06; - - nz = a; - a = (uint8_t) a; - goto loop; - -// 12. BRANCHING COMMANDS - - case 0x2F: // BRA rel - pc += (BOOST::int8_t) data; - goto inc_pc_loop; - - case 0x30: // BMI - BRANCH( (nz & nz_neg_mask) ) - - case 0x10: // BPL - BRANCH( !(nz & nz_neg_mask) ) - - case 0xB0: // BCS - BRANCH( c & 0x100 ) - - case 0x90: // BCC - BRANCH( !(c & 0x100) ) - - case 0x70: // BVS - BRANCH( psw & v40 ) - - case 0x50: // BVC - BRANCH( !(psw & v40) ) - - #define CBRANCH( cond )\ - {\ - pc++;\ - if ( cond )\ - goto cbranch_taken_loop;\ - rel_time -= 2;\ - goto inc_pc_loop;\ - } - - case 0x03: // BBS dp.bit,rel - case 0x23: - case 0x43: - case 0x63: - case 0x83: - case 0xA3: - case 0xC3: - case 0xE3: - CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) - - case 0x13: // BBC dp.bit,rel - case 0x33: - case 0x53: - case 0x73: - case 0x93: - case 0xB3: - case 0xD3: - case 0xF3: - CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) - - case 0xDE: // CBNE dp+X,rel - data = (uint8_t) (data + x); - // fall through - case 0x2E:{// CBNE dp,rel - int temp; - // 61% from timer - READ_DP_TIMER( -4, data, temp ); - CBRANCH( temp != a ) - } - - case 0x6E: { // DBNZ dp,rel - unsigned temp = READ_DP( -4, data ) - 1; - WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); - CBRANCH( temp ) - } - - case 0xFE: // DBNZ Y,rel - y = (uint8_t) (y - 1); - BRANCH( y ) - - case 0x1F: // JMP [abs+X] - SET_PC( READ_PC16( pc ) + x ); - // fall through - case 0x5F: // JMP abs - SET_PC( READ_PC16( pc ) ); - goto loop; - -// 13. SUB-ROUTINE CALL RETURN COMMANDS - - case 0x0F:{// BRK - int temp; - int ret_addr = GET_PC(); - SUSPICIOUS_OPCODE( "BRK" ); - SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified - PUSH16( ret_addr ); - GET_PSW( temp ); - psw = (psw | b10) & ~i04; - PUSH( temp ); - goto loop; - } - - case 0x4F:{// PCALL offset - int ret_addr = GET_PC() + 1; - SET_PC( 0xFF00 | data ); - PUSH16( ret_addr ); - goto loop; - } - - case 0x01: // TCALL n - case 0x11: - case 0x21: - case 0x31: - case 0x41: - case 0x51: - case 0x61: - case 0x71: - case 0x81: - case 0x91: - case 0xA1: - case 0xB1: - case 0xC1: - case 0xD1: - case 0xE1: - case 0xF1: { - int ret_addr = GET_PC(); - SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); - PUSH16( ret_addr ); - goto loop; - } - -// 14. STACK OPERATION COMMANDS - - { - int temp; - case 0x7F: // RET1 - temp = *sp; - SET_PC( GET_LE16( sp + 1 ) ); - sp += 3; - goto set_psw; - case 0x8E: // POP PSW - POP( temp ); - set_psw: - SET_PSW( temp ); - goto loop; - } - - case 0x0D: { // PUSH PSW - int temp; - GET_PSW( temp ); - PUSH( temp ); - goto loop; - } - - case 0x2D: // PUSH A - PUSH( a ); - goto loop; - - case 0x4D: // PUSH X - PUSH( x ); - goto loop; - - case 0x6D: // PUSH Y - PUSH( y ); - goto loop; - - case 0xAE: // POP A - POP( a ); - goto loop; - - case 0xCE: // POP X - POP( x ); - goto loop; - - case 0xEE: // POP Y - POP( y ); - goto loop; - -// 15. BIT OPERATION COMMANDS - - case 0x02: // SET1 - case 0x22: - case 0x42: - case 0x62: - case 0x82: - case 0xA2: - case 0xC2: - case 0xE2: - case 0x12: // CLR1 - case 0x32: - case 0x52: - case 0x72: - case 0x92: - case 0xB2: - case 0xD2: - case 0xF2: { - int bit = 1 << (opcode >> 5); - int mask = ~bit; - if ( opcode & 0x10 ) - bit = 0; - data += dp; - WRITE( 0, data, (READ( -1, data ) & mask) | bit ); - goto inc_pc_loop; - } - - case 0x0E: // TSET1 abs - case 0x4E: // TCLR1 abs - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data ); - nz = (uint8_t) (a - temp); - temp &= ~a; - if ( opcode == 0x0E ) - temp |= a; - WRITE( 0, data, temp ); - } - goto loop; - - case 0x4A: // AND1 C,mem.bit - c &= MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x6A: // AND1 C,/mem.bit - c &= ~MEM_BIT( 0 ); - pc += 2; - goto loop; - - case 0x0A: // OR1 C,mem.bit - c |= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x2A: // OR1 C,/mem.bit - c |= ~MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0x8A: // EOR1 C,mem.bit - c ^= MEM_BIT( -1 ); - pc += 2; - goto loop; - - case 0xEA: // NOT1 mem.bit - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -1, data & 0x1FFF ); - temp ^= 1 << (data >> 13); - WRITE( 0, data & 0x1FFF, temp ); - } - goto loop; - - case 0xCA: // MOV1 mem.bit,C - data = READ_PC16( pc ); - pc += 2; - { - unsigned temp = READ( -2, data & 0x1FFF ); - unsigned bit = data >> 13; - temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); - WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); - } - goto loop; - - case 0xAA: // MOV1 C,mem.bit - c = MEM_BIT( 0 ); - pc += 2; - goto loop; - -// 16. PROGRAM PSW FLAG OPERATION COMMANDS - - case 0x60: // CLRC - c = 0; - goto loop; - - case 0x80: // SETC - c = ~0; - goto loop; - - case 0xED: // NOTC - c ^= 0x100; - goto loop; - - case 0xE0: // CLRV - psw &= ~(v40 | h08); - goto loop; - - case 0x20: // CLRP - dp = 0; - goto loop; - - case 0x40: // SETP - dp = 0x100; - goto loop; - - case 0xA0: // EI - SUSPICIOUS_OPCODE( "EI" ); - psw |= i04; - goto loop; - - case 0xC0: // DI - SUSPICIOUS_OPCODE( "DI" ); - psw &= ~i04; - goto loop; - -// 17. OTHER COMMANDS - - case 0x00: // NOP - goto loop; - - case 0xFF:{// STOP - // handle PC wrap-around - unsigned addr = GET_PC() - 1; - if ( addr >= 0x10000 ) - { - addr &= 0xFFFF; - SET_PC( addr ); - dprintf( "SPC: PC wrapped around\n" ); - goto loop; - } - } - // fall through - case 0xEF: // SLEEP - SUSPICIOUS_OPCODE( "STOP/SLEEP" ); - --pc; - rel_time = 0; - m.cpu_error = "SPC emulation error"; - goto stop; - } // switch - - assert( 0 ); // catch any unhandled instructions -} -out_of_time: - rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode -stop: - - // Uncache registers - if ( GET_PC() >= 0x10000 ) - dprintf( "SPC: PC wrapped around\n" ); - m.cpu_regs.pc = (uint16_t) GET_PC(); - m.cpu_regs.sp = ( uint8_t) GET_SP(); - m.cpu_regs.a = ( uint8_t) a; - m.cpu_regs.x = ( uint8_t) x; - m.cpu_regs.y = ( uint8_t) y; - { - int temp; - GET_PSW( temp ); - m.cpu_regs.psw = (uint8_t) temp; - } -} -SPC_CPU_RUN_FUNC_END diff --git a/apu/SPC_DSP.cpp b/apu/SPC_DSP.cpp deleted file mode 100644 index e6ba49ed..00000000 --- a/apu/SPC_DSP.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_DSP.h" - -#include "blargg_endian.h" -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -#if INT_MAX < 0x7FFFFFFF - #error "Requires that int type have at least 32 bits" -#endif - -// TODO: add to blargg_endian.h -#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) -#define GET_LE16A( addr ) GET_LE16( addr ) -#define SET_LE16A( addr, data ) SET_LE16( addr, data ) - -static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = -{ - 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, - 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, - 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, - 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, - 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, - 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF, - 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, - 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF -}; - -// if ( io < -32768 ) io = -32768; -// if ( io > 32767 ) io = 32767; -#define CLAMP16( io )\ -{\ - if ( (int16_t) io != io )\ - io = (io >> 31) ^ 0x7FFF;\ -} - -// Access global DSP register -#define REG(n) m.regs [r_##n] - -// Access voice DSP register -#define VREG(r,n) r [v_##n] - -#define WRITE_SAMPLES( l, r, out ) \ -{\ - out [0] = l;\ - out [1] = r;\ - out += 2;\ - if ( out >= m.out_end )\ - {\ - check( out == m.out_end );\ - check( m.out_end != &m.extra [extra_size] || \ - (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ - out = m.extra;\ - m.out_end = &m.extra [extra_size];\ - }\ -}\ - -void SPC_DSP::set_output( sample_t* out, int size ) -{ - require( (size & 1) == 0 ); // must be even - if ( !out ) - { - out = m.extra; - size = extra_size; - } - m.out_begin = out; - m.out = out; - m.out_end = out + size; -} - -// Volume registers and efb are signed! Easy to forget int8_t cast. -// Prefixes are to avoid accidental use of locals with same names. - -// Gaussian interpolation - -static short const gauss [512] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, - 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, - 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, - 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, - 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, - 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, - 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, - 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, - 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, - 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, - 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, - 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, - 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, - 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, - 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, - 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, - 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, - 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, - 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, - 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, -1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, -1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, -1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, -1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, -1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, -1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, -1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, -}; - -inline int SPC_DSP::interpolate( voice_t const* v ) -{ - // Make pointers into gaussian based on fractional position between samples - int offset = v->interp_pos >> 4 & 0xFF; - short const* fwd = gauss + 255 - offset; - short const* rev = gauss + offset; // mirror left half of gaussian - - int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; - int out; - out = (fwd [ 0] * in [0]) >> 11; - out += (fwd [256] * in [1]) >> 11; - out += (rev [256] * in [2]) >> 11; - out = (int16_t) out; - out += (rev [ 0] * in [3]) >> 11; - - CLAMP16( out ); - out &= ~1; - return out; -} - - -//// Counters - -int const simple_counter_range = 2048 * 5 * 3; // 30720 - -static unsigned const counter_rates [32] = -{ - simple_counter_range + 1, // never fires - 2048, 1536, - 1280, 1024, 768, - 640, 512, 384, - 320, 256, 192, - 160, 128, 96, - 80, 64, 48, - 40, 32, 24, - 20, 16, 12, - 10, 8, 6, - 5, 4, 3, - 2, - 1 -}; - -static unsigned const counter_offsets [32] = -{ - 1, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 536, 0, 1040, - 0, - 0 -}; - -inline void SPC_DSP::init_counter() -{ - m.counter = 0; -} - -inline void SPC_DSP::run_counters() -{ - if ( --m.counter < 0 ) - m.counter = simple_counter_range - 1; -} - -inline unsigned SPC_DSP::read_counter( int rate ) -{ - return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; -} - - -//// Envelope - -inline void SPC_DSP::run_envelope( voice_t* const v ) -{ - int env = v->env; - if ( v->env_mode == env_release ) // 60% - { - if ( (env -= 0x8) < 0 ) - env = 0; - v->env = env; - } - else - { - int rate; - int env_data = VREG(v->regs,adsr1); - if ( m.t_adsr0 & 0x80 ) // 99% ADSR - { - if ( v->env_mode >= env_decay ) // 99% - { - env--; - env -= env >> 8; - rate = env_data & 0x1F; - if ( v->env_mode == env_decay ) // 1% - rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; - } - else // env_attack - { - rate = (m.t_adsr0 & 0x0F) * 2 + 1; - env += rate < 31 ? 0x20 : 0x400; - } - } - else // GAIN - { - int mode; - env_data = VREG(v->regs,gain); - mode = env_data >> 5; - if ( mode < 4 ) // direct - { - env = env_data * 0x10; - rate = 31; - } - else - { - rate = env_data & 0x1F; - if ( mode == 4 ) // 4: linear decrease - { - env -= 0x20; - } - else if ( mode < 6 ) // 5: exponential decrease - { - env--; - env -= env >> 8; - } - else // 6,7: linear increase - { - env += 0x20; - if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) - env += 0x8 - 0x20; // 7: two-slope linear increase - } - } - } - - // Sustain level - if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) - v->env_mode = env_sustain; - - v->hidden_env = env; - - // unsigned cast because linear decrease going negative also triggers this - if ( (unsigned) env > 0x7FF ) - { - env = (env < 0 ? 0 : 0x7FF); - if ( v->env_mode == env_attack ) - v->env_mode = env_decay; - } - - if ( !read_counter( rate ) ) - v->env = env; // nothing else is controlled by the counter - } -} - - -//// BRR Decoding - -inline void SPC_DSP::decode_brr( voice_t* v ) -{ - // Arrange the four input nybbles in 0xABCD order for easy decoding - int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - - int const header = m.t_brr_header; - - // Write to next four samples in circular buffer - int* pos = &v->buf [v->buf_pos]; - int* end; - if ( (v->buf_pos += 4) >= brr_buf_size ) - v->buf_pos = 0; - - // Decode four samples - for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) - { - // Extract nybble and sign-extend - int s = (int16_t) nybbles >> 12; - - // Shift sample based on header - int const shift = header >> 4; - s = (s << shift) >> 1; - if ( shift >= 0xD ) // handle invalid range - s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - - // Apply IIR filter (8 is the most commonly used) - int const filter = header & 0x0C; - int const p1 = pos [brr_buf_size - 1]; - int const p2 = pos [brr_buf_size - 2] >> 1; - if ( filter >= 8 ) - { - s += p1; - s -= p2; - if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 - { - s += p2 >> 4; - s += (p1 * -3) >> 6; - } - else // s += p1 * 0.8984375 - p2 * 0.40625 - { - s += (p1 * -13) >> 7; - s += (p2 * 3) >> 4; - } - } - else if ( filter ) // s += p1 * 0.46875 - { - s += p1 >> 1; - s += (-p1) >> 5; - } - - // Adjust and write sample - CLAMP16( s ); - s = (int16_t) (s * 2); - pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around - } -} - - -//// Misc - -#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() - -MISC_CLOCK( 27 ) -{ - m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON -} -MISC_CLOCK( 28 ) -{ - m.t_non = REG(non); - m.t_eon = REG(eon); - m.t_dir = REG(dir); -} -MISC_CLOCK( 29 ) -{ - if ( (m.every_other_sample ^= 1) != 0 ) - m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read -} -MISC_CLOCK( 30 ) -{ - if ( m.every_other_sample ) - { - m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; - } - - run_counters(); - - // Noise - if ( !read_counter( REG(flg) & 0x1F ) ) - { - int feedback = (m.noise << 13) ^ (m.noise << 14); - m.noise = (feedback & 0x4000) ^ (m.noise >> 1); - } -} - - -//// Voices - -#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) - -inline VOICE_CLOCK( V1 ) -{ - m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; - m.t_srcn = VREG(v->regs,srcn); -} -inline VOICE_CLOCK( V2 ) -{ - // Read sample pointer (ignored if not needed) - uint8_t const* entry = &m.ram [m.t_dir_addr]; - if ( !v->kon_delay ) - entry += 2; - m.t_brr_next_addr = GET_LE16A( entry ); - - m.t_adsr0 = VREG(v->regs,adsr0); - - // Read pitch, spread over two clocks - m.t_pitch = VREG(v->regs,pitchl); -} -inline VOICE_CLOCK( V3a ) -{ - m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; -} -inline VOICE_CLOCK( V3b ) -{ - // Read BRR header and byte - m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; - m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking -} -VOICE_CLOCK( V3c ) -{ - // Pitch modulation using previous voice's output - if ( m.t_pmon & v->vbit ) - m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - - if ( v->kon_delay ) - { - // Get ready to start BRR decoding on next sample - if ( v->kon_delay == 5 ) - { - v->brr_addr = m.t_brr_next_addr; - v->brr_offset = 1; - v->buf_pos = 0; - m.t_brr_header = 0; // header is ignored on this sample - m.kon_check = true; - - if (take_spc_snapshot) - { - take_spc_snapshot = 0; - if (spc_snapshot_callback) - spc_snapshot_callback(); - } - } - - // Envelope is never run during KON - v->env = 0; - v->hidden_env = 0; - - // Disable BRR decoding until last three samples - v->interp_pos = 0; - if ( --v->kon_delay & 3 ) - v->interp_pos = 0x4000; - - // Pitch is never added during KON - m.t_pitch = 0; - } - - // Gaussian interpolation - { - int output = interpolate( v ); - - // Noise - if ( m.t_non & v->vbit ) - output = (int16_t) (m.noise * 2); - - // Apply envelope - m.t_output = (output * v->env) >> 11 & ~1; - v->t_envx_out = (uint8_t) (v->env >> 4); - } - - // Immediate silence due to end of sample or soft reset - if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) - { - v->env_mode = env_release; - v->env = 0; - } - - if ( m.every_other_sample ) - { - // KOFF - if ( m.t_koff & v->vbit ) - v->env_mode = env_release; - - // KON - if ( m.kon & v->vbit ) - { - v->kon_delay = 5; - v->env_mode = env_attack; - } - } - - // Run envelope for next sample - if ( !v->kon_delay ) - run_envelope( v ); -} - -inline void SPC_DSP::voice_output( voice_t const* v, int ch ) -{ - // Apply left/right volume - int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; - amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); - - // Add to output total - m.t_main_out [ch] += amp; - CLAMP16( m.t_main_out [ch] ); - - // Optionally add to echo total - if ( m.t_eon & v->vbit ) - { - m.t_echo_out [ch] += amp; - CLAMP16( m.t_echo_out [ch] ); - } -} -VOICE_CLOCK( V4 ) -{ - // Decode BRR - m.t_looped = 0; - if ( v->interp_pos >= 0x4000 ) - { - decode_brr( v ); - - if ( (v->brr_offset += 2) >= brr_block_size ) - { - // Start decoding next BRR block - assert( v->brr_offset == brr_block_size ); - v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; - if ( m.t_brr_header & 1 ) - { - v->brr_addr = m.t_brr_next_addr; - m.t_looped = v->vbit; - } - v->brr_offset = 1; - } - } - - // Apply pitch - v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - - // Keep from getting too far ahead (when using pitch modulation) - if ( v->interp_pos > 0x7FFF ) - v->interp_pos = 0x7FFF; - - // Output left - voice_output( v, 0 ); -} -inline VOICE_CLOCK( V5 ) -{ - // Output right - voice_output( v, 1 ); - - // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier - int endx_buf = REG(endx) | m.t_looped; - - // Clear bit in ENDX if KON just began - if ( v->kon_delay == 5 ) - endx_buf &= ~v->vbit; - m.endx_buf = (uint8_t) endx_buf; -} -inline VOICE_CLOCK( V6 ) -{ - (void) v; // avoid compiler warning about unused v - m.outx_buf = (uint8_t) (m.t_output >> 8); -} -inline VOICE_CLOCK( V7 ) -{ - // Update ENDX - REG(endx) = m.endx_buf; - - m.envx_buf = v->t_envx_out; -} -inline VOICE_CLOCK( V8 ) -{ - // Update OUTX - VREG(v->regs,outx) = m.outx_buf; -} -inline VOICE_CLOCK( V9 ) -{ - // Update ENVX - VREG(v->regs,envx) = m.envx_buf; -} - -// Most voices do all these in one clock, so make a handy composite -inline VOICE_CLOCK( V3 ) -{ - voice_V3a( v ); - voice_V3b( v ); - voice_V3c( v ); -} - -// Common combinations of voice steps on different voices. This greatly reduces -// code size and allows everything to be inlined in these functions. -VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } -VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } -VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } - - -//// Echo - -// Current echo buffer pointer for left/right channel -#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) - -// Sample in echo history buffer, where 0 is the oldest -#define ECHO_FIR( i ) (m.echo_hist_pos [i]) - -// Calculate FIR point for left/right channel -#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) - -#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() - -inline void SPC_DSP::echo_read( int ch ) -{ - int s; - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); - else - s = GET_LE16SA( ECHO_PTR( ch ) ); - // second copy simplifies wrap-around handling - ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; -} - -ECHO_CLOCK( 22 ) -{ - // History - if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) - m.echo_hist_pos = m.echo_hist; - - m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; - echo_read( 0 ); - - // FIR (using l and r temporaries below helps compiler optimize) - int l = CALC_FIR( 0, 0 ); - int r = CALC_FIR( 0, 1 ); - - m.t_echo_in [0] = l; - m.t_echo_in [1] = r; -} -ECHO_CLOCK( 23 ) -{ - int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); - int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; - - echo_read( 1 ); -} -ECHO_CLOCK( 24 ) -{ - int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); - int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - - m.t_echo_in [0] += l; - m.t_echo_in [1] += r; -} -ECHO_CLOCK( 25 ) -{ - int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); - int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - - l = (int16_t) l; - r = (int16_t) r; - - l += (int16_t) CALC_FIR( 7, 0 ); - r += (int16_t) CALC_FIR( 7, 1 ); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_in [0] = l & ~1; - m.t_echo_in [1] = r & ~1; -} -inline int SPC_DSP::echo_output( int ch ) -{ - int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + - (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); - CLAMP16( out ); - return out; -} -ECHO_CLOCK( 26 ) -{ - // Left output volumes - // (save sample for next clock so we can output both together) - m.t_main_out [0] = echo_output( 0 ); - - // Echo feedback - int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); - int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - - CLAMP16( l ); - CLAMP16( r ); - - m.t_echo_out [0] = l & ~1; - m.t_echo_out [1] = r & ~1; -} -ECHO_CLOCK( 27 ) -{ - // Output - int l = m.t_main_out [0]; - int r = echo_output( 1 ); - m.t_main_out [0] = 0; - m.t_main_out [1] = 0; - - // TODO: global muting isn't this simple (turns DAC on and off - // or something, causing small ~37-sample pulse when first muted) - if ( REG(flg) & 0x40 ) - { - l = 0; - r = 0; - } - - // Output sample to DAC - #ifdef SPC_DSP_OUT_HOOK - SPC_DSP_OUT_HOOK( l, r ); - #else - sample_t* out = m.out; - WRITE_SAMPLES( l, r, out ); - m.out = out; - #endif -} -ECHO_CLOCK( 28 ) -{ - m.t_echo_enabled = REG(flg); -} -inline void SPC_DSP::echo_write( int ch ) -{ - if ( !(m.t_echo_enabled & 0x20) ) - { - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); - else - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - } - - m.t_echo_out [ch] = 0; -} -ECHO_CLOCK( 29 ) -{ - m.t_esa = REG(esa); - - if ( !m.echo_offset ) - m.echo_length = (REG(edl) & 0x0F) * 0x800; - - m.echo_offset += 4; - if ( m.echo_offset >= m.echo_length ) - m.echo_offset = 0; - - // Write left echo - echo_write( 0 ); - - m.t_echo_enabled = REG(flg); -} -ECHO_CLOCK( 30 ) -{ - // Write right echo - echo_write( 1 ); -} - - -//// Timing - -// Execute clock for a particular voice -#define V( clock, voice ) voice_##clock( &m.voices [voice] ); - -/* The most common sequence of clocks uses composite operations -for efficiency. For example, the following are equivalent to the -individual steps on the right: - -V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) -V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) -V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ - -// Voice 0 1 2 3 4 5 6 7 -#define GEN_DSP_TIMING \ -PHASE( 0) V(V5,0)V(V2,1)\ -PHASE( 1) V(V6,0)V(V3,1)\ -PHASE( 2) V(V7_V4_V1,0)\ -PHASE( 3) V(V8_V5_V2,0)\ -PHASE( 4) V(V9_V6_V3,0)\ -PHASE( 5) V(V7_V4_V1,1)\ -PHASE( 6) V(V8_V5_V2,1)\ -PHASE( 7) V(V9_V6_V3,1)\ -PHASE( 8) V(V7_V4_V1,2)\ -PHASE( 9) V(V8_V5_V2,2)\ -PHASE(10) V(V9_V6_V3,2)\ -PHASE(11) V(V7_V4_V1,3)\ -PHASE(12) V(V8_V5_V2,3)\ -PHASE(13) V(V9_V6_V3,3)\ -PHASE(14) V(V7_V4_V1,4)\ -PHASE(15) V(V8_V5_V2,4)\ -PHASE(16) V(V9_V6_V3,4)\ -PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ -PHASE(18) V(V8_V5_V2,5)\ -PHASE(19) V(V9_V6_V3,5)\ -PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ -PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ -PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ -PHASE(23) V(V7,7) echo_23();\ -PHASE(24) V(V8,7) echo_24();\ -PHASE(25) V(V3b,0) V(V9,7) echo_25();\ -PHASE(26) echo_26();\ -PHASE(27) misc_27(); echo_27();\ -PHASE(28) misc_28(); echo_28();\ -PHASE(29) misc_29(); echo_29();\ -PHASE(30) misc_30();V(V3c,0) echo_30();\ -PHASE(31) V(V4,0) V(V1,2)\ - -#if !SPC_DSP_CUSTOM_RUN - -void SPC_DSP::run( int clocks_remain ) -{ - require( clocks_remain > 0 ); - - int const phase = m.phase; - m.phase = (phase + clocks_remain) & 31; - switch ( phase ) - { - loop: - - #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: - GEN_DSP_TIMING - #undef PHASE - - if ( --clocks_remain ) - goto loop; - } -} - -#endif - - -//// Setup - -void SPC_DSP::init( void* ram_64k ) -{ - m.ram = (uint8_t*) ram_64k; - mute_voices( 0 ); - disable_surround( false ); - set_output( 0, 0 ); - reset(); - - stereo_switch = 0xffff; - take_spc_snapshot = 0; - spc_snapshot_callback = 0; - - #ifndef NDEBUG - // be sure this sign-extends - assert( (int16_t) 0x8000 == -0x8000 ); - - // be sure right shift preserves sign - assert( (-1 >> 1) == -1 ); - - // check clamp macro - int i; - i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); - i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - - blargg_verify_byte_order(); - #endif -} - -void SPC_DSP::soft_reset_common() -{ - require( m.ram ); // init() must have been called already - - m.noise = 0x4000; - m.echo_hist_pos = m.echo_hist; - m.every_other_sample = 1; - m.echo_offset = 0; - m.phase = 0; - - init_counter(); - - for (int i = 0; i < voice_count; i++) - m.voices[i].voice_number = i; -} - -void SPC_DSP::soft_reset() -{ - REG(flg) = 0xE0; - soft_reset_common(); -} - -void SPC_DSP::load( uint8_t const regs [register_count] ) -{ - memcpy( m.regs, regs, sizeof m.regs ); - memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - - // Internal state - for ( int i = voice_count; --i >= 0; ) - { - voice_t* v = &m.voices [i]; - v->brr_offset = 1; - v->vbit = 1 << i; - v->regs = &m.regs [i * 0x10]; - } - m.new_kon = REG(kon); - m.t_dir = REG(dir); - m.t_esa = REG(esa); - - soft_reset_common(); -} - -void SPC_DSP::reset() { load( initial_regs ); } - - -//// State save/load - -#if !SPC_NO_COPY_STATE_FUNCS - -void SPC_State_Copier::copy( void* state, size_t size ) -{ - func( buf, state, size ); -} - -int SPC_State_Copier::copy_int( int state, int size ) -{ - BOOST::uint8_t s [2]; - SET_LE16( s, state ); - func( buf, &s, size ); - return GET_LE16( s ); -} - -void SPC_State_Copier::skip( int count ) -{ - if ( count > 0 ) - { - char temp [64]; - memset( temp, 0, sizeof temp ); - do - { - int n = sizeof temp; - if ( n > count ) - n = count; - count -= n; - func( buf, temp, n ); - } - while ( count ); - } -} - -void SPC_State_Copier::extra() -{ - int n = 0; - SPC_State_Copier& copier = *this; - SPC_COPY( uint8_t, n ); - skip( n ); -} - -void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) -{ - SPC_State_Copier copier( io, copy ); - - // DSP registers - copier.copy( m.regs, register_count ); - - // Internal state - - // Voices - int i; - for ( i = 0; i < voice_count; i++ ) - { - voice_t* v = &m.voices [i]; - - // BRR buffer - int i; - for ( i = 0; i < brr_buf_size; i++ ) - { - int s = v->buf [i]; - SPC_COPY( int16_t, s ); - v->buf [i] = v->buf [i + brr_buf_size] = s; - } - - SPC_COPY( uint16_t, v->interp_pos ); - SPC_COPY( uint16_t, v->brr_addr ); - SPC_COPY( uint16_t, v->env ); - SPC_COPY( int16_t, v->hidden_env ); - SPC_COPY( uint8_t, v->buf_pos ); - SPC_COPY( uint8_t, v->brr_offset ); - SPC_COPY( uint8_t, v->kon_delay ); - { - int m = v->env_mode; - SPC_COPY( uint8_t, m ); - v->env_mode = (enum env_mode_t) m; - } - SPC_COPY( uint8_t, v->t_envx_out ); - - copier.extra(); - } - - // Echo history - for ( i = 0; i < echo_hist_size; i++ ) - { - int j; - for ( j = 0; j < 2; j++ ) - { - int s = m.echo_hist_pos [i] [j]; - SPC_COPY( int16_t, s ); - m.echo_hist [i] [j] = s; // write back at offset 0 - } - } - m.echo_hist_pos = m.echo_hist; - memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - - // Misc - SPC_COPY( uint8_t, m.every_other_sample ); - SPC_COPY( uint8_t, m.kon ); - - SPC_COPY( uint16_t, m.noise ); - SPC_COPY( uint16_t, m.counter ); - SPC_COPY( uint16_t, m.echo_offset ); - SPC_COPY( uint16_t, m.echo_length ); - SPC_COPY( uint8_t, m.phase ); - - SPC_COPY( uint8_t, m.new_kon ); - SPC_COPY( uint8_t, m.endx_buf ); - SPC_COPY( uint8_t, m.envx_buf ); - SPC_COPY( uint8_t, m.outx_buf ); - - SPC_COPY( uint8_t, m.t_pmon ); - SPC_COPY( uint8_t, m.t_non ); - SPC_COPY( uint8_t, m.t_eon ); - SPC_COPY( uint8_t, m.t_dir ); - SPC_COPY( uint8_t, m.t_koff ); - - SPC_COPY( uint16_t, m.t_brr_next_addr ); - SPC_COPY( uint8_t, m.t_adsr0 ); - SPC_COPY( uint8_t, m.t_brr_header ); - SPC_COPY( uint8_t, m.t_brr_byte ); - SPC_COPY( uint8_t, m.t_srcn ); - SPC_COPY( uint8_t, m.t_esa ); - SPC_COPY( uint8_t, m.t_echo_enabled ); - - SPC_COPY( int16_t, m.t_main_out [0] ); - SPC_COPY( int16_t, m.t_main_out [1] ); - SPC_COPY( int16_t, m.t_echo_out [0] ); - SPC_COPY( int16_t, m.t_echo_out [1] ); - SPC_COPY( int16_t, m.t_echo_in [0] ); - SPC_COPY( int16_t, m.t_echo_in [1] ); - - SPC_COPY( uint16_t, m.t_dir_addr ); - SPC_COPY( uint16_t, m.t_pitch ); - SPC_COPY( int16_t, m.t_output ); - SPC_COPY( uint16_t, m.t_echo_ptr ); - SPC_COPY( uint8_t, m.t_looped ); - - copier.extra(); -} -#endif - - -//// Snes9x Accessor - -void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) -{ - spc_snapshot_callback = callback; -} - -void SPC_DSP::dump_spc_snapshot( void ) -{ - take_spc_snapshot = 1; -} - -void SPC_DSP::set_stereo_switch( int value ) -{ - stereo_switch = value; -} - -SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) -{ - return m.voices[ch].regs[addr]; -} - -int SPC_DSP::envx_value( int ch ) -{ - return m.voices[ch].env; -} diff --git a/apu/SPC_DSP.h b/apu/SPC_DSP.h deleted file mode 100644 index 61d05ab5..00000000 --- a/apu/SPC_DSP.h +++ /dev/null @@ -1,319 +0,0 @@ -// Highly accurate SNES SPC-700 DSP emulator - -// snes_spc 0.9.0 -#ifndef SPC_DSP_H -#define SPC_DSP_H - -#include "blargg_common.h" - -extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } - -class SPC_DSP { -public: - typedef BOOST::uint8_t uint8_t; - -// Setup - - // Initializes DSP and has it use the 64K RAM provided - void init( void* ram_64k ); - - // Sets destination for output samples. If out is NULL or out_size is 0, - // doesn't generate any. - typedef short sample_t; - void set_output( sample_t* out, int out_size ); - - // Number of samples written to output since it was last set, always - // a multiple of 2. Undefined if more samples were generated than - // output buffer could hold. - int sample_count() const; - -// Emulation - - // Resets DSP to power-on state - void reset(); - - // Emulates pressing reset switch on SNES - void soft_reset(); - - // Reads/writes DSP registers. For accuracy, you must first call run() - // to catch the DSP up to present. - int read ( int addr ) const; - void write( int addr, int data ); - - // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks - // a pair of samples is be generated. - void run( int clock_count ); - -// Sound control - - // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). - // Reduces emulation accuracy. - enum { voice_count = 8 }; - void mute_voices( int mask ); - -// State - - // Resets DSP and uses supplied values to initialize registers - enum { register_count = 128 }; - void load( uint8_t const regs [register_count] ); - - // Saves/loads exact emulator state - enum { state_size = 640 }; // maximum space needed when saving - typedef dsp_copy_func_t copy_func_t; - void copy_state( unsigned char** io, copy_func_t ); - - // Returns non-zero if new key-on events occurred since last call - bool check_kon(); - -// Snes9x Accessor - - int stereo_switch; - int take_spc_snapshot; - int rom_enabled; // mirror - uint8_t *rom, *hi_ram; // mirror - void (*spc_snapshot_callback) (void); - - void set_spc_snapshot_callback( void (*callback) (void) ); - void dump_spc_snapshot( void ); - void set_stereo_switch( int ); - uint8_t reg_value( int, int ); - int envx_value( int ); - -// DSP register addresses - - // Global registers - enum { - r_mvoll = 0x0C, r_mvolr = 0x1C, - r_evoll = 0x2C, r_evolr = 0x3C, - r_kon = 0x4C, r_koff = 0x5C, - r_flg = 0x6C, r_endx = 0x7C, - r_efb = 0x0D, r_pmon = 0x2D, - r_non = 0x3D, r_eon = 0x4D, - r_dir = 0x5D, r_esa = 0x6D, - r_edl = 0x7D, - r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F - }; - - // Voice registers - enum { - v_voll = 0x00, v_volr = 0x01, - v_pitchl = 0x02, v_pitchh = 0x03, - v_srcn = 0x04, v_adsr0 = 0x05, - v_adsr1 = 0x06, v_gain = 0x07, - v_envx = 0x08, v_outx = 0x09 - }; - -public: - enum { extra_size = 16 }; - sample_t* extra() { return m.extra; } - sample_t const* out_pos() const { return m.out; } - void disable_surround( bool ) { } // not supported -public: - BLARGG_DISABLE_NOTHROW - - typedef BOOST::int8_t int8_t; - typedef BOOST::int16_t int16_t; - - enum { echo_hist_size = 8 }; - - enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; - enum { brr_buf_size = 12 }; - struct voice_t - { - int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) - int buf_pos; // place in buffer where next samples will be decoded - int interp_pos; // relative fractional position in sample (0x1000 = 1.0) - int brr_addr; // address of current BRR block - int brr_offset; // current decoding offset in BRR block - uint8_t* regs; // pointer to voice's DSP registers - int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. - int kon_delay; // KON delay/current setup phase - env_mode_t env_mode; - int env; // current envelope level - int hidden_env; // used by GAIN mode 7, very obscure quirk - uint8_t t_envx_out; - int voice_number; - }; -private: - enum { brr_block_size = 9 }; - - struct state_t - { - uint8_t regs [register_count]; - - // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) - int echo_hist [echo_hist_size * 2] [2]; - int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - - int every_other_sample; // toggles every sample - int kon; // KON value when last checked - int noise; - int counter; - int echo_offset; // offset from ESA in echo buffer - int echo_length; // number of bytes that echo_offset will stop at - int phase; // next clock cycle to run (0-31) - bool kon_check; // set when a new KON occurs - - // Hidden registers also written to when main register is written to - int new_kon; - uint8_t endx_buf; - uint8_t envx_buf; - uint8_t outx_buf; - - // Temporary state between clocks - - // read once per sample - int t_pmon; - int t_non; - int t_eon; - int t_dir; - int t_koff; - - // read a few clocks ahead then used - int t_brr_next_addr; - int t_adsr0; - int t_brr_header; - int t_brr_byte; - int t_srcn; - int t_esa; - int t_echo_enabled; - - // internal state that is recalculated every sample - int t_dir_addr; - int t_pitch; - int t_output; - int t_looped; - int t_echo_ptr; - - // left/right sums - int t_main_out [2]; - int t_echo_out [2]; - int t_echo_in [2]; - - voice_t voices [voice_count]; - - // non-emulation state - uint8_t* ram; // 64K shared RAM between DSP and SMP - int mute_mask; - sample_t* out; - sample_t* out_end; - sample_t* out_begin; - sample_t extra [extra_size]; - }; - state_t m; - - void init_counter(); - void run_counters(); - unsigned read_counter( int rate ); - - int interpolate( voice_t const* v ); - void run_envelope( voice_t* const v ); - void decode_brr( voice_t* v ); - - void misc_27(); - void misc_28(); - void misc_29(); - void misc_30(); - - void voice_output( voice_t const* v, int ch ); - void voice_V1( voice_t* const ); - void voice_V2( voice_t* const ); - void voice_V3( voice_t* const ); - void voice_V3a( voice_t* const ); - void voice_V3b( voice_t* const ); - void voice_V3c( voice_t* const ); - void voice_V4( voice_t* const ); - void voice_V5( voice_t* const ); - void voice_V6( voice_t* const ); - void voice_V7( voice_t* const ); - void voice_V8( voice_t* const ); - void voice_V9( voice_t* const ); - void voice_V7_V4_V1( voice_t* const ); - void voice_V8_V5_V2( voice_t* const ); - void voice_V9_V6_V3( voice_t* const ); - - void echo_read( int ch ); - int echo_output( int ch ); - void echo_write( int ch ); - void echo_22(); - void echo_23(); - void echo_24(); - void echo_25(); - void echo_26(); - void echo_27(); - void echo_28(); - void echo_29(); - void echo_30(); - - void soft_reset_common(); -}; - -#include - -inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } - -inline int SPC_DSP::read( int addr ) const -{ - assert( (unsigned) addr < register_count ); - return m.regs [addr]; -} - -inline void SPC_DSP::write( int addr, int data ) -{ - assert( (unsigned) addr < register_count ); - - m.regs [addr] = (uint8_t) data; - switch ( addr & 0x0F ) - { - case v_envx: - m.envx_buf = (uint8_t) data; - break; - - case v_outx: - m.outx_buf = (uint8_t) data; - break; - - case 0x0C: - if ( addr == r_kon ) - m.new_kon = (uint8_t) data; - - if ( addr == r_endx ) // always cleared, regardless of data written - { - m.endx_buf = 0; - m.regs [r_endx] = 0; - } - break; - } -} - -inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } - -inline bool SPC_DSP::check_kon() -{ - bool old = m.kon_check; - m.kon_check = 0; - return old; -} - -#if !SPC_NO_COPY_STATE_FUNCS - -class SPC_State_Copier { - SPC_DSP::copy_func_t func; - unsigned char** buf; -public: - SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } - void copy( void* state, size_t size ); - int copy_int( int state, int size ); - void skip( int count ); - void extra(); -}; - -#define SPC_COPY( type, state )\ -{\ - state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ - assert( (BOOST::type) state == state );\ -} - -#endif - -#endif diff --git a/apu/SPC_Filter.cpp b/apu/SPC_Filter.cpp deleted file mode 100644 index b3d57708..00000000 --- a/apu/SPC_Filter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// snes_spc 0.9.0. http://www.slack.net/~ant/ - -#include "SPC_Filter.h" - -#include - -/* Copyright (C) 2007 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more -details. You should have received a copy of the GNU Lesser General Public -License along with this module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } - -SPC_Filter::SPC_Filter() -{ - gain = gain_unit; - bass = bass_norm; - clear(); -} - -void SPC_Filter::run( short* io, int count ) -{ - require( (count & 1) == 0 ); // must be even - - int const gain = this->gain; - int const bass = this->bass; - chan_t* c = &ch [2]; - do - { - // cache in registers - int sum = (--c)->sum; - int pp1 = c->pp1; - int p1 = c->p1; - - for ( int i = 0; i < count; i += 2 ) - { - // Low-pass filter (two point FIR with coeffs 0.25, 0.75) - int f = io [i] + p1; - p1 = io [i] * 3; - - // High-pass filter ("leaky integrator") - int delta = f - pp1; - pp1 = f; - int s = sum >> (gain_bits + 2); - sum += (delta * gain) - (sum >> bass); - - // Clamp to 16 bits - if ( (short) s != s ) - s = (s >> 31) ^ 0x7FFF; - - io [i] = (short) s; - } - - c->p1 = p1; - c->pp1 = pp1; - c->sum = sum; - ++io; - } - while ( c != ch ); -} diff --git a/apu/SPC_Filter.h b/apu/SPC_Filter.h deleted file mode 100644 index d5c83cb8..00000000 --- a/apu/SPC_Filter.h +++ /dev/null @@ -1,47 +0,0 @@ -// Simple low-pass and high-pass filter to better match sound output of a SNES - -// snes_spc 0.9.0 -#ifndef SPC_FILTER_H -#define SPC_FILTER_H - -#include "blargg_common.h" - -struct SPC_Filter { -public: - - // Filters count samples of stereo sound in place. Count must be a multiple of 2. - typedef short sample_t; - void run( sample_t* io, int count ); - -// Optional features - - // Clears filter to silence - void clear(); - - // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit - // are fine, since output is clamped to 16-bit sample range. - enum { gain_unit = 0x100 }; - void set_gain( int gain ); - - // Sets amount of bass (logarithmic scale) - enum { bass_none = 0 }; - enum { bass_norm = 8 }; // normal amount - enum { bass_max = 31 }; - void set_bass( int bass ); - -public: - SPC_Filter(); - BLARGG_DISABLE_NOTHROW -private: - enum { gain_bits = 8 }; - int gain; - int bass; - struct chan_t { int p1, pp1, sum; }; - chan_t ch [2]; -}; - -inline void SPC_Filter::set_gain( int g ) { gain = g; } - -inline void SPC_Filter::set_bass( int b ) { bass = b; } - -#endif diff --git a/apu/apu.cpp b/apu/apu.cpp index 47f03b6b..de70a4e1 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -175,14 +175,13 @@ Nintendo Co., Limited and its subsidiary companies. ***********************************************************************************/ - #include #include "snes9x.h" #include "apu.h" #include "snapshot.h" #include "display.h" -#include "linear_resampler.h" #include "hermite_resampler.h" + #include "snes/snes.hpp" #define APU_DEFAULT_INPUT_RATE 32000 @@ -192,27 +191,12 @@ #define APU_DENOMINATOR_NTSC 328125 #define APU_NUMERATOR_PAL 34176 #define APU_DENOMINATOR_PAL 709379 -#define APU_DEFAULT_RESAMPLER HermiteResampler - -SNES_SPC *spc_core = NULL; namespace SNES { CPU cpu; } -static uint8 APUROM[64] = -{ - 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, - 0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78, - 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4, - 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, - 0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, - 0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA, - 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD, - 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF -}; - namespace spc { static apu_callback sa_callback = NULL; @@ -233,8 +217,8 @@ namespace spc static int32 reference_time; static uint32 remainder; - static const int timing_hack_numerator = SNES_SPC::tempo_unit; - static int timing_hack_denominator = SNES_SPC::tempo_unit; + static const int timing_hack_numerator = 256; + static int timing_hack_denominator = 256; /* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup if necessary on game load. */ static uint32 ratio_numerator = APU_NUMERATOR_NTSC; @@ -360,11 +344,12 @@ int S9xGetSampleCount (void) return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1)); } +/* TODO: Attach */ void S9xFinalizeSamples (void) { if (!Settings.Mute) { - if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count())) + if (!spc::resampler->push((short *) spc::landing_buffer, SNES::dsp.spc_dsp.sample_count ())) { /* We weren't able to process the entire buffer. Potential overrun. */ spc::sound_in_sync = FALSE; @@ -382,7 +367,7 @@ void S9xFinalizeSamples (void) else spc::sound_in_sync = FALSE; - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); } void S9xLandSamples (void) @@ -458,7 +443,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) arguments. Use 2x in the resampler for buffer leveling with SoundSync */ if (!spc::resampler) { - spc::resampler = new APU_DEFAULT_RESAMPLER(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + spc::resampler = new HermiteResampler(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); if (!spc::resampler) { delete[] spc::landing_buffer; @@ -468,7 +453,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) else spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); UpdatePlaybackRate(); @@ -479,7 +464,8 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) void S9xSetSoundControl (uint8 voice_switch) { - spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); + /* + spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); */ } void S9xSetSoundMute (bool8 mute) @@ -491,7 +477,8 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { - spc_core->dsp_dump_spc_snapshot(); +/* No SPC dumping ATM in byuu SMP */ +/* spc_core->dsp_dump_spc_snapshot(); */ } static void SPCSnapshotCallback (void) @@ -502,15 +489,6 @@ static void SPCSnapshotCallback (void) bool8 S9xInitAPU (void) { - spc_core = new SNES_SPC; - if (!spc_core) - return (FALSE); - - spc_core->init(); - spc_core->init_rom(APUROM); - - spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback); - spc::landing_buffer = NULL; spc::shrink_buffer = NULL; spc::resampler = NULL; @@ -520,12 +498,6 @@ bool8 S9xInitAPU (void) void S9xDeinitAPU (void) { - if (spc_core) - { - delete spc_core; - spc_core = NULL; - } - if (spc::resampler) { delete spc::resampler; @@ -559,12 +531,14 @@ static inline int S9xAPUGetClockRemainder (int32 cpucycles) uint8 S9xAPUReadPort (int port) { - return ((uint8) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port)); + S9xAPUExecute (); + return ((uint8) SNES::smp.port_read (port & 3)); } void S9xAPUWritePort (int port, uint8 byte) { - spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte); + S9xAPUExecute (); + SNES::smp.port_write (port & 3, byte); } void S9xAPUSetReferenceTime (int32 cpucycles) @@ -574,8 +548,8 @@ void S9xAPUSetReferenceTime (int32 cpucycles) void S9xAPUExecute (void) { - /* Accumulate partial APU cycles */ - spc_core->end_frame(S9xAPUGetClock(CPU.Cycles)); + SNES::smp.clock -= S9xAPUGetClock (CPU.Cycles); + SNES::smp.enter (); spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); @@ -586,7 +560,7 @@ void S9xAPUEndScanline (void) { S9xAPUExecute(); - if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) + if (SNES::dsp.spc_dsp.sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) S9xLandSamples(); } @@ -595,8 +569,7 @@ void S9xAPUTimingSetSpeedup (int ticks) if (ticks != 0) printf("APU speedup hack: %d\n", ticks); - spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; - spc_core->set_tempo(spc::timing_hack_denominator); + spc::timing_hack_denominator = 256 - ticks; spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC; spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC; @@ -610,15 +583,18 @@ void S9xAPUAllowTimeOverflow (bool allow) if (allow) printf("APU time overflow allowed\n"); - spc_core->spc_allow_time_overflow(allow); + /* spc_core->spc_allow_time_overflow(allow); */ } void S9xResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; - spc_core->reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + SNES::cpu.frequency = Settings.PAL ? PAL_MASTER_CLOCK : NTSC_MASTER_CLOCK; + SNES::smp.power (); + SNES::dsp.power (); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); spc::resampler->clear(); } @@ -627,38 +603,27 @@ void S9xSoftResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; - spc_core->soft_reset(); - spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::smp.reset (); + SNES::dsp.reset (); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); spc::resampler->clear(); } -static void from_apu_to_state (uint8 **buf, void *var, size_t size) -{ - memcpy(*buf, var, size); - *buf += size; -} - -static void to_apu_from_state (uint8 **buf, void *var, size_t size) -{ - memcpy(var, *buf, size); - *buf += size; -} - void S9xAPUSaveState (uint8 *block) { - uint8 *ptr = block; +/* uint8 *ptr = block; spc_core->copy_state(&ptr, from_apu_to_state); SET_LE32(ptr, spc::reference_time); ptr += sizeof(int32); - SET_LE32(ptr, spc::remainder); + SET_LE32(ptr, spc::remainder); */ } void S9xAPULoadState (uint8 *block) { - uint8 *ptr = block; + /*uint8 *ptr = block; S9xResetAPU(); @@ -666,5 +631,5 @@ void S9xAPULoadState (uint8 *block) spc::reference_time = GET_LE32(ptr); ptr += sizeof(int32); - spc::remainder = GET_LE32(ptr); + spc::remainder = GET_LE32(ptr); */ } diff --git a/apu/apu.h b/apu/apu.h index 358469da..c0967caa 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -180,7 +180,6 @@ #define _APU_H_ #include "snes9x.h" -#include "SNES_SPC.h" typedef void (*apu_callback) (void *); @@ -214,6 +213,4 @@ void S9xClearSamples (void); bool8 S9xMixSamples (uint8 *, int); void S9xSetSamplesAvailableCallback (apu_callback, void *); -extern SNES_SPC *spc_core; - #endif diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index f82bd824..c0a2a9c8 100755 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -18,12 +18,6 @@ void DSP::synchronize_smp() { void DSP::enter() { spc_dsp.run(1); step(24); - -/* signed count = spc_dsp.sample_count(); - if(count > 0) { - for(unsigned n = 0; n < count; n += 2) audio.sample(samplebuffer[n + 0], samplebuffer[n + 1]); - spc_dsp.set_output(samplebuffer, 8192); - } */ } uint8 DSP::read(uint8 addr) { @@ -37,12 +31,10 @@ void DSP::write(uint8 addr, uint8 data) { void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); - spc_dsp.set_output(samplebuffer, 8192); } void DSP::reset() { spc_dsp.soft_reset(); - spc_dsp.set_output(samplebuffer, 8192); } void DSP::channel_enable(unsigned channel, bool enable) { diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index 634c6da4..ef2dc7c7 100755 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -17,9 +17,9 @@ public: DSP(); -private: SPC_DSP spc_dsp; - int16 samplebuffer[8192]; + +private: bool channel_enabled[8]; }; diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index ba26d0b4..04a2da4e 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -42,8 +42,6 @@ void SMP::enter() { void SMP::power() { #ifdef BSNES Processor::frequency = system.apu_frequency(); -#else - Processor::frequency = 1025600; #endif Processor::clock = 0; diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 47b687ff..b4010a67 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -23,10 +23,12 @@ public: void enter () { + return; } void port_write (uint8 port, uint8 data) { + } uint8 port_read (uint8 port) diff --git a/apu/blargg_common.h b/apu/blargg_common.h deleted file mode 100644 index 75edff39..00000000 --- a/apu/blargg_common.h +++ /dev/null @@ -1,186 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// snes_spc 0.9.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include -#include - -#undef BLARGG_COMMON_H -// allow blargg_config.h to #include blargg_common.h -#include "blargg_config.h" -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -// BLARGG_RESTRICT: equivalent to restrict, where supported -#if defined (__GNUC__) || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -// STATIC_CAST(T,expr): Used in place of static_cast (expr) -#ifndef STATIC_CAST - #define STATIC_CAST(T,expr) ((T) (expr)) -#endif - -// blargg_err_t (0 on success, otherwise error string) -#ifndef blargg_err_t - typedef const char* blargg_err_t; -#endif - -// blargg_vector - very lightweight vector of POD types (no constructor/destructor) -template -class blargg_vector { - T* begin_; - size_t size_; -public: - blargg_vector() : begin_( 0 ), size_( 0 ) { } - ~blargg_vector() { free( begin_ ); } - size_t size() const { return size_; } - T* begin() const { return begin_; } - T* end() const { return begin_ + size_; } - blargg_err_t resize( size_t n ) - { - // TODO: blargg_common.cpp to hold this as an outline function, ugh - void* p = realloc( begin_, n * sizeof (T) ); - if ( p ) - begin_ = (T*) p; - else if ( n > size_ ) // realloc failure only a problem if expanding - return "Out of memory"; - size_ = n; - return 0; - } - void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } - T& operator [] ( size_t n ) const - { - assert( n <= size_ ); // <= to allow past-the-end value - return begin_ [n]; - } -}; - -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if operator new can return NULL - #if __cplusplus >= 199711 || defined (__GNUC__) - #define BLARGG_THROWS( spec ) throw spec - #else - #define BLARGG_THROWS( spec ) - #endif - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ - void operator delete ( void* p ) { free( p ); } - #define BLARGG_NEW new -#else - #include - #define BLARGG_NEW new (std::nothrow) -#endif - -// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) - -// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -#ifndef BOOST_STATIC_ASSERT - #ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) - #else - // Some other compilers fail when declaring same function multiple times in class, - // so differentiate them by line - #define BOOST_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) - #endif -#endif - -// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, -// compiler is assumed to support bool. If undefined, availability is determined. -#ifndef BLARGG_COMPILER_HAS_BOOL - #if defined (__MWERKS__) - #if !__option(bool) - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (_MSC_VER) - #if _MSC_VER < 1100 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif - #elif defined (__GNUC__) - // supports bool - #elif __cplusplus < 199711 - #define BLARGG_COMPILER_HAS_BOOL 0 - #endif -#endif -#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL - // If you get errors here, modify your blargg_config.h file - typedef int bool; - const bool true = 1; - const bool false = 0; -#endif - -// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough - -#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF - typedef long blargg_long; -#else - typedef int blargg_long; -#endif - -#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF - typedef unsigned long blargg_ulong; -#else - typedef unsigned blargg_ulong; -#endif - -// BOOST::int8_t etc. - -// HAVE_STDINT_H: If defined, use for int8_t etc. -#if defined (HAVE_STDINT_H) - #include - #define BOOST - -// HAVE_INTTYPES_H: If defined, use for int8_t etc. -#elif defined (HAVE_INTTYPES_H) - #include - #define BOOST - -#else - struct BOOST - { - #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F - typedef signed char int8_t; - typedef unsigned char uint8_t; - #else - // No suitable 8-bit type available - typedef struct see_blargg_common_h int8_t; - typedef struct see_blargg_common_h uint8_t; - #endif - - #if USHRT_MAX == 0xFFFF - typedef short int16_t; - typedef unsigned short uint16_t; - #else - // No suitable 16-bit type available - typedef struct see_blargg_common_h int16_t; - typedef struct see_blargg_common_h uint16_t; - #endif - - #if ULONG_MAX == 0xFFFFFFFF - typedef long int32_t; - typedef unsigned long uint32_t; - #elif UINT_MAX == 0xFFFFFFFF - typedef int int32_t; - typedef unsigned int uint32_t; - #else - // No suitable 32-bit type available - typedef struct see_blargg_common_h int32_t; - typedef struct see_blargg_common_h uint32_t; - #endif - }; -#endif - -#endif -#endif diff --git a/apu/blargg_config.h b/apu/blargg_config.h deleted file mode 100644 index 9dc69db8..00000000 --- a/apu/blargg_config.h +++ /dev/null @@ -1,24 +0,0 @@ -// snes_spc 0.9.0 user configuration file. Don't replace when updating library. - -// snes_spc 0.9.0 -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment to disable debugging checks -//#define NDEBUG 1 - -// Uncomment to enable platform-specific (and possibly non-portable) optimizations -//#define BLARGG_NONPORTABLE 1 - -// Uncomment if automatic byte-order determination doesn't work -//#define BLARGG_BIG_ENDIAN 1 - -// Uncomment if you get errors in the bool section of blargg_common.h -//#define BLARGG_COMPILER_HAS_BOOL 1 - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/apu/blargg_endian.h b/apu/blargg_endian.h deleted file mode 100644 index f2daca64..00000000 --- a/apu/blargg_endian.h +++ /dev/null @@ -1,185 +0,0 @@ -// CPU Byte Order Utilities - -// snes_spc 0.9.0 -#ifndef BLARGG_ENDIAN -#define BLARGG_ENDIAN - -#include "blargg_common.h" - -// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ - defined (__x86_64__) || defined (__ia64__) || defined (__i386__) - #define BLARGG_CPU_X86 1 - #define BLARGG_CPU_CISC 1 -#endif - -#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) - #define BLARGG_CPU_POWERPC 1 - #define BLARGG_CPU_RISC 1 -#endif - -// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only -// one may be #defined to 1. Only needed if something actually depends on byte order. -#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) -#ifdef __GLIBC__ - // GCC handles this for us - #include - #if __BYTE_ORDER == __LITTLE_ENDIAN - #define BLARGG_LITTLE_ENDIAN 1 - #elif __BYTE_ORDER == __BIG_ENDIAN - #define BLARGG_BIG_ENDIAN 1 - #endif -#else - -#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ - (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) - #define BLARGG_LITTLE_ENDIAN 1 -#endif - -#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__sparc__) || BLARGG_CPU_POWERPC || \ - (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) - #define BLARGG_BIG_ENDIAN 1 -#elif !defined (__mips__) - // No endian specified; assume little-endian, since it's most common - #define BLARGG_LITTLE_ENDIAN 1 -#endif -#endif -#endif - -#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN - #undef BLARGG_LITTLE_ENDIAN - #undef BLARGG_BIG_ENDIAN -#endif - -inline void blargg_verify_byte_order() -{ - #ifndef NDEBUG - #if BLARGG_BIG_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i == 0 ); - #elif BLARGG_LITTLE_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i != 0 ); - #endif - #endif -} - -inline unsigned get_le16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 8 | - (unsigned) ((unsigned char const*) p) [1]; -} - -inline blargg_ulong get_le32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | - (blargg_ulong) ((unsigned char const*) p) [2] << 16 | - (blargg_ulong) ((unsigned char const*) p) [1] << 8 | - (blargg_ulong) ((unsigned char const*) p) [0]; -} - -inline blargg_ulong get_be32( void const* p ) -{ - return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | - (blargg_ulong) ((unsigned char const*) p) [1] << 16 | - (blargg_ulong) ((unsigned char const*) p) [2] << 8 | - (blargg_ulong) ((unsigned char const*) p) [3]; -} - -inline void set_le16( void* p, unsigned n ) -{ - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [0] = (unsigned char) n; -} - -inline void set_be16( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) n; -} - -inline void set_le32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [0] = (unsigned char) n; - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); -} - -inline void set_be32( void* p, blargg_ulong n ) -{ - ((unsigned char*) p) [3] = (unsigned char) n; - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); -} - -#if BLARGG_NONPORTABLE - // Optimized implementation if byte order is known - #if BLARGG_LITTLE_ENDIAN - #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #elif BLARGG_BIG_ENDIAN - #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) - #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) - #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - - #if BLARGG_CPU_POWERPC - // PowerPC has special byte-reversed instructions - #if defined (__MWERKS__) - #define GET_LE16( addr ) (__lhbrx( addr, 0 )) - #define GET_LE32( addr ) (__lwbrx( addr, 0 )) - #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) - #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) - #elif defined (__GNUC__) - #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) - #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) - #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) - #endif - #endif - #endif -#endif - -#ifndef GET_LE16 - #define GET_LE16( addr ) get_le16( addr ) - #define SET_LE16( addr, data ) set_le16( addr, data ) -#endif - -#ifndef GET_LE32 - #define GET_LE32( addr ) get_le32( addr ) - #define SET_LE32( addr, data ) set_le32( addr, data ) -#endif - -#ifndef GET_BE16 - #define GET_BE16( addr ) get_be16( addr ) - #define SET_BE16( addr, data ) set_be16( addr, data ) -#endif - -#ifndef GET_BE32 - #define GET_BE32( addr ) get_be32( addr ) - #define SET_BE32( addr, data ) set_be32( addr, data ) -#endif - -// auto-selecting versions - -inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } -inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } -inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } -inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } -inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } -inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } -inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } -inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } - -#endif diff --git a/apu/blargg_source.h b/apu/blargg_source.h deleted file mode 100644 index 5e45c4fb..00000000 --- a/apu/blargg_source.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Included at the beginning of library source files, after all other #include lines. -Sets up helpful macros and services used in my source code. They don't need -module an annoying module prefix on their names since they are defined after -all other #include lines. */ - -// snes_spc 0.9.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -// If debugging is enabled, abort program if expr is false. Meant for checking -// internal state and consistency. A failed assertion indicates a bug in the module. -// void assert( bool expr ); -#include - -// If debugging is enabled and expr is false, abort program. Meant for checking -// caller-supplied parameters and operations that are outside the control of the -// module. A failed requirement indicates a bug outside the module. -// void require( bool expr ); -#undef require -#define require( expr ) assert( expr ) - -// Like printf() except output goes to debug log file. Might be defined to do -// nothing (not even evaluate its arguments). -// void dprintf( const char* format, ... ); -static inline void blargg_dprintf_( const char*, ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -// If enabled, evaluate expr and if false, make debug log entry with source file -// and line. Meant for finding situations that should be examined further, but that -// don't indicate a problem. In all cases, execution continues normally. -#undef check -#define check( expr ) ((void) 0) - -// If expr yields error string, return it from current function, otherwise continue. -#undef RETURN_ERR -#define RETURN_ERR( expr ) do { \ - blargg_err_t blargg_return_err_ = (expr); \ - if ( blargg_return_err_ ) return blargg_return_err_; \ - } while ( 0 ) - -// If ptr is 0, return out of memory error string. -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) - -// Avoid any macros which evaluate their arguments multiple times -#undef min -#undef max - -#define DEF_MIN_MAX( type ) \ - static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ - static inline type max( type x, type y ) { if ( y < x ) return x; return y; } - -DEF_MIN_MAX( int ) -DEF_MIN_MAX( unsigned ) -DEF_MIN_MAX( long ) -DEF_MIN_MAX( unsigned long ) -DEF_MIN_MAX( float ) -DEF_MIN_MAX( double ) - -#undef DEF_MIN_MAX - -/* -// using const references generates crappy code, and I am currenly only using these -// for built-in types, so they take arguments by value - -// TODO: remove -inline int min( int x, int y ) -template -inline T min( T x, T y ) -{ - if ( x < y ) - return x; - return y; -} - -template -inline T max( T x, T y ) -{ - if ( x < y ) - return y; - return x; -} -*/ - -// TODO: good idea? bad idea? -#undef byte -#define byte byte_ -typedef unsigned char byte; - -// deprecated -#define BLARGG_CHECK_ALLOC CHECK_ALLOC -#define BLARGG_RETURN_ERR RETURN_ERR - -// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif diff --git a/apu/license.txt b/apu/license.txt deleted file mode 100644 index 5ab7695a..00000000 --- a/apu/license.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/apu/linear_resampler.h b/apu/linear_resampler.h deleted file mode 100644 index 35789db1..00000000 --- a/apu/linear_resampler.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Simple fixed-point linear resampler by BearOso*/ - -#ifndef __LINEAR_RESAMPLER_H -#define __LINEAR_RESAMPLER_H - -#include "resampler.h" -#include "snes9x.h" - -static const int f_prec = 15; -static const uint32 f__one = (1 << f_prec); - -#define lerp(t, a, b) (((((b) - (a)) * (t)) >> f_prec) + (a)) - -class LinearResampler : public Resampler -{ - protected: - uint32 f__r_step; - uint32 f__inv_r_step; - uint32 f__r_frac; - int r_left, r_right; - - public: - LinearResampler (int num_samples) : Resampler (num_samples) - { - f__r_frac = 0; - } - - ~LinearResampler () - { - } - - void - time_ratio (double ratio) - { - if (ratio == 0.0) - ratio = 1.0; - f__r_step = (uint32) (ratio * f__one); - f__inv_r_step = (uint32) (f__one / ratio); - clear (); - } - - void - clear (void) - { - ring_buffer::clear (); - f__r_frac = 0; - r_left = 0; - r_right = 0; - } - - void - read (short *data, int num_samples) - { - int i_position = start >> 1; - short *internal_buffer = (short *) buffer; - int o_position = 0; - int consumed = 0; - int max_samples = (buffer_size >> 1); - - while (o_position < num_samples && consumed < buffer_size) - { - if (f__r_step == f__one) - { - data[o_position] = internal_buffer[i_position]; - data[o_position + 1] = internal_buffer[i_position + 1]; - - o_position += 2; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - - continue; - } - - while (f__r_frac <= f__one && o_position < num_samples) - { - data[o_position] = lerp (f__r_frac, - r_left, - internal_buffer[i_position]); - data[o_position + 1] = lerp (f__r_frac, - r_right, - internal_buffer[i_position + 1]); - - o_position += 2; - - f__r_frac += f__r_step; - } - - if (f__r_frac > f__one) - { - f__r_frac -= f__one; - r_left = internal_buffer[i_position]; - r_right = internal_buffer[i_position + 1]; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - } - } - - size -= consumed << 1; - start += consumed << 1; - if (start >= buffer_size) - start -= buffer_size; - } - - inline int - avail (void) - { - return (((size >> 2) * f__inv_r_step) - ((f__r_frac * f__inv_r_step) >> f_prec)) >> (f_prec - 1); - } -}; - -#endif /* __LINEAR_RESAMPLER_H */ diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 4ec45d06..607d70bb 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -119,11 +119,7 @@ endif # APU snes9x_gtk_SOURCES += \ - ../apu/apu.cpp \ - ../apu/SNES_SPC.cpp \ - ../apu/SNES_SPC_misc.cpp \ - ../apu/SNES_SPC_state.cpp \ - ../apu/SPC_Filter.cpp + ../apu/apu.cpp # Byuu's APU snes9x_gtk_SOURCES += \ diff --git a/snapshot.cpp b/snapshot.cpp index 7b758b42..e2163de6 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1269,7 +1269,7 @@ bool8 S9xUnfreezeGame (const char *filename) void S9xFreezeToStream (STREAM stream) { char buffer[1024]; - uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + //uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; S9xSetSoundMute(TRUE); @@ -1298,8 +1298,8 @@ void S9xFreezeToStream (STREAM stream) FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - S9xAPUSaveState(soundsnapshot); - FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + //S9xAPUSaveState(soundsnapshot); + //FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); struct SControlSnapshot ctl_snap; S9xControlPreSaveState(&ctl_snap); @@ -1410,7 +1410,7 @@ void S9xFreezeToStream (STREAM stream) S9xSetSoundMute(FALSE); - delete [] soundsnapshot; + //delete [] soundsnapshot; } int S9xUnfreezeFromStream (STREAM stream) @@ -1496,7 +1496,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS) break; - result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + // result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); if (result != SUCCESS) break; @@ -2278,6 +2278,8 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie bool8 S9xSPCDump (const char *filename) { + /* No SPC dumping in byuu SMP */ + /* FILE *fs; uint8 buf[SNES_SPC::spc_file_size]; size_t ignore; @@ -2296,6 +2298,6 @@ bool8 S9xSPCDump (const char *filename) fclose(fs); S9xSetSoundMute(FALSE); - + */ return (TRUE); } From 5d5eaedd5e9d95f6d275962dd498c839f97ebe80 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 22 Jun 2011 06:03:29 -0500 Subject: [PATCH 012/130] New SMP is tentatively "running" now. --- apu/apu.cpp | 4 +- apu/bapu/smp/core.cpp | 8 + apu/bapu/smp/smp.cpp | 2 + apu/bapu/snes/snes.hpp | 27 +- gtk/src/snes9x.ui | 14804 +++++++++++++++++++++------------------ 5 files changed, 8004 insertions(+), 6841 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index de70a4e1..65df1b59 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -538,7 +538,7 @@ uint8 S9xAPUReadPort (int port) void S9xAPUWritePort (int port, uint8 byte) { S9xAPUExecute (); - SNES::smp.port_write (port & 3, byte); + SNES::cpu.port_write (port & 3, byte); } void S9xAPUSetReferenceTime (int32 cpucycles) @@ -591,6 +591,7 @@ void S9xResetAPU (void) spc::reference_time = 0; spc::remainder = 0; + SNES::cpu.reset (); SNES::cpu.frequency = Settings.PAL ? PAL_MASTER_CLOCK : NTSC_MASTER_CLOCK; SNES::smp.power (); SNES::dsp.power (); @@ -603,6 +604,7 @@ void S9xSoftResetAPU (void) { spc::reference_time = 0; spc::remainder = 0; + SNES::cpu.reset (); SNES::smp.reset (); SNES::dsp.reset (); SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 6e0a29b2..eb03b46e 100755 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -3,7 +3,11 @@ void SMP::tick() { timer1.tick(); timer2.tick(); +#ifdef BSNES clock += cycle_step_cpu; +#else + clock++; +#endif dsp.clock -= 24; synchronize_dsp(); } @@ -71,7 +75,11 @@ void SMP::op_step() { timer1.tick(cycle_count_table[opcode]); timer2.tick(cycle_count_table[opcode]); +#ifdef BSNES clock += cycle_table_cpu[opcode]; +#else + clock += cycle_count_table[opcode]; +#endif dsp.clock -= cycle_table_dsp[opcode]; synchronize_dsp(); diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 04a2da4e..7a1b2e25 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -20,11 +20,13 @@ namespace SNES { #include "timing.cpp" void SMP::synchronize_cpu() { +#ifdef BSNES if(CPU::Threaded == true) { //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } else { while(clock >= 0) cpu.enter(); } +#endif } void SMP::synchronize_dsp() { diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index b4010a67..30845973 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -1,6 +1,8 @@ #ifndef __SNES_HPP #define __SNES_HPP +#define CYCLE_ACCURATE + #include "snes9x.h" #define alwaysinline inline @@ -12,36 +14,43 @@ namespace SNES struct Processor { unsigned frequency; - int64 clock; + int clock; }; +#include "smp/smp.hpp" +#include "dsp/dsp.hpp" + class CPU { public: enum { Threaded = false }; int frequency; + uint8 registers[4]; - void enter () + inline void enter () { return; } - void port_write (uint8 port, uint8 data) + inline void reset () { - + registers[0] = registers[1] = registers[2] = registers[3] = 0; } - uint8 port_read (uint8 port) + inline void port_write (uint8 port, uint8 data) { - return 0; + registers[port & 3] = data; + } + + inline uint8 port_read (uint8 port) + { + // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); + return registers[port & 3]; } }; extern CPU cpu; -#include "smp/smp.hpp" -#include "dsp/dsp.hpp" - } /* namespace SNES */ #endif diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index 3f86e43d..2cd0e909 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -1,5822 +1,108 @@ - + - - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - Snes9x - - - - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - _File - True - - - - - _Open ROM Image... - True - True - image2 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Open Recent - True - - - - - True - - - - - Open with _NetPlay... - True - Open a ROM to use with NetPlay - True - image3 - False - - - - - - True - Open _MultiCart... - True - - - - - - True - - - - - True - _Load State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - From _File... - True - - - - - - - - - - True - _Save State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - To _File... - True - - - - - - - - - - True - - - - - Save SPC... - True - True - image4 - False - - - - - - True - - - - - Show ROM _Info... - True - True - image5 - False - - - - - - True - - - - - _Quit - True - True - image18 - False - - - - - - - - - - True - _Emulation - True - - - - - Run / _Continue - True - True - image6 - False - - - - - - _Pause - True - True - image7 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - Load _Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image8 - False - - - - - - R_ecord Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image19 - False - - - - - - _Stop Recording - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image9 - False - - - - - - _Jump to Frame... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image10 - False - - - - - - True - - - - - Sy_nc Clients - True - True - image11 - False - - - - - - True - - - - - Reset - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image12 - False - - - - - - Soft _Reset - True - True - image13 - False - - - - - - - - - - True - _View - True - - - - - - _Hide Menu - True - True - image14 - False - - - - - - True - _Status Bar - True - - - - - - True - - - - - _Change Size - True - True - image17 - False - - - True - - - True - False - Exact Pixels - True - - - - - True - _1x - True - - - - - - True - _2x - True - - - - - - True - _3x - True - - - - - - True - _4x - True - - - - - - True - _5x - True - - - - - - True - - - - - True - False - Correct Aspect - True - - - - - True - 1x - True - - - - - - True - 2x - True - - - - - - True - 3x - True - - - - - - True - 4x - True - - - - - - True - 5x - True - - - - - - - - - - True - - - - - _Fullscreen - True - True - image15 - False - - - - - - - - - - True - _Options - True - - - - - True - Controller Ports - True - - - - - True - SNES Port 1 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad1 - - - - - - True - Superscope - True - True - joypad1 - - - - - - - - - - True - SNES Port 2 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad2 - - - - - - True - Multitap - True - joypad2 - - - - - - True - Superscope - True - True - joypad2 - - - - - - - - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Cheats... - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - _Preferences... - True - True - image16 - False - - - - - - - - - - False - 0 - - - - - 256 - 224 - True - True - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - - - - - - - - 1 - - - - - True - - - False - 2 - - - - - - - GDK_KEY_PRESS_MASK - Snes9x Preferences - center - 480 - dialog + + 560 + 448 + False + About Snes9x + normal True - - - + True + False + 2 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + 5 - + True - True - left - 0 - 1 - 0 - + False + 5 - + True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - never - automatic - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - queue - none - - - True - 5 - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Use fullscreen on ROM open - True - True - False - Go to fullscreen mode immediately after opening a ROM - True - True - - - False - False - 0 - - - - - Show frame rate - True - True - False - True - True - - - False - False - 1 - - - - - Use overscanned height - True - True - False - Use SNES extended height. Will probably cause letterboxing - True - True - - - False - False - 2 - - - - - True - 12 - - - Change fullscreen resolution: - True - True - False - Changes the screen resolution when running Snes9x in fullscreen mode - True - True - - - False - False - 0 - - - - - True - liststore14 - - - - 0 - - - - - 1 - - - - - False - False - 3 - - - - - - - - - True - <b>Basic Settings</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Scale image to fit window - True - True - False - Scales the image so no black bars are present - True - True - - - False - False - 0 - - - - - True - 12 - - - Maintain aspect-ratio: - True - True - False - Scales the image as large as possible without distortion - True - True - - - False - False - 0 - - - - - True - liststore13 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - True - 5 - - - Use - True - True - False - Allows scaling and filtering to use multiple processors - True - True - - - False - False - 0 - - - - - True - True - adjustment17 - True - True - - - False - 1 - - - - - True - threads for filtering and scaling - - - False - 2 - - - - - 2 - - - - - True - 12 - - - True - High-resolution effect: - - - False - 0 - - - - - True - liststore15 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - True - 12 - - - True - 0 - Apply scaling filter: - - - False - 0 - - - - - True - liststore12 - - - - - 0 - - - - - False - 1 - - - - - False - False - 4 - - - - - - - - - True - <b>Image Adjustments</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Video preset: - - - False - 0 - - - - - True - - - Composite - True - True - True - - - - False - 0 - - - - - S-Video - True - True - True - - - - False - 1 - - - - - RGB - True - True - True - - - - False - 2 - - - - - Monochrome - True - True - True - - - - False - 3 - - - - - False - 1 - - - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 11 - 2 - 12 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Artifacts: - - - 6 - 7 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Sharpness: - - - 4 - 5 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Brightness: - - - 3 - 4 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Contrast: - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Saturation: - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Hue: - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment16 - False - -1 - 2 - left - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment15 - False - -1 - 2 - left - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment14 - False - -1 - 2 - left - - - 1 - 2 - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment13 - False - -1 - 2 - left - - - 1 - 2 - 3 - 4 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment12 - False - -1 - 2 - left - - - 1 - 2 - 4 - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment11 - False - -1 - 2 - left - - - 1 - 2 - 6 - 7 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment10 - False - -1 - 2 - left - - - 1 - 2 - 7 - 8 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment9 - False - -1 - 2 - left - - - 1 - 2 - 8 - 9 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment8 - False - -1 - 2 - left - - - 1 - 2 - 9 - 10 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment7 - False - -1 - 2 - left - - - 1 - 2 - 10 - 11 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Gamma: - - - 7 - 8 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fringing: - - - 8 - 9 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Bleed: - - - 9 - 10 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Resolution: - - - 10 - 11 - GTK_FILL - - - - - True - - - 2 - 5 - 6 - - - - - 1 - - - - - Merge odd and even fields - True - True - False - True - - - 2 - - - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore11 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - - - - - True - <b>NTSC Filter</b> - True - - - - - False - 2 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore10 - - - - 0 - - - - - False - 1 - - - - - - - - - True - <b>Scanline Filter</b> - True - - - - - False - 3 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore9 - - - - - 0 - - - - - 0 - - - - - Bilinear-filter output - True - True - False - True - True - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - Sync to vertical blank - True - True - False - Sync the image to the vertical retrace to stop tearing - True - True - - - False - False - 0 - - - - - Reduce input lag - True - True - False - Sync the program with the video output after every displayed frame to reduce input latency - True - - - 1 - - - - - Allow non-power-of-two textures - True - True - False - Prevents edge artifacts, but can slow performance - True - - - 2 - - - - - Use pixel-buffer objects - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Can be faster or slower depending on drivers - True - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Different formats can yield highly different performance - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Pixel-buffer format: - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore8 - - - - 0 - - - - - False - 1 - - - - - - - 4 - - - - - True - 5 - - - Use GLSL shader: - True - True - False - 0 - True - - - False - 0 - - - - - True - True - - True - - - 1 - - - - - Browse... - True - True - True - - - - False - 2 - - - - - 5 - - - - - 2 - - - - - True - - - Force an inverted byte-ordering - True - True - False - Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card - True - - - 0 - - - - - 3 - - - - - - - - - True - <b>Hardware Acceleration</b> - True - - - - - False - 4 - - - - - - + False + gtk-missing-image - - - True - - - True - video-display - - - 0 - - - - - True - Display - True - - - False - False - 1 - - - - - False - - + + + False + True + 0 + + + + + True + False + 0 + 10 + 10 + label106 + True + center + True + + + False + True + 1 + + + + + True + False + queue - - True - True - never - automatic - - - True - queue - none - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 12 - - - True - Sound driver: - - - False - False - 0 - - - - - True - liststore7 - - - - 0 - - - - - False - False - 1 - - - - - False - False - 0 - - - - - Synchronize with sound - True - True - False - Base emulation speed on the rate sound is output - True - - - False - False - 1 - - - - - Mute sound output - True - True - False - Disables output of sound - True - True - - - False - False - 2 - - - - - Stereo - True - True - False - Output two channels, left and right - True - True - - - False - False - 3 - - - - - True - 4 - 2 - 10 - 5 - - - True - 0 - Playback rate: - - - GTK_FILL - - - - - - True - 5 - - - True - True - adjustment6 - True - True - - - False - 0 - - - - - True - milliseconds - - - False - 1 - - - - - 1 - 2 - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Buffer size: - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Input rate: - - - 1 - 2 - GTK_FILL - - - - - True - True - Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option - adjustment5 - False - 0 - left - - - 1 - 2 - 1 - 2 - - - - - True - - - True - liststore6 - - - - 0 - - - - - False - False - 0 - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Video rate: - - - 2 - 3 - GTK_FILL - - - - - True - label - - - 1 - 2 - 2 - 3 - - - - - False - 4 - - - - - - - - - True - <b>Sound Settings</b> - True - - - - - - - - - 1 - - - - - True - - - True - audio-x-generic - - - 0 - - - - - True - Sound - True - - - False - False - 1 - - - - - 1 - False - - - - + True True automatic - automatic - - True - queue - none - - - True - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 10 - - - True - Frameskip: - - - False - False - 0 - - - - - True - liststore5 - - - - 0 - - - - - False - False - 1 - - - - - False - 0 - - - - - Block invalid VRAM access - True - True - False - True - - - 1 - - - - - Allow opposing dpad directions - True - True - False - Let left and right or up and down be pressed at the same time - True - - - 2 - - - - - - - - - True - <b>Accuracy</b> - True - - - - - False - 0 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Pause emulation when switching away from Snes9x - True - True - False - True - - - 0 - - - - - True - 12 - - - True - The ESC key should: - - - False - 0 - - - - - True - liststore4 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - - - - - True - <b>Window Switching</b> - True - - - - - False - 1 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - Prevent the screensaver from activating - True - True - False - True - - - 0 - - - - - - - - - True - <b>Screensaver</b> - True - - - - - False - 2 - - - - - - - - - 2 - - - - - True - - - True - utilities-terminal - - - 0 - - - - - True - Emulation - True - - - False - False - 1 - - - - - 2 - False - - - - - True - 5 - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - True - 5 - 3 - 5 - 5 - - - True - True - False - - gtk-clear - - - - - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 2 - 3 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 3 - 4 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 4 - 5 - - - - - Browse... - True - True - True - - - - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 3 - 4 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 4 - 5 - GTK_FILL - - - - - - True - 0 - SRAM: - - - GTK_FILL - - - - - True - 0 - Save states: - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Cheats: - - - 2 - 3 - GTK_FILL - - - - - True - 0 - Patches: - - - 3 - 4 - GTK_FILL - - - - - True - 0 - Exports: - - - 4 - 5 - GTK_FILL - - - - - False - 0 - - - - - - - - - True - <b>Game Data Locations</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - 5 - - - True - Save SRAM: - - - False - 0 - - - - - True - True - Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs - - 5 - 1 - - - False - 1 - - - - - True - seconds after change - - - False - 2 - - - - - - - - - True - <b>Automatic Saving</b> - True - - - - - False - 1 - - - - - 3 - - - - - True - - - True - folder - - - 0 - - - - - True - Files - True - - - False - False - 1 - - - - - 3 - False - - - - - True - 5 - 5 - - - True - 5 - - - True - 5 - <b>Joypad:</b> - True - - - False - False - 0 - - - - - True - liststore3 - - - - - 0 - - - - - False - 1 - - - - - True - - - False - 2 - - - - - _Reset - True - True - True - True - - - - False - False - 3 - - - - - True - - - False - 4 - - - - - True - Swap with: - - - False - 5 - - - - - True - liststore2 - - - - 0 - - - - - False - 6 - - - - - _Swap - True - True - True - True - - - - False - 7 - - - - - False - 0 - - - - - Use modifier keys (CTRL, SHIFT, ALT) directly + True True - False - Allow using modifier keys as independent keys instead of modifiers - True - True + False + False + textbuffer1 - - False - False - 1 - - - - - True - True - - - - True - 10 - 12 - - - True - 6 - 2 - 10 - 5 - - - True - 0 - Up - - - GTK_FILL - - - - - - True - 0 - Down - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Left - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Right - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Start - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Select - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 0 - - - - - True - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - - - - - - - True - Buttons - - - False - - - - - True - 5 - 2 - 2 - 5 - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - <b>Sticky</b> - True - center - - - 1 - 2 - - - - - - - True - 0 - <b>Turbo</b> - True - center - - - - - - - - - 1 - False - - - - - True - Turbo / Sticky Buttons - - - 1 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - 5 - 5 - - - True - Set new axis bindings at: - - - False - False - 0 - - - - - True - True - Changes the amount a joystick should be tilted to register a button press - adjustment4 - 1 - True - - - False - False - 1 - - - - - True - percent - - - False - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Joystick Axis Threshold</b> - True - - - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Center all axes on all joysticks and press Calibrate. - - - False - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - Cali_brate - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - - - - False - False - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Calibration</b> - True - - - - - 1 - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Joystick Options - - - 2 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - 3 - - - 4 - - - - - True - - - True - input-gaming - - - 0 - - - - - True - Joypads - True - - - False - False - 1 - - - - - 4 - False - - - - - True - 5 - 5 - - - True - 0 - 5 - <b>Snes9x Emulator Shortcut Keys</b> - True - - - False - False - 0 - - - - - True - - - False - False - 1 - - - - - True - True - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 11 - 2 - 10 - 5 - - - True - 0 - Soft reset - - - 9 - 10 - GTK_FILL - - - - - - True - 0 - Hardware reset - - - 8 - 9 - GTK_FILL - - - - - - True - 0 - Increase frame time - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Decrease frame time - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Increase frame rate - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Decrease frame rate - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Pause - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle turbo - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Enable turbo - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Open ROM - - - GTK_FILL - - - - - - True - 0 - Quit Snes9x - - - 10 - 11 - GTK_FILL - GTK_FILL - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 10 - 11 - GTK_FILL - - - - - - - - - - - True - Emulation - - - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 8 - 2 - 10 - 5 - - - True - 0 - Toggle BG layer 0 - - - GTK_FILL - - - - - - True - 0 - Toggle BG layer 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sprites - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - BG layering hack - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Screenshot - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle fullscreen - - - 7 - 8 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - - - - - 1 - - - - - True - Graphics - - - 1 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 10 - 4 - 10 - 5 - - - True - 0 - <b>Quick save state</b> - True - center - - - 2 - - - - - - - True - 0 - <b>Quick load state</b> - True - - - 2 - 4 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - - - - - - - True - 0 - Slot 0 - - - 1 - 2 - - - - - - - True - 0 - Slot 2 - - - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 8 - 9 - - - - - - - True - 0 - Slot 0 - - - 2 - 3 - 1 - 2 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - 2 - 3 - - - - - - - True - 0 - Slot 2 - - - 2 - 3 - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 2 - 3 - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 2 - 3 - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 2 - 3 - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 2 - 3 - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 2 - 3 - 8 - 9 - - - - - - - True - 0 - Slot 8 - - - 2 - 3 - 9 - 10 - - - - - - - True - 0 - Slot 8 - - - 9 - 10 - - - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 8 - 9 - GTK_FILL - - - - - - - - - 2 - - - - - True - Save States - - - 2 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 9 - 2 - 10 - 5 - - - True - 0 - Toggle sound channel 0 - - - GTK_FILL - - - - - - True - 0 - Toggle sound channel 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 4 - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 5 - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 6 - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 7 - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Toggle all sound channels - - - 8 - 9 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - - - - - 3 - - - - - True - Sound - - - 3 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 6 - 2 - 10 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Seek to frame - - - 4 - 5 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Load Movie - - - 3 - 4 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Stop movie recording - - - 2 - 3 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Begin movie recording - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Save SPC - - - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - 0 - Swap controllers 1 & 2 - - - 5 - 6 - GTK_FILL - - - - - - True - True - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Misc - - - 4 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - False - 3 - - - - - 5 - - - - - True - - - True - input-keyboard - - - 0 - - - - - True - Shortcuts - True - - - False - False - 1 - - - - - 5 - False - + + True + True + 2 + - 2 + True + True + 0 - + True + False end - - gtk-cancel + + gtk-close True True - True - False + True + False True @@ -5825,70 +111,132 @@ 0 - - - gtk-apply - True - True - True - False - True - - - - False - False - 1 - - - - - gtk-ok - True - True - True - False - True - - - False - False - 2 - - - - - gtk-about - True - True - True - True - - - - False - False - 3 - True - - False + True end - 0 + 1 - cancel_button - ok_button - button1 - button8 + button15 + + 1 + 60 + 1 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 1.0408340855860843e-17 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + 2 + 8 + 2 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 100 + 50 + 1 + 10 + + + 31500 + 32500 + 31990 + 1 + 10 + + + 2 + 256 + 2 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 Advance to Frame @@ -5898,67 +246,13 @@ True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - The current frame in the movie is - True - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fast-forward to frame - - - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - 1 - - - - - 1 - - - - - False - 1 - - True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end @@ -5968,6 +262,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5985,6 +280,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5996,10 +292,84 @@ False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + The current frame in the movie is + True + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fast-forward to frame + + + True + True + 0 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + True + True + 1 + + + + + True + True + 1 + + + + + False + True + 1 + + @@ -6007,6 +377,114 @@ button2 + + True + False + gtk-media-next + 1 + + + True + False + gtk-revert-to-saved + 1 + + + True + False + gtk-redo + 1 + + + True + False + gtk-refresh + 1 + + + True + False + gtk-leave-fullscreen + 1 + + + True + False + gtk-fullscreen + 1 + + + True + False + gtk-preferences + 1 + + + True + False + gtk-zoom-in + 1 + + + True + False + gtk-quit + 1 + + + True + False + gtk-media-record + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-network + 1 + + + True + False + gtk-save + 1 + + + True + False + gtk-dialog-info + 1 + + + True + False + gtk-go-forward + 1 + + + True + False + gtk-media-pause + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-media-stop + 1 + @@ -6024,6 +502,104 @@ + + + + + + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + 0% + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + None + + + SuperEagle + + + 2xSaI + + + Super2xSaI + + + EPX + + + EPX Smooth + + + Blargg's NTSC + + + Scanlines + + + Simple2x + + + Simple3x + + + Simple4x + + + + + + + + + + + 8:7 Square pixels + + + 4:3 SNES correct aspect + + + @@ -6219,103 +795,202 @@ - - - - - - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - 0% - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - None - - - SuperEagle - - - 2xSaI - - - Super2xSaI - - - EPX - - - EPX Smooth - - - Blargg's NTSC - - - Scanlines - - - Simple2x - - - Simple3x - - - Simple4x - - - - - - - - - - - 8:7 Square pixels - - - 4:3 SNES correct aspect - - + + 512 + 350 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Snes9x Cheats + center-on-parent + dialog + True + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-close + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + False + False + 0 + + + + + False + True + end + 0 + + + + + True + False + 5 + + + True + False + 0 + in + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + 0 + Code: + + + False + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + False + True + 1 + + + + + True + False + 0 + Description: + + + False + True + 2 + + + + + True + True + 21 + True + False + False + True + True + + + False + True + 3 + + + + + gtk-add + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 4 + + + + + gtk-remove + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 5 + + + + + False + False + 1 + + + + + True + True + 1 + + + + + + button7 + @@ -6340,153 +1015,977 @@ - - 512 - 350 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Snes9x Cheats - center-on-parent - dialog - True - - + + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + Snes9x + + + + + + + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 + False - + True - 5 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True - 0 - in - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False + _File + True + + + False + + + _Open ROM Image... + True + False + False + True + image2 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + Open Recent + True + + + + + True + False + + + + + Open with _NetPlay... + True + False + Open a ROM to use with NetPlay + False + True + image3 + False + + + + + + True + False + False + Open _MultiCart... + True + + + + + + True + False + + + + + True + False + False + _Load State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + From _File... + True + + + + + + + + + + True + False + False + _Save State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + To _File... + True + + + + + + + + + + True + False + + + + + Save SPC... + True + False + False + True + image4 + False + + + + + + True + False + + + + + Show ROM _Info... + True + False + False + True + image5 + False + + + + + + True + False + + + + + _Quit + True + False + False + True + image18 + False + + + - - - - - 0 - - + True - 5 - 5 - - - True - 0 - Code: + False + False + _Emulation + True + + + False + + + Run / _Continue + True + False + False + True + image6 + False + + + + + + _Pause + True + False + False + True + image7 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + Load _Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image8 + False + + + + + + R_ecord Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image19 + False + + + + + + _Stop Recording + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image9 + False + + + + + + _Jump to Frame... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image10 + False + + + + + + True + False + + + + + Sy_nc Clients + True + False + False + True + image11 + False + + + + + + True + False + + + + + Reset + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image12 + False + + + + + + Soft _Reset + True + False + False + True + image13 + False + + + + + + + + + + True + False + False + _View + True + + + + False + + + _Hide Menu + True + False + False + True + image14 + False + + + + + + True + False + False + _Status Bar + True + + + + + + True + False + + + + + _Change Size + True + False + False + True + image17 + False + + + True + False + + + True + False + False + False + Exact Pixels + True + + + + + True + False + False + _1x + True + + + + + + True + False + False + _2x + True + + + + + + True + False + False + _3x + True + + + + + + True + False + False + _4x + True + + + + + + True + False + False + _5x + True + + + + + + True + False + + + + + True + False + False + False + Correct Aspect + True + + + + + True + False + False + 1x + True + + + + + + True + False + False + 2x + True + + + + + + True + False + False + 3x + True + + + + + + True + False + False + 4x + True + + + + + + True + False + False + 5x + True + + + + + + + + + + True + False + + + + + _Fullscreen + True + False + False + True + image15 + False + + + + + + + + + + True + False + False + _Options + True + + + False + + + True + False + False + Controller Ports + True + + + False + + + True + False + False + SNES Port 1 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad1 + + + + + + True + False + False + Superscope + True + True + joypad1 + + + + + + + + + + True + False + False + SNES Port 2 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad2 + + + + + + True + False + False + Multitap + True + joypad2 + + + + + + True + False + False + Superscope + True + True + joypad2 + + + + + + + + + + + + + + True + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + _Cheats... + True + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + _Preferences... + True + False + False + True + image16 + False + + + - - False - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - False - 1 - - - - - True - 0 - Description: - - - False - 2 - - - - - True - True - 21 - True - - - False - 3 - - - - - gtk-add - True - True - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 4 - - - - - gtk-remove - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 5 - - - False - False - 1 - + False + True + 0 + + + + + 256 + 224 + True + True + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + + + + + + + + True + True 1 - - + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + False + True + 2 + + + + + + + False + 5 + Open Multiple ROM Images (MultiCart) + center-on-parent + 320 + dialog + + + True + False + + + True + False end - - gtk-close + + gtk-cancel True True True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -6495,20 +1994,122 @@ 0 + + + gtk-ok + True + True + True + False + True + + + False + False + 1 + + False + True end 0 + + + True + False + 5 + + + True + False + 12 + + + True + False + Slot A: + + + False + True + 0 + + + + + True + False + Select an Image for Slot A + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Slot B: + + + False + True + 0 + + + + + True + False + Select an Image for Slot B + + + True + True + 1 + + + + + False + True + 1 + + + + + True + True + 1 + + - button7 + button14 + button13 + False 5 Snes9x NetPlay center-on-parent @@ -6516,344 +2117,12 @@ True + False 2 - - - True - 5 - 5 - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - True - The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image - False - - - 0 - - - - - Browse... - True - True - True - - - - False - 1 - - - - - True - True - True - - - - True - Clear entry - gtk-clear - 1 - - - - - False - 2 - - - - - - - - - True - <b>ROM Image</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - - - Connect to another computer - True - True - False - Connect to another computer that is running Snes9x NetPlay as a server - True - True - - - 0 - - - - - True - 5 - 5 - - - True - Name or IP address: - - - False - 0 - - - - - True - True - Domain name or internet protocol address of a remote computer - - - 1 - - - - - True - Port: - - - False - 2 - - - - - True - True - Connect to specified TCP port on remote computer - adjustment3 - True - True - - - False - 3 - - - - - 1 - - - - - Act as a server - True - True - False - Host a game on this computer as Player 1, requiring extra throughput to support multitple users - True - True - connect_radio - - - - 2 - - - - - - - - - True - <b>Server</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Sync using reset - True - True - False - Reset the game when players join instead of transferring potentially unreliable freeze states - True - - - False - 0 - - - - - Send ROM image to clients - True - True - False - Send the running game image to players instead of requiring them to have their own copies - True - - - False - 1 - - - - - True - 5 - - - True - Default port: - - - False - 0 - - - - - True - True - TCP port used as a connection point for remote clients - adjustment2 - True - True - - - False - 1 - - - - - False - 2 - - - - - True - 5 - - - True - Ask server to pause when - - - False - 0 - - - - - True - True - adjustment1 - True - True - - - False - 1 - - - - - True - frames behind - - - False - 2 - - - - - False - 3 - - - - - - - - - True - <b>Settings</b> - True - - - - - 2 - - - - - 1 - - True + False end @@ -6861,6 +2130,7 @@ True True True + False True @@ -6876,6 +2146,7 @@ True True True + False True @@ -6887,10 +2158,423 @@ False + True end 0 + + + True + False + 5 + 5 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + True + The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image + False + False + False + True + True + + + True + True + 0 + + + + + Browse... + True + True + True + False + + + + False + True + 1 + + + + + True + True + True + False + + + + True + False + Clear entry + gtk-clear + 1 + + + + + False + True + 2 + + + + + + + + + True + False + <b>ROM Image</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + + + Connect to another computer + True + True + False + Connect to another computer that is running Snes9x NetPlay as a server + False + True + True + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + Name or IP address: + + + False + True + 0 + + + + + True + True + Domain name or internet protocol address of a remote computer + False + False + True + True + + + True + True + 1 + + + + + True + False + Port: + + + False + True + 2 + + + + + True + True + Connect to specified TCP port on remote computer + False + False + True + True + adjustment3 + True + True + + + False + True + 3 + + + + + True + True + 1 + + + + + Act as a server + True + True + False + Host a game on this computer as Player 1, requiring extra throughput to support multitple users + False + True + True + connect_radio + + + + True + True + 2 + + + + + + + + + True + False + <b>Server</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Sync using reset + True + True + False + Reset the game when players join instead of transferring potentially unreliable freeze states + False + True + + + False + True + 0 + + + + + Send ROM image to clients + True + True + False + Send the running game image to players instead of requiring them to have their own copies + False + True + + + False + True + 1 + + + + + True + False + 5 + + + True + False + Default port: + + + False + True + 0 + + + + + True + True + TCP port used as a connection point for remote clients + False + False + True + True + adjustment2 + True + True + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 5 + + + True + False + Ask server to pause when + + + False + True + 0 + + + + + True + True + False + False + True + True + adjustment1 + True + True + + + False + True + 1 + + + + + True + False + frames behind + + + False + True + 2 + + + + + False + True + 3 + + + + + + + + + True + False + <b>Settings</b> + True + + + + + True + True + 2 + + + + + True + True + 1 + + @@ -6898,92 +2582,33 @@ button10 - - 5 - Open Multiple ROM Images (MultiCart) - center-on-parent - 320 + + False + GDK_KEY_PRESS_MASK + Snes9x Preferences + center + 480 dialog + True + + - + True - - - True - 5 - - - True - 12 - - - True - Slot A: - - - False - 0 - - - - - True - Select an Image for Slot A - - - 1 - - - - - False - 0 - - - - - True - 12 - - - True - Slot B: - - - False - 0 - - - - - True - Select an Image for Slot B - - - 1 - - - - - False - 1 - - - - - 1 - - + False - + True + False end - + gtk-cancel True True - True + True + False + False True @@ -6993,12 +2618,15 @@ - - gtk-ok + + gtk-apply True True - True + True + False + False True + False @@ -7006,220 +2634,5841 @@ 1 + + + gtk-ok + True + True + True + False + False + True + + + False + False + 2 + + + + + gtk-about + True + True + True + False + True + + + + False + False + 3 + True + + False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + left + 0 + 1 + 0 + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + never + automatic + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + queue + none + + + True + False + 5 + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Use fullscreen on ROM open + True + True + False + Go to fullscreen mode immediately after opening a ROM + False + True + True + + + False + False + 0 + + + + + Show frame rate + True + True + False + False + True + True + + + False + False + 1 + + + + + Use overscanned height + True + True + False + Use SNES extended height. Will probably cause letterboxing + False + True + True + + + False + False + 2 + + + + + True + False + 12 + + + Change fullscreen resolution: + True + True + False + Changes the screen resolution when running Snes9x in fullscreen mode + False + True + True + + + False + False + 0 + + + + + True + False + liststore14 + + + + 0 + + + + + True + True + 1 + + + + + False + False + 3 + + + + + + + + + True + False + <b>Basic Settings</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Scale image to fit window + True + True + False + Scales the image so no black bars are present + False + True + True + + + False + False + 0 + + + + + True + False + 12 + + + Maintain aspect-ratio: + True + True + False + Scales the image as large as possible without distortion + False + True + True + + + False + False + 0 + + + + + True + False + liststore13 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + True + False + 5 + + + Use + True + True + False + Allows scaling and filtering to use multiple processors + False + True + True + + + False + False + 0 + + + + + True + True + False + False + True + True + adjustment17 + True + True + + + False + True + 1 + + + + + True + False + threads for filtering and scaling + + + False + True + 2 + + + + + True + True + 2 + + + + + True + False + 12 + + + True + False + High-resolution effect: + + + False + True + 0 + + + + + True + False + liststore15 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + True + False + 12 + + + True + False + 0 + Apply scaling filter: + + + False + True + 0 + + + + + True + False + liststore12 + + + + + 0 + + + + + False + True + 1 + + + + + False + False + 4 + + + + + + + + + True + False + <b>Image Adjustments</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Video preset: + + + False + True + 0 + + + + + True + False + + + Composite + True + True + True + False + + + + False + True + 0 + + + + + S-Video + True + True + True + False + + + + False + True + 1 + + + + + RGB + True + True + True + False + + + + False + True + 2 + + + + + Monochrome + True + True + True + False + + + + False + True + 3 + + + + + False + True + 1 + + + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 11 + 2 + 12 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Artifacts: + + + 6 + 7 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Sharpness: + + + 4 + 5 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Brightness: + + + 3 + 4 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Contrast: + + + 2 + 3 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Saturation: + + + 1 + 2 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Hue: + + + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment16 + False + -1 + 2 + left + + + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment15 + False + -1 + 2 + left + + + 1 + 2 + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment14 + False + -1 + 2 + left + + + 1 + 2 + 2 + 3 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment13 + False + -1 + 2 + left + + + 1 + 2 + 3 + 4 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment12 + False + -1 + 2 + left + + + 1 + 2 + 4 + 5 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment11 + False + -1 + 2 + left + + + 1 + 2 + 6 + 7 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment10 + False + -1 + 2 + left + + + 1 + 2 + 7 + 8 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment9 + False + -1 + 2 + left + + + 1 + 2 + 8 + 9 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment8 + False + -1 + 2 + left + + + 1 + 2 + 9 + 10 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment7 + False + -1 + 2 + left + + + 1 + 2 + 10 + 11 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Gamma: + + + 7 + 8 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fringing: + + + 8 + 9 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Bleed: + + + 9 + 10 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Resolution: + + + 10 + 11 + GTK_FILL + + + + + True + False + + + 2 + 5 + 6 + + + + + True + True + 1 + + + + + Merge odd and even fields + True + True + False + False + True + + + True + True + 2 + + + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore11 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + + + + + True + False + <b>NTSC Filter</b> + True + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore10 + + + + 0 + + + + + False + True + 1 + + + + + + + + + True + False + <b>Scanline Filter</b> + True + + + + + False + True + 3 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore9 + + + + + 0 + + + + + True + True + 0 + + + + + Bilinear-filter output + True + True + False + False + True + True + + + True + True + 1 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + Sync to vertical blank + True + True + False + Sync the image to the vertical retrace to stop tearing + False + True + True + + + False + False + 0 + + + + + Reduce input lag + True + True + False + Sync the program with the video output after every displayed frame to reduce input latency + False + True + + + True + True + 1 + + + + + Allow non-power-of-two textures + True + True + False + Prevents edge artifacts, but can slow performance + False + True + + + True + True + 2 + + + + + Use pixel-buffer objects + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Can be faster or slower depending on drivers + False + True + + + True + True + 3 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Different formats can yield highly different performance + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Pixel-buffer format: + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore8 + + + + 0 + + + + + False + True + 1 + + + + + + + True + True + 4 + + + + + True + False + 5 + + + Use GLSL shader: + True + True + False + False + 0 + True + + + False + True + 0 + + + + + True + True + • + True + False + False + True + True + + + True + True + 1 + + + + + Browse... + True + True + True + False + + + + False + True + 2 + + + + + True + True + 5 + + + + + True + True + 2 + + + + + True + False + + + Force an inverted byte-ordering + True + True + False + Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card + False + True + + + True + True + 0 + + + + + True + True + 3 + + + + + + + + + True + False + <b>Hardware Acceleration</b> + True + + + + + False + True + 4 + + + + + + + + + + + True + False + + + True + False + video-display + + + True + True + 0 + + + + + True + False + Display + True + + + False + False + 1 + + + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 12 + + + True + False + Sound driver: + + + False + False + 0 + + + + + True + False + liststore7 + + + + 0 + + + + + False + False + 1 + + + + + False + False + 0 + + + + + Synchronize with sound + True + True + False + Base emulation speed on the rate sound is output + False + True + + + False + False + 1 + + + + + Mute sound output + True + True + False + Disables output of sound + False + True + True + + + False + False + 2 + + + + + Stereo + True + True + False + Output two channels, left and right + False + True + True + + + False + False + 3 + + + + + True + False + 4 + 2 + 10 + 5 + + + True + False + 0 + Playback rate: + + + GTK_FILL + + + + + + True + False + 5 + + + True + True + False + False + True + True + adjustment6 + True + True + + + False + True + 0 + + + + + True + False + milliseconds + + + False + True + 1 + + + + + 1 + 2 + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Buffer size: + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Input rate: + + + 1 + 2 + GTK_FILL + + + + + True + True + Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option + adjustment5 + False + 0 + left + + + 1 + 2 + 1 + 2 + + + + + True + False + + + True + False + liststore6 + + + + 0 + + + + + False + False + 0 + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Video rate: + + + 2 + 3 + GTK_FILL + + + + + True + False + label + + + 1 + 2 + 2 + 3 + + + + + False + True + 4 + + + + + + + + + True + False + <b>Sound Settings</b> + True + + + + + + + + + 1 + + + + + True + False + + + True + False + audio-x-generic + + + True + True + 0 + + + + + True + False + Sound + True + + + False + False + 1 + + + + + 1 + False + + + + + True + True + automatic + automatic + + + True + False + queue + none + + + True + False + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 10 + + + True + False + Frameskip: + + + False + False + 0 + + + + + True + False + liststore5 + + + + 0 + + + + + False + False + 1 + + + + + False + True + 0 + + + + + Block invalid VRAM access + True + True + False + False + True + + + True + True + 1 + + + + + Allow opposing dpad directions + True + True + False + Let left and right or up and down be pressed at the same time + False + True + + + True + True + 2 + + + + + + + + + True + False + <b>Accuracy</b> + True + + + + + False + True + 0 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Pause emulation when switching away from Snes9x + True + True + False + False + True + + + True + True + 0 + + + + + True + False + 12 + + + True + False + The ESC key should: + + + False + True + 0 + + + + + True + False + liststore4 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + False + <b>Window Switching</b> + True + + + + + False + True + 1 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + Prevent the screensaver from activating + True + True + False + False + True + + + True + True + 0 + + + + + + + + + True + False + <b>Screensaver</b> + True + + + + + False + True + 2 + + + + + + + + + 2 + + + + + True + False + + + True + False + utilities-terminal + + + True + True + 0 + + + + + True + False + Emulation + True + + + False + False + 1 + + + + + 2 + False + + + + + True + False + 5 + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + True + False + 5 + 3 + 5 + 5 + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 2 + 3 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 3 + 4 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 4 + 5 + + + + + Browse... + True + True + True + False + + + + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + SRAM: + + + GTK_FILL + + + + + True + False + 0 + Save states: + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Cheats: + + + 2 + 3 + GTK_FILL + + + + + True + False + 0 + Patches: + + + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Exports: + + + 4 + 5 + GTK_FILL + + + + + False + True + 0 + + + + + + + + + True + False + <b>Game Data Locations</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + 5 + + + True + False + Save SRAM: + + + False + True + 0 + + + + + True + True + Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs + • + 5 + 1 + False + False + True + True + + + False + True + 1 + + + + + True + False + seconds after change + + + False + True + 2 + + + + + + + + + True + False + <b>Automatic Saving</b> + True + + + + + False + True + 1 + + + + + 3 + + + + + True + False + + + True + False + folder + + + True + True + 0 + + + + + True + False + Files + True + + + False + False + 1 + + + + + 3 + False + + + + + True + False + 5 + 5 + + + True + False + 5 + + + True + False + 5 + <b>Joypad:</b> + True + + + False + False + 0 + + + + + True + False + liststore3 + + + + + 0 + + + + + False + True + 1 + + + + + True + False + + + False + True + 2 + + + + + _Reset + True + True + True + False + True + + + + False + False + 3 + + + + + True + False + + + False + True + 4 + + + + + True + False + Swap with: + + + False + True + 5 + + + + + True + False + liststore2 + + + + 0 + + + + + False + True + 6 + + + + + _Swap + True + True + True + False + True + + + + False + True + 7 + + + + + False + True + 0 + + + + + Use modifier keys (CTRL, SHIFT, ALT) directly + True + True + False + Allow using modifier keys as independent keys instead of modifiers + False + True + True + + + False + False + 1 + + + + + True + True + + + + True + False + 10 + 12 + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + Up + + + GTK_FILL + + + + + + True + False + 0 + Down + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Left + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Right + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Start + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Select + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + 1 + + + + + + + True + False + Buttons + + + False + + + + + True + False + 5 + 2 + 2 + 5 + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + <b>Sticky</b> + True + center + + + 1 + 2 + + + + + + + True + False + 0 + <b>Turbo</b> + True + center + + + + + + + + + 1 + False + + + + + True + False + Turbo / Sticky Buttons + + + 1 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + 5 + 5 + + + True + False + Set new axis bindings at: + + + False + False + 0 + + + + + True + True + Changes the amount a joystick should be tilted to register a button press + False + False + True + True + adjustment4 + 1 + True + + + False + False + 1 + + + + + True + False + percent + + + False + False + 2 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Joystick Axis Threshold</b> + True + + + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Center all axes on all joysticks and press Calibrate. + + + False + False + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + Cali_brate + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 0 + + + + + + + + False + False + 1 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Calibration</b> + True + + + + + True + True + 1 + + + + + 2 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Joystick Options + + + 2 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + True + 3 + + + + + 4 + + + + + True + False + + + True + False + input-gaming + + + True + True + 0 + + + + + True + False + Joypads + True + + + False + False + 1 + + + + + 4 + False + + + + + True + False + 5 + 5 + + + True + False + 0 + 5 + <b>Snes9x Emulator Shortcut Keys</b> + True + + + False + False + 0 + + + + + True + False + + + False + False + 1 + + + + + True + True + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 11 + 2 + 10 + 5 + + + True + False + 0 + Soft reset + + + 9 + 10 + GTK_FILL + + + + + + True + False + 0 + Hardware reset + + + 8 + 9 + GTK_FILL + + + + + + True + False + 0 + Increase frame time + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Decrease frame time + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Increase frame rate + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Decrease frame rate + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Pause + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle turbo + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Enable turbo + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Open ROM + + + GTK_FILL + + + + + + True + False + 0 + Quit Snes9x + + + 10 + 11 + GTK_FILL + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 10 + 11 + GTK_FILL + + + + + + + + + + + True + False + Emulation + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 8 + 2 + 10 + 5 + + + True + False + 0 + Toggle BG layer 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sprites + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + BG layering hack + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Screenshot + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle fullscreen + + + 7 + 8 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + + + + + 1 + + + + + True + False + Graphics + + + 1 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 10 + 4 + 10 + 5 + + + True + False + 0 + <b>Quick save state</b> + True + center + + + 2 + + + + + + + True + False + 0 + <b>Quick load state</b> + True + + + 2 + 4 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + + + + + + + True + False + 0 + Slot 0 + + + 1 + 2 + + + + + + + True + False + 0 + Slot 2 + + + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 8 + 9 + + + + + + + True + False + 0 + Slot 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + 2 + 3 + + + + + + + True + False + 0 + Slot 2 + + + 2 + 3 + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 2 + 3 + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 2 + 3 + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 2 + 3 + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 2 + 3 + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 2 + 3 + 8 + 9 + + + + + + + True + False + 0 + Slot 8 + + + 2 + 3 + 9 + 10 + + + + + + + True + False + 0 + Slot 8 + + + 9 + 10 + + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 8 + 9 + GTK_FILL + + + + + + + + + 2 + + + + + True + False + Save States + + + 2 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 9 + 2 + 10 + 5 + + + True + False + 0 + Toggle sound channel 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 4 + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 5 + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 6 + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 7 + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Toggle all sound channels + + + 8 + 9 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + + + + + 3 + + + + + True + False + Sound + + + 3 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 6 + 2 + 10 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Seek to frame + + + 4 + 5 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Load Movie + + + 3 + 4 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Stop movie recording + + + 2 + 3 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Begin movie recording + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Save SPC + + + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + False + 0 + Swap controllers 1 & 2 + + + 5 + 6 + GTK_FILL + + + + + + True + True + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 4 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Misc + + + 4 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + False + 3 + + + + + 5 + + + + + True + False + + + True + False + input-keyboard + + + True + True + 0 + + + + + True + False + Shortcuts + True + + + False + False + 1 + + + + + 5 + False + + + + + + + True + True + 2 + + - button14 - button13 + cancel_button + ok_button + button1 + button8 - - True - gtk-open - 1 - - - True - gtk-network - 1 - - - True - gtk-save - 1 - - - True - gtk-dialog-info - 1 - - - True - gtk-quit - 1 - - - True - gtk-go-forward - 1 - - - True - gtk-media-pause - 1 - - - True - gtk-open - 1 - - - True - gtk-media-record - 1 - - - True - gtk-media-stop - 1 - - - True - gtk-media-next - 1 - - - True - gtk-revert-to-saved - 1 - - - True - gtk-redo - 1 - - - True - gtk-refresh - 1 - - - True - gtk-leave-fullscreen - 1 - - - True - gtk-zoom-in - 1 - - - True - gtk-fullscreen - 1 - - - True - gtk-preferences - 1 - - - 1 - 1 - 60 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 50 - 1 - 100 - 1 - 10 - - - 31990 - 31500 - 32500 - 1 - 10 - - - 2 - 2 - 256 - 1 - 1 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 1.0408340855860843e-17 - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 2 - 2 - 8 - 1 - 1 - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. @@ -7396,111 +8645,4 @@ Super NES and Super Nintendo Entertainment System are trademarks of Nintendo Co., Limited and its subsidiary companies. - - 560 - 448 - About Snes9x - normal - True - - - True - 2 - - - True - 5 - - - True - 5 - - - True - gtk-missing-image - - - - - False - 0 - - - - - True - 0 - 10 - 10 - label106 - True - center - True - - - False - 1 - - - - - True - queue - - - True - True - automatic - - - True - True - False - False - textbuffer1 - - - - - - - 2 - - - - - 0 - - - - - True - end - - - gtk-close - True - True - True - True - - - False - False - 0 - - - - - False - end - 1 - - - - - - button15 - - From 1af39f384549a8464b28c052ea3cacf49fdaf757 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:24:13 -0500 Subject: [PATCH 013/130] Clean things up slightly. Switch CYCLE_ACCURATE off, since things seem to work fine without it. --- apu/apu.cpp | 16 ++++------------ apu/bapu/smp/core.cpp | 4 ++-- apu/bapu/smp/smp.cpp | 10 +++++++--- apu/bapu/smp/smp.hpp | 4 ++-- apu/bapu/snes/snes.hpp | 25 +++++++++++++++---------- memmap.cpp | 25 ++++++------------------- snapshot.cpp | 2 +- 7 files changed, 37 insertions(+), 49 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 65df1b59..604478d6 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -464,8 +464,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) void S9xSetSoundControl (uint8 voice_switch) { - /* - spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); */ + SNES::dsp.spc_dsp.set_stereo_switch (voice_switch << 8 | voice_switch); } void S9xSetSoundMute (bool8 mute) @@ -477,7 +476,7 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { -/* No SPC dumping ATM in byuu SMP */ +/* TODO: SPC dumping */ /* spc_core->dsp_dump_spc_snapshot(); */ } @@ -578,14 +577,6 @@ void S9xAPUTimingSetSpeedup (int ticks) UpdatePlaybackRate(); } -void S9xAPUAllowTimeOverflow (bool allow) -{ - if (allow) - printf("APU time overflow allowed\n"); - - /* spc_core->spc_allow_time_overflow(allow); */ -} - void S9xResetAPU (void) { spc::reference_time = 0; @@ -614,6 +605,7 @@ void S9xSoftResetAPU (void) void S9xAPUSaveState (uint8 *block) { +// TODO: Save states /* uint8 *ptr = block; spc_core->copy_state(&ptr, from_apu_to_state); @@ -625,7 +617,7 @@ void S9xAPUSaveState (uint8 *block) void S9xAPULoadState (uint8 *block) { - /*uint8 *ptr = block; +/* uint8 *ptr = block; S9xResetAPU(); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index eb03b46e..01f265a5 100755 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -3,7 +3,7 @@ void SMP::tick() { timer1.tick(); timer2.tick(); -#ifdef BSNES +#ifndef SNES9X clock += cycle_step_cpu; #else clock++; @@ -75,7 +75,7 @@ void SMP::op_step() { timer1.tick(cycle_count_table[opcode]); timer2.tick(cycle_count_table[opcode]); -#ifdef BSNES +#ifndef SNES9X clock += cycle_table_cpu[opcode]; #else clock += cycle_count_table[opcode]; diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 7a1b2e25..49556f3f 100755 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,4 +1,8 @@ +#ifndef SNES9X #define CYCLE_ACCURATE +#else +#undef CYCLE_ACCURATE +#endif #include @@ -20,7 +24,7 @@ namespace SNES { #include "timing.cpp" void SMP::synchronize_cpu() { -#ifdef BSNES +#ifndef SNES9X if(CPU::Threaded == true) { //if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread); } else { @@ -42,7 +46,7 @@ void SMP::enter() { } void SMP::power() { -#ifdef BSNES +#ifndef SNES9X Processor::frequency = system.apu_frequency(); #endif @@ -92,7 +96,7 @@ void SMP::reset() { timer0.stage3_ticks = timer1.stage3_ticks = timer2.stage3_ticks = 0; } -#ifdef BSNES +#ifndef SNES9X void SMP::serialize(serializer &s) { Processor::serialize(s); diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index be52f77a..5d2c3d64 100755 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -17,7 +17,7 @@ public: void power(); void reset(); -#ifdef BSNES +#ifndef SNES9X void serialize(serializer&); #endif SMP(); @@ -35,7 +35,7 @@ public: alwaysinline unsigned operator=(unsigned data) { n = data & 0x80; v = data & 0x40; p = data & 0x20; b = data & 0x10; h = data & 0x08; i = data & 0x04; z = data & 0x02; c = data & 0x01; - return *this; + return data; } alwaysinline unsigned operator|=(unsigned data) { return operator=(operator unsigned() | data); } diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 30845973..be7e73f1 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -1,11 +1,21 @@ #ifndef __SNES_HPP #define __SNES_HPP -#define CYCLE_ACCURATE - #include "snes9x.h" -#define alwaysinline inline +#define SNES9X + +#if defined(__GNUC__) + #define inline inline + #define alwaysinline inline __attribute__((always_inline)) +#elif defined(_MSC_VER) + #define inline inline + #define alwaysinline inline __forceinline +#else + #define inline inline + #define alwaysinline inline +#endif + #define debugvirtual namespace SNES @@ -27,22 +37,17 @@ public: int frequency; uint8 registers[4]; - inline void enter () - { - return; - } - inline void reset () { registers[0] = registers[1] = registers[2] = registers[3] = 0; } - inline void port_write (uint8 port, uint8 data) + alwaysinline void port_write (uint8 port, uint8 data) { registers[port & 3] = data; } - inline uint8 port_read (uint8 port) + alwaysinline uint8 port_read (uint8 port) { // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); return registers[port & 3]; diff --git a/memmap.cpp b/memmap.cpp index 81edf082..7bf9bf6e 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -1502,7 +1502,7 @@ bool8 CMemory::LoadROM (const char *filename) ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); - + again: Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); @@ -2254,7 +2254,7 @@ void CMemory::InitROM (void) Settings.SETA = 0; Settings.SRTC = FALSE; Settings.BS = FALSE; - + SuperFX.nRomBanks = CalculatedSize >> 15; //// Parse ROM header and read ROM informatoin @@ -3204,7 +3204,7 @@ void CMemory::Map_SPC7110HiROMMap (void) map_System(); map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); - map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize); @@ -3499,14 +3499,13 @@ void CMemory::ApplyROMFixes (void) //// APU timing hacks :( Timings.APUSpeedup = 0; - Timings.APUAllowTimeOverflow = FALSE; if (!Settings.DisableGameSpecificHacks) { if (match_id("AVCJ")) // Rendering Ranger R2 - Timings.APUSpeedup = 4; + Timings.APUSpeedup = 2; - if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki +/* if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki match_id("JG ") || // Illusion of Gaia match_id("CQ ") || // Stunt Race FX match_na("SOULBLADER - 1") || // Soul Blader @@ -3540,22 +3539,10 @@ void CMemory::ApplyROMFixes (void) 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! - Timings.APUSpeedup = 1; - - if (match_na ("EARTHWORM JIM 2") || // Earthworm Jim 2 - match_na ("NBA Hangtime") || // NBA Hang Time - match_na ("MSPACMAN") || // Ms Pacman - match_na ("THE MASK") || // The Mask - match_na ("PRIMAL RAGE") || // Primal Rage - match_na ("PORKY PIGS HAUNTED") || // Porky Pig's Haunted Holiday - match_na ("Big Sky Trooper") || // Big Sky Trooper - match_id ("A35") || // Mechwarrior 3050 / Battle Tech 3050 - match_na ("DOOM TROOPERS")) // Doom Troopers - Timings.APUAllowTimeOverflow = TRUE; + Timings.APUSpeedup = 1; */ } S9xAPUTimingSetSpeedup(Timings.APUSpeedup); - S9xAPUAllowTimeOverflow(Timings.APUAllowTimeOverflow); //// Other timing hacks :( diff --git a/snapshot.cpp b/snapshot.cpp index e2163de6..55823b4e 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2278,7 +2278,7 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie bool8 S9xSPCDump (const char *filename) { - /* No SPC dumping in byuu SMP */ + /* TODO: No SPC dumping in byuu SMP */ /* FILE *fs; uint8 buf[SNES_SPC::spc_file_size]; From 196d1ed2c78a023bd22dfb034089ca25bf80d502 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:26:15 -0500 Subject: [PATCH 014/130] Remove debugging line. --- apu/bapu/snes/snes.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index be7e73f1..17e6305a 100755 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -49,7 +49,6 @@ public: alwaysinline uint8 port_read (uint8 port) { - // printf ("APU Read %2x from port %d\n", registers[port & 3], port & 3); return registers[port & 3]; } }; From ebc9b7086028ff686e5c9bf3d2a8d737806bb5cc Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 05:29:04 -0500 Subject: [PATCH 015/130] Fix permissions. --- apu/bapu/dsp/SPC_DSP.cpp | 0 apu/bapu/dsp/SPC_DSP.h | 0 apu/bapu/dsp/blargg_common.h | 0 apu/bapu/dsp/blargg_config.h | 0 apu/bapu/dsp/blargg_endian.h | 0 apu/bapu/dsp/blargg_source.h | 0 apu/bapu/dsp/dsp.cpp | 0 apu/bapu/dsp/dsp.hpp | 0 apu/bapu/dsp/serialization.cpp | 0 apu/bapu/smp/algorithms.cpp | 0 apu/bapu/smp/core.cpp | 0 apu/bapu/smp/core/generate.cpp | 0 apu/bapu/smp/core/op_misc.b | 0 apu/bapu/smp/core/op_misc.cpp | 0 apu/bapu/smp/core/op_mov.b | 0 apu/bapu/smp/core/op_mov.cpp | 0 apu/bapu/smp/core/op_pc.b | 0 apu/bapu/smp/core/op_pc.cpp | 0 apu/bapu/smp/core/op_read.b | 0 apu/bapu/smp/core/op_read.cpp | 0 apu/bapu/smp/core/op_rmw.b | 0 apu/bapu/smp/core/op_rmw.cpp | 0 apu/bapu/smp/core/opcycle_misc.cpp | 0 apu/bapu/smp/core/opcycle_mov.cpp | 0 apu/bapu/smp/core/opcycle_pc.cpp | 0 apu/bapu/smp/core/opcycle_read.cpp | 0 apu/bapu/smp/core/opcycle_rmw.cpp | 0 apu/bapu/smp/debugger/debugger.cpp | 0 apu/bapu/smp/debugger/debugger.hpp | 0 apu/bapu/smp/debugger/disassembler.cpp | 0 apu/bapu/smp/iplrom.cpp | 0 apu/bapu/smp/memory.cpp | 0 apu/bapu/smp/smp.cpp | 0 apu/bapu/smp/smp.hpp | 0 apu/bapu/smp/timing.cpp | 0 apu/bapu/snes/snes.hpp | 0 36 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 apu/bapu/dsp/SPC_DSP.cpp mode change 100755 => 100644 apu/bapu/dsp/SPC_DSP.h mode change 100755 => 100644 apu/bapu/dsp/blargg_common.h mode change 100755 => 100644 apu/bapu/dsp/blargg_config.h mode change 100755 => 100644 apu/bapu/dsp/blargg_endian.h mode change 100755 => 100644 apu/bapu/dsp/blargg_source.h mode change 100755 => 100644 apu/bapu/dsp/dsp.cpp mode change 100755 => 100644 apu/bapu/dsp/dsp.hpp mode change 100755 => 100644 apu/bapu/dsp/serialization.cpp mode change 100755 => 100644 apu/bapu/smp/algorithms.cpp mode change 100755 => 100644 apu/bapu/smp/core.cpp mode change 100755 => 100644 apu/bapu/smp/core/generate.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_misc.b mode change 100755 => 100644 apu/bapu/smp/core/op_misc.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_mov.b mode change 100755 => 100644 apu/bapu/smp/core/op_mov.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_pc.b mode change 100755 => 100644 apu/bapu/smp/core/op_pc.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_read.b mode change 100755 => 100644 apu/bapu/smp/core/op_read.cpp mode change 100755 => 100644 apu/bapu/smp/core/op_rmw.b mode change 100755 => 100644 apu/bapu/smp/core/op_rmw.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_misc.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_mov.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_pc.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_read.cpp mode change 100755 => 100644 apu/bapu/smp/core/opcycle_rmw.cpp mode change 100755 => 100644 apu/bapu/smp/debugger/debugger.cpp mode change 100755 => 100644 apu/bapu/smp/debugger/debugger.hpp mode change 100755 => 100644 apu/bapu/smp/debugger/disassembler.cpp mode change 100755 => 100644 apu/bapu/smp/iplrom.cpp mode change 100755 => 100644 apu/bapu/smp/memory.cpp mode change 100755 => 100644 apu/bapu/smp/smp.cpp mode change 100755 => 100644 apu/bapu/smp/smp.hpp mode change 100755 => 100644 apu/bapu/smp/timing.cpp mode change 100755 => 100644 apu/bapu/snes/snes.hpp diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_common.h b/apu/bapu/dsp/blargg_common.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_config.h b/apu/bapu/dsp/blargg_config.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_endian.h b/apu/bapu/dsp/blargg_endian.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/blargg_source.h b/apu/bapu/dsp/blargg_source.h old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/algorithms.cpp b/apu/bapu/smp/algorithms.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/generate.cpp b/apu/bapu/smp/core/generate.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_misc.b b/apu/bapu/smp/core/op_misc.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_misc.cpp b/apu/bapu/smp/core/op_misc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_mov.b b/apu/bapu/smp/core/op_mov.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_mov.cpp b/apu/bapu/smp/core/op_mov.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_pc.b b/apu/bapu/smp/core/op_pc.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_pc.cpp b/apu/bapu/smp/core/op_pc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_read.b b/apu/bapu/smp/core/op_read.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_read.cpp b/apu/bapu/smp/core/op_read.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_rmw.b b/apu/bapu/smp/core/op_rmw.b old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/op_rmw.cpp b/apu/bapu/smp/core/op_rmw.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/debugger.cpp b/apu/bapu/smp/debugger/debugger.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/debugger.hpp b/apu/bapu/smp/debugger/debugger.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/debugger/disassembler.cpp b/apu/bapu/smp/debugger/disassembler.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/iplrom.cpp b/apu/bapu/smp/iplrom.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/memory.cpp b/apu/bapu/smp/memory.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp old mode 100755 new mode 100644 diff --git a/apu/bapu/smp/timing.cpp b/apu/bapu/smp/timing.cpp old mode 100755 new mode 100644 diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp old mode 100755 new mode 100644 From 08f5601c5f1615ac22c193f487c519978d5179c3 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 06:14:14 -0500 Subject: [PATCH 016/130] Reduce the sync footprint slightly with less indirection. --- apu/bapu/dsp/dsp.cpp | 13 ------------- apu/bapu/dsp/dsp.hpp | 2 -- apu/bapu/smp/core.cpp | 15 +++++++++------ apu/bapu/smp/smp.cpp | 2 ++ 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index c0a2a9c8..0a6137c4 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,19 +7,6 @@ DSP dsp; #include "SPC_DSP.cpp" -void DSP::step(unsigned clocks) { - clock += clocks; -} - -void DSP::synchronize_smp() { - while(clock >= 0) smp.enter(); -} - -void DSP::enter() { - spc_dsp.run(1); - step(24); -} - uint8 DSP::read(uint8 addr) { return spc_dsp.read(addr); } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index ef2dc7c7..1109bda8 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -3,13 +3,11 @@ class DSP : public Processor { public: enum { Threaded = false }; - alwaysinline void step(unsigned clocks); alwaysinline void synchronize_smp(); uint8 read(uint8 addr); void write(uint8 addr, uint8 data); - void enter(); void power(); void reset(); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 01f265a5..df4076c1 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -5,11 +5,12 @@ void SMP::tick() { #ifndef SNES9X clock += cycle_step_cpu; -#else - clock++; -#endif dsp.clock -= 24; synchronize_dsp(); +#else + clock++; + dsp.spc_dsp.run(1); +#endif } void SMP::op_io() { @@ -77,11 +78,13 @@ void SMP::op_step() { #ifndef SNES9X clock += cycle_table_cpu[opcode]; -#else - clock += cycle_count_table[opcode]; -#endif dsp.clock -= cycle_table_dsp[opcode]; synchronize_dsp(); +#else + clock += cycle_count_table[opcode]; + dsp.spc_dsp.run(cycle_count_table[opcode]); +#endif + #endif } diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index 49556f3f..e0bb9019 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -34,11 +34,13 @@ void SMP::synchronize_cpu() { } void SMP::synchronize_dsp() { +#ifndef SNES9X if(DSP::Threaded == true) { //if(dsp.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(dsp.thread); } else { while(dsp.clock < 0) dsp.enter(); } +#endif } void SMP::enter() { From 7c468e51c017ed8692b656bb5ef7739a33b259d4 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 23 Jun 2011 06:28:34 -0500 Subject: [PATCH 017/130] Remove parts of DSP wrapper we don't need. --- apu/bapu/dsp/dsp.cpp | 18 ------------------ apu/bapu/dsp/dsp.hpp | 15 ++++++--------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index 0a6137c4..dc2027cb 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,14 +7,6 @@ DSP dsp; #include "SPC_DSP.cpp" -uint8 DSP::read(uint8 addr) { - return spc_dsp.read(addr); -} - -void DSP::write(uint8 addr, uint8 data) { - spc_dsp.write(addr, data); -} - void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); @@ -24,17 +16,7 @@ void DSP::reset() { spc_dsp.soft_reset(); } -void DSP::channel_enable(unsigned channel, bool enable) { - channel_enabled[channel & 7] = enable; - unsigned mask = 0; - for(unsigned i = 0; i < 8; i++) { - if(channel_enabled[i] == false) mask |= 1 << i; - } - spc_dsp.mute_voices(mask); -} - DSP::DSP() { - for(unsigned i = 0; i < 8; i++) channel_enabled[i] = true; } } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index 1109bda8..ae965f3d 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -2,23 +2,20 @@ class DSP : public Processor { public: - enum { Threaded = false }; - alwaysinline void synchronize_smp(); + inline uint8 read(uint8 addr) { + return spc_dsp.read(addr); + } - uint8 read(uint8 addr); - void write(uint8 addr, uint8 data); + inline void write(uint8 addr, uint8 data) { + spc_dsp.write(addr, data); + } void power(); void reset(); - void channel_enable(unsigned channel, bool enable); - DSP(); SPC_DSP spc_dsp; - -private: - bool channel_enabled[8]; }; extern DSP dsp; From 39add9b47e06425adc075b7c5df2581c7d84cce8 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Fri, 24 Jun 2011 06:42:04 -0500 Subject: [PATCH 018/130] Save states support for new APU. --- apu/apu.cpp | 27 +++++---- apu/apu.h | 2 +- apu/bapu/dsp/dsp.cpp | 31 +++++++++- apu/bapu/dsp/dsp.hpp | 3 + apu/bapu/smp/smp.hpp | 3 + apu/bapu/smp/smp_state.cpp | 119 +++++++++++++++++++++++++++++++++++++ apu/bapu/snes/snes.hpp | 2 +- gtk/Makefile.am | 4 +- snapshot.cpp | 10 ++-- 9 files changed, 178 insertions(+), 23 deletions(-) create mode 100644 apu/bapu/smp/smp_state.cpp diff --git a/apu/apu.cpp b/apu/apu.cpp index 604478d6..80f1ed4c 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -194,6 +194,8 @@ namespace SNES { +#include "dsp/blargg_endian.h" + CPU cpu; } @@ -229,8 +231,6 @@ static void EightBitize (uint8 *, int); static void DeStereo (uint8 *, int); static void ReverseStereo (uint8 *, int); static void UpdatePlaybackRate (void); -static void from_apu_to_state (uint8 **, void *, size_t); -static void to_apu_from_state (uint8 **, void *, size_t); static void SPCSnapshotCallback (void); static inline int S9xAPUGetClock (int32); static inline int S9xAPUGetClockRemainder (int32); @@ -605,25 +605,30 @@ void S9xSoftResetAPU (void) void S9xAPUSaveState (uint8 *block) { -// TODO: Save states -/* uint8 *ptr = block; + uint8 *ptr = block; - spc_core->copy_state(&ptr, from_apu_to_state); + SNES::smp.save_state (&ptr); + SNES::dsp.save_state (&ptr); - SET_LE32(ptr, spc::reference_time); + SNES::set_le32(ptr, spc::reference_time); ptr += sizeof(int32); - SET_LE32(ptr, spc::remainder); */ + SNES::set_le32(ptr, spc::remainder); + ptr += sizeof(int32); + memcpy (ptr, SNES::cpu.registers, 4); } void S9xAPULoadState (uint8 *block) { -/* uint8 *ptr = block; + uint8 *ptr = block; S9xResetAPU(); - spc_core->copy_state(&ptr, to_apu_from_state); + SNES::smp.load_state (&ptr); + SNES::dsp.load_state (&ptr); - spc::reference_time = GET_LE32(ptr); + spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); - spc::remainder = GET_LE32(ptr); */ + spc::remainder = SNES::get_le32(ptr); + ptr += sizeof(int32); + memcpy (SNES::cpu.registers, ptr, 4); } diff --git a/apu/apu.h b/apu/apu.h index c0967caa..77cc4bfd 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -183,7 +183,7 @@ typedef void (*apu_callback) (void *); -#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) +#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) bool8 S9xInitAPU (void); void S9xDeinitAPU (void); diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/dsp.cpp index dc2027cb..ef2c48da 100644 --- a/apu/bapu/dsp/dsp.cpp +++ b/apu/bapu/dsp/dsp.cpp @@ -7,16 +7,41 @@ DSP dsp; #include "SPC_DSP.cpp" -void DSP::power() { +void DSP::power() +{ spc_dsp.init(smp.apuram); spc_dsp.reset(); } -void DSP::reset() { +void DSP::reset() +{ spc_dsp.soft_reset(); } -DSP::DSP() { +static void from_dsp_to_state (uint8 **buf, void *var, size_t size) +{ + memcpy(*buf, var, size); + *buf += size; +} + +static void to_dsp_from_state (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +void DSP::save_state (uint8 **ptr) +{ + spc_dsp.copy_state(ptr, from_dsp_to_state); +} + +void DSP::load_state (uint8 **ptr) +{ + spc_dsp.copy_state(ptr, to_dsp_from_state); +} + +DSP::DSP() +{ } } diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/dsp.hpp index ae965f3d..83d51eb5 100644 --- a/apu/bapu/dsp/dsp.hpp +++ b/apu/bapu/dsp/dsp.hpp @@ -10,6 +10,9 @@ public: spc_dsp.write(addr, data); } + void save_state(uint8 **); + void load_state(uint8 **); + void power(); void reset(); diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 5d2c3d64..b50bb631 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -19,6 +19,9 @@ public: #ifndef SNES9X void serialize(serializer&); +#else + void load_state(uint8 **); + void save_state(uint8 **); #endif SMP(); ~SMP(); diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp new file mode 100644 index 00000000..2e590e69 --- /dev/null +++ b/apu/bapu/smp/smp_state.cpp @@ -0,0 +1,119 @@ +#include "snes/snes.hpp" + +namespace SNES { + +#include "dsp/blargg_endian.h" + +void SMP::save_state(uint8 **block) { + uint8 *ptr = *block; + memcpy(ptr, apuram, 64 * 1024); + ptr += 64 * 1024; + +#undef INT32 +#define INT32(i) set_le32(ptr, (i)); ptr += sizeof(int32) + INT32(clock); + + INT32(opcode_number); + INT32(opcode_cycle); + + INT32(regs.pc); + INT32(regs.sp); + INT32(regs.a); + INT32(regs.x); + INT32(regs.y); + + INT32(regs.p.n); + INT32(regs.p.v); + INT32(regs.p.p); + INT32(regs.p.b); + INT32(regs.p.h); + INT32(regs.p.i); + INT32(regs.p.z); + INT32(regs.p.c); + + INT32(status.iplrom_enable); + + INT32(status.dsp_addr); + + INT32(status.ram00f8); + INT32(status.ram00f9); + + INT32(timer0.enable); + INT32(timer0.target); + INT32(timer0.stage1_ticks); + INT32(timer0.stage2_ticks); + INT32(timer0.stage3_ticks); + + INT32(timer1.enable); + INT32(timer1.target); + INT32(timer1.stage1_ticks); + INT32(timer1.stage2_ticks); + INT32(timer1.stage3_ticks); + + INT32(timer2.enable); + INT32(timer2.target); + + INT32(timer2.stage1_ticks); + INT32(timer2.stage2_ticks); + INT32(timer2.stage3_ticks); + + *block = ptr; +} + +void SMP::load_state(uint8 **block) { + uint8 *ptr = *block; + memcpy(apuram, ptr, 64 * 1024); + ptr += 64 * 1024; + +#undef INT32 +#define INT32(i) i = get_le32(ptr); ptr += sizeof(int32) + INT32(clock); + + INT32(opcode_number); + INT32(opcode_cycle); + + INT32(regs.pc); + INT32(regs.sp); + INT32(regs.a); + INT32(regs.x); + INT32(regs.y); + + INT32(regs.p.n); + INT32(regs.p.v); + INT32(regs.p.p); + INT32(regs.p.b); + INT32(regs.p.h); + INT32(regs.p.i); + INT32(regs.p.z); + INT32(regs.p.c); + + INT32(status.iplrom_enable); + + INT32(status.dsp_addr); + + INT32(status.ram00f8); + INT32(status.ram00f9); + + INT32(timer0.enable); + INT32(timer0.target); + INT32(timer0.stage1_ticks); + INT32(timer0.stage2_ticks); + INT32(timer0.stage3_ticks); + + INT32(timer1.enable); + INT32(timer1.target); + INT32(timer1.stage1_ticks); + INT32(timer1.stage2_ticks); + INT32(timer1.stage3_ticks); + + INT32(timer2.enable); + INT32(timer2.target); + + INT32(timer2.stage1_ticks); + INT32(timer2.stage2_ticks); + INT32(timer2.stage3_ticks); + + *block = ptr; +} + +} diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 17e6305a..58a2d8a0 100644 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -24,7 +24,7 @@ namespace SNES struct Processor { unsigned frequency; - int clock; + int32 clock; }; #include "smp/smp.hpp" diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 607d70bb..85ee9055 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -124,9 +124,9 @@ snes9x_gtk_SOURCES += \ # Byuu's APU snes9x_gtk_SOURCES += \ ../apu/bapu/dsp/dsp.cpp \ - ../apu/bapu/dsp/serialization.cpp \ ../apu/bapu/dsp/SPC_DSP.cpp \ - ../apu/bapu/smp/smp.cpp + ../apu/bapu/smp/smp.cpp \ + ../apu/bapu/smp/smp_state.cpp # DSP snes9x_gtk_SOURCES += \ diff --git a/snapshot.cpp b/snapshot.cpp index 55823b4e..d07c430b 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1269,7 +1269,7 @@ bool8 S9xUnfreezeGame (const char *filename) void S9xFreezeToStream (STREAM stream) { char buffer[1024]; - //uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; + uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE]; S9xSetSoundMute(TRUE); @@ -1298,8 +1298,8 @@ void S9xFreezeToStream (STREAM stream) FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); - //S9xAPUSaveState(soundsnapshot); - //FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + S9xAPUSaveState(soundsnapshot); + FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); struct SControlSnapshot ctl_snap; S9xControlPreSaveState(&ctl_snap); @@ -1410,7 +1410,7 @@ void S9xFreezeToStream (STREAM stream) S9xSetSoundMute(FALSE); - //delete [] soundsnapshot; + delete [] soundsnapshot; } int S9xUnfreezeFromStream (STREAM stream) @@ -1496,7 +1496,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (result != SUCCESS) break; - // result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); if (result != SUCCESS) break; From 7963d0e66ba4707ef8d4aee800c63291249e12af Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Fri, 24 Jun 2011 18:09:08 -0500 Subject: [PATCH 019/130] Remove serialization.cpp. --- apu/bapu/dsp/serialization.cpp | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 apu/bapu/dsp/serialization.cpp diff --git a/apu/bapu/dsp/serialization.cpp b/apu/bapu/dsp/serialization.cpp deleted file mode 100644 index 0565a1b5..00000000 --- a/apu/bapu/dsp/serialization.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef DSP_CPP - -static void dsp_state_save(unsigned char **out, void *in, size_t size) { - memcpy(*out, in, size); - *out += size; -} - -static void dsp_state_load(unsigned char **in, void *out, size_t size) { - memcpy(out, *in, size); - *in += size; -} - -void DSP::serialize(serializer &s) { - Processor::serialize(s); - s.array(samplebuffer); - - unsigned char state[SPC_DSP::state_size]; - unsigned char *p = state; - memset(&state, 0, SPC_DSP::state_size); - if(s.mode() == serializer::Save) { - spc_dsp.copy_state(&p, dsp_state_save); - s.array(state); - } else if(s.mode() == serializer::Load) { - s.array(state); - spc_dsp.copy_state(&p, dsp_state_load); - } else { - s.array(state); - } -} - -#endif From 2e94b98e904dcc1441087007b46f290c5dc08225 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 25 Jun 2011 03:10:42 -0500 Subject: [PATCH 020/130] Clear up CYCLE_ACCURATE confusion. Rename dsp.* to sdsp.*. --- apu/bapu/dsp/{dsp.cpp => sdsp.cpp} | 0 apu/bapu/dsp/{dsp.hpp => sdsp.hpp} | 0 apu/bapu/smp/smp.cpp | 4 ---- apu/bapu/snes/snes.hpp | 2 +- gtk/Makefile.am | 2 +- 5 files changed, 2 insertions(+), 6 deletions(-) rename apu/bapu/dsp/{dsp.cpp => sdsp.cpp} (100%) rename apu/bapu/dsp/{dsp.hpp => sdsp.hpp} (100%) diff --git a/apu/bapu/dsp/dsp.cpp b/apu/bapu/dsp/sdsp.cpp similarity index 100% rename from apu/bapu/dsp/dsp.cpp rename to apu/bapu/dsp/sdsp.cpp diff --git a/apu/bapu/dsp/dsp.hpp b/apu/bapu/dsp/sdsp.hpp similarity index 100% rename from apu/bapu/dsp/dsp.hpp rename to apu/bapu/dsp/sdsp.hpp diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index e0bb9019..a8092fcb 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,8 +1,4 @@ -#ifndef SNES9X #define CYCLE_ACCURATE -#else -#undef CYCLE_ACCURATE -#endif #include diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 58a2d8a0..3e8cd2b3 100644 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -28,7 +28,7 @@ struct Processor }; #include "smp/smp.hpp" -#include "dsp/dsp.hpp" +#include "dsp/sdsp.hpp" class CPU { diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 85ee9055..9f380914 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -123,7 +123,7 @@ snes9x_gtk_SOURCES += \ # Byuu's APU snes9x_gtk_SOURCES += \ - ../apu/bapu/dsp/dsp.cpp \ + ../apu/bapu/dsp/sdsp.cpp \ ../apu/bapu/dsp/SPC_DSP.cpp \ ../apu/bapu/smp/smp.cpp \ ../apu/bapu/smp/smp_state.cpp From ebc9e721f6f4374ac23ac419b2ebfd0c96c694c3 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sun, 26 Jun 2011 05:33:14 -0500 Subject: [PATCH 021/130] Add SPC dumping support. --- apu/apu.cpp | 29 ++++++- apu/apu.h | 4 +- apu/bapu/dsp/SPC_DSP.cpp | 161 +++++++++++++++++++------------------ apu/bapu/smp/smp.hpp | 1 + apu/bapu/smp/smp_state.cpp | 68 +++++++++++++++- snapshot.cpp | 26 ------ snapshot.h | 1 - 7 files changed, 179 insertions(+), 111 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 80f1ed4c..11bb5c7d 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -476,8 +476,8 @@ void S9xSetSoundMute (bool8 mute) void S9xDumpSPCSnapshot (void) { -/* TODO: SPC dumping */ -/* spc_core->dsp_dump_spc_snapshot(); */ + SNES::dsp.spc_dsp.dump_spc_snapshot(); + } static void SPCSnapshotCallback (void) @@ -492,6 +492,8 @@ bool8 S9xInitAPU (void) spc::shrink_buffer = NULL; spc::resampler = NULL; + SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); + return (TRUE); } @@ -632,3 +634,26 @@ void S9xAPULoadState (uint8 *block) ptr += sizeof(int32); memcpy (SNES::cpu.registers, ptr, 4); } + +bool8 S9xSPCDump (const char *filename) +{ + FILE *fs; + uint8 buf[SPC_FILE_SIZE]; + size_t ignore; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + S9xSetSoundMute(TRUE); + + SNES::smp.save_spc (buf); + + ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs); + + fclose(fs); + + S9xSetSoundMute(FALSE); + + return (TRUE); +} diff --git a/apu/apu.h b/apu/apu.h index 77cc4bfd..44b183a8 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -183,7 +183,8 @@ typedef void (*apu_callback) (void *); -#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) +#define SPC_SAVE_STATE_BLOCK_SIZE (1024 * 65) +#define SPC_FILE_SIZE (66048) bool8 S9xInitAPU (void); void S9xDeinitAPU (void); @@ -199,6 +200,7 @@ void S9xAPUAllowTimeOverflow (bool); void S9xAPULoadState (uint8 *); void S9xAPUSaveState (uint8 *); void S9xDumpSPCSnapshot (void); +bool8 S9xSPCDump (const char *); bool8 S9xInitSound (int, int); bool8 S9xOpenSoundDevice (void); diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp index e6ba49ed..e3719203 100644 --- a/apu/bapu/dsp/SPC_DSP.cpp +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -132,7 +132,7 @@ inline int SPC_DSP::interpolate( voice_t const* v ) int offset = v->interp_pos >> 4 & 0xFF; short const* fwd = gauss + 255 - offset; short const* rev = gauss + offset; // mirror left half of gaussian - + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; int out; out = (fwd [ 0] * in [0]) >> 11; @@ -140,7 +140,7 @@ inline int SPC_DSP::interpolate( voice_t const* v ) out += (rev [256] * in [2]) >> 11; out = (int16_t) out; out += (rev [ 0] * in [3]) >> 11; - + CLAMP16( out ); out &= ~1; return out; @@ -262,13 +262,13 @@ inline void SPC_DSP::run_envelope( voice_t* const v ) } } } - + // Sustain level if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) v->env_mode = env_sustain; - + v->hidden_env = env; - + // unsigned cast because linear decrease going negative also triggers this if ( (unsigned) env > 0x7FF ) { @@ -276,7 +276,7 @@ inline void SPC_DSP::run_envelope( voice_t* const v ) if ( v->env_mode == env_attack ) v->env_mode = env_decay; } - + if ( !read_counter( rate ) ) v->env = env; // nothing else is controlled by the counter } @@ -289,27 +289,27 @@ inline void SPC_DSP::decode_brr( voice_t* v ) { // Arrange the four input nybbles in 0xABCD order for easy decoding int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; - + int const header = m.t_brr_header; - + // Write to next four samples in circular buffer int* pos = &v->buf [v->buf_pos]; int* end; if ( (v->buf_pos += 4) >= brr_buf_size ) v->buf_pos = 0; - + // Decode four samples for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) { // Extract nybble and sign-extend int s = (int16_t) nybbles >> 12; - + // Shift sample based on header int const shift = header >> 4; s = (s << shift) >> 1; if ( shift >= 0xD ) // handle invalid range s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) - + // Apply IIR filter (8 is the most commonly used) int const filter = header & 0x0C; int const p1 = pos [brr_buf_size - 1]; @@ -334,7 +334,7 @@ inline void SPC_DSP::decode_brr( voice_t* v ) s += p1 >> 1; s += (-p1) >> 5; } - + // Adjust and write sample CLAMP16( s ); s = (int16_t) (s * 2); @@ -367,11 +367,11 @@ MISC_CLOCK( 30 ) if ( m.every_other_sample ) { m.kon = m.new_kon; - m.t_koff = REG(koff) | m.mute_mask; + m.t_koff = REG(koff) | m.mute_mask; } - + run_counters(); - + // Noise if ( !read_counter( REG(flg) & 0x1F ) ) { @@ -397,9 +397,9 @@ inline VOICE_CLOCK( V2 ) if ( !v->kon_delay ) entry += 2; m.t_brr_next_addr = GET_LE16A( entry ); - + m.t_adsr0 = VREG(v->regs,adsr0); - + // Read pitch, spread over two clocks m.t_pitch = VREG(v->regs,pitchl); } @@ -418,7 +418,7 @@ VOICE_CLOCK( V3c ) // Pitch modulation using previous voice's output if ( m.t_pmon & v->vbit ) m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; - + if ( v->kon_delay ) { // Get ready to start BRR decoding on next sample @@ -437,46 +437,46 @@ VOICE_CLOCK( V3c ) spc_snapshot_callback(); } } - + // Envelope is never run during KON v->env = 0; v->hidden_env = 0; - + // Disable BRR decoding until last three samples v->interp_pos = 0; if ( --v->kon_delay & 3 ) v->interp_pos = 0x4000; - + // Pitch is never added during KON m.t_pitch = 0; } - + // Gaussian interpolation { int output = interpolate( v ); - + // Noise if ( m.t_non & v->vbit ) output = (int16_t) (m.noise * 2); - + // Apply envelope m.t_output = (output * v->env) >> 11 & ~1; v->t_envx_out = (uint8_t) (v->env >> 4); } - + // Immediate silence due to end of sample or soft reset if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) { v->env_mode = env_release; v->env = 0; } - + if ( m.every_other_sample ) { // KOFF if ( m.t_koff & v->vbit ) v->env_mode = env_release; - + // KON if ( m.kon & v->vbit ) { @@ -484,7 +484,7 @@ VOICE_CLOCK( V3c ) v->env_mode = env_attack; } } - + // Run envelope for next sample if ( !v->kon_delay ) run_envelope( v ); @@ -499,7 +499,7 @@ inline void SPC_DSP::voice_output( voice_t const* v, int ch ) // Add to output total m.t_main_out [ch] += amp; CLAMP16( m.t_main_out [ch] ); - + // Optionally add to echo total if ( m.t_eon & v->vbit ) { @@ -514,7 +514,7 @@ VOICE_CLOCK( V4 ) if ( v->interp_pos >= 0x4000 ) { decode_brr( v ); - + if ( (v->brr_offset += 2) >= brr_block_size ) { // Start decoding next BRR block @@ -528,14 +528,14 @@ VOICE_CLOCK( V4 ) v->brr_offset = 1; } } - + // Apply pitch v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; - + // Keep from getting too far ahead (when using pitch modulation) if ( v->interp_pos > 0x7FFF ) v->interp_pos = 0x7FFF; - + // Output left voice_output( v, 0 ); } @@ -543,10 +543,10 @@ inline VOICE_CLOCK( V5 ) { // Output right voice_output( v, 1 ); - + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier int endx_buf = REG(endx) | m.t_looped; - + // Clear bit in ENDX if KON just began if ( v->kon_delay == 5 ) endx_buf &= ~v->vbit; @@ -561,7 +561,7 @@ inline VOICE_CLOCK( V7 ) { // Update ENDX REG(endx) = m.endx_buf; - + m.envx_buf = v->t_envx_out; } inline VOICE_CLOCK( V8 ) @@ -619,14 +619,14 @@ ECHO_CLOCK( 22 ) // History if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) m.echo_hist_pos = m.echo_hist; - + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; echo_read( 0 ); - + // FIR (using l and r temporaries below helps compiler optimize) int l = CALC_FIR( 0, 0 ); int r = CALC_FIR( 0, 1 ); - + m.t_echo_in [0] = l; m.t_echo_in [1] = r; } @@ -634,17 +634,17 @@ ECHO_CLOCK( 23 ) { int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); - + m.t_echo_in [0] += l; m.t_echo_in [1] += r; - + echo_read( 1 ); } ECHO_CLOCK( 24 ) { int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); - + m.t_echo_in [0] += l; m.t_echo_in [1] += r; } @@ -652,16 +652,16 @@ ECHO_CLOCK( 25 ) { int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); - + l = (int16_t) l; r = (int16_t) r; - + l += (int16_t) CALC_FIR( 7, 0 ); r += (int16_t) CALC_FIR( 7, 1 ); - + CLAMP16( l ); CLAMP16( r ); - + m.t_echo_in [0] = l & ~1; m.t_echo_in [1] = r & ~1; } @@ -677,14 +677,14 @@ ECHO_CLOCK( 26 ) // Left output volumes // (save sample for next clock so we can output both together) m.t_main_out [0] = echo_output( 0 ); - + // Echo feedback int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); - + CLAMP16( l ); CLAMP16( r ); - + m.t_echo_out [0] = l & ~1; m.t_echo_out [1] = r & ~1; } @@ -695,7 +695,7 @@ ECHO_CLOCK( 27 ) int r = echo_output( 1 ); m.t_main_out [0] = 0; m.t_main_out [1] = 0; - + // TODO: global muting isn't this simple (turns DAC on and off // or something, causing small ~37-sample pulse when first muted) if ( REG(flg) & 0x40 ) @@ -703,7 +703,7 @@ ECHO_CLOCK( 27 ) l = 0; r = 0; } - + // Output sample to DAC #ifdef SPC_DSP_OUT_HOOK SPC_DSP_OUT_HOOK( l, r ); @@ -732,17 +732,17 @@ inline void SPC_DSP::echo_write( int ch ) ECHO_CLOCK( 29 ) { m.t_esa = REG(esa); - + if ( !m.echo_offset ) m.echo_length = (REG(edl) & 0x0F) * 0x800; - + m.echo_offset += 4; if ( m.echo_offset >= m.echo_length ) m.echo_offset = 0; - + // Write left echo echo_write( 0 ); - + m.t_echo_enabled = REG(flg); } ECHO_CLOCK( 30 ) @@ -805,17 +805,17 @@ PHASE(31) V(V4,0) V(V1,2)\ void SPC_DSP::run( int clocks_remain ) { require( clocks_remain > 0 ); - + int const phase = m.phase; m.phase = (phase + clocks_remain) & 31; switch ( phase ) { loop: - + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: GEN_DSP_TIMING #undef PHASE - + if ( --clocks_remain ) goto loop; } @@ -837,19 +837,20 @@ void SPC_DSP::init( void* ram_64k ) stereo_switch = 0xffff; take_spc_snapshot = 0; spc_snapshot_callback = 0; + rom_enabled = 0; #ifndef NDEBUG // be sure this sign-extends assert( (int16_t) 0x8000 == -0x8000 ); - + // be sure right shift preserves sign assert( (-1 >> 1) == -1 ); - + // check clamp macro int i; i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); - + blargg_verify_byte_order(); #endif } @@ -857,13 +858,13 @@ void SPC_DSP::init( void* ram_64k ) void SPC_DSP::soft_reset_common() { require( m.ram ); // init() must have been called already - + m.noise = 0x4000; m.echo_hist_pos = m.echo_hist; m.every_other_sample = 1; m.echo_offset = 0; m.phase = 0; - + init_counter(); for (int i = 0; i < voice_count; i++) @@ -880,7 +881,7 @@ void SPC_DSP::load( uint8_t const regs [register_count] ) { memcpy( m.regs, regs, sizeof m.regs ); memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); - + // Internal state for ( int i = voice_count; --i >= 0; ) { @@ -892,7 +893,7 @@ void SPC_DSP::load( uint8_t const regs [register_count] ) m.new_kon = REG(kon); m.t_dir = REG(dir); m.t_esa = REG(esa); - + soft_reset_common(); } @@ -945,18 +946,18 @@ void SPC_State_Copier::extra() void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) { SPC_State_Copier copier( io, copy ); - + // DSP registers copier.copy( m.regs, register_count ); - + // Internal state - + // Voices int i; for ( i = 0; i < voice_count; i++ ) { voice_t* v = &m.voices [i]; - + // BRR buffer int i; for ( i = 0; i < brr_buf_size; i++ ) @@ -965,7 +966,7 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) SPC_COPY( int16_t, s ); v->buf [i] = v->buf [i + brr_buf_size] = s; } - + SPC_COPY( uint16_t, v->interp_pos ); SPC_COPY( uint16_t, v->brr_addr ); SPC_COPY( uint16_t, v->env ); @@ -979,10 +980,10 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) v->env_mode = (enum env_mode_t) m; } SPC_COPY( uint8_t, v->t_envx_out ); - + copier.extra(); } - + // Echo history for ( i = 0; i < echo_hist_size; i++ ) { @@ -996,28 +997,28 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) } m.echo_hist_pos = m.echo_hist; memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); - + // Misc SPC_COPY( uint8_t, m.every_other_sample ); SPC_COPY( uint8_t, m.kon ); - + SPC_COPY( uint16_t, m.noise ); SPC_COPY( uint16_t, m.counter ); SPC_COPY( uint16_t, m.echo_offset ); SPC_COPY( uint16_t, m.echo_length ); SPC_COPY( uint8_t, m.phase ); - + SPC_COPY( uint8_t, m.new_kon ); SPC_COPY( uint8_t, m.endx_buf ); SPC_COPY( uint8_t, m.envx_buf ); SPC_COPY( uint8_t, m.outx_buf ); - + SPC_COPY( uint8_t, m.t_pmon ); SPC_COPY( uint8_t, m.t_non ); SPC_COPY( uint8_t, m.t_eon ); SPC_COPY( uint8_t, m.t_dir ); SPC_COPY( uint8_t, m.t_koff ); - + SPC_COPY( uint16_t, m.t_brr_next_addr ); SPC_COPY( uint8_t, m.t_adsr0 ); SPC_COPY( uint8_t, m.t_brr_header ); @@ -1025,20 +1026,20 @@ void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) SPC_COPY( uint8_t, m.t_srcn ); SPC_COPY( uint8_t, m.t_esa ); SPC_COPY( uint8_t, m.t_echo_enabled ); - + SPC_COPY( int16_t, m.t_main_out [0] ); SPC_COPY( int16_t, m.t_main_out [1] ); SPC_COPY( int16_t, m.t_echo_out [0] ); SPC_COPY( int16_t, m.t_echo_out [1] ); SPC_COPY( int16_t, m.t_echo_in [0] ); SPC_COPY( int16_t, m.t_echo_in [1] ); - + SPC_COPY( uint16_t, m.t_dir_addr ); SPC_COPY( uint16_t, m.t_pitch ); SPC_COPY( int16_t, m.t_output ); SPC_COPY( uint16_t, m.t_echo_ptr ); SPC_COPY( uint8_t, m.t_looped ); - + copier.extra(); } #endif diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index b50bb631..638c400d 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -22,6 +22,7 @@ public: #else void load_state(uint8 **); void save_state(uint8 **); + void save_spc (uint8 *); #endif SMP(); ~SMP(); diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index 2e590e69..7c5179c4 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -1,9 +1,75 @@ #include "snes/snes.hpp" +#include + +typedef struct spc_file { + uint8 header[33]; + uint8 idtag[3]; + uint8 version_minor; + + uint8 pc_low; + uint8 pc_high; + uint8 a; + uint8 x; + uint8 y; + uint8 psw; + uint8 sp; + uint8 unused_a[2]; + + uint8 id666[210]; + + uint8 apuram[65536]; + uint8 dsp_registers[128]; + uint8 unused_b[64]; + uint8 iplrom[64]; +} spc_file; namespace SNES { #include "dsp/blargg_endian.h" +void SMP::save_spc (uint8 *block) { + spc_file out; + + const char *header = "SNES-SPC700 Sound File Data v0.30"; + memcpy (out.header, header, 33); + out.idtag[0] = out.idtag[1] = 26; + out.idtag[2] = 27; + out.version_minor = 30; + + out.pc_low = regs.pc & 0xff; + out.pc_high = (regs.pc >> 8) & 0xff; + out.a = regs.a; + out.x = regs.x; + out.y = regs.y; + out.psw = (uint8) ((unsigned) regs.p); + out.sp = regs.sp; + out.unused_a[0] = out.unused_a[1] = 0; + + memset (out.id666, 0, 210); + memcpy (out.apuram, apuram, 65536); + + for (int i = 0xf2; i <= 0xf7; i++) + { + out.apuram[i] = mmio_read (i); + } + + for (int i = 0xfd; i <= 0xff; i++) + { + out.apuram[i] = mmio_read (i); + } + + for (int i = 0; i < 128; i++) + { + out.dsp_registers[i] = dsp.read (i); + } + + memset (out.unused_b, 0, 64); + memcpy (out.iplrom, iplrom, 64); + + memcpy (block, &out, 66048); +} + + void SMP::save_state(uint8 **block) { uint8 *ptr = *block; memcpy(ptr, apuram, 64 * 1024); @@ -116,4 +182,4 @@ void SMP::load_state(uint8 **block) { *block = ptr; } -} +} /* namespace SNES */ diff --git a/snapshot.cpp b/snapshot.cpp index d07c430b..e6cd879a 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2275,29 +2275,3 @@ static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fie } } } - -bool8 S9xSPCDump (const char *filename) -{ - /* TODO: No SPC dumping in byuu SMP */ - /* - FILE *fs; - uint8 buf[SNES_SPC::spc_file_size]; - size_t ignore; - - fs = fopen(filename, "wb"); - if (!fs) - return (FALSE); - - S9xSetSoundMute(TRUE); - - spc_core->init_header(buf); - spc_core->save_spc(buf); - - ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs); - - fclose(fs); - - S9xSetSoundMute(FALSE); - */ - return (TRUE); -} diff --git a/snapshot.h b/snapshot.h index d55b8b7e..1cb4bd8c 100644 --- a/snapshot.h +++ b/snapshot.h @@ -195,6 +195,5 @@ bool8 S9xFreezeGame (const char *); bool8 S9xUnfreezeGame (const char *); void S9xFreezeToStream (STREAM); int S9xUnfreezeFromStream (STREAM); -bool8 S9xSPCDump (const char *); #endif From 7be597615970032662c95fbc3c2ed1806d058b05 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 10:23:58 -0500 Subject: [PATCH 022/130] Remove unneeded echo buffer hacks. --- apu/bapu/dsp/SPC_DSP.cpp | 14 ++--------- apu/bapu/dsp/SPC_DSP.h | 52 +++++++++++++++++++--------------------- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/apu/bapu/dsp/SPC_DSP.cpp b/apu/bapu/dsp/SPC_DSP.cpp index e3719203..aa036c09 100644 --- a/apu/bapu/dsp/SPC_DSP.cpp +++ b/apu/bapu/dsp/SPC_DSP.cpp @@ -605,11 +605,7 @@ VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } inline void SPC_DSP::echo_read( int ch ) { - int s; - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - s = GET_LE16SA( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0] ); - else - s = GET_LE16SA( ECHO_PTR( ch ) ); + int s = GET_LE16SA( ECHO_PTR( ch ) ); // second copy simplifies wrap-around handling ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; } @@ -720,12 +716,7 @@ ECHO_CLOCK( 28 ) inline void SPC_DSP::echo_write( int ch ) { if ( !(m.t_echo_enabled & 0x20) ) - { - if ( m.t_echo_ptr >= 0xffc0 && rom_enabled ) - SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] ); - else - SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); - } + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); m.t_echo_out [ch] = 0; } @@ -837,7 +828,6 @@ void SPC_DSP::init( void* ram_64k ) stereo_switch = 0xffff; take_spc_snapshot = 0; spc_snapshot_callback = 0; - rom_enabled = 0; #ifndef NDEBUG // be sure this sign-extends diff --git a/apu/bapu/dsp/SPC_DSP.h b/apu/bapu/dsp/SPC_DSP.h index 61d05ab5..ca61cc95 100644 --- a/apu/bapu/dsp/SPC_DSP.h +++ b/apu/bapu/dsp/SPC_DSP.h @@ -11,7 +11,7 @@ extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, s class SPC_DSP { public: typedef BOOST::uint8_t uint8_t; - + // Setup // Initializes DSP and has it use the 64K RAM provided @@ -34,7 +34,7 @@ public: // Emulates pressing reset switch on SNES void soft_reset(); - + // Reads/writes DSP registers. For accuracy, you must first call run() // to catch the DSP up to present. int read ( int addr ) const; @@ -43,7 +43,7 @@ public: // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks // a pair of samples is be generated. void run( int clock_count ); - + // Sound control // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). @@ -52,7 +52,7 @@ public: void mute_voices( int mask ); // State - + // Resets DSP and uses supplied values to initialize registers enum { register_count = 128 }; void load( uint8_t const regs [register_count] ); @@ -69,8 +69,6 @@ public: int stereo_switch; int take_spc_snapshot; - int rom_enabled; // mirror - uint8_t *rom, *hi_ram; // mirror void (*spc_snapshot_callback) (void); void set_spc_snapshot_callback( void (*callback) (void) ); @@ -110,12 +108,12 @@ public: void disable_surround( bool ) { } // not supported public: BLARGG_DISABLE_NOTHROW - + typedef BOOST::int8_t int8_t; typedef BOOST::int16_t int16_t; - + enum { echo_hist_size = 8 }; - + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; enum { brr_buf_size = 12 }; struct voice_t @@ -136,15 +134,15 @@ public: }; private: enum { brr_block_size = 9 }; - + struct state_t { uint8_t regs [register_count]; - + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) int echo_hist [echo_hist_size * 2] [2]; int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] - + int every_other_sample; // toggles every sample int kon; // KON value when last checked int noise; @@ -153,22 +151,22 @@ private: int echo_length; // number of bytes that echo_offset will stop at int phase; // next clock cycle to run (0-31) bool kon_check; // set when a new KON occurs - + // Hidden registers also written to when main register is written to int new_kon; uint8_t endx_buf; uint8_t envx_buf; uint8_t outx_buf; - + // Temporary state between clocks - + // read once per sample int t_pmon; int t_non; int t_eon; int t_dir; int t_koff; - + // read a few clocks ahead then used int t_brr_next_addr; int t_adsr0; @@ -177,21 +175,21 @@ private: int t_srcn; int t_esa; int t_echo_enabled; - + // internal state that is recalculated every sample int t_dir_addr; int t_pitch; int t_output; int t_looped; int t_echo_ptr; - + // left/right sums int t_main_out [2]; int t_echo_out [2]; int t_echo_in [2]; - + voice_t voices [voice_count]; - + // non-emulation state uint8_t* ram; // 64K shared RAM between DSP and SMP int mute_mask; @@ -201,11 +199,11 @@ private: sample_t extra [extra_size]; }; state_t m; - + void init_counter(); void run_counters(); unsigned read_counter( int rate ); - + int interpolate( voice_t const* v ); void run_envelope( voice_t* const v ); void decode_brr( voice_t* v ); @@ -244,7 +242,7 @@ private: void echo_28(); void echo_29(); void echo_30(); - + void soft_reset_common(); }; @@ -261,22 +259,22 @@ inline int SPC_DSP::read( int addr ) const inline void SPC_DSP::write( int addr, int data ) { assert( (unsigned) addr < register_count ); - + m.regs [addr] = (uint8_t) data; switch ( addr & 0x0F ) { case v_envx: m.envx_buf = (uint8_t) data; break; - + case v_outx: m.outx_buf = (uint8_t) data; break; - + case 0x0C: if ( addr == r_kon ) m.new_kon = (uint8_t) data; - + if ( addr == r_endx ) // always cleared, regardless of data written { m.endx_buf = 0; From 02a3b83c87f7b792371ce57cc56d74ee85382a45 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 13:20:26 -0500 Subject: [PATCH 023/130] Fix landing buffer size claim. --- apu/apu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 11bb5c7d..8072c19e 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -367,7 +367,7 @@ void S9xFinalizeSamples (void) else spc::sound_in_sync = FALSE; - SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); } void S9xLandSamples (void) @@ -453,7 +453,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) else spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); - SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size); UpdatePlaybackRate(); From 91e69af029d2e8d213f92119ec986bb70d18468a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 15:41:17 -0500 Subject: [PATCH 024/130] Loosen SMP<->DSP synchronization. --- apu/apu.cpp | 1 + apu/bapu/dsp/sdsp.hpp | 10 ++++++++++ apu/bapu/smp/core.cpp | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 8072c19e..d9c214b9 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -560,6 +560,7 @@ void S9xAPUExecute (void) void S9xAPUEndScanline (void) { S9xAPUExecute(); + SNES::dsp.synchronize(); if (SNES::dsp.spc_dsp.sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) S9xLandSamples(); diff --git a/apu/bapu/dsp/sdsp.hpp b/apu/bapu/dsp/sdsp.hpp index 83d51eb5..baf1e88b 100644 --- a/apu/bapu/dsp/sdsp.hpp +++ b/apu/bapu/dsp/sdsp.hpp @@ -1,12 +1,22 @@ #include "SPC_DSP.h" +#include class DSP : public Processor { public: inline uint8 read(uint8 addr) { + synchronize (); return spc_dsp.read(addr); } + inline void synchronize (void) { + if (clock) { + spc_dsp.run (clock); + clock = 0; + } + } + inline void write(uint8 addr, uint8 data) { + synchronize (); spc_dsp.write(addr, data); } diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index df4076c1..b5266cec 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -9,7 +9,7 @@ void SMP::tick() { synchronize_dsp(); #else clock++; - dsp.spc_dsp.run(1); + dsp.clock++; #endif } @@ -82,7 +82,7 @@ void SMP::op_step() { synchronize_dsp(); #else clock += cycle_count_table[opcode]; - dsp.spc_dsp.run(cycle_count_table[opcode]); + dsp.clock += cycle_count_table[opcode]; #endif From e3788c39e49876fd639e83b5de6efef01c5b9588 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 27 Jun 2011 16:28:45 -0500 Subject: [PATCH 025/130] Zero clock at appropriate times. --- apu/bapu/dsp/sdsp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apu/bapu/dsp/sdsp.cpp b/apu/bapu/dsp/sdsp.cpp index ef2c48da..0fe01476 100644 --- a/apu/bapu/dsp/sdsp.cpp +++ b/apu/bapu/dsp/sdsp.cpp @@ -11,11 +11,13 @@ void DSP::power() { spc_dsp.init(smp.apuram); spc_dsp.reset(); + clock = 0; } void DSP::reset() { spc_dsp.soft_reset(); + clock = 0; } static void from_dsp_to_state (uint8 **buf, void *var, size_t size) @@ -42,6 +44,7 @@ void DSP::load_state (uint8 **ptr) DSP::DSP() { + clock = 0; } } From 4d2fbc241af8199e891788346fdbc32a60e9a7c9 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 2 Jul 2011 04:25:13 +0200 Subject: [PATCH 026/130] Win32: add support for cg meta shaders (currently opengl only) --- win32/CCGShader.cpp | 119 ++++++++ win32/CCGShader.h | 43 +++ win32/CGLCG.cpp | 594 ++++++++++++++++++++++++++++++++++++++++ win32/CGLCG.h | 87 ++++++ win32/COpenGL.cpp | 146 +++------- win32/COpenGL.h | 3 + win32/cgFunctions.cpp | 14 +- win32/cgFunctions.h | 9 +- win32/snes9xw.vcproj | 16 ++ win32/win32_display.cpp | 18 +- win32/wsnes9x.cpp | 5 +- 11 files changed, 940 insertions(+), 114 deletions(-) create mode 100644 win32/CCGShader.cpp create mode 100644 win32/CCGShader.h create mode 100644 win32/CGLCG.cpp create mode 100644 win32/CGLCG.h diff --git a/win32/CCGShader.cpp b/win32/CCGShader.cpp new file mode 100644 index 00000000..91bd530b --- /dev/null +++ b/win32/CCGShader.cpp @@ -0,0 +1,119 @@ +#include "CCGShader.h" +#include "../conffile.h" + +CCGShader::CCGShader(void) +{ + +} + +CCGShader::~CCGShader(void) +{ +} + +cgScaleType CCGShader::scaleStringToEnum(const char *scale) +{ + if(!strcasecmp(scale,"source")) { + return CG_SCALE_SOURCE; + } else if(!strcasecmp(scale,"viewport")) { + return CG_SCALE_VIEWPORT; + } else if(!strcasecmp(scale,"absolute")) { + return CG_SCALE_ABSOLUTE; + } else { + return CG_SCALE_NONE; + } +} + +bool CCGShader::LoadShader(const char *path) +{ + ConfigFile conf; + int shaderCount; + char keyName[100]; + + shaderPasses.clear(); + lookupTextures.clear(); + + if(strlen(path)<4 || strcasecmp(&path[strlen(path)-4],".cgp")) { + shaderPass pass; + pass.scaleParams.scaleTypeX = CG_SCALE_NONE; + pass.scaleParams.scaleTypeY = CG_SCALE_NONE; + pass.linearFilter = false; + pass.filterSet = false; + strcpy(pass.cgShaderFile,path); + shaderPasses.push_back(pass); + return true; + } else { + conf.LoadFile(path); + } + + shaderCount = conf.GetInt("::shaders",0); + + if(shaderCount<1) + return false; + + for(int i=0;i + +enum cgScaleType { CG_SCALE_NONE, CG_SCALE_SOURCE, CG_SCALE_VIEWPORT, CG_SCALE_ABSOLUTE }; +typedef struct _cgScaleParams { + cgScaleType scaleTypeX; + cgScaleType scaleTypeY; + float scaleX; + float scaleY; + unsigned absX; + unsigned absY; +} cgScaleParams; + +class CCGShader +{ +private: + cgScaleType scaleStringToEnum(const char* scale); +public: + typedef struct _shaderPass { + cgScaleParams scaleParams; + bool linearFilter; + bool filterSet; + char cgShaderFile[PATH_MAX]; + } shaderPass; + typedef struct _lookupTexture { + char id[PATH_MAX]; + char texturePath[PATH_MAX]; + bool linearfilter; + } lookupTexture; + + CCGShader(void); + ~CCGShader(void); + bool LoadShader(const char *path); + + std::vector shaderPasses; + std::vector lookupTextures; +}; + +#endif diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp new file mode 100644 index 00000000..4aedf338 --- /dev/null +++ b/win32/CGLCG.cpp @@ -0,0 +1,594 @@ +#include "CGLCG.h" +#include "wsnes9x.h" +#include "win32_display.h" +#include + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +float npot(float desired) +{ + float out=512.0; + while(outcgContext = cgContext; + fboFunctionsLoaded = FALSE; + ClearPasses(); + LoadFBOFunctions(); + frameCnt=0; +} + +CGLCG::~CGLCG(void) +{ +} + +void CGLCG::ClearPasses() +{ + if(shaderPasses.size()>1) { + for(std::vector::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { + if(it->cgFragmentProgram) + cgDestroyProgram(it->cgFragmentProgram); + if(it->cgVertexProgram) + cgDestroyProgram(it->cgVertexProgram); + if(it->fbo) + glDeleteFramebuffers(1,&it->fbo); + if(it->tex) + glDeleteTextures(1,&it->tex); + } + } + for(std::vector::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) { + if(it->tex) + glDeleteTextures(1,&it->tex); + } + shaderPasses.clear(); + lookupTextures.clear(); + shaderLoaded = false; +} + +bool CGLCG::LoadFBOFunctions() +{ + if(fboFunctionsLoaded) + return true; + + const char *extensions = (const char *) glGetString(GL_EXTENSIONS); + + if(extensions && strstr(extensions, "framebuffer_object")) { + glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"); + glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers"); + glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"); + glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"); + glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus"); + glClientActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glClientActiveTexture"); + + if(glGenFramebuffers && glDeleteFramebuffers && glBindFramebuffer && glFramebufferTexture2D && glClientActiveTexture) { + fboFunctionsLoaded = true; + } + + } + return fboFunctionsLoaded; +} + +void CGLCG::checkForCgError(const char *situation) +{ + char buffer[4096]; + CGerror error = cgGetError(); + const char *string = cgGetErrorString(error); + + if (error != CG_NO_ERROR) { + sprintf(buffer, + "Situation: %s\n" + "Error: %s\n\n" + "Cg compiler output...\n", situation, string); + MessageBoxA(0, buffer, + "Cg error", MB_OK|MB_ICONEXCLAMATION); + if (error == CG_COMPILER_ERROR) { + MessageBoxA(0, cgGetLastListing(cgContext), + "Cg compilation error", MB_OK|MB_ICONEXCLAMATION); + } + } +} + +#define IS_SLASH(x) ((x) == TEXT('\\') || (x) == TEXT('/')) + +bool CGLCG::LoadShader(const TCHAR *shaderFile) +{ + CCGShader cgShader; + TCHAR shaderPath[MAX_PATH]; + TCHAR tempPath[MAX_PATH]; + CGprofile vertexProfile, fragmentProfile; + GLenum error; + + if(!fboFunctionsLoaded) { + MessageBox(NULL, TEXT("Your OpenGL graphics driver does not support framebuffer objects.\nYou will not be able to use CG shaders in OpenGL mode."), TEXT("CG Error"), + MB_OK|MB_ICONEXCLAMATION); + return false; + } + + vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); + fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); + + cgGLDisableProfile(vertexProfile); + cgGLDisableProfile(fragmentProfile); + + ClearPasses(); + + if (shaderFile == NULL || *shaderFile==TEXT('\0')) + return true; + + lstrcpy(shaderPath,shaderFile); + for(int i=lstrlen(shaderPath); i>=0; i--){ + if(IS_SLASH(shaderPath[i])){ + shaderPath[i]=TEXT('\0'); + break; + } + } + + SetCurrentDirectory(shaderPath); + if(!cgShader.LoadShader(_tToChar(shaderFile))) + return false; + + cgGLSetOptimalOptions(vertexProfile); + cgGLSetOptimalOptions(fragmentProfile); + + shaderPasses.push_back(shaderPass()); + + for(std::vector::iterator it=cgShader.shaderPasses.begin();it!=cgShader.shaderPasses.end();it++) { + shaderPasses.push_back(shaderPass()); + shaderPass &pass = shaderPasses.back(); + pass.scaleParams = it->scaleParams; + pass.linearFilter = (pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet)?GUI.BilinearFilter:it->linearFilter; + _tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH); + char *fileContents = ReadShaderFileContents(tempPath); + if(!fileContents) + return false; + + pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + vertexProfile, "main_vertex", NULL); + + checkForCgError("Compiling vertex program"); + + pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + fragmentProfile, "main_fragment", NULL); + + checkForCgError("Compiling fragment program"); + + delete [] fileContents; + if(!pass.cgVertexProgram || !pass.cgFragmentProgram) { + return false; + } + cgGLLoadProgram(pass.cgVertexProgram); + cgGLLoadProgram(pass.cgFragmentProgram); + + glGenFramebuffers(1,&pass.fbo); + glGenTextures(1,&pass.tex); + glBindTexture(GL_TEXTURE_2D,pass.tex); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + for(std::vector::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) { + lookupTextures.push_back(lookupTexture()); + lookupTexture &tex = lookupTextures.back(); + strcpy(tex.id,it->id); + glGenTextures(1,&tex.tex); + glBindTexture(GL_TEXTURE_2D,tex.tex); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST); + _tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH); + int strLen = strlen(it->texturePath); + if(strLen>4) { + if(!strcasecmp(&it->texturePath[strLen-4],".png")) { + int width, height; + bool hasAlpha; + GLubyte *texData; + if(loadPngImage(tempPath,width,height,hasAlpha,&texData)) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, width, + height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texData); + free(texData); + } + } else if(!strcasecmp(&it->texturePath[strLen-4],".tga")) { + STGA stga; + if(loadTGA(tempPath,stga)) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, stga.width); + glTexImage2D(GL_TEXTURE_2D, 0, 4, stga.width, + stga.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, stga.data); + } + } + + } + } + + glClientActiveTexture(GL_TEXTURE1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2,GL_FLOAT,0,lut_coords); + glClientActiveTexture(GL_TEXTURE0); + + shaderLoaded = true; + + return true; +} + +void CGLCG::setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown) +{ + float tX = inputSize.x / textureSize.x; + float tY = inputSize.y / textureSize.y; + + if(topdown) { + shaderPasses[pass].texcoords[0] = 0.0f; + shaderPasses[pass].texcoords[1] = tY; + shaderPasses[pass].texcoords[2] = tX; + shaderPasses[pass].texcoords[3] = tY; + shaderPasses[pass].texcoords[4] = tX; + shaderPasses[pass].texcoords[5] = 0.0f; + shaderPasses[pass].texcoords[6] = 0.0f; + shaderPasses[pass].texcoords[7] = 0.0f; + } else { + shaderPasses[pass].texcoords[0] = 0.0f; + shaderPasses[pass].texcoords[1] = 0.0f; + shaderPasses[pass].texcoords[2] = tX; + shaderPasses[pass].texcoords[3] = 0.0f; + shaderPasses[pass].texcoords[4] = tX; + shaderPasses[pass].texcoords[5] = tY; + shaderPasses[pass].texcoords[6] = 0.0f; + shaderPasses[pass].texcoords[7] = tY; + } + + glTexCoordPointer(2, GL_FLOAT, 0, shaderPasses[pass].texcoords); +} + +void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize) +{ + GLenum error; + frameCnt++; + CGprofile vertexProfile, fragmentProfile; + + if(!shaderLoaded) + return; + + vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); + fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); + + cgGLEnableProfile(vertexProfile); + cgGLEnableProfile(fragmentProfile); + + shaderPasses[0].tex = origTex; + shaderPasses[0].outputSize = inputSize; + shaderPasses[0].textureSize = textureSize; + + for(int i=1;i1) { + for(int i=1;iwidth; + outHeight = info_ptr->height; + switch (info_ptr->color_type) { + case PNG_COLOR_TYPE_RGBA: + outHasAlpha = true; + break; + case PNG_COLOR_TYPE_RGB: + outHasAlpha = false; + break; + default: + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + return false; + } + unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr); + *outData = (unsigned char*) malloc(row_bytes * outHeight); + + png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr); + + for (int i = 0; i < outHeight; i++) { + memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes); + } + + /* Clean up after the read, + * and free any memory allocated */ + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return true; +} + +bool CGLCG::loadTGA(const TCHAR *filename, STGA& tgaFile) +{ + FILE *file; + unsigned char type[4]; + unsigned char info[6]; + + file = _tfopen(filename, TEXT("rb")); + + if (!file) + return false; + + fread (&type, sizeof (char), 3, file); + fseek (file, 12, SEEK_SET); + fread (&info, sizeof (char), 6, file); + + //image type either 2 (color) or 3 (greyscale) + if (type[1] != 0 || (type[2] != 2 && type[2] != 3)) + { + fclose(file); + return false; + } + + tgaFile.width = info[0] + info[1] * 256; + tgaFile.height = info[2] + info[3] * 256; + tgaFile.byteCount = info[4] / 8; + + if (tgaFile.byteCount != 3 && tgaFile.byteCount != 4) { + fclose(file); + return false; + } + + long imageSize = tgaFile.width * tgaFile.height * tgaFile.byteCount; + + //allocate memory for image data + unsigned char *tempBuf = new unsigned char[imageSize]; + tgaFile.data = new unsigned char[tgaFile.width * tgaFile.height * 4]; + + //read in image data + fread(tempBuf, sizeof(unsigned char), imageSize, file); + + //swap line order and convert to RBGA + for(int i=0;i +#include +#include "glext.h" +#include "cgFunctions.h" +#include "CCGShader.h" +#include + +typedef struct _xySize { + double x; + double y; +} xySize; + +class CGLCG +{ +private: + typedef struct _STGA { + _STGA() {data = (unsigned char*)0; + width = 0; + height = 0; + byteCount = 0;} + + ~_STGA() { delete[] data; data = 0; } + + void destroy() { delete[] data; data = 0; } + + int width; + int height; + unsigned char byteCount; + unsigned char* data; + } STGA; + typedef struct _shaderPass { + cgScaleParams scaleParams; + bool linearFilter; + CGprogram cgVertexProgram, cgFragmentProgram; + GLuint tex; + GLuint fbo; + xySize outputSize; + xySize textureSize; + GLfloat texcoords[8]; + _shaderPass() {cgVertexProgram=NULL; + cgFragmentProgram=NULL; + fbo=NULL; + tex=NULL;} + } shaderPass; + typedef struct _lookupTexture { + char id[PATH_MAX]; + GLuint tex; + _lookupTexture() {tex=NULL;} + } lookupTexture; + + std::vector shaderPasses; + std::vector lookupTextures; + + bool fboFunctionsLoaded; + bool shaderLoaded; + bool LoadFBOFunctions(); + void checkForCgError(const char *situation); + void setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown=false); + void setShaderVars(int pass); + bool loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData); + bool loadTGA(const TCHAR *filename, STGA& tgaFile); + + CGcontext cgContext; + int frameCnt; + static const GLfloat lut_coords[8]; + + + PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; + PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; + PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; + PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; + PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; + PFNGLACTIVETEXTUREPROC glClientActiveTexture; + +public: + CGLCG(CGcontext cgContext); + ~CGLCG(void); + + bool LoadShader(const TCHAR *shaderFile); + void Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize); + void ClearPasses(); +}; + +#endif diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 66597c79..4819990f 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -211,6 +211,7 @@ COpenGL::COpenGL(void) cgVertexProgram = cgFragmentProgram = NULL; cgAvailable = false; frameCount = 0; + cgShader = NULL; } COpenGL::~COpenGL(void) @@ -285,6 +286,7 @@ bool COpenGL::Initialize(HWND hWnd) cgAvailable = loadCgFunctions(); if(cgAvailable) { cgContext = cgCreateContext(); + cgShader = new CGLCG(cgContext); } GetClientRect(hWnd,&windowRect); @@ -323,6 +325,10 @@ void COpenGL::DeInitialize() if(cgAvailable) unloadCgLibrary(); cgAvailable = false; + if(cgShader) { + delete cgShader; + cgShader = NULL; + } } void COpenGL::CreateDrawSurface() @@ -402,6 +408,7 @@ void COpenGL::SetupVertices() texcoords[5] = 0.0f; texcoords[6] = 0.0f; texcoords[7] = 0.0f; + glTexCoordPointer(2, GL_FLOAT, 0, texcoords); } void COpenGL::Render(SSurface Src) @@ -421,6 +428,7 @@ void COpenGL::Render(SSurface Src) } if(pboFunctionsLoaded) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer); Dst.Surface = (unsigned char *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY); } else { Dst.Surface = noPboBuffer; @@ -444,18 +452,25 @@ void COpenGL::Render(SSurface Src) ApplyDisplayChanges(); } - if (shader_type != OGL_SHADER_NONE) { - GLint location; + glBindTexture(GL_TEXTURE_2D,drawTexture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); + glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer); - float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; - RECT windowSize; - GetClientRect(hWnd,&windowSize); - float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), - (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; - float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; - float frameCnt = (float)++frameCount; + if(pboFunctionsLoaded) + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + if (shader_type != OGL_SHADER_NONE) { if(shader_type == OGL_SHADER_GLSL) { + GLint location; + + float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; + RECT windowSize; + GetClientRect(hWnd,&windowSize); + float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), + (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; + float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; + float frameCnt = (float)++frameCount; location = glGetUniformLocation (shaderProgram, "rubyInputSize"); glUniform2fv (location, 1, inputSize); @@ -465,37 +480,26 @@ void COpenGL::Render(SSurface Src) location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); glUniform2fv (location, 1, textureSize); } else if(shader_type == OGL_SHADER_CG) { - CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); - - cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); - -#define setProgram2fv(program,varname,floats)\ -{\ - CGparameter cgp = cgGetNamedParameter(program, varname);\ - if(cgp)\ - cgGLSetParameter2fv(cgp,floats);\ -}\ - -#define setProgram1f(program,varname,val)\ -{\ - CGparameter cgp = cgGetNamedParameter(program, varname);\ - if(cgp)\ - cgGLSetParameter1f(cgp,val);\ -}\ - - setProgram2fv(cgFragmentProgram,"IN.video_size",inputSize); - setProgram2fv(cgFragmentProgram,"IN.texture_size",textureSize); - setProgram2fv(cgFragmentProgram,"IN.output_size",outputSize); - setProgram1f(cgFragmentProgram,"IN.frame_count",frameCnt); - setProgram2fv(cgVertexProgram,"IN.video_size",inputSize); - setProgram2fv(cgVertexProgram,"IN.texture_size",textureSize); - setProgram2fv(cgVertexProgram,"IN.output_size",outputSize); - setProgram1f(cgVertexProgram,"IN.frame_count",frameCnt); + xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight }; + RECT windowSize, displayRect; + GetClientRect(hWnd,&windowSize); + xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom }; + //Get maximum rect respecting AR setting + displayRect=CalculateDisplayRect(windowSize.right,windowSize.bottom,windowSize.right,windowSize.bottom); + xySize viewportSize = { (double)(displayRect.right - displayRect.left), + (double)(displayRect.bottom - displayRect.top) }; + xySize textureSize = { (double)quadTextureSize, (double)quadTextureSize }; + cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize); } } - glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); - glTexSubImage2D (GL_TEXTURE_2D,0,0,0,dstRect.right-dstRect.left,dstRect.bottom-dstRect.top,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,pboFunctionsLoaded?0:noPboBuffer); + if(GUI.BilinearFilter) { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClear(GL_COLOR_BUFFER_BIT); @@ -515,13 +519,6 @@ bool COpenGL::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight) bool COpenGL::ApplyDisplayChanges(void) { - if(GUI.BilinearFilter) { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } if(wglSwapIntervalEXT) { wglSwapIntervalEXT(GUI.Vsync?1:0); } @@ -683,7 +680,9 @@ bool COpenGL::SetShaders(const TCHAR *file) SetShadersCG(NULL); SetShadersGLSL(NULL); shader_type = OGL_SHADER_NONE; - if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) { + if(file!=NULL && ( + (lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) || + (lstrlen(file)>4 && _tcsncicmp(&file[lstrlen(file)-4],TEXT(".cgp"),4)==0))) { return SetShadersCG(file); } else { return SetShadersGLSL(file); @@ -712,70 +711,15 @@ void COpenGL::checkForCgError(const char *situation) bool COpenGL::SetShadersCG(const TCHAR *file) { - TCHAR errorMsg[MAX_PATH + 50]; - HRESULT hr; - CGprofile vertexProfile, fragmentProfile; - - if(cgFragmentProgram) { - cgDestroyProgram(cgFragmentProgram); - cgFragmentProgram = NULL; - } - if(cgVertexProgram) { - cgDestroyProgram(cgVertexProgram); - cgVertexProgram = NULL; - } - - if(cgAvailable) { - vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); - fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); - - cgGLDisableProfile(vertexProfile); - cgGLDisableProfile(fragmentProfile); - } - - if (file == NULL || *file==TEXT('\0')) - return true; - if(!cgAvailable) { MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), MB_OK|MB_ICONEXCLAMATION); return false; } - cgGLSetOptimalOptions(vertexProfile); - cgGLSetOptimalOptions(fragmentProfile); - - char *fileContents = ReadShaderFileContents(file); - if(!fileContents) + if(!cgShader->LoadShader(file)) return false; - cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, - vertexProfile, "main_vertex", NULL); - - checkForCgError("Compiling vertex program"); - - cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, - fragmentProfile, "main_fragment", NULL); - - checkForCgError("Compiling fragment program"); - - delete [] fileContents; - - if(!cgVertexProgram || !cgFragmentProgram) { - return false; - } - - if(cgVertexProgram) { - cgGLEnableProfile(vertexProfile); - cgGLLoadProgram(cgVertexProgram); - cgGLBindProgram(cgVertexProgram); - } - if(cgFragmentProgram) { - cgGLEnableProfile(fragmentProfile); - cgGLLoadProgram(cgFragmentProgram); - cgGLBindProgram(cgFragmentProgram); - } - shader_type = OGL_SHADER_CG; return true; diff --git a/win32/COpenGL.h b/win32/COpenGL.h index cd10f85b..12448c8a 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -183,6 +183,7 @@ #include #include #include "cgFunctions.h" +#include "CGLCG.h" #include "glext.h" #include "wglext.h" @@ -219,6 +220,8 @@ private: current_ogl_shader_type shader_type; bool cgAvailable; + CGLCG *cgShader; + GLuint shaderProgram; GLuint vertexShader; GLuint fragmentShader; diff --git a/win32/cgFunctions.cpp b/win32/cgFunctions.cpp index 7229f3e1..e458f486 100644 --- a/win32/cgFunctions.cpp +++ b/win32/cgFunctions.cpp @@ -211,6 +211,10 @@ CGGLDP cgGLDisableProfile = NULL; CGGLSOO cgGLSetOptimalOptions = NULL; CGGLLP cgGLLoadProgram = NULL; CGGLBP cgGLBindProgram = NULL; +CGGLSTP cgGLSetTextureParameter = NULL; +CGGLETP cgGLEnableTextureParameter = NULL; +CGGLSPP cgGLSetParameterPointer = NULL; +CGGLECS cgGLEnableClientState = NULL; bool loadCgFunctions() { @@ -256,6 +260,10 @@ bool loadCgFunctions() cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions"); cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram"); cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram"); + cgGLSetTextureParameter = (CGGLSTP)GetProcAddress(hCgGLDll,"cgGLSetTextureParameter"); + cgGLEnableTextureParameter = (CGGLETP)GetProcAddress(hCgGLDll,"cgGLEnableTextureParameter"); + cgGLSetParameterPointer = (CGGLSPP)GetProcAddress(hCgGLDll,"cgGLSetParameterPointer"); + cgGLEnableClientState = (CGGLECS)GetProcAddress(hCgGLDll,"cgGLEnableClientState"); if( //cg.dll @@ -285,7 +293,11 @@ bool loadCgFunctions() !cgGLDisableProfile || !cgGLSetOptimalOptions || !cgGLLoadProgram || - !cgGLBindProgram) { + !cgGLBindProgram || + !cgGLSetTextureParameter || + !cgGLEnableTextureParameter || + !cgGLSetParameterPointer || + !cgGLEnableClientState) { unloadCgLibrary(); return false; } diff --git a/win32/cgFunctions.h b/win32/cgFunctions.h index 324eca32..636dd833 100644 --- a/win32/cgFunctions.h +++ b/win32/cgFunctions.h @@ -243,7 +243,14 @@ typedef CGGL_API void (CGGLENTRY *CGGLLP)(CGprogram program); extern CGGLLP cgGLLoadProgram; typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program); extern CGGLBP cgGLBindProgram; - +typedef CGGL_API void (CGGLENTRY *CGGLSTP)(CGparameter param, GLuint texobj); +extern CGGLSTP cgGLSetTextureParameter; +typedef CGGL_API void (CGGLENTRY *CGGLETP)(CGparameter param); +extern CGGLETP cgGLEnableTextureParameter; +typedef CGGL_API void (CGGLENTRY *CGGLSPP)(CGparameter param, GLint fsize, GLenum type, GLsizei stride, const GLvoid *pointer); +extern CGGLSPP cgGLSetParameterPointer; +typedef CGGL_API void (CGGLENTRY *CGGLECS)(CGparameter param); +extern CGGLECS cgGLEnableClientState; //cgfunctions.cpp diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 4b5bda35..94d0dbb1 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -3129,6 +3129,14 @@ + + + + @@ -3209,6 +3217,14 @@ RelativePath=".\cgFunctions.h" > + + + + diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index 2809347b..72afd1ea 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -272,27 +272,27 @@ void WinDisplayApplyChanges() RECT CalculateDisplayRect(unsigned int sourceWidth,unsigned int sourceHeight, unsigned int displayWidth,unsigned int displayHeight) { - float xFactor; - float yFactor; - float minFactor; - float renderWidthCalc,renderHeightCalc; + double xFactor; + double yFactor; + double minFactor; + double renderWidthCalc,renderHeightCalc; int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; - float snesAspect = (float)GUI.AspectWidth/hExtend; + double snesAspect = (double)GUI.AspectWidth/hExtend; RECT drawRect; if(GUI.Stretch) { if(GUI.AspectRatio) { //fix for hi-res images with FILTER_NONE //where we need to correct the aspect ratio - renderWidthCalc = (float)sourceWidth; - renderHeightCalc = (float)sourceHeight; + renderWidthCalc = (double)sourceWidth; + renderHeightCalc = (double)sourceHeight; if(renderWidthCalc/renderHeightCalc>snesAspect) renderWidthCalc = renderHeightCalc * snesAspect; else if(renderWidthCalc/renderHeightCalc Date: Sun, 3 Jul 2011 20:42:28 +0200 Subject: [PATCH 027/130] Win32: fix various meta shader problems and edge cases (themaister) --- win32/CCGShader.cpp | 2 ++ win32/CGLCG.cpp | 28 ++++++++++++++-------------- win32/COpenGL.cpp | 7 +++++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/win32/CCGShader.cpp b/win32/CCGShader.cpp index 91bd530b..8c589039 100644 --- a/win32/CCGShader.cpp +++ b/win32/CCGShader.cpp @@ -115,5 +115,7 @@ bool CCGShader::LoadShader(const char *path) id = strtok(NULL,";"); } + free(shaderIds); + return true; } diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 4aedf338..550e7623 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -266,7 +266,7 @@ void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize shaderPasses[0].tex = origTex; shaderPasses[0].outputSize = inputSize; - shaderPasses[0].textureSize = textureSize; + shaderPasses[0].textureSize = textureSize; for(int i=1;i Date: Sun, 3 Jul 2011 23:12:41 +0200 Subject: [PATCH 028/130] Win32: add PREV support to cg meta shaders, clean up code --- win32/CCGShader.h | 6 +- win32/CGLCG.cpp | 174 ++++++++++++++++++++++++++++++++++++++-------- win32/CGLCG.h | 12 +++- win32/COpenGL.cpp | 31 ++++----- 4 files changed, 171 insertions(+), 52 deletions(-) diff --git a/win32/CCGShader.h b/win32/CCGShader.h index 9c3322df..9fe2f7fe 100644 --- a/win32/CCGShader.h +++ b/win32/CCGShader.h @@ -36,8 +36,10 @@ public: ~CCGShader(void); bool LoadShader(const char *path); - std::vector shaderPasses; - std::vector lookupTextures; + typedef std::vector passVector; + typedef std::vector lutVector; + passVector shaderPasses; + lutVector lookupTextures; }; #endif diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 550e7623..1667dfae 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -24,16 +24,21 @@ CGLCG::CGLCG(CGcontext cgContext) ClearPasses(); LoadFBOFunctions(); frameCnt=0; + prevTex=0; } CGLCG::~CGLCG(void) { + LoadShader(NULL); } void CGLCG::ClearPasses() { + /* clean up cg programs, fbos and textures from all regular passes + pass 0 is the orignal texture, so ignore that + */ if(shaderPasses.size()>1) { - for(std::vector::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { + for(glPassVector::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { if(it->cgFragmentProgram) cgDestroyProgram(it->cgFragmentProgram); if(it->cgVertexProgram) @@ -44,12 +49,13 @@ void CGLCG::ClearPasses() glDeleteTextures(1,&it->tex); } } - for(std::vector::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) { + for(glLutVector::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) { if(it->tex) glDeleteTextures(1,&it->tex); } shaderPasses.clear(); lookupTextures.clear(); + shaderLoaded = false; } @@ -120,6 +126,11 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) ClearPasses(); + if(prevTex) { + glDeleteTextures(1,&prevTex); + prevTex=0; + } + if (shaderFile == NULL || *shaderFile==TEXT('\0')) return true; @@ -138,13 +149,25 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) cgGLSetOptimalOptions(vertexProfile); cgGLSetOptimalOptions(fragmentProfile); + /* insert dummy pass that will contain the original texture + */ shaderPasses.push_back(shaderPass()); - for(std::vector::iterator it=cgShader.shaderPasses.begin();it!=cgShader.shaderPasses.end();it++) { - shaderPasses.push_back(shaderPass()); - shaderPass &pass = shaderPasses.back(); + for(CCGShader::passVector::iterator it=cgShader.shaderPasses.begin(); + it!=cgShader.shaderPasses.end();it++) { + shaderPass pass; + pass.scaleParams = it->scaleParams; - pass.linearFilter = (pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet)?GUI.BilinearFilter:it->linearFilter; + /* if this is the last pass (the only one that can have CG_SCALE_NONE) + and no filter has been set use the GUI setting + */ + if(pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet) { + pass.linearFilter = GUI.BilinearFilter; + } else { + pass.linearFilter = it->linearFilter; + } + + // paths in the meta file can be relative _tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH); char *fileContents = ReadShaderFileContents(tempPath); if(!fileContents) @@ -167,6 +190,9 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) cgGLLoadProgram(pass.cgVertexProgram); cgGLLoadProgram(pass.cgFragmentProgram); + /* generate framebuffer and texture for this pass and apply + default texture settings + */ glGenFramebuffers(1,&pass.fbo); glGenTextures(1,&pass.tex); glBindTexture(GL_TEXTURE_2D,pass.tex); @@ -174,19 +200,26 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + shaderPasses.push_back(pass); } - for(std::vector::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) { - lookupTextures.push_back(lookupTexture()); - lookupTexture &tex = lookupTextures.back(); + for(std::vector::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) { + lookupTexture tex; strcpy(tex.id,it->id); + + /* generate texture for the lut and apply specified filter setting + */ glGenTextures(1,&tex.tex); glBindTexture(GL_TEXTURE_2D,tex.tex); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, it->linearfilter?GL_LINEAR:GL_NEAREST); + _tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH); + + // simple file extension png/tga decision int strLen = strlen(it->texturePath); if(strLen>4) { if(!strcasecmp(&it->texturePath[strLen-4],".png")) { @@ -207,15 +240,27 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) stga.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, stga.data); } } - } + lookupTextures.push_back(tex); } + /* enable texture unit 1 for the lookup textures + */ glClientActiveTexture(GL_TEXTURE1); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2,GL_FLOAT,0,lut_coords); glClientActiveTexture(GL_TEXTURE0); + /* generate a texture that we can swap with the original texture + and pass back to the main opengl code + */ + glGenTextures(1,&prevTex); + glBindTexture(GL_TEXTURE_2D,prevTex); + glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,512,512,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL); + glBindTexture(GL_TEXTURE_2D,0); + prevTexSize.x = prevTexSize.y = prevTexImageSize.x = prevTexImageSize.y = 0; + memset(prevTexCoords,0,sizeof(prevTexCoords)); + shaderLoaded = true; return true; @@ -226,6 +271,7 @@ void CGLCG::setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdo float tX = inputSize.x / textureSize.x; float tY = inputSize.y / textureSize.y; + // last pass uses top-down coordinates, all others bottom-up if(topdown) { shaderPasses[pass].texcoords[0] = 0.0f; shaderPasses[pass].texcoords[1] = tY; @@ -249,7 +295,7 @@ void CGLCG::setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdo glTexCoordPointer(2, GL_FLOAT, 0, shaderPasses[pass].texcoords); } -void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize) +void CGLCG::Render(GLuint &origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize) { GLenum error; frameCnt++; @@ -264,10 +310,14 @@ void CGLCG::Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize cgGLEnableProfile(vertexProfile); cgGLEnableProfile(fragmentProfile); + /* set up our dummy pass for easier loop code + */ shaderPasses[0].tex = origTex; shaderPasses[0].outputSize = inputSize; shaderPasses[0].textureSize = textureSize; + /* loop through all real passes + */ for(int i=1;i1) { + /* PASSX parameters, only for third pass and up + */ + if(pass>2) { for(int i=1;i shaderPasses; - std::vector lookupTextures; + typedef std::vector glPassVector; + typedef std::vector glLutVector; + glPassVector shaderPasses; + glLutVector lookupTextures; bool fboFunctionsLoaded; bool shaderLoaded; @@ -66,6 +68,10 @@ private: CGcontext cgContext; int frameCnt; static const GLfloat lut_coords[8]; + GLuint prevTex; + xySize prevTexSize; + xySize prevTexImageSize; + GLfloat prevTexCoords[8]; PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; @@ -80,7 +86,7 @@ public: ~CGLCG(void); bool LoadShader(const TCHAR *shaderFile); - void Render(GLuint origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize); + void Render(GLuint &origTex, xySize textureSize, xySize inputSize, xySize viewportSize, xySize windowSize); void ClearPasses(); }; diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 617fa781..28d1466a 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -289,8 +289,7 @@ bool COpenGL::Initialize(HWND hWnd) cgShader = new CGLCG(cgContext); } - GetClientRect(hWnd,&windowRect); - ChangeRenderSize(windowRect.right,windowRect.bottom); + ApplyDisplayChanges(); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClear(GL_COLOR_BUFFER_BIT); @@ -322,13 +321,13 @@ void COpenGL::DeInitialize() afterRenderHeight = 0; shaderFunctionsLoaded = false; shader_type = OGL_SHADER_NONE; - if(cgAvailable) - unloadCgLibrary(); - cgAvailable = false; if(cgShader) { delete cgShader; cgShader = NULL; } + if(cgAvailable) + unloadCgLibrary(); + cgAvailable = false; } void COpenGL::CreateDrawSurface() @@ -350,6 +349,7 @@ void COpenGL::CreateDrawSurface() glGenBuffers(1,&drawBuffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER,drawBuffer); glBufferData(GL_PIXEL_UNPACK_BUFFER,quadTextureSize*quadTextureSize*2,NULL,GL_STREAM_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0); } else { noPboBuffer = new BYTE[quadTextureSize*quadTextureSize*2]; } @@ -357,7 +357,6 @@ void COpenGL::CreateDrawSurface() glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); } - ApplyDisplayChanges(); } void COpenGL::DestroyDrawSurface() @@ -450,13 +449,7 @@ void COpenGL::Render(SSurface Src) afterRenderHeight = dstRect.bottom; afterRenderWidth = dstRect.right; - /* disable UNPACK_BUFFER, since ApplyDisplayChanges can lead to texture - calls in the cg shader class which are not allowed */ - if(pboFunctionsLoaded) - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - ApplyDisplayChanges(); - if(pboFunctionsLoaded) - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, drawBuffer); + ChangeRenderSize(0,0); } glBindTexture(GL_TEXTURE_2D,drawTexture); @@ -518,7 +511,13 @@ void COpenGL::Render(SSurface Src) bool COpenGL::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight) { - RECT displayRect=CalculateDisplayRect(afterRenderWidth,afterRenderHeight,newWidth,newHeight); + RECT displayRect, windowSize; + if(newWidth==0||newHeight==0) { + GetClientRect(hWnd,&windowSize); + newWidth = windowSize.right; + newHeight = windowSize.bottom; + } + displayRect=CalculateDisplayRect(afterRenderWidth,afterRenderHeight,newWidth,newHeight); glViewport(displayRect.left,newHeight-displayRect.bottom,displayRect.right-displayRect.left,displayRect.bottom-displayRect.top); SetupVertices(); return true; @@ -534,9 +533,7 @@ bool COpenGL::ApplyDisplayChanges(void) else SetShaders(NULL); - RECT windowSize; - GetClientRect(hWnd,&windowSize); - ChangeRenderSize(windowSize.right,windowSize.bottom); + ChangeRenderSize(0,0); return true; } From 63b0a6d45e58e87aaec62bf531ee0ef34f1d0ad7 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 4 Jul 2011 17:33:09 -0500 Subject: [PATCH 029/130] Add DSP clock remainder to save state. --- apu/apu.cpp | 4 ++++ apu/bapu/smp/smp.hpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index d9c214b9..aeb116e9 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -617,6 +617,8 @@ void S9xAPUSaveState (uint8 *block) ptr += sizeof(int32); SNES::set_le32(ptr, spc::remainder); ptr += sizeof(int32); + SNES::set_le32(ptr, SNES::dsp.clock); + ptr += sizeof(int32); memcpy (ptr, SNES::cpu.registers, 4); } @@ -633,6 +635,8 @@ void S9xAPULoadState (uint8 *block) ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); ptr += sizeof(int32); + SNES::dsp.clock = SNES::get_le32(ptr); + ptr += sizeof(int32); memcpy (SNES::cpu.registers, ptr, 4); } diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 638c400d..1bf75129 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -93,7 +93,7 @@ public: Timer<128> timer1; Timer< 16> timer2; - void tick(); + alwaysinline void tick(); alwaysinline void op_io(); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); From 2b5a54b401668d46d20fd69411800c5790a1f892 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 5 Jul 2011 06:23:24 -0500 Subject: [PATCH 030/130] Inline ticks. This should fix speed issues. --- apu/bapu/smp/smp.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 1bf75129..cb57f334 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -85,15 +85,15 @@ public: uint8 stage2_ticks; uint8 stage3_ticks; - void tick(); - void tick(unsigned clocks); + inline void tick(); + inline void tick(unsigned clocks); }; Timer<128> timer0; Timer<128> timer1; Timer< 16> timer2; - alwaysinline void tick(); + inline void tick(); alwaysinline void op_io(); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); From baa4de371356b57d87cc3fafcf9c615022ad1a62 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 5 Jul 2011 14:05:36 -0500 Subject: [PATCH 031/130] Save a few more mmapped registers to SPC files. Fix key-on trigger. --- apu/apu.cpp | 3 +-- apu/bapu/smp/smp_state.cpp | 2 +- gtk/src/gtk_file.cpp | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index aeb116e9..c41634c8 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -492,8 +492,6 @@ bool8 S9xInitAPU (void) spc::shrink_buffer = NULL; spc::resampler = NULL; - SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); - return (TRUE); } @@ -590,6 +588,7 @@ void S9xResetAPU (void) SNES::smp.power (); SNES::dsp.power (); SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + SNES::dsp.spc_dsp.set_spc_snapshot_callback(SPCSnapshotCallback); spc::resampler->clear(); } diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index 7c5179c4..e3b9d446 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -48,7 +48,7 @@ void SMP::save_spc (uint8 *block) { memset (out.id666, 0, 210); memcpy (out.apuram, apuram, 65536); - for (int i = 0xf2; i <= 0xf7; i++) + for (int i = 0xf2; i <= 0xf9; i++) { out.apuram[i] = mmio_read (i); } diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index 0610d439..2182e39e 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -157,6 +157,7 @@ S9xGetDirectory (enum s9x_getdirtype dirtype) case SCREENSHOT_DIR: case SPC_DIR: sprintf (path, "%s", gui_config->export_directory); + break; default: path[0] = '\0'; From 4fdc7af7da2712d4ef7280d56d39207f6a67fd5f Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 6 Jul 2011 09:20:31 -0500 Subject: [PATCH 032/130] Set the output buffer after loading state so the first set of samples isn't excluded. --- apu/apu.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apu/apu.cpp b/apu/apu.cpp index c41634c8..795dd2f7 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -630,6 +630,8 @@ void S9xAPULoadState (uint8 *block) SNES::smp.load_state (&ptr); SNES::dsp.load_state (&ptr); + SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); From 1f4f1f06d9490da35960ef6f6ba23a4d51649a1a Mon Sep 17 00:00:00 2001 From: zones Date: Mon, 18 Jul 2011 22:11:30 +0900 Subject: [PATCH 033/130] G-NEXT add-on cart support (untested) --- memmap.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++- memmap.h | 2 + 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/memmap.cpp b/memmap.cpp index 81edf082..d1771c79 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -941,6 +941,8 @@ 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 bool8 is_GNEXT_BIOS (uint8 *, uint32); +static bool8 is_GNEXT_Add_On (uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); static bool8 ReadUPSPatch (Reader *, long, int32 &); @@ -1239,6 +1241,22 @@ static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) return (FALSE); } +static bool8 is_GNEXT_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x180000 && strncmp((char *) (data + 0x7fc0), "SFC SDGUNDAMGNEXT", 17) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_GNEXT_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); @@ -1756,6 +1774,9 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) else if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) Multi.cartType = 3; + else + if (is_GNEXT_BIOS(ROM, Multi.cartSizeA)) + Multi.cartType = 5; } else if (Multi.cartSizeB) @@ -1776,6 +1797,10 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) r = LoadSameGame(cartA, cartB); break; + case 5: + r = LoadGNEXT(cartA, cartB); + break; + default: r = FALSE; } @@ -1915,6 +1940,43 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) return (TRUE); } +bool8 CMemory::LoadGNEXT (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0; + Multi.cartOffsetB = 0x400000; + Multi.sramA = SRAM; + Multi.sramB = NULL; + + Multi.sramSizeA = ROM[0x7fd8]; + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + Multi.sramSizeB = 0; + Multi.sramMaskB = 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + + 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_GNEXT_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; + else + strcpy(Multi.fileNameB, cartB); + } + + strcpy(ROMFilename, Multi.fileNameA); + + LoROM = TRUE; + HiROM = FALSE; + CalculatedSize = Multi.cartSizeA; + + return (TRUE); +} + bool8 CMemory::LoadSRTC (void) { FILE *fp; @@ -2461,7 +2523,12 @@ void CMemory::InitROM (void) Map_SuperFXLoROMMap(); else if (Settings.SA1) - Map_SA1LoROMMap(); + { + if (Multi.cartType == 5) + Map_GNEXTSA1LoROMMap(); + else + Map_SA1LoROMMap(); + } else if (Settings.SDD1) Map_SDD1LoROMMap(); @@ -3143,6 +3210,51 @@ void CMemory::Map_SA1LoROMMap (void) BWRAM = SRAM; } +void CMemory::Map_GNEXTSA1LoROMMap (void) +{ + printf("Map_GNEXTSA1LoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + + 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); + + // FIXME: untested! + map_hirom_offset(0x70, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + 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"); diff --git a/memmap.h b/memmap.h index 2b05de61..4991ae83 100644 --- a/memmap.h +++ b/memmap.h @@ -277,6 +277,7 @@ struct CMemory bool8 LoadMultiCart (const char *, const char *); bool8 LoadSufamiTurbo (const char *, const char *); bool8 LoadSameGame (const char *, const char *); + bool8 LoadGNEXT (const char *, const char *); bool8 LoadSRAM (const char *); bool8 SaveSRAM (const char *); void ClearSRAM (bool8 onlyNonSavedSRAM = 0); @@ -317,6 +318,7 @@ struct CMemory void Map_SetaDSPLoROMMap (void); void Map_SDD1LoROMMap (void); void Map_SA1LoROMMap (void); + void Map_GNEXTSA1LoROMMap (void); void Map_HiROMMap (void); void Map_ExtendedHiROMMap (void); void Map_SameGameHiROMMap (void); From f141d498d9e220f361e830ed3cd2637041d144bc Mon Sep 17 00:00:00 2001 From: zones Date: Wed, 20 Jul 2011 21:03:03 +0900 Subject: [PATCH 034/130] G-NEXT combined image support --- memmap.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/memmap.cpp b/memmap.cpp index d1771c79..5d27f355 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -1557,6 +1557,8 @@ again: CalculatedSize = (totalFileSize / 0x2000) * 0x2000; if (CalculatedSize > 0x400000 && + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x3423 && // exclude SA-1 + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x3523 && (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1 (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 && (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110 From e84f4f1a25c928c17e6db55bfcc41651cfce080d Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Sat, 27 Aug 2011 00:13:36 -0300 Subject: [PATCH 035/130] Changed the current version numbers to make this more up to date and to include a message about Zack discontinuing the PSP port. --- docs/portsofsnes9x.txt | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index d05365cb..5e311bbf 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -1,5 +1,5 @@ These are all the known ports of Snes9X to other consoles/handhelds/etc as of -2011/04/24. They are all supported and welcomed on the official Snes9X site. +2011/08/26. They are all supported and welcomed on the official Snes9X site. **If you know of anyone who is currently working on a port of Snes9X, or if you have some interest in making a port, please have them go to the Snes9X forums @@ -14,24 +14,26 @@ Ports and how to get them running are as follows: Name: Snes9X Euphoria Latest version: R5 Beta Homepage/forum: http://www.retroemu.com/forum/ -Maintainer: Zack +Maintainer: Open due to Zack discontinuing the port; he has made the source code +available. If you are interested in taking over the project or starting a new port +from scratch, let Ryan and/or Jerremy know ASAP. HOW TO GET IT RUNNING: *DISCLAIMER* You will have to do some Googling, including but not limited to: * Downgrading/upgrading your firmware * Checking if your PSP-2000 series can use Pandora's Battery -* Checking if your PSP-3000 series can use the DaveeFTW Downgrader +* Checking if your PSP-3000 series can use DaveeFTW's and/or some1's Downgrader * Creating Pandora's Battery * Finding the hacks, HENs, CFWs, etc and how to use/install them 1. Make sure your PSP is hackable in some way. This means: * PSP-1000 series and certain PSP-2000 series can use Pandora Battery * PSP-2000 series that can't use Pandora Battery, most PSP-3000 series, and PSP -Gos are hackable via other means (DaveeFTW Downgrader, etc) +Gos are hackable via other means (DaveeFTW's and/or some1's Downgrader, etc) 2. Make sure your PSP has custom firmware or a HEN that's useable (you'll have to upgrade/downgrade the firmware as necessary). (Hint: I personally prefer -5.50 GEN-D3 on the Pandora-able PSPs; 6.20 or 6.35 PRO-B4 or better on the +5.50 GEN-D3 on the Pandora-able PSPs; latest version of 6.20 or 6.35 PRO CFW on the non-Pandora-able PSPs.) 3. When that’s done, be sure to put the Snes9X Euphoria folder in /PSP/GAME on @@ -39,6 +41,10 @@ your PSP’s memory stick (PSP-1000/2000/3000 series) or internal memory (PSP Go). Be sure to copy the ROMs into the roms folder, saves (*.srm, etc) into the saves folder, and cheats into the cheats folder. +Note: as of right now, there is no one to maintain the PSP port; I am leaving these +instructions up just in case someone wants to take it over, and you can use these +tips to get other homebrews going. + *Wii/Gamecube version of Snes9X* Name: Snes9X GX Latest Version: 4.2.7 @@ -66,7 +72,7 @@ Gamecube: You might need a modchip. *Android and iOS (Apple iPhone/iPod Touch) version of Snes9X* Name: Snes9X EX -Latest Version: 1.3.23 +Latest Version: 1.4.2 Homepage/forum: http://www.explusalpha.com/home/snes9x-ex Maintainer: Rakashazi (on the Snes9X forums) @@ -74,8 +80,13 @@ HOW TO GET IT RUNNING: *DISCLAIMER* You will have to do some Googling, including but not limited to: * iOS (iPhone/iPod Touch) ONLY!!!: Jailbreaking your firmware -Android: It appears you can just download from the Android app-store thingy and -run it from there :) Be sure to copy over your ROMs, saves, etc though. +Android: It appears you can just download from the Android Marketplace and run +it from there :) Be sure to copy over your ROMs, saves, etc though. + +UPDATE from SparroHawc: Yup, the app store download works great - no need to root +the phone, and you can browse the contents of the phone's filesystem to find the +ROMs anywhere. The saves, I believe, will be put in the same directory as the +loaded ROM. iOS: You’ll have to jailbreak your firmware and install the Cydia app installer. Then you’ll have to install the BigBoss repository within Cydia and From 9974967eef206db3c2ce18c0086bf8a873a30e6e Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Mon, 29 Aug 2011 00:07:05 -0300 Subject: [PATCH 036/130] Fixed the formatting of the docs file, now it's at 80 characters/line again; fixed a few inconsistencies. --- docs/portsofsnes9x.txt | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 5e311bbf..4b1fc818 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -14,40 +14,43 @@ Ports and how to get them running are as follows: Name: Snes9X Euphoria Latest version: R5 Beta Homepage/forum: http://www.retroemu.com/forum/ -Maintainer: Open due to Zack discontinuing the port; he has made the source code -available. If you are interested in taking over the project or starting a new port -from scratch, let Ryan and/or Jerremy know ASAP. +Maintainer: Open due to Zack discontinuing the port; he has made the source +code available. If you are interested in taking over the project or starting a +new port from scratch, let Ryan and/or Jerremy know ASAP. HOW TO GET IT RUNNING: *DISCLAIMER* You will have to do some Googling, including but not limited to: * Downgrading/upgrading your firmware * Checking if your PSP-2000 series can use Pandora's Battery * Checking if your PSP-3000 series can use DaveeFTW's and/or some1's Downgrader -* Creating Pandora's Battery +* Creating Pandora's Battery (as needed) * Finding the hacks, HENs, CFWs, etc and how to use/install them 1. Make sure your PSP is hackable in some way. This means: -* PSP-1000 series and certain PSP-2000 series can use Pandora Battery -* PSP-2000 series that can't use Pandora Battery, most PSP-3000 series, and PSP -Gos are hackable via other means (DaveeFTW's and/or some1's Downgrader, etc) +* All PSP-1000 series and certain PSP-2000 series can use Pandora Battery; this +would be considered fully hackable. +* PSP-2000 series that can't use Pandora Battery, just about all PSP-3000 +series, and PSP Gos are hackable via other means (DaveeFTW's and/or some1's +Downgrader, etc); this would be considered partially hackable. 2. Make sure your PSP has custom firmware or a HEN that's useable (you'll have to upgrade/downgrade the firmware as necessary). (Hint: I personally prefer -5.50 GEN-D3 on the Pandora-able PSPs; latest version of 6.20 or 6.35 PRO CFW on the -non-Pandora-able PSPs.) +5.50 GEN-D3 if your PSP can use Pandora Battery; latest version of 6.20 or +6.35 PRO CFW if your PSP can't use Pandora Battery (if you can't downgrade past +6.35, then you should be able to use 6.39 and/or 6.60 PRO).) 3. When that’s done, be sure to put the Snes9X Euphoria folder in /PSP/GAME on your PSP’s memory stick (PSP-1000/2000/3000 series) or internal memory (PSP Go). Be sure to copy the ROMs into the roms folder, saves (*.srm, etc) into the saves folder, and cheats into the cheats folder. -Note: as of right now, there is no one to maintain the PSP port; I am leaving these -instructions up just in case someone wants to take it over, and you can use these -tips to get other homebrews going. +Note: as of right now, there is no one to maintain the PSP port; I am leaving +these instructions up just in case someone wants to take it over, and you can +use these tips to get other homebrews going. *Wii/Gamecube version of Snes9X* Name: Snes9X GX -Latest Version: 4.2.7 +Latest Version: 4.2.8 Homepage/forum: http://code.google.com/p/snes9x-gx Maintainer: Tantric From a2b407dace57e07db4275390a680fc56f185c468 Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Mon, 29 Aug 2011 00:08:08 -0300 Subject: [PATCH 037/130] Forgot to fix the PSP port's homepage to instead go to the Google Code page for the source code, my bad! --- docs/portsofsnes9x.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 4b1fc818..8d643d2b 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -13,7 +13,7 @@ Ports and how to get them running are as follows: *PSP Version of Snes9X* Name: Snes9X Euphoria Latest version: R5 Beta -Homepage/forum: http://www.retroemu.com/forum/ +Homepage/forum: http://code.google.com/p/snes9x-euphoria/ Maintainer: Open due to Zack discontinuing the port; he has made the source code available. If you are interested in taking over the project or starting a new port from scratch, let Ryan and/or Jerremy know ASAP. From cf6715c9e1173b694a7d0143a2fad05edb2c8a2b Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Mon, 29 Aug 2011 00:09:51 -0300 Subject: [PATCH 038/130] re-worded some of the Wii section, forgot to add this in the first two times, whoops --- docs/portsofsnes9x.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 8d643d2b..5054c292 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -56,8 +56,9 @@ Maintainer: Tantric HOW TO GET IT RUNNING: *DISCLAIMER* You will have to do some Googling, including but not limited to: -* Finding the latest Homebrew Channel, Snes9X GX Channel, and/or IOS58 -installers and installing them +* Finding and installing the latest versions of: Homebrew Channel, Snes9X GX +Channel (optional), and/or IOS58 installer (also optional; this is to make the +Snes9X GX channel work) * Finding a modchip for your GameCube and installing it Wii: You will need the latest Homebrew Channel installed on your Wii. After From 1a774e9f2733cda4f8b98346a9e1d30f1dc474d0 Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Mon, 29 Aug 2011 00:19:32 -0300 Subject: [PATCH 039/130] Fixed the dates, sorry for these constant one change and commit things, I need to work on that :/ --- docs/portsofsnes9x.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 5054c292..35e2645a 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -1,5 +1,5 @@ These are all the known ports of Snes9X to other consoles/handhelds/etc as of -2011/08/26. They are all supported and welcomed on the official Snes9X site. +2011/08/28. They are all supported and welcomed on the official Snes9X site. **If you know of anyone who is currently working on a port of Snes9X, or if you have some interest in making a port, please have them go to the Snes9X forums @@ -130,4 +130,4 @@ Really, it's not hard. Read the readme, and use a softmod or modchip and a replacement dashboard. After that's installed, it should be as simple as copying over the emulator, ROMs, saves, etc to the X-Box and it should work. -Updated most recently by: 2011/4/24 adventure_of_link \ No newline at end of file +Updated most recently by: 2011/8/28 adventure_of_link \ No newline at end of file From 4668ae585004a312aeb3a4e0ad953d4c5f9058ee Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 7 Sep 2011 11:46:52 -0500 Subject: [PATCH 040/130] Fix save state error. --- apu/apu.cpp | 7 ++----- apu/bapu/smp/core.cpp | 1 - apu/bapu/smp/smp.hpp | 2 ++ apu/bapu/smp/smp_state.cpp | 16 ++++++++++++++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 795dd2f7..237f3939 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -625,13 +625,9 @@ void S9xAPULoadState (uint8 *block) { uint8 *ptr = block; - S9xResetAPU(); - SNES::smp.load_state (&ptr); SNES::dsp.load_state (&ptr); - SNES::dsp.spc_dsp.set_output ((SNES::SPC_DSP::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); - spc::reference_time = SNES::get_le32(ptr); ptr += sizeof(int32); spc::remainder = SNES::get_le32(ptr); @@ -655,7 +651,8 @@ bool8 S9xSPCDump (const char *filename) SNES::smp.save_spc (buf); - ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs); + if ((ignore = fwrite(buf, SPC_FILE_SIZE, 1, fs)) <= 0) + fprintf (stderr, "Couldn't write file %s.\n", filename); fclose(fs); diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index b5266cec..5664da36 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -44,7 +44,6 @@ void SMP::op_step() { #define op_writeaddr(addr, data) op_write(addr, data) #define op_readstack() op_read(0x0100 | ++regs.sp) #define op_writestack(data) op_write(0x0100 | regs.sp--, data) - static unsigned rd, wr, dp, sp, ya, bit; #if defined(CYCLE_ACCURATE) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index cb57f334..9d7a9ea7 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -50,6 +50,8 @@ public: unsigned opcode_number; unsigned opcode_cycle; + unsigned rd, wr, dp, sp, ya, bit; + struct Regs { uint16 pc; uint8 sp; diff --git a/apu/bapu/smp/smp_state.cpp b/apu/bapu/smp/smp_state.cpp index e3b9d446..adefdacb 100644 --- a/apu/bapu/smp/smp_state.cpp +++ b/apu/bapu/smp/smp_state.cpp @@ -118,11 +118,17 @@ void SMP::save_state(uint8 **block) { INT32(timer2.enable); INT32(timer2.target); - INT32(timer2.stage1_ticks); INT32(timer2.stage2_ticks); INT32(timer2.stage3_ticks); + INT32(rd); + INT32(wr); + INT32(dp); + INT32(sp); + INT32(ya); + INT32(bit); + *block = ptr; } @@ -174,11 +180,17 @@ void SMP::load_state(uint8 **block) { INT32(timer2.enable); INT32(timer2.target); - INT32(timer2.stage1_ticks); INT32(timer2.stage2_ticks); INT32(timer2.stage3_ticks); + INT32(rd); + INT32(wr); + INT32(dp); + INT32(sp); + INT32(ya); + INT32(bit); + *block = ptr; } From 6ebc68c01771d11e7c626c5861ac12a755d28810 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 28 Jul 2011 22:01:52 +0200 Subject: [PATCH 041/130] Win32: fix multirom dialog --- win32/wsnes9x.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index c5926472..aa8252cb 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -5553,8 +5553,6 @@ INT_PTR CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar case IDOK: GetDlgItemText(hDlg, IDC_MULTICART_EDITA, multiRomA, MAX_PATH); GetDlgItemText(hDlg, IDC_MULTICART_EDITB, multiRomB, MAX_PATH); - if(*multiRomA) _tfullpath(multiRomA, multiRomA, MAX_PATH); - if(*multiRomB) _tfullpath(multiRomB, multiRomB, MAX_PATH); EndDialog(hDlg, 1); return true; case IDCANCEL: @@ -5563,21 +5561,17 @@ INT_PTR CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar case IDC_MULTICART_SWAP: GetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom2, MAX_PATH); GetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom1, MAX_PATH); - if(*rom1) _tfullpath(rom1, rom1, MAX_PATH); - if(*rom2) _tfullpath(rom2, rom2, MAX_PATH); SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1); SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2); break; case IDC_MULTICART_BROWSEA: if(!DoOpenRomDialog(rom1, true)) break; - _tfullpath(rom1, rom1, MAX_PATH); SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1); break; case IDC_MULTICART_BROWSEB: if(!DoOpenRomDialog(rom2, true)) break; - _tfullpath(rom2, rom2, MAX_PATH); SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2); break; case IDC_MULTICART_CLEARA: From b44200207134a477f7d4b4bd1a425cddad90e82b Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 9 Sep 2011 23:52:35 +0200 Subject: [PATCH 042/130] Win32: only display cg error message if shader file has been set --- win32/COpenGL.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 28d1466a..c5beb828 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -716,8 +716,9 @@ void COpenGL::checkForCgError(const char *situation) bool COpenGL::SetShadersCG(const TCHAR *file) { if(!cgAvailable) { - MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), - MB_OK|MB_ICONEXCLAMATION); + if(file) + MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), + MB_OK|MB_ICONEXCLAMATION); return false; } From b4f07bc9be7eeef9aa0baafb6ba82e9aad4f6369 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 10 Sep 2011 16:20:00 +0200 Subject: [PATCH 043/130] Add bps soft-patching support --- memmap.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 164 insertions(+), 8 deletions(-) diff --git a/memmap.cpp b/memmap.cpp index 5d27f355..3b7ebce1 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -3750,9 +3750,10 @@ void CMemory::ApplyROMFixes (void) } } -// UPS % IPS +// BPS % UPS % IPS -static uint32 ReadUPSPointer (const uint8 *data, unsigned &addr, unsigned size) +// number decoding used for both BPS and UPS +static uint32 XPSdecode (const uint8 *data, unsigned &addr, unsigned size) { uint32 offset = 0, shift = 1; while(addr < size) { @@ -3807,8 +3808,8 @@ static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) if(patch_crc32 != pp_crc32) { delete[] data; return false; } //patch is corrupted if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; } //patch is for a different ROM - uint32 px_size = ReadUPSPointer(data, addr, size); - uint32 py_size = ReadUPSPointer(data, addr, size); + uint32 px_size = XPSdecode(data, addr, size); + uint32 py_size = XPSdecode(data, addr, size); uint32 out_size = ((uint32) rom_size == px_size) ? py_size : px_size; if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; } //applying this patch will overflow Memory.ROM buffer @@ -3820,7 +3821,7 @@ static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) uint32 relative = 0; while(addr < size - 12) { - relative += ReadUPSPointer(data, addr, size); + relative += XPSdecode(data, addr, size); while(addr < size - 12) { uint8 x = data[addr++]; Memory.ROM[relative++] ^= x; @@ -3852,6 +3853,101 @@ static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) } } +// header notes for UPS patches also apply to BPS +// +// logic taken from http://byuu.org/programming/bps and the accompanying source +// +static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) +{ + uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ... + uint32 size = 0; + while(true) { + int value = r->get_char(); + if(value == EOF) break; + data[size++] = value; + if(size >= 8 * 1024 * 1024) { + //prevent buffer overflow: SNES-made BPS patches should never be this big anyway ... + delete[] data; + return false; + } + } + + /* 4-byte header + 1-byte input size + 1-byte output size + 1-byte metadata size + + 4-byte unpatched CRC32 + 4-byte patched CRC32 + 4-byte patch CRC32 */ + if(size < 19) { delete[] data; return false; } //patch is too small + + uint32 addr = 0; + if(data[addr++] != 'B') { delete[] data; return false; } //patch has an invalid header + if(data[addr++] != 'P') { delete[] data; return false; } //... + if(data[addr++] != 'S') { delete[] data; return false; } //... + if(data[addr++] != '1') { delete[] data; return false; } //... + + uint32 patch_crc32 = caCRC32(data, size - 4); //don't include patch CRC32 itself in CRC32 calculation + uint32 rom_crc32 = caCRC32(Memory.ROM, rom_size); + uint32 source_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size - 9] << 24); + uint32 target_crc32 = (data[size - 8] << 0) + (data[size - 7] << 8) + (data[size - 6] << 16) + (data[size - 5] << 24); + uint32 pp_crc32 = (data[size - 4] << 0) + (data[size - 3] << 8) + (data[size - 2] << 16) + (data[size - 1] << 24); + if(patch_crc32 != pp_crc32) { delete[] data; return false; } //patch is corrupted + if(rom_crc32 != source_crc32) { delete[] data; return false; } //patch is for a different ROM + + uint32 source_size = XPSdecode(data, addr, size); + uint32 target_size = XPSdecode(data, addr, size); + uint32 metadata_size = XPSdecode(data, addr, size); + addr += metadata_size; + + if(target_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; } //applying this patch will overflow Memory.ROM buffer + + enum : uint32 { SourceRead, TargetRead, SourceCopy, TargetCopy }; + uint32 outputOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0; + + uint8 *patched_rom = new uint8[target_size]; + memset(patched_rom,0,target_size); + + while(addr < size - 12) { + uint32 length = XPSdecode(data, addr, size); + uint32 mode = length & 3; + length = (length >> 2) + 1; + + switch(mode) { + case SourceRead: + while(length--) patched_rom[outputOffset++] = Memory.ROM[outputOffset]; + break; + case TargetRead: + while(length--) patched_rom[outputOffset++] = data[addr++]; + break; + case SourceCopy: + case TargetCopy: + int32 offset = XPSdecode(data, addr, size); + bool negative = offset & 1; + offset >>= 1; + if(negative) offset = -offset; + + if(mode == SourceCopy) { + sourceRelativeOffset += offset; + while(length--) patched_rom[outputOffset++] = Memory.ROM[sourceRelativeOffset++]; + } else { + targetRelativeOffset += offset; + while(length--) patched_rom[outputOffset++] = patched_rom[targetRelativeOffset++]; + } + break; + } + } + + delete[] data; + + uint32 out_crc32 = caCRC32(patched_rom, target_size); + if(out_crc32 == target_crc32) { + memcpy(Memory.ROM, patched_rom, target_size); + rom_size = target_size; + delete[] patched_rom; + return true; + } else { + delete[] patched_rom; + fprintf(stderr, "WARNING: BPS patching failed.\nROM has not been altered.\n"); + return false; + } +} + static long ReadInt (Reader *r, unsigned nbytes) { long v = 0; @@ -3969,7 +4065,7 @@ static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK) { if (print) - printf("Using IPS or UPS patch %s", name); + printf("Using patch %s", name); return (port); } @@ -3994,9 +4090,70 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1]; const char *n; + _splitpath(rom_filename, drive, dir, name, ext); + + // BPS + _makepath(fname, drive, dir, name, "bps"); + + if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + { + printf("Using BPS patch %s", fname); + + ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + +#ifdef UNZIP_SUPPORT + if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip")) + { + unzFile file = unzOpen(rom_filename); + if (file) + { + int port = unzFindExtension(file, "bps"); + if (port == UNZ_OK) + { + printf(" in %s", rom_filename); + + ret = ReadBPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + printf("!\n"); + else + printf(" failed!\n"); + } + } + } +#endif + + n = S9xGetFilename(".bps", IPS_DIR); + + if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + { + printf("Using BPS patch %s", n); + + ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + // UPS - _splitpath(rom_filename, drive, dir, name, ext); _makepath(fname, drive, dir, name, "ups"); if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) @@ -4058,7 +4215,6 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r // IPS - _splitpath(rom_filename, drive, dir, name, ext); _makepath(fname, drive, dir, name, "ips"); if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) From a19395ee3c2ffd2e742952e37f4624017036c19e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 12:54:51 -0500 Subject: [PATCH 044/130] Start converting some opcodes to cycle-based. --- apu/bapu/smp/core.cpp | 13 + apu/bapu/smp/core/opcycle_misc.cpp | 420 ++++++++--------------------- apu/bapu/smp/core/opcycle_rmw.cpp | 90 ++----- apu/bapu/smp/smp.hpp | 2 + 4 files changed, 147 insertions(+), 378 deletions(-) diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 5664da36..7e9c4a95 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -13,12 +13,25 @@ void SMP::tick() { #endif } +void SMP::tick(unsigned clocks) { + timer0.tick(clocks); + timer1.tick(clocks); + timer2.tick(clocks); + + clock += clocks; + dsp.clock += clocks; +} + void SMP::op_io() { #if defined(CYCLE_ACCURATE) tick(); #endif } +void SMP::op_io(unsigned clocks) { + tick(clocks); +} + uint8 SMP::op_read(uint16 addr) { #if defined(CYCLE_ACCURATE) tick(); diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 963f9fc2..5fe164f1 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,188 +1,109 @@ case 0x00: { - switch(opcode_cycle++) { - case 1: - op_io(); - opcode_cycle = 0; - break; - } + op_io(); + opcode_cycle = 0; break; } case 0xef: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } + op_io(2); + regs.pc--; + opcode_cycle = 0; break; } case 0xff: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.pc--; - opcode_cycle = 0; - break; - } + op_io(2); + regs.pc--; + opcode_cycle = 0; break; } case 0x9f: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(4); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xdf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; - } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; + op_io(2); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xbe: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; - } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; + op_io(2); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0x60: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.c = 0; + opcode_cycle = 0; break; } case 0x20: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.p = 0; + opcode_cycle = 0; break; } case 0x80: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.c = 1; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.c = 1; + opcode_cycle = 0; break; } case 0x40: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.p = 1; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.p = 1; + opcode_cycle = 0; break; } case 0xe0: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.p.v = 0; - regs.p.h = 0; - opcode_cycle = 0; - break; - } + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; break; } case 0xed: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.c = !regs.p.c; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.c = !regs.p.c; + opcode_cycle = 0; break; } case 0xa0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 1; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.i = 1; + opcode_cycle = 0; break; } @@ -473,224 +394,93 @@ case 0xf2: { } case 0x2d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.a); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.a); + opcode_cycle = 0; break; } case 0x4d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.x); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.x); + opcode_cycle = 0; break; } case 0x6d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.y); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.y); + opcode_cycle = 0; break; } case 0x0d: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_writestack(regs.p); - opcode_cycle = 0; - break; - } + op_io(2); + op_writestack(regs.p); + opcode_cycle = 0; break; } case 0xae: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.a = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.a = op_readstack(); + opcode_cycle = 0; break; } case 0xce: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.x = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.x = op_readstack(); + opcode_cycle = 0; break; } case 0xee: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.y = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.y = op_readstack(); + opcode_cycle = 0; break; } case 0x8e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - regs.p = op_readstack(); - opcode_cycle = 0; - break; - } + op_io(2); + regs.p = op_readstack(); + opcode_cycle = 0; break; } case 0xcf: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + op_io(8); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; break; } case 0x9e: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_io(); - break; - case 7: - op_io(); - break; - case 8: - op_io(); - break; - case 9: - op_io(); - break; - case 10: - op_io(); - break; - case 11: - op_io(); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); - } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; + op_io(11); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index eca62f02..4677628e 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,99 +1,63 @@ case 0xbc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_inc(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; break; } case 0x3d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_inc(regs.x); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; break; } case 0xfc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_inc(regs.y); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; break; } case 0x9c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_dec(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; break; } case 0x1d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = op_dec(regs.x); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; break; } case 0xdc: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = op_dec(regs.y); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; break; } case 0x1c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_asl(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; break; } case 0x5c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_lsr(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; break; } case 0x3c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_rol(regs.a); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 9d7a9ea7..0a17cb8f 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -96,7 +96,9 @@ public: Timer< 16> timer2; inline void tick(); + inline void tick(unsigned clocks); alwaysinline void op_io(); + alwaysinline void op_io(unsigned clocks); debugvirtual alwaysinline uint8 op_read(uint16 addr); debugvirtual alwaysinline void op_write(uint16 addr, uint8 data); debugvirtual alwaysinline void op_step(); From a50f6989efce45a9401ef3c4a808fabd47f513e8 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 15:45:18 -0500 Subject: [PATCH 045/130] Finish converting opcycle_misc/opcycle_rmw to pseudo-cycle. --- apu/bapu/smp/core/opcycle_misc.cpp | 301 +++++------------- apu/bapu/smp/core/opcycle_rmw.cpp | 488 ++++++++--------------------- 2 files changed, 219 insertions(+), 570 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 5fe164f1..43a72305 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -108,288 +108,153 @@ case 0xa0: { } case 0xc0: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - op_io(); - regs.p.i = 0; - opcode_cycle = 0; - break; - } + op_io(2); + regs.p.i = 0; + opcode_cycle = 0; break; } case 0x02: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x12: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x01; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x22: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x32: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x02; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x42: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x52: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x04; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x62: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x72: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x08; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x82: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x92: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x10; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xa2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xb2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x20; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xc2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xd2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x40; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xe2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= 0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xf2: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd &= ~0x80; - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index 4677628e..fcacfc71 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -73,442 +73,226 @@ case 0x7c: { } case 0xab: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_inc(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x8b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_dec(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x0b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_asl(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x4b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_lsr(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x2b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_rol(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0x6b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd = op_ror(rd); - op_writedp(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; break; } case 0xbb: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x9b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x1b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x5b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x3b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0x7b: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - break; - case 4: - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; break; } case 0xac: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_inc(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x8c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_dec(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_asl(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x4c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_lsr(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x2c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_rol(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x6c: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - break; - case 4: - rd = op_ror(rd); - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd | regs.a); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; break; } case 0x4e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - break; - case 4: - op_readaddr(dp); - break; - case 5: - op_writeaddr(dp, rd &~ regs.a); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; break; } case 0x3a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd++; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; break; } case 0x1a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - rd--; - break; - case 3: - op_writedp(dp++, rd); - break; - case 4: - rd += op_readdp(dp) << 8; - break; - case 5: - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; break; } From d6e2f1c8e6c0916be016958dc8bd483e5be60e35 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 16:20:14 -0500 Subject: [PATCH 046/130] More pseudo-cycle modifications. --- apu/bapu/smp/core/opcycle_pc.cpp | 1519 ++++++------------------ apu/bapu/smp/core/opcycle_read.cpp | 1734 ++++++++-------------------- 2 files changed, 863 insertions(+), 2390 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index 1cdda647..ed808a6b 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,1347 +1,588 @@ case 0x2f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(0){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xf0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xd0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.z){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xb0: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x90: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.c){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x70: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x50: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.v){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x30: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(!regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x10: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - if(regs.p.n){ opcode_cycle = 0; break; } - break; - case 2: - op_io(); - break; - case 3: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x03: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x13: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x23: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x33: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x43: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x53: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x63: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x73: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x83: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x93: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xa3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xb3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xc3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xd3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xe3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xf3: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x2e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - sp = op_readdp(dp); - break; - case 3: - rd = op_readpc(); - break; - case 4: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xde: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp + regs.x); - break; - case 4: - rd = op_readpc(); - break; - case 5: - op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } - break; - case 6: - op_io(); - break; - case 7: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x6e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - wr = op_readdp(dp); - break; - case 3: - op_writedp(dp, --wr); - break; - case 4: - rd = op_readpc(); - if(wr == 0x00){ opcode_cycle = 0; break; } - break; - case 5: - op_io(); - break; - case 6: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0xfe: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - regs.y--; - break; - case 3: - op_io(); - if(regs.y == 0x00){ opcode_cycle = 0; break; } - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc += (int8)rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + op_io(2); + regs.pc += (int8)rd; + opcode_cycle = 0; break; } case 0x5f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; break; } case 0x1f: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - dp += regs.x; - break; - case 4: - rd = op_readaddr(dp); - break; - case 5: - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; break; } case 0x3f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - rd |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x4f: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - op_io(); - break; - case 4: - op_writestack(regs.pc >> 8); - break; - case 5: - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; - opcode_cycle = 0; - break; - } + rd = op_readpc(); + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; break; } case 0x01: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x11: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x21: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x31: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x41: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x51: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x61: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x71: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x81: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x91: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xa1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xb1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xc1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xd1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xe1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0xf1: { - switch(opcode_cycle++) { - case 1: - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - break; - case 2: - rd |= op_readaddr(dp + 1) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_io(); - break; - case 6: - op_writestack(regs.pc >> 8); - break; - case 7: - op_writestack(regs.pc); - regs.pc = rd; - opcode_cycle = 0; - break; - } + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x0f: { - switch(opcode_cycle++) { - case 1: - rd = op_readaddr(0xffde); - break; - case 2: - rd |= op_readaddr(0xffdf) << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - break; - case 5: - op_writestack(regs.pc >> 8); - break; - case 6: - op_writestack(regs.pc); - break; - case 7: - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; - opcode_cycle = 0; - break; - } + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; break; } case 0x6f: { - switch(opcode_cycle++) { - case 1: - rd = op_readstack(); - break; - case 2: - rd |= op_readstack() << 8; - break; - case 3: - op_io(); - break; - case 4: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + opcode_cycle = 0; break; } case 0x7f: { - switch(opcode_cycle++) { - case 1: - regs.p = op_readstack(); - break; - case 2: - rd = op_readstack(); - break; - case 3: - rd |= op_readstack() << 8; - break; - case 4: - op_io(); - break; - case 5: - op_io(); - regs.pc = rd; - opcode_cycle = 0; - break; - } + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 6c19f3a9..3eb1cd77 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,1599 +1,831 @@ case 0x88: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x28: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x68: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0xc8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0xad: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x48: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x08: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x86: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x26: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x66: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x46: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x06: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa6: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x84: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x24: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x64: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x3e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0x7e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x44: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x04: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x94: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x34: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x74: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x54: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x14: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb4: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x85: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x25: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x65: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x1e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; break; } case 0x5e: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; break; } case 0x45: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x05: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x95: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x96: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x35: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x36: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x75: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x76: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x55: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x56: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x15: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0x16: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb5: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0xb6: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - op_io(); - break; - case 4: - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x87: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x27: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x67: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x47: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x07: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xa7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc() + regs.x; - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x97: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; break; } case 0x37: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; break; } case 0x77: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; break; } case 0x57: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; break; } case 0x17: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; break; } case 0xb7: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - op_io(); - break; - case 3: - sp = op_readdp(dp); - break; - case 4: - sp |= op_readdp(dp + 1) << 8; - break; - case 5: - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; break; } case 0x99: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x39: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x79: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - break; - case 4: - (0) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x59: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x19: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0xb9: { - switch(opcode_cycle++) { - case 1: - op_io(); - break; - case 2: - rd = op_readdp(regs.y); - break; - case 3: - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - break; - case 4: - (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; - break; - } + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; break; } case 0x89: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x29: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x69: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x49: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x09: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0xa9: { - switch(opcode_cycle++) { - case 1: - sp = op_readpc(); - break; - case 2: - rd = op_readdp(sp); - break; - case 3: - dp = op_readpc(); - break; - case 4: - wr = op_readdp(dp); - break; - case 5: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x98: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x38: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x78: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x58: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x18: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0xb8: { - switch(opcode_cycle++) { - case 1: - rd = op_readpc(); - break; - case 2: - dp = op_readpc(); - break; - case 3: - wr = op_readdp(dp); - break; - case 4: - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; - break; - } + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; break; } case 0x7a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x9a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - op_io(); - break; - case 4: - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x5a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - rd = op_readdp(dp); - break; - case 3: - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; break; } case 0x4a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x6a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x8a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0xea: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - break; - case 4: - op_writeaddr(dp, rd); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + opcode_cycle = 0; break; } case 0x0a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; break; } case 0x2a: { - switch(opcode_cycle++) { - case 1: - dp = op_readpc(); - break; - case 2: - dp |= op_readpc() << 8; - break; - case 3: - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - break; - case 4: - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); - opcode_cycle = 0; - break; - } + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; break; } From 6b9d6caf54d36b580ba832f0e53d862147e2a80e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 17:02:26 -0500 Subject: [PATCH 047/130] Remove extra case bracker from 2-cycle MOV opcodes. --- apu/bapu/smp/core/opcycle_mov.cpp | 116 +++++++++++------------------- 1 file changed, 40 insertions(+), 76 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index 635c7ca5..9096bc25 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -1,112 +1,76 @@ case 0x7d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xdd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0x5d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0xfd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; break; } case 0x9d: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0xbd: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.sp = regs.x; - opcode_cycle = 0; - break; - } + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; break; } case 0xe8: { - switch(opcode_cycle++) { - case 1: - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); - opcode_cycle = 0; - break; - } + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; break; } case 0xcd: { - switch(opcode_cycle++) { - case 1: - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); - opcode_cycle = 0; - break; - } + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; break; } case 0x8d: { - switch(opcode_cycle++) { - case 1: - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); - opcode_cycle = 0; - break; - } + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; break; } From b97e56d64d2e2dabf1829d256078a181563eb539 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Sep 2011 17:12:03 -0500 Subject: [PATCH 048/130] Group some MOV opcode cycles together. --- apu/bapu/smp/core/opcycle_mov.cpp | 128 +++++++++--------------------- 1 file changed, 36 insertions(+), 92 deletions(-) diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index 9096bc25..b358b66c 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -96,8 +96,6 @@ case 0xbf: { break; case 2: regs.a = op_readdp(regs.x++); - break; - case 3: op_io(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -156,11 +154,9 @@ case 0xf4: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.a = op_readdp(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -174,11 +170,9 @@ case 0xf9: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.x = op_readdp(sp + regs.y); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -192,11 +186,9 @@ case 0xfb: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: regs.y = op_readdp(sp + regs.x); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -228,11 +220,9 @@ case 0xe9: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: regs.x = op_readaddr(sp); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -246,11 +236,9 @@ case 0xec: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: regs.y = op_readaddr(sp); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -264,14 +252,10 @@ case 0xf5: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; - break; - case 3: op_io(); break; - case 4: + case 2: regs.a = op_readaddr(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -285,14 +269,10 @@ case 0xf6: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; - break; - case 3: op_io(); break; - case 4: + case 2: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -306,17 +286,15 @@ case 0xe7: { switch(opcode_cycle++) { case 1: dp = op_readpc() + regs.x; - break; - case 2: op_io(); break; - case 3: + case 2: sp = op_readdp(dp); break; - case 4: + case 3: sp |= op_readdp(dp + 1) << 8; break; - case 5: + case 4: regs.a = op_readaddr(sp); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -330,17 +308,15 @@ case 0xf7: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); break; - case 3: + case 2: sp = op_readdp(dp); break; - case 4: + case 3: sp |= op_readdp(dp + 1) << 8; break; - case 5: + case 4: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -373,14 +349,12 @@ case 0x8f: { switch(opcode_cycle++) { case 1: rd = op_readpc(); - break; - case 2: dp = op_readpc(); break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, rd); opcode_cycle = 0; break; @@ -407,12 +381,8 @@ case 0xc6: { case 0xaf: { switch(opcode_cycle++) { case 1: - op_io(); - break; + op_io(2); case 2: - op_io(); - break; - case 3: op_writedp(regs.x++, regs.a); opcode_cycle = 0; break; @@ -472,15 +442,13 @@ case 0xd4: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.x; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.a); opcode_cycle = 0; break; @@ -492,15 +460,13 @@ case 0xd9: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.y; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.x); opcode_cycle = 0; break; @@ -512,15 +478,13 @@ case 0xdb: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: op_io(); dp += regs.x; break; - case 3: + case 2: op_readdp(dp); break; - case 4: + case 3: op_writedp(dp, regs.y); opcode_cycle = 0; break; @@ -589,18 +553,14 @@ case 0xd5: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; - break; - case 3: op_io(); dp += regs.x; break; - case 4: + case 2: op_readaddr(dp); break; - case 5: + case 3: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -612,18 +572,14 @@ case 0xd6: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; - break; - case 3: op_io(); dp += regs.y; break; - case 4: + case 2: op_readaddr(dp); break; - case 5: + case 3: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -635,21 +591,19 @@ case 0xc7: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: op_io(); sp += regs.x; break; - case 3: + case 2: dp = op_readdp(sp); break; - case 4: + case 3: dp |= op_readdp(sp + 1) << 8; break; - case 5: + case 4: op_readaddr(dp); break; - case 6: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -667,15 +621,13 @@ case 0xd7: { break; case 3: dp |= op_readdp(sp + 1) << 8; - break; - case 4: op_io(); dp += regs.y; break; - case 5: + case 4: op_readaddr(dp); break; - case 6: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -690,11 +642,9 @@ case 0xba: { break; case 2: regs.a = op_readdp(sp); - break; - case 3: op_io(); break; - case 4: + case 3: regs.y = op_readdp(sp + 1); regs.p.n = !!(regs.ya & 0x8000); regs.p.z = (regs.ya == 0); @@ -727,11 +677,9 @@ case 0xaa: { switch(opcode_cycle++) { case 1: sp = op_readpc(); - break; - case 2: sp |= op_readpc() << 8; break; - case 3: + case 2: bit = sp >> 13; sp &= 0x1fff; rd = op_readaddr(sp); @@ -746,21 +694,17 @@ case 0xca: { switch(opcode_cycle++) { case 1: dp = op_readpc(); - break; - case 2: dp |= op_readpc() << 8; break; - case 3: + case 2: bit = dp >> 13; dp &= 0x1fff; rd = op_readaddr(dp); if(regs.p.c)rd |= (1 << bit); else rd &= ~(1 << bit); - break; - case 4: op_io(); break; - case 5: + case 3: op_writeaddr(dp, rd); opcode_cycle = 0; break; From 70159fd93999b22b495d18c9f2f5ee8f39cbaecd Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 19 Sep 2011 15:15:19 -0500 Subject: [PATCH 049/130] Pair opcode read with first instruction cycle. Remove opcode_cycle switching from unneeded cases. --- apu/bapu/smp/core.cpp | 7 +- apu/bapu/smp/core/opcycle_misc.cpp | 40 ----------- apu/bapu/smp/core/opcycle_mov.cpp | 81 ++++++++++----------- apu/bapu/smp/core/opcycle_pc.cpp | 110 ++++++++--------------------- apu/bapu/smp/core/opcycle_read.cpp | 87 ----------------------- apu/bapu/smp/core/opcycle_rmw.cpp | 40 +---------- 6 files changed, 71 insertions(+), 294 deletions(-) diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index 7e9c4a95..a7a70072 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -60,10 +60,11 @@ void SMP::op_step() { #if defined(CYCLE_ACCURATE) - if(opcode_cycle == 0) { + if(opcode_cycle == 0) opcode_number = op_readpc(); - opcode_cycle++; - } else switch(opcode_number) { +// opcode_cycle++; + + switch(opcode_number) { #include "core/opcycle_misc.cpp" #include "core/opcycle_mov.cpp" #include "core/opcycle_pc.cpp" diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index 43a72305..d266ef92 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,20 +1,17 @@ case 0x00: { op_io(); - opcode_cycle = 0; break; } case 0xef: { op_io(2); regs.pc--; - opcode_cycle = 0; break; } case 0xff: { op_io(2); regs.pc--; - opcode_cycle = 0; break; } @@ -23,7 +20,6 @@ case 0x9f: { regs.a = (regs.a >> 4) | (regs.a << 4); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -38,7 +34,6 @@ case 0xdf: { } regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -53,35 +48,30 @@ case 0xbe: { } regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } case 0x60: { op_io(); regs.p.c = 0; - opcode_cycle = 0; break; } case 0x20: { op_io(); regs.p.p = 0; - opcode_cycle = 0; break; } case 0x80: { op_io(); regs.p.c = 1; - opcode_cycle = 0; break; } case 0x40: { op_io(); regs.p.p = 1; - opcode_cycle = 0; break; } @@ -89,28 +79,24 @@ case 0xe0: { op_io(); regs.p.v = 0; regs.p.h = 0; - opcode_cycle = 0; break; } case 0xed: { op_io(2); regs.p.c = !regs.p.c; - opcode_cycle = 0; break; } case 0xa0: { op_io(2); regs.p.i = 1; - opcode_cycle = 0; break; } case 0xc0: { op_io(2); regs.p.i = 0; - opcode_cycle = 0; break; } @@ -119,7 +105,6 @@ case 0x02: { rd = op_readdp(dp); rd |= 0x01; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -128,7 +113,6 @@ case 0x12: { rd = op_readdp(dp); rd &= ~0x01; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -137,7 +121,6 @@ case 0x22: { rd = op_readdp(dp); rd |= 0x02; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -146,7 +129,6 @@ case 0x32: { rd = op_readdp(dp); rd &= ~0x02; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -155,7 +137,6 @@ case 0x42: { rd = op_readdp(dp); rd |= 0x04; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -164,7 +145,6 @@ case 0x52: { rd = op_readdp(dp); rd &= ~0x04; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -173,7 +153,6 @@ case 0x62: { rd = op_readdp(dp); rd |= 0x08; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -182,7 +161,6 @@ case 0x72: { rd = op_readdp(dp); rd &= ~0x08; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -191,7 +169,6 @@ case 0x82: { rd = op_readdp(dp); rd |= 0x10; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -200,7 +177,6 @@ case 0x92: { rd = op_readdp(dp); rd &= ~0x10; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -209,7 +185,6 @@ case 0xa2: { rd = op_readdp(dp); rd |= 0x20; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -218,7 +193,6 @@ case 0xb2: { rd = op_readdp(dp); rd &= ~0x20; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -227,7 +201,6 @@ case 0xc2: { rd = op_readdp(dp); rd |= 0x40; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -236,7 +209,6 @@ case 0xd2: { rd = op_readdp(dp); rd &= ~0x40; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -245,7 +217,6 @@ case 0xe2: { rd = op_readdp(dp); rd |= 0x80; op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -254,63 +225,54 @@ case 0xf2: { rd = op_readdp(dp); rd &= ~0x80; op_writedp(dp, rd); - opcode_cycle = 0; break; } case 0x2d: { op_io(2); op_writestack(regs.a); - opcode_cycle = 0; break; } case 0x4d: { op_io(2); op_writestack(regs.x); - opcode_cycle = 0; break; } case 0x6d: { op_io(2); op_writestack(regs.y); - opcode_cycle = 0; break; } case 0x0d: { op_io(2); op_writestack(regs.p); - opcode_cycle = 0; break; } case 0xae: { op_io(2); regs.a = op_readstack(); - opcode_cycle = 0; break; } case 0xce: { op_io(2); regs.x = op_readstack(); - opcode_cycle = 0; break; } case 0xee: { op_io(2); regs.y = op_readstack(); - opcode_cycle = 0; break; } case 0x8e: { op_io(2); regs.p = op_readstack(); - opcode_cycle = 0; break; } @@ -322,7 +284,6 @@ case 0xcf: { //result is set based on y (high-byte) only regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } @@ -345,7 +306,6 @@ case 0x9e: { //result is set based on a (quotient) only regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index b358b66c..fd44ad29 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -3,7 +3,6 @@ case 0x7d: { regs.a = regs.x; regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -12,7 +11,6 @@ case 0xdd: { regs.a = regs.y; regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -21,7 +19,6 @@ case 0x5d: { regs.x = regs.a; regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } @@ -30,7 +27,6 @@ case 0xfd: { regs.y = regs.a; regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } @@ -39,14 +35,12 @@ case 0x9d: { regs.x = regs.sp; regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } case 0xbd: { op_io(); regs.sp = regs.x; - opcode_cycle = 0; break; } @@ -54,7 +48,6 @@ case 0xe8: { regs.a = op_readpc(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); - opcode_cycle = 0; break; } @@ -62,7 +55,6 @@ case 0xcd: { regs.x = op_readpc(); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); - opcode_cycle = 0; break; } @@ -70,12 +62,11 @@ case 0x8d: { regs.y = op_readpc(); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); - opcode_cycle = 0; break; } case 0xe6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -90,7 +81,7 @@ case 0xe6: { } case 0xbf: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -106,7 +97,7 @@ case 0xbf: { } case 0xe4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -121,7 +112,7 @@ case 0xe4: { } case 0xf8: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -136,7 +127,7 @@ case 0xf8: { } case 0xeb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -151,7 +142,7 @@ case 0xeb: { } case 0xf4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -167,7 +158,7 @@ case 0xf4: { } case 0xf9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -183,7 +174,7 @@ case 0xf9: { } case 0xfb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -199,7 +190,7 @@ case 0xfb: { } case 0xe5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -217,7 +208,7 @@ case 0xe5: { } case 0xe9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -233,7 +224,7 @@ case 0xe9: { } case 0xec: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -249,7 +240,7 @@ case 0xec: { } case 0xf5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -266,7 +257,7 @@ case 0xf5: { } case 0xf6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -283,7 +274,7 @@ case 0xf6: { } case 0xe7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc() + regs.x; op_io(); @@ -305,7 +296,7 @@ case 0xe7: { } case 0xf7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -327,7 +318,7 @@ case 0xf7: { } case 0xfa: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -346,7 +337,7 @@ case 0xfa: { } case 0x8f: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: rd = op_readpc(); dp = op_readpc(); @@ -363,7 +354,7 @@ case 0x8f: { } case 0xc6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(); break; @@ -379,7 +370,7 @@ case 0xc6: { } case 0xaf: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: op_io(2); case 2: @@ -391,7 +382,7 @@ case 0xaf: { } case 0xc4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -407,7 +398,7 @@ case 0xc4: { } case 0xd8: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -423,7 +414,7 @@ case 0xd8: { } case 0xcb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -439,7 +430,7 @@ case 0xcb: { } case 0xd4: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -457,7 +448,7 @@ case 0xd4: { } case 0xd9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -475,7 +466,7 @@ case 0xd9: { } case 0xdb: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); op_io(); @@ -493,7 +484,7 @@ case 0xdb: { } case 0xc5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -512,7 +503,7 @@ case 0xc5: { } case 0xc9: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -531,7 +522,7 @@ case 0xc9: { } case 0xcc: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -550,7 +541,7 @@ case 0xcc: { } case 0xd5: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; @@ -569,7 +560,7 @@ case 0xd5: { } case 0xd6: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; @@ -588,7 +579,7 @@ case 0xd6: { } case 0xc7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); op_io(); @@ -612,7 +603,7 @@ case 0xc7: { } case 0xd7: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -636,7 +627,7 @@ case 0xd7: { } case 0xba: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); break; @@ -655,7 +646,7 @@ case 0xba: { } case 0xda: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); break; @@ -674,7 +665,7 @@ case 0xda: { } case 0xaa: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: sp = op_readpc(); sp |= op_readpc() << 8; @@ -691,7 +682,7 @@ case 0xaa: { } case 0xca: { - switch(opcode_cycle++) { + switch(++opcode_cycle) { case 1: dp = op_readpc(); dp |= op_readpc() << 8; diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index ed808a6b..022179d1 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,81 +1,72 @@ case 0x2f: { rd = op_readpc(); - if(0){ opcode_cycle = 0; break; } + if(0){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xf0: { rd = op_readpc(); - if(!regs.p.z){ opcode_cycle = 0; break; } + if(!regs.p.z){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xd0: { rd = op_readpc(); - if(regs.p.z){ opcode_cycle = 0; break; } + if(regs.p.z){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0xb0: { rd = op_readpc(); - if(!regs.p.c){ opcode_cycle = 0; break; } + if(!regs.p.c){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x90: { rd = op_readpc(); - if(regs.p.c){ opcode_cycle = 0; break; } + if(regs.p.c){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x70: { rd = op_readpc(); - if(!regs.p.v){ opcode_cycle = 0; break; } + if(!regs.p.v){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x50: { rd = op_readpc(); - if(regs.p.v){ opcode_cycle = 0; break; } + if(regs.p.v){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x30: { rd = op_readpc(); - if(!regs.p.n){ opcode_cycle = 0; break; } + if(!regs.p.n){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } case 0x10: { rd = op_readpc(); - if(regs.p.n){ opcode_cycle = 0; break; } + if(regs.p.n){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -84,10 +75,9 @@ case 0x03: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + if((sp & 0x01) != 0x01){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -96,10 +86,9 @@ case 0x13: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + if((sp & 0x01) == 0x01){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -108,10 +97,9 @@ case 0x23: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + if((sp & 0x02) != 0x02){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -120,10 +108,9 @@ case 0x33: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + if((sp & 0x02) == 0x02){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -132,10 +119,9 @@ case 0x43: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + if((sp & 0x04) != 0x04){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -144,10 +130,9 @@ case 0x53: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + if((sp & 0x04) == 0x04){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -156,10 +141,9 @@ case 0x63: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + if((sp & 0x08) != 0x08){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -168,10 +152,9 @@ case 0x73: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + if((sp & 0x08) == 0x08){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -180,10 +163,9 @@ case 0x83: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + if((sp & 0x10) != 0x10){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -192,10 +174,9 @@ case 0x93: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + if((sp & 0x10) == 0x10){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -204,10 +185,9 @@ case 0xa3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + if((sp & 0x20) != 0x20){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -216,10 +196,9 @@ case 0xb3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + if((sp & 0x20) == 0x20){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -228,10 +207,9 @@ case 0xc3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + if((sp & 0x40) != 0x40){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -240,10 +218,9 @@ case 0xd3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + if((sp & 0x40) == 0x40){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -252,10 +229,9 @@ case 0xe3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + if((sp & 0x80) != 0x80){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -264,10 +240,9 @@ case 0xf3: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + if((sp & 0x80) == 0x80){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -276,10 +251,9 @@ case 0x2e: { sp = op_readdp(dp); rd = op_readpc(); op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } + if(regs.a == sp){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -289,10 +263,9 @@ case 0xde: { sp = op_readdp(dp + regs.x); rd = op_readpc(); op_io(); - if(regs.a == sp){ opcode_cycle = 0; break; } + if(regs.a == sp){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -301,10 +274,9 @@ case 0x6e: { wr = op_readdp(dp); op_writedp(dp, --wr); rd = op_readpc(); - if(wr == 0x00){ opcode_cycle = 0; break; } + if(wr == 0x00){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -313,10 +285,9 @@ case 0xfe: { op_io(); regs.y--; op_io(); - if(regs.y == 0x00){ opcode_cycle = 0; break; } + if(regs.y == 0x00){ break; } op_io(2); regs.pc += (int8)rd; - opcode_cycle = 0; break; } @@ -324,7 +295,6 @@ case 0x5f: { rd = op_readpc(); rd |= op_readpc() << 8; regs.pc = rd; - opcode_cycle = 0; break; } @@ -336,7 +306,6 @@ case 0x1f: { rd = op_readaddr(dp); rd |= op_readaddr(dp + 1) << 8; regs.pc = rd; - opcode_cycle = 0; break; } @@ -347,7 +316,6 @@ case 0x3f: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -357,7 +325,6 @@ case 0x4f: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = 0xff00 | rd; - opcode_cycle = 0; break; } @@ -369,7 +336,6 @@ case 0x01: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -381,7 +347,6 @@ case 0x11: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -393,7 +358,6 @@ case 0x21: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -405,7 +369,6 @@ case 0x31: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -417,7 +380,6 @@ case 0x41: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -429,7 +391,6 @@ case 0x51: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -441,7 +402,6 @@ case 0x61: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -453,7 +413,6 @@ case 0x71: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -465,7 +424,6 @@ case 0x81: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -477,7 +435,6 @@ case 0x91: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -489,7 +446,6 @@ case 0xa1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -501,7 +457,6 @@ case 0xb1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -513,7 +468,6 @@ case 0xc1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -525,7 +479,6 @@ case 0xd1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -537,7 +490,6 @@ case 0xe1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -549,7 +501,6 @@ case 0xf1: { op_writestack(regs.pc >> 8); op_writestack(regs.pc); regs.pc = rd; - opcode_cycle = 0; break; } @@ -563,7 +514,6 @@ case 0x0f: { regs.pc = rd; regs.p.b = 1; regs.p.i = 0; - opcode_cycle = 0; break; } @@ -572,7 +522,6 @@ case 0x6f: { rd |= op_readstack() << 8; op_io(2); regs.pc = rd; - opcode_cycle = 0; break; } @@ -582,7 +531,6 @@ case 0x7f: { rd |= op_readstack() << 8; op_io(2); regs.pc = rd; - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 3eb1cd77..2a16a3c8 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,56 +1,48 @@ case 0x88: { rd = op_readpc(); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } case 0x28: { rd = op_readpc(); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } case 0x68: { rd = op_readpc(); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } case 0xc8: { rd = op_readpc(); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } case 0xad: { rd = op_readpc(); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } case 0x48: { rd = op_readpc(); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } case 0x08: { rd = op_readpc(); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } case 0xa8: { rd = op_readpc(); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -58,7 +50,6 @@ case 0x86: { op_io(); rd = op_readdp(regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -66,7 +57,6 @@ case 0x26: { op_io(); rd = op_readdp(regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -74,7 +64,6 @@ case 0x66: { op_io(); rd = op_readdp(regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -82,7 +71,6 @@ case 0x46: { op_io(); rd = op_readdp(regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -90,7 +78,6 @@ case 0x06: { op_io(); rd = op_readdp(regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -98,7 +85,6 @@ case 0xa6: { op_io(); rd = op_readdp(regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -106,7 +92,6 @@ case 0x84: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -114,7 +99,6 @@ case 0x24: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -122,7 +106,6 @@ case 0x64: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -130,7 +113,6 @@ case 0x3e: { dp = op_readpc(); rd = op_readdp(dp); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } @@ -138,7 +120,6 @@ case 0x7e: { dp = op_readpc(); rd = op_readdp(dp); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } @@ -146,7 +127,6 @@ case 0x44: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -154,7 +134,6 @@ case 0x04: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -162,7 +141,6 @@ case 0xa4: { dp = op_readpc(); rd = op_readdp(dp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -171,7 +149,6 @@ case 0x94: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -180,7 +157,6 @@ case 0x34: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -189,7 +165,6 @@ case 0x74: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -198,7 +173,6 @@ case 0x54: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -207,7 +181,6 @@ case 0x14: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -216,7 +189,6 @@ case 0xb4: { op_io(); rd = op_readdp(dp + regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -225,7 +197,6 @@ case 0x85: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -234,7 +205,6 @@ case 0x25: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -243,7 +213,6 @@ case 0x65: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -252,7 +221,6 @@ case 0x1e: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.x = op_cmp(regs.x, rd); - opcode_cycle = 0; break; } @@ -261,7 +229,6 @@ case 0x5e: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.y = op_cmp(regs.y, rd); - opcode_cycle = 0; break; } @@ -270,7 +237,6 @@ case 0x45: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -279,7 +245,6 @@ case 0x05: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -288,7 +253,6 @@ case 0xa5: { dp |= op_readpc() << 8; rd = op_readaddr(dp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -298,7 +262,6 @@ case 0x95: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -308,7 +271,6 @@ case 0x96: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -318,7 +280,6 @@ case 0x35: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -328,7 +289,6 @@ case 0x36: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -338,7 +298,6 @@ case 0x75: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -348,7 +307,6 @@ case 0x76: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -358,7 +316,6 @@ case 0x55: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -368,7 +325,6 @@ case 0x56: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -378,7 +334,6 @@ case 0x15: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -388,7 +343,6 @@ case 0x16: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -398,7 +352,6 @@ case 0xb5: { op_io(); rd = op_readaddr(dp + regs.x); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -408,7 +361,6 @@ case 0xb6: { op_io(); rd = op_readaddr(dp + regs.y); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -419,7 +371,6 @@ case 0x87: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -430,7 +381,6 @@ case 0x27: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -441,7 +391,6 @@ case 0x67: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -452,7 +401,6 @@ case 0x47: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -463,7 +411,6 @@ case 0x07: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -474,7 +421,6 @@ case 0xa7: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -485,7 +431,6 @@ case 0x97: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_adc(regs.a, rd); - opcode_cycle = 0; break; } @@ -496,7 +441,6 @@ case 0x37: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_and(regs.a, rd); - opcode_cycle = 0; break; } @@ -507,7 +451,6 @@ case 0x77: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_cmp(regs.a, rd); - opcode_cycle = 0; break; } @@ -518,7 +461,6 @@ case 0x57: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_eor(regs.a, rd); - opcode_cycle = 0; break; } @@ -529,7 +471,6 @@ case 0x17: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_or(regs.a, rd); - opcode_cycle = 0; break; } @@ -540,7 +481,6 @@ case 0xb7: { sp |= op_readdp(dp + 1) << 8; rd = op_readaddr(sp + regs.y); regs.a = op_sbc(regs.a, rd); - opcode_cycle = 0; break; } @@ -550,7 +490,6 @@ case 0x99: { wr = op_readdp(regs.x); wr = op_adc(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -560,7 +499,6 @@ case 0x39: { wr = op_readdp(regs.x); wr = op_and(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -570,7 +508,6 @@ case 0x79: { wr = op_readdp(regs.x); wr = op_cmp(wr, rd); (0) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -580,7 +517,6 @@ case 0x59: { wr = op_readdp(regs.x); wr = op_eor(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -590,7 +526,6 @@ case 0x19: { wr = op_readdp(regs.x); wr = op_or(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -600,7 +535,6 @@ case 0xb9: { wr = op_readdp(regs.x); wr = op_sbc(wr, rd); (1) ? op_writedp(regs.x, wr) : op_io(); - opcode_cycle = 0; break; } @@ -611,7 +545,6 @@ case 0x89: { wr = op_readdp(dp); wr = op_adc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -622,7 +555,6 @@ case 0x29: { wr = op_readdp(dp); wr = op_and(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -633,7 +565,6 @@ case 0x69: { wr = op_readdp(dp); wr = op_cmp(wr, rd); (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -644,7 +575,6 @@ case 0x49: { wr = op_readdp(dp); wr = op_eor(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -655,7 +585,6 @@ case 0x09: { wr = op_readdp(dp); wr = op_or(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -666,7 +595,6 @@ case 0xa9: { wr = op_readdp(dp); wr = op_sbc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -676,7 +604,6 @@ case 0x98: { wr = op_readdp(dp); wr = op_adc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -686,7 +613,6 @@ case 0x38: { wr = op_readdp(dp); wr = op_and(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -696,7 +622,6 @@ case 0x78: { wr = op_readdp(dp); wr = op_cmp(wr, rd); (0) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -706,7 +631,6 @@ case 0x58: { wr = op_readdp(dp); wr = op_eor(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -716,7 +640,6 @@ case 0x18: { wr = op_readdp(dp); wr = op_or(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -726,7 +649,6 @@ case 0xb8: { wr = op_readdp(dp); wr = op_sbc(wr, rd); (1) ? op_writedp(dp, wr) : op_io(); - opcode_cycle = 0; break; } @@ -736,7 +658,6 @@ case 0x7a: { op_io(); rd |= op_readdp(dp + 1) << 8; regs.ya = op_addw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -746,7 +667,6 @@ case 0x9a: { op_io(); rd |= op_readdp(dp + 1) << 8; regs.ya = op_subw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -755,7 +675,6 @@ case 0x5a: { rd = op_readdp(dp); rd |= op_readdp(dp + 1) << 8; op_cmpw(regs.ya, rd); - opcode_cycle = 0; break; } @@ -766,7 +685,6 @@ case 0x4a: { dp &= 0x1fff; rd = op_readaddr(dp); regs.p.c = regs.p.c & !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -777,7 +695,6 @@ case 0x6a: { dp &= 0x1fff; rd = op_readaddr(dp); regs.p.c = regs.p.c & !(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -789,7 +706,6 @@ case 0x8a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -801,7 +717,6 @@ case 0xea: { rd = op_readaddr(dp); rd ^= (1 << bit); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -813,7 +728,6 @@ case 0x0a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c | !!(rd & (1 << bit)); - opcode_cycle = 0; break; } @@ -825,7 +739,6 @@ case 0x2a: { rd = op_readaddr(dp); op_io(); regs.p.c = regs.p.c | !(rd & (1 << bit)); - opcode_cycle = 0; break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index fcacfc71..9b0dd2fb 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,75 +1,61 @@ case 0xbc: { op_io(); regs.a = op_inc(regs.a); - opcode_cycle = 0; break; } case 0x3d: { op_io(); regs.x = op_inc(regs.x); - opcode_cycle = 0; break; } case 0xfc: { op_io(); regs.y = op_inc(regs.y); - opcode_cycle = 0; break; } case 0x9c: { op_io(); regs.a = op_dec(regs.a); - opcode_cycle = 0; break; } case 0x1d: { op_io(); regs.x = op_dec(regs.x); - opcode_cycle = 0; break; } case 0xdc: { op_io(); regs.y = op_dec(regs.y); - opcode_cycle = 0; break; } case 0x1c: { op_io(); regs.a = op_asl(regs.a); - opcode_cycle = 0; break; } case 0x5c: { op_io(); regs.a = op_lsr(regs.a); - opcode_cycle = 0; break; } case 0x3c: { op_io(); regs.a = op_rol(regs.a); - opcode_cycle = 0; break; } case 0x7c: { - switch(opcode_cycle++) { - case 1: - op_io(); - regs.a = op_ror(regs.a); - opcode_cycle = 0; + op_io(); + regs.a = op_ror(regs.a); break; - } - break; } case 0xab: { @@ -77,7 +63,6 @@ case 0xab: { rd = op_readdp(dp); rd = op_inc(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -86,7 +71,6 @@ case 0x8b: { rd = op_readdp(dp); rd = op_dec(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -95,7 +79,6 @@ case 0x0b: { rd = op_readdp(dp); rd = op_asl(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -104,7 +87,6 @@ case 0x4b: { rd = op_readdp(dp); rd = op_lsr(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -113,7 +95,6 @@ case 0x2b: { rd = op_readdp(dp); rd = op_rol(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -122,7 +103,6 @@ case 0x6b: { rd = op_readdp(dp); rd = op_ror(rd); op_writedp(dp, rd); - opcode_cycle = 0; break; } @@ -132,7 +112,6 @@ case 0xbb: { rd = op_readdp(dp + regs.x); rd = op_inc(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -142,7 +121,6 @@ case 0x9b: { rd = op_readdp(dp + regs.x); rd = op_dec(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -152,7 +130,6 @@ case 0x1b: { rd = op_readdp(dp + regs.x); rd = op_asl(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -162,7 +139,6 @@ case 0x5b: { rd = op_readdp(dp + regs.x); rd = op_lsr(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -172,7 +148,6 @@ case 0x3b: { rd = op_readdp(dp + regs.x); rd = op_rol(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -182,7 +157,6 @@ case 0x7b: { rd = op_readdp(dp + regs.x); rd = op_ror(rd); op_writedp(dp + regs.x, rd); - opcode_cycle = 0; break; } @@ -192,7 +166,6 @@ case 0xac: { rd = op_readaddr(dp); rd = op_inc(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -202,7 +175,6 @@ case 0x8c: { rd = op_readaddr(dp); rd = op_dec(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -212,7 +184,6 @@ case 0x0c: { rd = op_readaddr(dp); rd = op_asl(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -222,7 +193,6 @@ case 0x4c: { rd = op_readaddr(dp); rd = op_lsr(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -232,7 +202,6 @@ case 0x2c: { rd = op_readaddr(dp); rd = op_rol(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -242,7 +211,6 @@ case 0x6c: { rd = op_readaddr(dp); rd = op_ror(rd); op_writeaddr(dp, rd); - opcode_cycle = 0; break; } @@ -254,7 +222,6 @@ case 0x0e: { regs.p.z = ((regs.a - rd) == 0); op_readaddr(dp); op_writeaddr(dp, rd | regs.a); - opcode_cycle = 0; break; } @@ -266,7 +233,6 @@ case 0x4e: { regs.p.z = ((regs.a - rd) == 0); op_readaddr(dp); op_writeaddr(dp, rd &~ regs.a); - opcode_cycle = 0; break; } @@ -279,7 +245,6 @@ case 0x3a: { op_writedp(dp, rd >> 8); regs.p.n = !!(rd & 0x8000); regs.p.z = (rd == 0); - opcode_cycle = 0; break; } @@ -292,7 +257,6 @@ case 0x1a: { op_writedp(dp, rd >> 8); regs.p.n = !!(rd & 0x8000); regs.p.z = (rd == 0); - opcode_cycle = 0; break; } From efd1a6dd386f79feab336fa9c8b4647feedab181 Mon Sep 17 00:00:00 2001 From: Michael Moorman Date: Wed, 28 Sep 2011 03:55:19 -0400 Subject: [PATCH 050/130] Updating POTFILES.in to replace .glade with .ui and add netplay translations --- gtk/po/POTFILES.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gtk/po/POTFILES.in b/gtk/po/POTFILES.in index 32e6d8d8..dead100a 100644 --- a/gtk/po/POTFILES.in +++ b/gtk/po/POTFILES.in @@ -2,7 +2,8 @@ src/gtk_binding.cpp src/gtk_cheat.cpp src/gtk_config.cpp src/gtk_display_driver_opengl.cpp +src/gtk_netplay.cpp src/gtk_preferences.cpp src/gtk_s9x.cpp src/gtk_s9xwindow.cpp -src/snes9x.glade +src/snes9x.ui From bbdd19b22ea48f400874872acefab9ac83d1988a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 18 Oct 2011 09:10:39 -0500 Subject: [PATCH 051/130] Fix file path issue. Rebuild UI file so it works on GTK+ 2.24+. --- gtk/src/gtk_file.cpp | 1 + gtk/src/snes9x.ui | 14804 ++++++++++++++++++++++------------------- 2 files changed, 7974 insertions(+), 6831 deletions(-) diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index 0610d439..2182e39e 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -157,6 +157,7 @@ S9xGetDirectory (enum s9x_getdirtype dirtype) case SCREENSHOT_DIR: case SPC_DIR: sprintf (path, "%s", gui_config->export_directory); + break; default: path[0] = '\0'; diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index 3f86e43d..2cd0e909 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -1,5822 +1,108 @@ - + - - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - Snes9x - - - - - - - - - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - _File - True - - - - - _Open ROM Image... - True - True - image2 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Open Recent - True - - - - - True - - - - - Open with _NetPlay... - True - Open a ROM to use with NetPlay - True - image3 - False - - - - - - True - Open _MultiCart... - True - - - - - - True - - - - - True - _Load State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - From _File... - True - - - - - - - - - - True - _Save State - True - - - - - - True - Slot _0 - True - - - - - - True - Slot _1 - True - - - - - - True - Slot _2 - True - - - - - - True - Slot _3 - True - - - - - - True - Slot _4 - True - - - - - - True - Slot _5 - True - - - - - - True - Slot _6 - True - - - - - - True - Slot _7 - True - - - - - - True - Slot _8 - True - - - - - - True - - - - - True - To _File... - True - - - - - - - - - - True - - - - - Save SPC... - True - True - image4 - False - - - - - - True - - - - - Show ROM _Info... - True - True - image5 - False - - - - - - True - - - - - _Quit - True - True - image18 - False - - - - - - - - - - True - _Emulation - True - - - - - Run / _Continue - True - True - image6 - False - - - - - - _Pause - True - True - image7 - False - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - Load _Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image8 - False - - - - - - R_ecord Movie... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image19 - False - - - - - - _Stop Recording - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image9 - False - - - - - - _Jump to Frame... - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image10 - False - - - - - - True - - - - - Sy_nc Clients - True - True - image11 - False - - - - - - True - - - - - Reset - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - image12 - False - - - - - - Soft _Reset - True - True - image13 - False - - - - - - - - - - True - _View - True - - - - - - _Hide Menu - True - True - image14 - False - - - - - - True - _Status Bar - True - - - - - - True - - - - - _Change Size - True - True - image17 - False - - - True - - - True - False - Exact Pixels - True - - - - - True - _1x - True - - - - - - True - _2x - True - - - - - - True - _3x - True - - - - - - True - _4x - True - - - - - - True - _5x - True - - - - - - True - - - - - True - False - Correct Aspect - True - - - - - True - 1x - True - - - - - - True - 2x - True - - - - - - True - 3x - True - - - - - - True - 4x - True - - - - - - True - 5x - True - - - - - - - - - - True - - - - - _Fullscreen - True - True - image15 - False - - - - - - - - - - True - _Options - True - - - - - True - Controller Ports - True - - - - - True - SNES Port 1 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad1 - - - - - - True - Superscope - True - True - joypad1 - - - - - - - - - - True - SNES Port 2 - True - - - - - - True - Joypad - True - - - - - - True - Mouse - True - joypad2 - - - - - - True - Multitap - True - joypad2 - - - - - - True - Superscope - True - True - joypad2 - - - - - - - - - - - - - - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Cheats... - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - _Preferences... - True - True - image16 - False - - - - - - - - - - False - 0 - - - - - 256 - 224 - True - True - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK - - - - - - - - 1 - - - - - True - - - False - 2 - - - - - - - GDK_KEY_PRESS_MASK - Snes9x Preferences - center - 480 - dialog + + 560 + 448 + False + About Snes9x + normal True - - - + True + False + 2 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + 5 - + True - True - left - 0 - 1 - 0 - + False + 5 - + True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - never - automatic - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - queue - none - - - True - 5 - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Use fullscreen on ROM open - True - True - False - Go to fullscreen mode immediately after opening a ROM - True - True - - - False - False - 0 - - - - - Show frame rate - True - True - False - True - True - - - False - False - 1 - - - - - Use overscanned height - True - True - False - Use SNES extended height. Will probably cause letterboxing - True - True - - - False - False - 2 - - - - - True - 12 - - - Change fullscreen resolution: - True - True - False - Changes the screen resolution when running Snes9x in fullscreen mode - True - True - - - False - False - 0 - - - - - True - liststore14 - - - - 0 - - - - - 1 - - - - - False - False - 3 - - - - - - - - - True - <b>Basic Settings</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 5 - - - Scale image to fit window - True - True - False - Scales the image so no black bars are present - True - True - - - False - False - 0 - - - - - True - 12 - - - Maintain aspect-ratio: - True - True - False - Scales the image as large as possible without distortion - True - True - - - False - False - 0 - - - - - True - liststore13 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - True - 5 - - - Use - True - True - False - Allows scaling and filtering to use multiple processors - True - True - - - False - False - 0 - - - - - True - True - adjustment17 - True - True - - - False - 1 - - - - - True - threads for filtering and scaling - - - False - 2 - - - - - 2 - - - - - True - 12 - - - True - High-resolution effect: - - - False - 0 - - - - - True - liststore15 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - True - 12 - - - True - 0 - Apply scaling filter: - - - False - 0 - - - - - True - liststore12 - - - - - 0 - - - - - False - 1 - - - - - False - False - 4 - - - - - - - - - True - <b>Image Adjustments</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Video preset: - - - False - 0 - - - - - True - - - Composite - True - True - True - - - - False - 0 - - - - - S-Video - True - True - True - - - - False - 1 - - - - - RGB - True - True - True - - - - False - 2 - - - - - Monochrome - True - True - True - - - - False - 3 - - - - - False - 1 - - - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 11 - 2 - 12 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Artifacts: - - - 6 - 7 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Sharpness: - - - 4 - 5 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Brightness: - - - 3 - 4 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Contrast: - - - 2 - 3 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Saturation: - - - 1 - 2 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Hue: - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment16 - False - -1 - 2 - left - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment15 - False - -1 - 2 - left - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment14 - False - -1 - 2 - left - - - 1 - 2 - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment13 - False - -1 - 2 - left - - - 1 - 2 - 3 - 4 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment12 - False - -1 - 2 - left - - - 1 - 2 - 4 - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment11 - False - -1 - 2 - left - - - 1 - 2 - 6 - 7 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment10 - False - -1 - 2 - left - - - 1 - 2 - 7 - 8 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment9 - False - -1 - 2 - left - - - 1 - 2 - 8 - 9 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment8 - False - -1 - 2 - left - - - 1 - 2 - 9 - 10 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - adjustment7 - False - -1 - 2 - left - - - 1 - 2 - 10 - 11 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Gamma: - - - 7 - 8 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fringing: - - - 8 - 9 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Bleed: - - - 9 - 10 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Resolution: - - - 10 - 11 - GTK_FILL - - - - - True - - - 2 - 5 - 6 - - - - - 1 - - - - - Merge odd and even fields - True - True - False - True - - - 2 - - - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore11 - - - - 0 - - - - - False - 1 - - - - - 3 - - - - - - - - - True - <b>NTSC Filter</b> - True - - - - - False - 2 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - 12 - - - True - 0 - Scanline intensity: - - - False - 0 - - - - - True - liststore10 - - - - 0 - - - - - False - 1 - - - - - - - - - True - <b>Scanline Filter</b> - True - - - - - False - 3 - - - - - True - 0 - none - - - True - 5 - 5 - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore9 - - - - - 0 - - - - - 0 - - - - - Bilinear-filter output - True - True - False - True - True - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - Sync to vertical blank - True - True - False - Sync the image to the vertical retrace to stop tearing - True - True - - - False - False - 0 - - - - - Reduce input lag - True - True - False - Sync the program with the video output after every displayed frame to reduce input latency - True - - - 1 - - - - - Allow non-power-of-two textures - True - True - False - Prevents edge artifacts, but can slow performance - True - - - 2 - - - - - Use pixel-buffer objects - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Can be faster or slower depending on drivers - True - - - 3 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Different formats can yield highly different performance - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Pixel-buffer format: - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - liststore8 - - - - 0 - - - - - False - 1 - - - - - - - 4 - - - - - True - 5 - - - Use GLSL shader: - True - True - False - 0 - True - - - False - 0 - - - - - True - True - - True - - - 1 - - - - - Browse... - True - True - True - - - - False - 2 - - - - - 5 - - - - - 2 - - - - - True - - - Force an inverted byte-ordering - True - True - False - Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card - True - - - 0 - - - - - 3 - - - - - - - - - True - <b>Hardware Acceleration</b> - True - - - - - False - 4 - - - - - - + False + gtk-missing-image - - - True - - - True - video-display - - - 0 - - - - - True - Display - True - - - False - False - 1 - - - - - False - - + + + False + True + 0 + + + + + True + False + 0 + 10 + 10 + label106 + True + center + True + + + False + True + 1 + + + + + True + False + queue - - True - True - never - automatic - - - True - queue - none - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 12 - - - True - Sound driver: - - - False - False - 0 - - - - - True - liststore7 - - - - 0 - - - - - False - False - 1 - - - - - False - False - 0 - - - - - Synchronize with sound - True - True - False - Base emulation speed on the rate sound is output - True - - - False - False - 1 - - - - - Mute sound output - True - True - False - Disables output of sound - True - True - - - False - False - 2 - - - - - Stereo - True - True - False - Output two channels, left and right - True - True - - - False - False - 3 - - - - - True - 4 - 2 - 10 - 5 - - - True - 0 - Playback rate: - - - GTK_FILL - - - - - - True - 5 - - - True - True - adjustment6 - True - True - - - False - 0 - - - - - True - milliseconds - - - False - 1 - - - - - 1 - 2 - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Buffer size: - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - 0 - Input rate: - - - 1 - 2 - GTK_FILL - - - - - True - True - Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option - adjustment5 - False - 0 - left - - - 1 - 2 - 1 - 2 - - - - - True - - - True - liststore6 - - - - 0 - - - - - False - False - 0 - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Video rate: - - - 2 - 3 - GTK_FILL - - - - - True - label - - - 1 - 2 - 2 - 3 - - - - - False - 4 - - - - - - - - - True - <b>Sound Settings</b> - True - - - - - - - - - 1 - - - - - True - - - True - audio-x-generic - - - 0 - - - - - True - Sound - True - - - False - False - 1 - - - - - 1 - False - - - - + True True automatic - automatic - - True - queue - none - - - True - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - 10 - - - True - Frameskip: - - - False - False - 0 - - - - - True - liststore5 - - - - 0 - - - - - False - False - 1 - - - - - False - 0 - - - - - Block invalid VRAM access - True - True - False - True - - - 1 - - - - - Allow opposing dpad directions - True - True - False - Let left and right or up and down be pressed at the same time - True - - - 2 - - - - - - - - - True - <b>Accuracy</b> - True - - - - - False - 0 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Pause emulation when switching away from Snes9x - True - True - False - True - - - 0 - - - - - True - 12 - - - True - The ESC key should: - - - False - 0 - - - - - True - liststore4 - - - - 0 - - - - - False - 1 - - - - - 1 - - - - - - - - - True - <b>Window Switching</b> - True - - - - - False - 1 - - - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - Prevent the screensaver from activating - True - True - False - True - - - 0 - - - - - - - - - True - <b>Screensaver</b> - True - - - - - False - 2 - - - - - - - - - 2 - - - - - True - - - True - utilities-terminal - - - 0 - - - - - True - Emulation - True - - - False - False - 1 - - - - - 2 - False - - - - - True - 5 - - - True - 5 - 0 - none - - - True - 12 - - - True - 5 - - - True - 5 - 3 - 5 - 5 - - - True - True - False - - gtk-clear - - - - - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 1 - 2 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 2 - 3 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 3 - 4 - - - - - True - True - False - - gtk-clear - - - - - 1 - 2 - 4 - 5 - - - - - Browse... - True - True - True - - - - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 3 - 4 - GTK_FILL - - - - - - Browse... - True - True - True - - - - 2 - 3 - 4 - 5 - GTK_FILL - - - - - - True - 0 - SRAM: - - - GTK_FILL - - - - - True - 0 - Save states: - - - 1 - 2 - GTK_FILL - - - - - True - 0 - Cheats: - - - 2 - 3 - GTK_FILL - - - - - True - 0 - Patches: - - - 3 - 4 - GTK_FILL - - - - - True - 0 - Exports: - - - 4 - 5 - GTK_FILL - - - - - False - 0 - - - - - - - - - True - <b>Game Data Locations</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - 5 - - - True - Save SRAM: - - - False - 0 - - - - - True - True - Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs - - 5 - 1 - - - False - 1 - - - - - True - seconds after change - - - False - 2 - - - - - - - - - True - <b>Automatic Saving</b> - True - - - - - False - 1 - - - - - 3 - - - - - True - - - True - folder - - - 0 - - - - - True - Files - True - - - False - False - 1 - - - - - 3 - False - - - - - True - 5 - 5 - - - True - 5 - - - True - 5 - <b>Joypad:</b> - True - - - False - False - 0 - - - - - True - liststore3 - - - - - 0 - - - - - False - 1 - - - - - True - - - False - 2 - - - - - _Reset - True - True - True - True - - - - False - False - 3 - - - - - True - - - False - 4 - - - - - True - Swap with: - - - False - 5 - - - - - True - liststore2 - - - - 0 - - - - - False - 6 - - - - - _Swap - True - True - True - True - - - - False - 7 - - - - - False - 0 - - - - - Use modifier keys (CTRL, SHIFT, ALT) directly + True True - False - Allow using modifier keys as independent keys instead of modifiers - True - True + False + False + textbuffer1 - - False - False - 1 - - - - - True - True - - - - True - 10 - 12 - - - True - 6 - 2 - 10 - 5 - - - True - 0 - Up - - - GTK_FILL - - - - - - True - 0 - Down - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Left - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Right - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Start - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Select - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 0 - - - - - True - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - - - - - - - True - Buttons - - - False - - - - - True - 5 - 2 - 2 - 5 - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - 5 - 6 - 2 - 10 - 5 - - - True - 0 - A - - - GTK_FILL - - - - - - True - 0 - B - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - X - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Y - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - L - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - R - - - 5 - 6 - GTK_FILL - - - - - - 50 - True - True - False - - - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 1 - 2 - GTK_FILL - - - - - True - 0 - <b>Sticky</b> - True - center - - - 1 - 2 - - - - - - - True - 0 - <b>Turbo</b> - True - center - - - - - - - - - 1 - False - - - - - True - Turbo / Sticky Buttons - - - 1 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - 5 - 5 - - - True - Set new axis bindings at: - - - False - False - 0 - - - - - True - True - Changes the amount a joystick should be tilted to register a button press - adjustment4 - 1 - True - - - False - False - 1 - - - - - True - percent - - - False - False - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Joystick Axis Threshold</b> - True - - - - - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Center all axes on all joysticks and press Calibrate. - - - False - False - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - Cali_brate - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - - - - False - False - 1 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Calibration</b> - True - - - - - 1 - - - - - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Joystick Options - - - 2 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - 3 - - - 4 - - - - - True - - - True - input-gaming - - - 0 - - - - - True - Joypads - True - - - False - False - 1 - - - - - 4 - False - - - - - True - 5 - 5 - - - True - 0 - 5 - <b>Snes9x Emulator Shortcut Keys</b> - True - - - False - False - 0 - - - - - True - - - False - False - 1 - - - - - True - True - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 11 - 2 - 10 - 5 - - - True - 0 - Soft reset - - - 9 - 10 - GTK_FILL - - - - - - True - 0 - Hardware reset - - - 8 - 9 - GTK_FILL - - - - - - True - 0 - Increase frame time - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Decrease frame time - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Increase frame rate - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Decrease frame rate - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Pause - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle turbo - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Enable turbo - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Open ROM - - - GTK_FILL - - - - - - True - 0 - Quit Snes9x - - - 10 - 11 - GTK_FILL - GTK_FILL - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 10 - 11 - GTK_FILL - - - - - - - - - - - True - Emulation - - - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 8 - 2 - 10 - 5 - - - True - 0 - Toggle BG layer 0 - - - GTK_FILL - - - - - - True - 0 - Toggle BG layer 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle BG layer 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sprites - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - BG layering hack - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Screenshot - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle fullscreen - - - 7 - 8 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - - - - - 1 - - - - - True - Graphics - - - 1 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 10 - 4 - 10 - 5 - - - True - 0 - <b>Quick save state</b> - True - center - - - 2 - - - - - - - True - 0 - <b>Quick load state</b> - True - - - 2 - 4 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - - - - - - - True - 0 - Slot 0 - - - 1 - 2 - - - - - - - True - 0 - Slot 2 - - - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 8 - 9 - - - - - - - True - 0 - Slot 0 - - - 2 - 3 - 1 - 2 - - - - - - - True - 0 - Slot 1 - - - 2 - 3 - 2 - 3 - - - - - - - True - 0 - Slot 2 - - - 2 - 3 - 3 - 4 - - - - - - - True - 0 - Slot 3 - - - 2 - 3 - 4 - 5 - - - - - - - True - 0 - Slot 4 - - - 2 - 3 - 5 - 6 - - - - - - - True - 0 - Slot 5 - - - 2 - 3 - 6 - 7 - - - - - - - True - 0 - Slot 6 - - - 2 - 3 - 7 - 8 - - - - - - - True - 0 - Slot 7 - - - 2 - 3 - 8 - 9 - - - - - - - True - 0 - Slot 8 - - - 2 - 3 - 9 - 10 - - - - - - - True - 0 - Slot 8 - - - 9 - 10 - - - - - - - 50 - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - 50 - True - True - False - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 1 - 2 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 3 - 4 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 2 - 3 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 4 - 5 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 5 - 6 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 9 - 10 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 7 - 8 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 6 - 7 - GTK_FILL - - - - - 50 - True - True - False - - - 3 - 4 - 8 - 9 - GTK_FILL - - - - - - - - - 2 - - - - - True - Save States - - - 2 - False - - - - - True - True - never - automatic - - - True - queue - none - - - True - 10 - 9 - 2 - 10 - 5 - - - True - 0 - Toggle sound channel 0 - - - GTK_FILL - - - - - - True - 0 - Toggle sound channel 1 - - - 1 - 2 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 2 - - - 2 - 3 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 3 - - - 3 - 4 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 4 - - - 4 - 5 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 5 - - - 5 - 6 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 6 - - - 6 - 7 - GTK_FILL - - - - - - True - 0 - Toggle sound channel 7 - - - 7 - 8 - GTK_FILL - - - - - - True - 0 - Toggle all sound channels - - - 8 - 9 - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 6 - 7 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 7 - 8 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 8 - 9 - GTK_FILL - - - - - - - - - 3 - - - - - True - Sound - - - 3 - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - 6 - 2 - 10 - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Seek to frame - - - 4 - 5 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Load Movie - - - 3 - 4 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Stop movie recording - - - 2 - 3 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Begin movie recording - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Save SPC - - - GTK_FILL - - - - - - True - True - False - - - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - True - False - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - 0 - Swap controllers 1 & 2 - - - 5 - 6 - GTK_FILL - - - - - - True - True - - - 1 - 2 - 5 - 6 - GTK_FILL - - - - - 4 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Misc - - - 4 - False - - - - - 2 - - - - - True - <small>Click an entry and then press the desired keys or joystick button -<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> - True - fill - True - - - False - False - 3 - - - - - 5 - - - - - True - - - True - input-keyboard - - - 0 - - - - - True - Shortcuts - True - - - False - False - 1 - - - - - 5 - False - + + True + True + 2 + - 2 + True + True + 0 - + True + False end - - gtk-cancel + + gtk-close True True - True - False + True + False True @@ -5825,70 +111,132 @@ 0 - - - gtk-apply - True - True - True - False - True - - - - False - False - 1 - - - - - gtk-ok - True - True - True - False - True - - - False - False - 2 - - - - - gtk-about - True - True - True - True - - - - False - False - 3 - True - - False + True end - 0 + 1 - cancel_button - ok_button - button1 - button8 + button15 + + 1 + 60 + 1 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 1.0408340855860843e-17 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + 2 + 8 + 2 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 9999 + 6096 + 1 + 1 + + + 1 + 100 + 50 + 1 + 10 + + + 31500 + 32500 + 31990 + 1 + 10 + + + 2 + 256 + 2 + 1 + 1 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + + -1 + 1 + 0.01 + 0.10000000000000001 + + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 Advance to Frame @@ -5898,67 +246,13 @@ True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - The current frame in the movie is - True - - - 0 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - Fast-forward to frame - - - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - 1 - - - - - 1 - - - - - False - 1 - - True + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end @@ -5968,6 +262,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5985,6 +280,7 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -5996,10 +292,84 @@ False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + The current frame in the movie is + True + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fast-forward to frame + + + True + True + 0 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + True + True + 1 + + + + + True + True + 1 + + + + + False + True + 1 + + @@ -6007,6 +377,114 @@ button2 + + True + False + gtk-media-next + 1 + + + True + False + gtk-revert-to-saved + 1 + + + True + False + gtk-redo + 1 + + + True + False + gtk-refresh + 1 + + + True + False + gtk-leave-fullscreen + 1 + + + True + False + gtk-fullscreen + 1 + + + True + False + gtk-preferences + 1 + + + True + False + gtk-zoom-in + 1 + + + True + False + gtk-quit + 1 + + + True + False + gtk-media-record + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-network + 1 + + + True + False + gtk-save + 1 + + + True + False + gtk-dialog-info + 1 + + + True + False + gtk-go-forward + 1 + + + True + False + gtk-media-pause + 1 + + + True + False + gtk-open + 1 + + + True + False + gtk-media-stop + 1 + @@ -6024,6 +502,104 @@ + + + + + + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + 0% + + + 12.5% + + + 25% + + + 50% + + + 100% + + + + + + + + + + + None + + + SuperEagle + + + 2xSaI + + + Super2xSaI + + + EPX + + + EPX Smooth + + + Blargg's NTSC + + + Scanlines + + + Simple2x + + + Simple3x + + + Simple4x + + + + + + + + + + + 8:7 Square pixels + + + 4:3 SNES correct aspect + + + @@ -6219,103 +795,202 @@ - - - - - - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - 0% - - - 12.5% - - - 25% - - - 50% - - - 100% - - - - - - - - - - - None - - - SuperEagle - - - 2xSaI - - - Super2xSaI - - - EPX - - - EPX Smooth - - - Blargg's NTSC - - - Scanlines - - - Simple2x - - - Simple3x - - - Simple4x - - - - - - - - - - - 8:7 Square pixels - - - 4:3 SNES correct aspect - - + + 512 + 350 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Snes9x Cheats + center-on-parent + dialog + True + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-close + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + False + False + 0 + + + + + False + True + end + 0 + + + + + True + False + 5 + + + True + False + 0 + in + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + 0 + Code: + + + False + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + False + True + 1 + + + + + True + False + 0 + Description: + + + False + True + 2 + + + + + True + True + 21 + True + False + False + True + True + + + False + True + 3 + + + + + gtk-add + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 4 + + + + + gtk-remove + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 5 + + + + + False + False + 1 + + + + + True + True + 1 + + + + + + button7 + @@ -6340,153 +1015,977 @@ - - 512 - 350 - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Snes9x Cheats - center-on-parent - dialog - True - - + + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + Snes9x + + + + + + + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 + False - + True - 5 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True - 0 - in - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False + _File + True + + + False + + + _Open ROM Image... + True + False + False + True + image2 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + Open Recent + True + + + + + True + False + + + + + Open with _NetPlay... + True + False + Open a ROM to use with NetPlay + False + True + image3 + False + + + + + + True + False + False + Open _MultiCart... + True + + + + + + True + False + + + + + True + False + False + _Load State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + From _File... + True + + + + + + + + + + True + False + False + _Save State + True + + + + False + + + True + False + False + Slot _0 + True + + + + + + True + False + False + Slot _1 + True + + + + + + True + False + False + Slot _2 + True + + + + + + True + False + False + Slot _3 + True + + + + + + True + False + False + Slot _4 + True + + + + + + True + False + False + Slot _5 + True + + + + + + True + False + False + Slot _6 + True + + + + + + True + False + False + Slot _7 + True + + + + + + True + False + False + Slot _8 + True + + + + + + True + False + + + + + True + False + False + To _File... + True + + + + + + + + + + True + False + + + + + Save SPC... + True + False + False + True + image4 + False + + + + + + True + False + + + + + Show ROM _Info... + True + False + False + True + image5 + False + + + + + + True + False + + + + + _Quit + True + False + False + True + image18 + False + + + - - - - - 0 - - + True - 5 - 5 - - - True - 0 - Code: + False + False + _Emulation + True + + + False + + + Run / _Continue + True + False + False + True + image6 + False + + + + + + _Pause + True + False + False + True + image7 + False + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + Load _Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image8 + False + + + + + + R_ecord Movie... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image19 + False + + + + + + _Stop Recording + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image9 + False + + + + + + _Jump to Frame... + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image10 + False + + + + + + True + False + + + + + Sy_nc Clients + True + False + False + True + image11 + False + + + + + + True + False + + + + + Reset + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + image12 + False + + + + + + Soft _Reset + True + False + False + True + image13 + False + + + + + + + + + + True + False + False + _View + True + + + + False + + + _Hide Menu + True + False + False + True + image14 + False + + + + + + True + False + False + _Status Bar + True + + + + + + True + False + + + + + _Change Size + True + False + False + True + image17 + False + + + True + False + + + True + False + False + False + Exact Pixels + True + + + + + True + False + False + _1x + True + + + + + + True + False + False + _2x + True + + + + + + True + False + False + _3x + True + + + + + + True + False + False + _4x + True + + + + + + True + False + False + _5x + True + + + + + + True + False + + + + + True + False + False + False + Correct Aspect + True + + + + + True + False + False + 1x + True + + + + + + True + False + False + 2x + True + + + + + + True + False + False + 3x + True + + + + + + True + False + False + 4x + True + + + + + + True + False + False + 5x + True + + + + + + + + + + True + False + + + + + _Fullscreen + True + False + False + True + image15 + False + + + + + + + + + + True + False + False + _Options + True + + + False + + + True + False + False + Controller Ports + True + + + False + + + True + False + False + SNES Port 1 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad1 + + + + + + True + False + False + Superscope + True + True + joypad1 + + + + + + + + + + True + False + False + SNES Port 2 + True + + + + False + + + True + False + False + Joypad + True + + + + + + True + False + False + Mouse + True + joypad2 + + + + + + True + False + False + Multitap + True + joypad2 + + + + + + True + False + False + Superscope + True + True + joypad2 + + + + + + + + + + + + + + True + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + _Cheats... + True + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + _Preferences... + True + False + False + True + image16 + False + + + - - False - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - False - 1 - - - - - True - 0 - Description: - - - False - 2 - - - - - True - True - 21 - True - - - False - 3 - - - - - gtk-add - True - True - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 4 - - - - - gtk-remove - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 5 - - - False - False - 1 - + False + True + 0 + + + + + 256 + 224 + True + True + False + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + + + + + + + + True + True 1 - - + + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + False + True + 2 + + + + + + + False + 5 + Open Multiple ROM Images (MultiCart) + center-on-parent + 320 + dialog + + + True + False + + + True + False end - - gtk-close + + gtk-cancel True True True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False True @@ -6495,20 +1994,122 @@ 0 + + + gtk-ok + True + True + True + False + True + + + False + False + 1 + + False + True end 0 + + + True + False + 5 + + + True + False + 12 + + + True + False + Slot A: + + + False + True + 0 + + + + + True + False + Select an Image for Slot A + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 12 + + + True + False + Slot B: + + + False + True + 0 + + + + + True + False + Select an Image for Slot B + + + True + True + 1 + + + + + False + True + 1 + + + + + True + True + 1 + + - button7 + button14 + button13 + False 5 Snes9x NetPlay center-on-parent @@ -6516,344 +2117,12 @@ True + False 2 - - - True - 5 - 5 - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - True - True - The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image - False - - - 0 - - - - - Browse... - True - True - True - - - - False - 1 - - - - - True - True - True - - - - True - Clear entry - gtk-clear - 1 - - - - - False - 2 - - - - - - - - - True - <b>ROM Image</b> - True - - - - - False - 0 - - - - - True - 0 - none - - - True - 5 - 12 - - - True - - - Connect to another computer - True - True - False - Connect to another computer that is running Snes9x NetPlay as a server - True - True - - - 0 - - - - - True - 5 - 5 - - - True - Name or IP address: - - - False - 0 - - - - - True - True - Domain name or internet protocol address of a remote computer - - - 1 - - - - - True - Port: - - - False - 2 - - - - - True - True - Connect to specified TCP port on remote computer - adjustment3 - True - True - - - False - 3 - - - - - 1 - - - - - Act as a server - True - True - False - Host a game on this computer as Player 1, requiring extra throughput to support multitple users - True - True - connect_radio - - - - 2 - - - - - - - - - True - <b>Server</b> - True - - - - - False - 1 - - - - - True - 0 - none - - - True - 12 - - - True - 5 - 5 - - - Sync using reset - True - True - False - Reset the game when players join instead of transferring potentially unreliable freeze states - True - - - False - 0 - - - - - Send ROM image to clients - True - True - False - Send the running game image to players instead of requiring them to have their own copies - True - - - False - 1 - - - - - True - 5 - - - True - Default port: - - - False - 0 - - - - - True - True - TCP port used as a connection point for remote clients - adjustment2 - True - True - - - False - 1 - - - - - False - 2 - - - - - True - 5 - - - True - Ask server to pause when - - - False - 0 - - - - - True - True - adjustment1 - True - True - - - False - 1 - - - - - True - frames behind - - - False - 2 - - - - - False - 3 - - - - - - - - - True - <b>Settings</b> - True - - - - - 2 - - - - - 1 - - True + False end @@ -6861,6 +2130,7 @@ True True True + False True @@ -6876,6 +2146,7 @@ True True True + False True @@ -6887,10 +2158,423 @@ False + True end 0 + + + True + False + 5 + 5 + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + True + The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image + False + False + False + True + True + + + True + True + 0 + + + + + Browse... + True + True + True + False + + + + False + True + 1 + + + + + True + True + True + False + + + + True + False + Clear entry + gtk-clear + 1 + + + + + False + True + 2 + + + + + + + + + True + False + <b>ROM Image</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + + + Connect to another computer + True + True + False + Connect to another computer that is running Snes9x NetPlay as a server + False + True + True + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + Name or IP address: + + + False + True + 0 + + + + + True + True + Domain name or internet protocol address of a remote computer + False + False + True + True + + + True + True + 1 + + + + + True + False + Port: + + + False + True + 2 + + + + + True + True + Connect to specified TCP port on remote computer + False + False + True + True + adjustment3 + True + True + + + False + True + 3 + + + + + True + True + 1 + + + + + Act as a server + True + True + False + Host a game on this computer as Player 1, requiring extra throughput to support multitple users + False + True + True + connect_radio + + + + True + True + 2 + + + + + + + + + True + False + <b>Server</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Sync using reset + True + True + False + Reset the game when players join instead of transferring potentially unreliable freeze states + False + True + + + False + True + 0 + + + + + Send ROM image to clients + True + True + False + Send the running game image to players instead of requiring them to have their own copies + False + True + + + False + True + 1 + + + + + True + False + 5 + + + True + False + Default port: + + + False + True + 0 + + + + + True + True + TCP port used as a connection point for remote clients + False + False + True + True + adjustment2 + True + True + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 5 + + + True + False + Ask server to pause when + + + False + True + 0 + + + + + True + True + False + False + True + True + adjustment1 + True + True + + + False + True + 1 + + + + + True + False + frames behind + + + False + True + 2 + + + + + False + True + 3 + + + + + + + + + True + False + <b>Settings</b> + True + + + + + True + True + 2 + + + + + True + True + 1 + + @@ -6898,92 +2582,33 @@ button10 - - 5 - Open Multiple ROM Images (MultiCart) - center-on-parent - 320 + + False + GDK_KEY_PRESS_MASK + Snes9x Preferences + center + 480 dialog + True + + - + True - - - True - 5 - - - True - 12 - - - True - Slot A: - - - False - 0 - - - - - True - Select an Image for Slot A - - - 1 - - - - - False - 0 - - - - - True - 12 - - - True - Slot B: - - - False - 0 - - - - - True - Select an Image for Slot B - - - 1 - - - - - False - 1 - - - - - 1 - - + False - + True + False end - + gtk-cancel True True - True + True + False + False True @@ -6993,12 +2618,15 @@ - - gtk-ok + + gtk-apply True True - True + True + False + False True + False @@ -7006,220 +2634,5841 @@ 1 + + + gtk-ok + True + True + True + False + False + True + + + False + False + 2 + + + + + gtk-about + True + True + True + False + True + + + + False + False + 3 + True + + False + True end 0 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + left + 0 + 1 + 0 + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + never + automatic + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + queue + none + + + True + False + 5 + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Use fullscreen on ROM open + True + True + False + Go to fullscreen mode immediately after opening a ROM + False + True + True + + + False + False + 0 + + + + + Show frame rate + True + True + False + False + True + True + + + False + False + 1 + + + + + Use overscanned height + True + True + False + Use SNES extended height. Will probably cause letterboxing + False + True + True + + + False + False + 2 + + + + + True + False + 12 + + + Change fullscreen resolution: + True + True + False + Changes the screen resolution when running Snes9x in fullscreen mode + False + True + True + + + False + False + 0 + + + + + True + False + liststore14 + + + + 0 + + + + + True + True + 1 + + + + + False + False + 3 + + + + + + + + + True + False + <b>Basic Settings</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 5 + + + Scale image to fit window + True + True + False + Scales the image so no black bars are present + False + True + True + + + False + False + 0 + + + + + True + False + 12 + + + Maintain aspect-ratio: + True + True + False + Scales the image as large as possible without distortion + False + True + True + + + False + False + 0 + + + + + True + False + liststore13 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + True + False + 5 + + + Use + True + True + False + Allows scaling and filtering to use multiple processors + False + True + True + + + False + False + 0 + + + + + True + True + False + False + True + True + adjustment17 + True + True + + + False + True + 1 + + + + + True + False + threads for filtering and scaling + + + False + True + 2 + + + + + True + True + 2 + + + + + True + False + 12 + + + True + False + High-resolution effect: + + + False + True + 0 + + + + + True + False + liststore15 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + True + False + 12 + + + True + False + 0 + Apply scaling filter: + + + False + True + 0 + + + + + True + False + liststore12 + + + + + 0 + + + + + False + True + 1 + + + + + False + False + 4 + + + + + + + + + True + False + <b>Image Adjustments</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Video preset: + + + False + True + 0 + + + + + True + False + + + Composite + True + True + True + False + + + + False + True + 0 + + + + + S-Video + True + True + True + False + + + + False + True + 1 + + + + + RGB + True + True + True + False + + + + False + True + 2 + + + + + Monochrome + True + True + True + False + + + + False + True + 3 + + + + + False + True + 1 + + + + + True + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 11 + 2 + 12 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Artifacts: + + + 6 + 7 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Sharpness: + + + 4 + 5 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Brightness: + + + 3 + 4 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Contrast: + + + 2 + 3 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Saturation: + + + 1 + 2 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Hue: + + + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment16 + False + -1 + 2 + left + + + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment15 + False + -1 + 2 + left + + + 1 + 2 + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment14 + False + -1 + 2 + left + + + 1 + 2 + 2 + 3 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment13 + False + -1 + 2 + left + + + 1 + 2 + 3 + 4 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment12 + False + -1 + 2 + left + + + 1 + 2 + 4 + 5 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment11 + False + -1 + 2 + left + + + 1 + 2 + 6 + 7 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment10 + False + -1 + 2 + left + + + 1 + 2 + 7 + 8 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment9 + False + -1 + 2 + left + + + 1 + 2 + 8 + 9 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment8 + False + -1 + 2 + left + + + 1 + 2 + 9 + 10 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + adjustment7 + False + -1 + 2 + left + + + 1 + 2 + 10 + 11 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Gamma: + + + 7 + 8 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fringing: + + + 8 + 9 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Bleed: + + + 9 + 10 + GTK_FILL + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Resolution: + + + 10 + 11 + GTK_FILL + + + + + True + False + + + 2 + 5 + 6 + + + + + True + True + 1 + + + + + Merge odd and even fields + True + True + False + False + True + + + True + True + 2 + + + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore11 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 3 + + + + + + + + + True + False + <b>NTSC Filter</b> + True + + + + + False + True + 2 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + 12 + + + True + False + 0 + Scanline intensity: + + + False + True + 0 + + + + + True + False + liststore10 + + + + 0 + + + + + False + True + 1 + + + + + + + + + True + False + <b>Scanline Filter</b> + True + + + + + False + True + 3 + + + + + True + False + 0 + none + + + True + False + 5 + 5 + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore9 + + + + + 0 + + + + + True + True + 0 + + + + + Bilinear-filter output + True + True + False + False + True + True + + + True + True + 1 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + Sync to vertical blank + True + True + False + Sync the image to the vertical retrace to stop tearing + False + True + True + + + False + False + 0 + + + + + Reduce input lag + True + True + False + Sync the program with the video output after every displayed frame to reduce input latency + False + True + + + True + True + 1 + + + + + Allow non-power-of-two textures + True + True + False + Prevents edge artifacts, but can slow performance + False + True + + + True + True + 2 + + + + + Use pixel-buffer objects + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Can be faster or slower depending on drivers + False + True + + + True + True + 3 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Different formats can yield highly different performance + 10 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Pixel-buffer format: + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + liststore8 + + + + 0 + + + + + False + True + 1 + + + + + + + True + True + 4 + + + + + True + False + 5 + + + Use GLSL shader: + True + True + False + False + 0 + True + + + False + True + 0 + + + + + True + True + • + True + False + False + True + True + + + True + True + 1 + + + + + Browse... + True + True + True + False + + + + False + True + 2 + + + + + True + True + 5 + + + + + True + True + 2 + + + + + True + False + + + Force an inverted byte-ordering + True + True + False + Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card + False + True + + + True + True + 0 + + + + + True + True + 3 + + + + + + + + + True + False + <b>Hardware Acceleration</b> + True + + + + + False + True + 4 + + + + + + + + + + + True + False + + + True + False + video-display + + + True + True + 0 + + + + + True + False + Display + True + + + False + False + 1 + + + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 12 + + + True + False + Sound driver: + + + False + False + 0 + + + + + True + False + liststore7 + + + + 0 + + + + + False + False + 1 + + + + + False + False + 0 + + + + + Synchronize with sound + True + True + False + Base emulation speed on the rate sound is output + False + True + + + False + False + 1 + + + + + Mute sound output + True + True + False + Disables output of sound + False + True + True + + + False + False + 2 + + + + + Stereo + True + True + False + Output two channels, left and right + False + True + True + + + False + False + 3 + + + + + True + False + 4 + 2 + 10 + 5 + + + True + False + 0 + Playback rate: + + + GTK_FILL + + + + + + True + False + 5 + + + True + True + False + False + True + True + adjustment6 + True + True + + + False + True + 0 + + + + + True + False + milliseconds + + + False + True + 1 + + + + + 1 + 2 + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Buffer size: + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Input rate: + + + 1 + 2 + GTK_FILL + + + + + True + True + Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option + adjustment5 + False + 0 + left + + + 1 + 2 + 1 + 2 + + + + + True + False + + + True + False + liststore6 + + + + 0 + + + + + False + False + 0 + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Video rate: + + + 2 + 3 + GTK_FILL + + + + + True + False + label + + + 1 + 2 + 2 + 3 + + + + + False + True + 4 + + + + + + + + + True + False + <b>Sound Settings</b> + True + + + + + + + + + 1 + + + + + True + False + + + True + False + audio-x-generic + + + True + True + 0 + + + + + True + False + Sound + True + + + False + False + 1 + + + + + 1 + False + + + + + True + True + automatic + automatic + + + True + False + queue + none + + + True + False + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + True + False + 10 + + + True + False + Frameskip: + + + False + False + 0 + + + + + True + False + liststore5 + + + + 0 + + + + + False + False + 1 + + + + + False + True + 0 + + + + + Block invalid VRAM access + True + True + False + False + True + + + True + True + 1 + + + + + Allow opposing dpad directions + True + True + False + Let left and right or up and down be pressed at the same time + False + True + + + True + True + 2 + + + + + + + + + True + False + <b>Accuracy</b> + True + + + + + False + True + 0 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + 5 + + + Pause emulation when switching away from Snes9x + True + True + False + False + True + + + True + True + 0 + + + + + True + False + 12 + + + True + False + The ESC key should: + + + False + True + 0 + + + + + True + False + liststore4 + + + + 0 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + + + + + True + False + <b>Window Switching</b> + True + + + + + False + True + 1 + + + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + Prevent the screensaver from activating + True + True + False + False + True + + + True + True + 0 + + + + + + + + + True + False + <b>Screensaver</b> + True + + + + + False + True + 2 + + + + + + + + + 2 + + + + + True + False + + + True + False + utilities-terminal + + + True + True + 0 + + + + + True + False + Emulation + True + + + False + False + 1 + + + + + 2 + False + + + + + True + False + 5 + + + True + False + 5 + 0 + none + + + True + False + 12 + + + True + False + 5 + + + True + False + 5 + 3 + 5 + 5 + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 1 + 2 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 2 + 3 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 3 + 4 + + + + + True + True + False + • + gtk-clear + False + False + True + True + + + + + 1 + 2 + 4 + 5 + + + + + Browse... + True + True + True + False + + + + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 1 + 2 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 2 + 3 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 3 + 4 + GTK_FILL + + + + + + Browse... + True + True + True + False + + + + 2 + 3 + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + SRAM: + + + GTK_FILL + + + + + True + False + 0 + Save states: + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Cheats: + + + 2 + 3 + GTK_FILL + + + + + True + False + 0 + Patches: + + + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Exports: + + + 4 + 5 + GTK_FILL + + + + + False + True + 0 + + + + + + + + + True + False + <b>Game Data Locations</b> + True + + + + + False + True + 0 + + + + + True + False + 0 + none + + + True + False + 5 + 12 + + + True + False + 5 + + + True + False + Save SRAM: + + + False + True + 0 + + + + + True + True + Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs + • + 5 + 1 + False + False + True + True + + + False + True + 1 + + + + + True + False + seconds after change + + + False + True + 2 + + + + + + + + + True + False + <b>Automatic Saving</b> + True + + + + + False + True + 1 + + + + + 3 + + + + + True + False + + + True + False + folder + + + True + True + 0 + + + + + True + False + Files + True + + + False + False + 1 + + + + + 3 + False + + + + + True + False + 5 + 5 + + + True + False + 5 + + + True + False + 5 + <b>Joypad:</b> + True + + + False + False + 0 + + + + + True + False + liststore3 + + + + + 0 + + + + + False + True + 1 + + + + + True + False + + + False + True + 2 + + + + + _Reset + True + True + True + False + True + + + + False + False + 3 + + + + + True + False + + + False + True + 4 + + + + + True + False + Swap with: + + + False + True + 5 + + + + + True + False + liststore2 + + + + 0 + + + + + False + True + 6 + + + + + _Swap + True + True + True + False + True + + + + False + True + 7 + + + + + False + True + 0 + + + + + Use modifier keys (CTRL, SHIFT, ALT) directly + True + True + False + Allow using modifier keys as independent keys instead of modifiers + False + True + True + + + False + False + 1 + + + + + True + True + + + + True + False + 10 + 12 + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + Up + + + GTK_FILL + + + + + + True + False + 0 + Down + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Left + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Right + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Start + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Select + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + 1 + + + + + + + True + False + Buttons + + + False + + + + + True + False + 5 + 2 + 2 + 5 + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + 5 + 6 + 2 + 10 + 5 + + + True + False + 0 + A + + + GTK_FILL + + + + + + True + False + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + <b>Sticky</b> + True + center + + + 1 + 2 + + + + + + + True + False + 0 + <b>Turbo</b> + True + center + + + + + + + + + 1 + False + + + + + True + False + Turbo / Sticky Buttons + + + 1 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + 5 + 5 + + + True + False + Set new axis bindings at: + + + False + False + 0 + + + + + True + True + Changes the amount a joystick should be tilted to register a button press + False + False + True + True + adjustment4 + 1 + True + + + False + False + 1 + + + + + True + False + percent + + + False + False + 2 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Joystick Axis Threshold</b> + True + + + + + False + True + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Center all axes on all joysticks and press Calibrate. + + + False + False + 0 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + Cali_brate + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 0 + + + + + + + + False + False + 1 + + + + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Calibration</b> + True + + + + + True + True + 1 + + + + + 2 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Joystick Options + + + 2 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + True + 3 + + + + + 4 + + + + + True + False + + + True + False + input-gaming + + + True + True + 0 + + + + + True + False + Joypads + True + + + False + False + 1 + + + + + 4 + False + + + + + True + False + 5 + 5 + + + True + False + 0 + 5 + <b>Snes9x Emulator Shortcut Keys</b> + True + + + False + False + 0 + + + + + True + False + + + False + False + 1 + + + + + True + True + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 11 + 2 + 10 + 5 + + + True + False + 0 + Soft reset + + + 9 + 10 + GTK_FILL + + + + + + True + False + 0 + Hardware reset + + + 8 + 9 + GTK_FILL + + + + + + True + False + 0 + Increase frame time + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Decrease frame time + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Increase frame rate + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Decrease frame rate + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Pause + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle turbo + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Enable turbo + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Open ROM + + + GTK_FILL + + + + + + True + False + 0 + Quit Snes9x + + + 10 + 11 + GTK_FILL + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 10 + 11 + GTK_FILL + + + + + + + + + + + True + False + Emulation + + + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 8 + 2 + 10 + 5 + + + True + False + 0 + Toggle BG layer 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle BG layer 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sprites + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + BG layering hack + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Screenshot + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle fullscreen + + + 7 + 8 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + + + + + 1 + + + + + True + False + Graphics + + + 1 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 10 + 4 + 10 + 5 + + + True + False + 0 + <b>Quick save state</b> + True + center + + + 2 + + + + + + + True + False + 0 + <b>Quick load state</b> + True + + + 2 + 4 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + + + + + + + True + False + 0 + Slot 0 + + + 1 + 2 + + + + + + + True + False + 0 + Slot 2 + + + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 8 + 9 + + + + + + + True + False + 0 + Slot 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + False + 0 + Slot 1 + + + 2 + 3 + 2 + 3 + + + + + + + True + False + 0 + Slot 2 + + + 2 + 3 + 3 + 4 + + + + + + + True + False + 0 + Slot 3 + + + 2 + 3 + 4 + 5 + + + + + + + True + False + 0 + Slot 4 + + + 2 + 3 + 5 + 6 + + + + + + + True + False + 0 + Slot 5 + + + 2 + 3 + 6 + 7 + + + + + + + True + False + 0 + Slot 6 + + + 2 + 3 + 7 + 8 + + + + + + + True + False + 0 + Slot 7 + + + 2 + 3 + 8 + 9 + + + + + + + True + False + 0 + Slot 8 + + + 2 + 3 + 9 + 10 + + + + + + + True + False + 0 + Slot 8 + + + 9 + 10 + + + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + False + False + True + True + + + 3 + 4 + 8 + 9 + GTK_FILL + + + + + + + + + 2 + + + + + True + False + Save States + + + 2 + False + + + + + True + True + never + automatic + + + True + False + queue + none + + + True + False + 10 + 9 + 2 + 10 + 5 + + + True + False + 0 + Toggle sound channel 0 + + + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 1 + + + 1 + 2 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 2 + + + 2 + 3 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 3 + + + 3 + 4 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 4 + + + 4 + 5 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 5 + + + 5 + 6 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 6 + + + 6 + 7 + GTK_FILL + + + + + + True + False + 0 + Toggle sound channel 7 + + + 7 + 8 + GTK_FILL + + + + + + True + False + 0 + Toggle all sound channels + + + 8 + 9 + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + + + + + 3 + + + + + True + False + Sound + + + 3 + False + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 6 + 2 + 10 + 5 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Seek to frame + + + 4 + 5 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Load Movie + + + 3 + 4 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Stop movie recording + + + 2 + 3 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Begin movie recording + + + 1 + 2 + GTK_FILL + + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Save SPC + + + GTK_FILL + + + + + + True + True + False + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + False + False + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + False + 0 + Swap controllers 1 & 2 + + + 5 + 6 + GTK_FILL + + + + + + True + True + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 4 + + + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Misc + + + 4 + False + + + + + True + True + 2 + + + + + True + False + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + False + 3 + + + + + 5 + + + + + True + False + + + True + False + input-keyboard + + + True + True + 0 + + + + + True + False + Shortcuts + True + + + False + False + 1 + + + + + 5 + False + + + + + + + True + True + 2 + + - button14 - button13 + cancel_button + ok_button + button1 + button8 - - True - gtk-open - 1 - - - True - gtk-network - 1 - - - True - gtk-save - 1 - - - True - gtk-dialog-info - 1 - - - True - gtk-quit - 1 - - - True - gtk-go-forward - 1 - - - True - gtk-media-pause - 1 - - - True - gtk-open - 1 - - - True - gtk-media-record - 1 - - - True - gtk-media-stop - 1 - - - True - gtk-media-next - 1 - - - True - gtk-revert-to-saved - 1 - - - True - gtk-redo - 1 - - - True - gtk-refresh - 1 - - - True - gtk-leave-fullscreen - 1 - - - True - gtk-zoom-in - 1 - - - True - gtk-fullscreen - 1 - - - True - gtk-preferences - 1 - - - 1 - 1 - 60 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 6096 - 1 - 9999 - 1 - 1 - - - 50 - 1 - 100 - 1 - 10 - - - 31990 - 31500 - 32500 - 1 - 10 - - - 2 - 2 - 256 - 1 - 1 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 1.0408340855860843e-17 - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - -1 - 1 - 0.01 - 0.10000000000000001 - - - 2 - 2 - 8 - 1 - 1 - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. @@ -7396,111 +8645,4 @@ Super NES and Super Nintendo Entertainment System are trademarks of Nintendo Co., Limited and its subsidiary companies. - - 560 - 448 - About Snes9x - normal - True - - - True - 2 - - - True - 5 - - - True - 5 - - - True - gtk-missing-image - - - - - False - 0 - - - - - True - 0 - 10 - 10 - label106 - True - center - True - - - False - 1 - - - - - True - queue - - - True - True - automatic - - - True - True - False - False - textbuffer1 - - - - - - - 2 - - - - - 0 - - - - - True - end - - - gtk-close - True - True - True - True - - - False - False - 0 - - - - - False - end - 1 - - - - - - button15 - - From 13c55b92607a3beb7d5c0f889e14a9d59d6ea43c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 18 Oct 2011 13:10:06 -0500 Subject: [PATCH 052/130] Allow switching between 3 SMP cores at compile-time. --- apu/bapu/smp/core.cpp | 19 +- apu/bapu/smp/core/opcycle_misc.cpp | 681 ++++++++--- apu/bapu/smp/core/opcycle_mov.cpp | 311 +++-- apu/bapu/smp/core/opcycle_pc.cpp | 1467 ++++++++++++++++++------ apu/bapu/smp/core/opcycle_read.cpp | 1647 ++++++++++++++++++++------- apu/bapu/smp/core/opcycle_rmw.cpp | 556 ++++++--- apu/bapu/smp/core/oppseudo_misc.cpp | 311 +++++ apu/bapu/smp/core/oppseudo_mov.cpp | 705 ++++++++++++ apu/bapu/smp/core/oppseudo_pc.cpp | 536 +++++++++ apu/bapu/smp/core/oppseudo_read.cpp | 744 ++++++++++++ apu/bapu/smp/core/oppseudo_rmw.cpp | 262 +++++ apu/bapu/smp/smp.cpp | 1 + 12 files changed, 6126 insertions(+), 1114 deletions(-) create mode 100644 apu/bapu/smp/core/oppseudo_misc.cpp create mode 100644 apu/bapu/smp/core/oppseudo_mov.cpp create mode 100644 apu/bapu/smp/core/oppseudo_pc.cpp create mode 100644 apu/bapu/smp/core/oppseudo_read.cpp create mode 100644 apu/bapu/smp/core/oppseudo_rmw.cpp diff --git a/apu/bapu/smp/core.cpp b/apu/bapu/smp/core.cpp index a7a70072..43234f6a 100644 --- a/apu/bapu/smp/core.cpp +++ b/apu/bapu/smp/core.cpp @@ -59,12 +59,25 @@ void SMP::op_step() { #define op_writestack(data) op_write(0x0100 | regs.sp--, data) #if defined(CYCLE_ACCURATE) + #if defined(PSEUDO_CYCLE) if(opcode_cycle == 0) opcode_number = op_readpc(); -// opcode_cycle++; switch(opcode_number) { + #include "core/oppseudo_misc.cpp" + #include "core/oppseudo_mov.cpp" + #include "core/oppseudo_pc.cpp" + #include "core/oppseudo_read.cpp" + #include "core/oppseudo_rmw.cpp" + } + + #else + + if(opcode_cycle == 0) { + opcode_number = op_readpc(); + opcode_cycle++; + } else switch(opcode_number) { #include "core/opcycle_misc.cpp" #include "core/opcycle_mov.cpp" #include "core/opcycle_pc.cpp" @@ -72,6 +85,7 @@ void SMP::op_step() { #include "core/opcycle_rmw.cpp" } + #endif // defined(PSEUDO_CYCLE) #else unsigned opcode = op_readpc(); @@ -98,8 +112,7 @@ void SMP::op_step() { dsp.clock += cycle_count_table[opcode]; #endif - - #endif + #endif // defined(CYCLE_ACCURATE) } const unsigned SMP::cycle_count_table[256] = { diff --git a/apu/bapu/smp/core/opcycle_misc.cpp b/apu/bapu/smp/core/opcycle_misc.cpp index d266ef92..963f9fc2 100644 --- a/apu/bapu/smp/core/opcycle_misc.cpp +++ b/apu/bapu/smp/core/opcycle_misc.cpp @@ -1,311 +1,696 @@ case 0x00: { - op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + opcode_cycle = 0; + break; + } break; } case 0xef: { - op_io(2); - regs.pc--; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } break; } case 0xff: { - op_io(2); - regs.pc--; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.pc--; + opcode_cycle = 0; + break; + } break; } case 0x9f: { - op_io(4); - regs.a = (regs.a >> 4) | (regs.a << 4); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xdf: { - op_io(2); - if(regs.p.c || (regs.a) > 0x99) { - regs.a += 0x60; - regs.p.c = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; } - if(regs.p.h || (regs.a & 15) > 0x09) { - regs.a += 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } case 0xbe: { - op_io(2); - if(!regs.p.c || (regs.a) > 0x99) { - regs.a -= 0x60; - regs.p.c = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; } - if(!regs.p.h || (regs.a & 15) > 0x09) { - regs.a -= 0x06; - } - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } case 0x60: { - op_io(); - regs.p.c = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 0; + opcode_cycle = 0; + break; + } break; } case 0x20: { - op_io(); - regs.p.p = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 0; + opcode_cycle = 0; + break; + } break; } case 0x80: { - op_io(); - regs.p.c = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.c = 1; + opcode_cycle = 0; + break; + } break; } case 0x40: { - op_io(); - regs.p.p = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.p = 1; + opcode_cycle = 0; + break; + } break; } case 0xe0: { - op_io(); - regs.p.v = 0; - regs.p.h = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.p.v = 0; + regs.p.h = 0; + opcode_cycle = 0; + break; + } break; } case 0xed: { - op_io(2); - regs.p.c = !regs.p.c; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.c = !regs.p.c; + opcode_cycle = 0; + break; + } break; } case 0xa0: { - op_io(2); - regs.p.i = 1; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 1; + opcode_cycle = 0; + break; + } break; } case 0xc0: { - op_io(2); - regs.p.i = 0; + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + regs.p.i = 0; + opcode_cycle = 0; + break; + } break; } case 0x02: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x01; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x12: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x01; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x01; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x22: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x02; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x32: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x02; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x02; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x42: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x04; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x52: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x04; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x04; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x62: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x08; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x72: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x08; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x08; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x82: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x10; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x92: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x10; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x10; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xa2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x20; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xb2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x20; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x20; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xc2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x40; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xd2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x40; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x40; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xe2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= 0x80; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= 0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xf2: { - dp = op_readpc(); - rd = op_readdp(dp); - rd &= ~0x80; - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd &= ~0x80; + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2d: { - op_io(2); - op_writestack(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x4d: { - op_io(2); - op_writestack(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.x); + opcode_cycle = 0; + break; + } break; } case 0x6d: { - op_io(2); - op_writestack(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x0d: { - op_io(2); - op_writestack(regs.p); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_writestack(regs.p); + opcode_cycle = 0; + break; + } break; } case 0xae: { - op_io(2); - regs.a = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.a = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xce: { - op_io(2); - regs.x = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.x = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xee: { - op_io(2); - regs.y = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.y = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0x8e: { - op_io(2); - regs.p = op_readstack(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + regs.p = op_readstack(); + opcode_cycle = 0; + break; + } break; } case 0xcf: { - op_io(8); - ya = regs.y * regs.a; - regs.a = ya; - regs.y = ya >> 8; - //result is set based on y (high-byte) only - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0x9e: { - op_io(11); - ya = regs.ya; - //overflow set if quotient >= 256 - regs.p.v = !!(regs.y >= regs.x); - regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); - if(regs.y < (regs.x << 1)) { - //if quotient is <= 511 (will fit into 9-bit result) - regs.a = ya / regs.x; - regs.y = ya % regs.x; - } else { - //otherwise, the quotient won't fit into regs.p.v + regs.a - //this emulates the odd behavior of the S-SMP in this case - regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); - regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_io(); + break; + case 7: + op_io(); + break; + case 8: + op_io(); + break; + case 9: + op_io(); + break; + case 10: + op_io(); + break; + case 11: + op_io(); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; } - //result is set based on a (quotient) only - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); break; } diff --git a/apu/bapu/smp/core/opcycle_mov.cpp b/apu/bapu/smp/core/opcycle_mov.cpp index fd44ad29..635c7ca5 100644 --- a/apu/bapu/smp/core/opcycle_mov.cpp +++ b/apu/bapu/smp/core/opcycle_mov.cpp @@ -1,72 +1,117 @@ case 0x7d: { - op_io(); - regs.a = regs.x; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xdd: { - op_io(); - regs.a = regs.y; - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0x5d: { - op_io(); - regs.x = regs.a; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0xfd: { - op_io(); - regs.y = regs.a; - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0x9d: { - op_io(); - regs.x = regs.sp; - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0xbd: { - op_io(); - regs.sp = regs.x; + switch(opcode_cycle++) { + case 1: + op_io(); + regs.sp = regs.x; + opcode_cycle = 0; + break; + } break; } case 0xe8: { - regs.a = op_readpc(); - regs.p.n = !!(regs.a & 0x80); - regs.p.z = (regs.a == 0); + switch(opcode_cycle++) { + case 1: + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } break; } case 0xcd: { - regs.x = op_readpc(); - regs.p.n = !!(regs.x & 0x80); - regs.p.z = (regs.x == 0); + switch(opcode_cycle++) { + case 1: + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } break; } case 0x8d: { - regs.y = op_readpc(); - regs.p.n = !!(regs.y & 0x80); - regs.p.z = (regs.y == 0); + switch(opcode_cycle++) { + case 1: + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } break; } case 0xe6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; @@ -81,12 +126,14 @@ case 0xe6: { } case 0xbf: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; case 2: regs.a = op_readdp(regs.x++); + break; + case 3: op_io(); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -97,7 +144,7 @@ case 0xbf: { } case 0xe4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -112,7 +159,7 @@ case 0xe4: { } case 0xf8: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -127,7 +174,7 @@ case 0xf8: { } case 0xeb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -142,12 +189,14 @@ case 0xeb: { } case 0xf4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.a = op_readdp(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -158,12 +207,14 @@ case 0xf4: { } case 0xf9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.x = op_readdp(sp + regs.y); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -174,12 +225,14 @@ case 0xf9: { } case 0xfb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - op_io(); break; case 2: + op_io(); + break; + case 3: regs.y = op_readdp(sp + regs.x); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -190,7 +243,7 @@ case 0xfb: { } case 0xe5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -208,12 +261,14 @@ case 0xe5: { } case 0xe9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: regs.x = op_readaddr(sp); regs.p.n = !!(regs.x & 0x80); regs.p.z = (regs.x == 0); @@ -224,12 +279,14 @@ case 0xe9: { } case 0xec: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: regs.y = op_readaddr(sp); regs.p.n = !!(regs.y & 0x80); regs.p.z = (regs.y == 0); @@ -240,13 +297,17 @@ case 0xec: { } case 0xf5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); break; case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: regs.a = op_readaddr(sp + regs.x); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -257,13 +318,17 @@ case 0xf5: { } case 0xf6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; - op_io(); break; case 2: + sp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -274,18 +339,20 @@ case 0xf6: { } case 0xe7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc() + regs.x; - op_io(); break; case 2: - sp = op_readdp(dp); + op_io(); break; case 3: - sp |= op_readdp(dp + 1) << 8; + sp = op_readdp(dp); break; case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: regs.a = op_readaddr(sp); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -296,18 +363,20 @@ case 0xe7: { } case 0xf7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); - op_io(); break; case 2: - sp = op_readdp(dp); + op_io(); break; case 3: - sp |= op_readdp(dp + 1) << 8; + sp = op_readdp(dp); break; case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: regs.a = op_readaddr(sp + regs.y); regs.p.n = !!(regs.a & 0x80); regs.p.z = (regs.a == 0); @@ -318,7 +387,7 @@ case 0xf7: { } case 0xfa: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -337,15 +406,17 @@ case 0xfa: { } case 0x8f: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: rd = op_readpc(); - dp = op_readpc(); break; case 2: - op_readdp(dp); + dp = op_readpc(); break; case 3: + op_readdp(dp); + break; + case 4: op_writedp(dp, rd); opcode_cycle = 0; break; @@ -354,7 +425,7 @@ case 0x8f: { } case 0xc6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: op_io(); break; @@ -370,10 +441,14 @@ case 0xc6: { } case 0xaf: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: - op_io(2); + op_io(); + break; case 2: + op_io(); + break; + case 3: op_writedp(regs.x++, regs.a); opcode_cycle = 0; break; @@ -382,7 +457,7 @@ case 0xaf: { } case 0xc4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -398,7 +473,7 @@ case 0xc4: { } case 0xd8: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -414,7 +489,7 @@ case 0xd8: { } case 0xcb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -430,16 +505,18 @@ case 0xcb: { } case 0xd4: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.x; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.a); opcode_cycle = 0; break; @@ -448,16 +525,18 @@ case 0xd4: { } case 0xd9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.y; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.x); opcode_cycle = 0; break; @@ -466,16 +545,18 @@ case 0xd9: { } case 0xdb: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: op_io(); dp += regs.x; break; - case 2: + case 3: op_readdp(dp); break; - case 3: + case 4: op_writedp(dp, regs.y); opcode_cycle = 0; break; @@ -484,7 +565,7 @@ case 0xdb: { } case 0xc5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -503,7 +584,7 @@ case 0xc5: { } case 0xc9: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -522,7 +603,7 @@ case 0xc9: { } case 0xcc: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -541,17 +622,21 @@ case 0xcc: { } case 0xd5: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: dp |= op_readpc() << 8; + break; + case 3: op_io(); dp += regs.x; break; - case 2: + case 4: op_readaddr(dp); break; - case 3: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -560,17 +645,21 @@ case 0xd5: { } case 0xd6: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); + break; + case 2: dp |= op_readpc() << 8; + break; + case 3: op_io(); dp += regs.y; break; - case 2: + case 4: op_readaddr(dp); break; - case 3: + case 5: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -579,22 +668,24 @@ case 0xd6: { } case 0xc7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); + break; + case 2: op_io(); sp += regs.x; break; - case 2: + case 3: dp = op_readdp(sp); break; - case 3: + case 4: dp |= op_readdp(sp + 1) << 8; break; - case 4: + case 5: op_readaddr(dp); break; - case 5: + case 6: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -603,7 +694,7 @@ case 0xc7: { } case 0xd7: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; @@ -612,13 +703,15 @@ case 0xd7: { break; case 3: dp |= op_readdp(sp + 1) << 8; + break; + case 4: op_io(); dp += regs.y; break; - case 4: + case 5: op_readaddr(dp); break; - case 5: + case 6: op_writeaddr(dp, regs.a); opcode_cycle = 0; break; @@ -627,15 +720,17 @@ case 0xd7: { } case 0xba: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); break; case 2: regs.a = op_readdp(sp); - op_io(); break; case 3: + op_io(); + break; + case 4: regs.y = op_readdp(sp + 1); regs.p.n = !!(regs.ya & 0x8000); regs.p.z = (regs.ya == 0); @@ -646,7 +741,7 @@ case 0xba: { } case 0xda: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); break; @@ -665,12 +760,14 @@ case 0xda: { } case 0xaa: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: sp = op_readpc(); - sp |= op_readpc() << 8; break; case 2: + sp |= op_readpc() << 8; + break; + case 3: bit = sp >> 13; sp &= 0x1fff; rd = op_readaddr(sp); @@ -682,20 +779,24 @@ case 0xaa: { } case 0xca: { - switch(++opcode_cycle) { + switch(opcode_cycle++) { case 1: dp = op_readpc(); - dp |= op_readpc() << 8; break; case 2: + dp |= op_readpc() << 8; + break; + case 3: bit = dp >> 13; dp &= 0x1fff; rd = op_readaddr(dp); if(regs.p.c)rd |= (1 << bit); else rd &= ~(1 << bit); + break; + case 4: op_io(); break; - case 3: + case 5: op_writeaddr(dp, rd); opcode_cycle = 0; break; diff --git a/apu/bapu/smp/core/opcycle_pc.cpp b/apu/bapu/smp/core/opcycle_pc.cpp index 022179d1..1cdda647 100644 --- a/apu/bapu/smp/core/opcycle_pc.cpp +++ b/apu/bapu/smp/core/opcycle_pc.cpp @@ -1,536 +1,1347 @@ case 0x2f: { - rd = op_readpc(); - if(0){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(0){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xf0: { - rd = op_readpc(); - if(!regs.p.z){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xd0: { - rd = op_readpc(); - if(regs.p.z){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.z){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xb0: { - rd = op_readpc(); - if(!regs.p.c){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x90: { - rd = op_readpc(); - if(regs.p.c){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.c){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x70: { - rd = op_readpc(); - if(!regs.p.v){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x50: { - rd = op_readpc(); - if(regs.p.v){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.v){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x30: { - rd = op_readpc(); - if(!regs.p.n){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(!regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x10: { - rd = op_readpc(); - if(regs.p.n){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + if(regs.p.n){ opcode_cycle = 0; break; } + break; + case 2: + op_io(); + break; + case 3: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x03: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) != 0x01){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) != 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x13: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x01) == 0x01){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x01) == 0x01){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x23: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) != 0x02){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) != 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x33: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x02) == 0x02){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x02) == 0x02){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x43: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) != 0x04){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) != 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x53: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x04) == 0x04){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x04) == 0x04){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x63: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) != 0x08){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) != 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x73: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x08) == 0x08){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x08) == 0x08){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x83: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) != 0x10){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) != 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x93: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x10) == 0x10){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x10) == 0x10){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xa3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) != 0x20){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) != 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xb3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x20) == 0x20){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x20) == 0x20){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xc3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) != 0x40){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) != 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xd3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x40) == 0x40){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x40) == 0x40){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xe3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) != 0x80){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) != 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xf3: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if((sp & 0x80) == 0x80){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if((sp & 0x80) == 0x80){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x2e: { - dp = op_readpc(); - sp = op_readdp(dp); - rd = op_readpc(); - op_io(); - if(regs.a == sp){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + rd = op_readpc(); + break; + case 4: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xde: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp + regs.x); - rd = op_readpc(); - op_io(); - if(regs.a == sp){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp + regs.x); + break; + case 4: + rd = op_readpc(); + break; + case 5: + op_io(); + if(regs.a == sp){ opcode_cycle = 0; break; } + break; + case 6: + op_io(); + break; + case 7: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x6e: { - dp = op_readpc(); - wr = op_readdp(dp); - op_writedp(dp, --wr); - rd = op_readpc(); - if(wr == 0x00){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + wr = op_readdp(dp); + break; + case 3: + op_writedp(dp, --wr); + break; + case 4: + rd = op_readpc(); + if(wr == 0x00){ opcode_cycle = 0; break; } + break; + case 5: + op_io(); + break; + case 6: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0xfe: { - rd = op_readpc(); - op_io(); - regs.y--; - op_io(); - if(regs.y == 0x00){ break; } - op_io(2); - regs.pc += (int8)rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + regs.y--; + break; + case 3: + op_io(); + if(regs.y == 0x00){ opcode_cycle = 0; break; } + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc += (int8)rd; + opcode_cycle = 0; + break; + } break; } case 0x5f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x1f: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - dp += regs.x; - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + dp += regs.x; + break; + case 4: + rd = op_readaddr(dp); + break; + case 5: + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x3f: { - rd = op_readpc(); - rd |= op_readpc() << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + rd |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x4f: { - rd = op_readpc(); - op_io(2); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = 0xff00 | rd; + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + op_io(); + break; + case 4: + op_writestack(regs.pc >> 8); + break; + case 5: + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + opcode_cycle = 0; + break; + } break; } case 0x01: { - dp = 0xffde - (0 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x11: { - dp = 0xffde - (1 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x21: { - dp = 0xffde - (2 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x31: { - dp = 0xffde - (3 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x41: { - dp = 0xffde - (4 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x51: { - dp = 0xffde - (5 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x61: { - dp = 0xffde - (6 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x71: { - dp = 0xffde - (7 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x81: { - dp = 0xffde - (8 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x91: { - dp = 0xffde - (9 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xa1: { - dp = 0xffde - (10 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xb1: { - dp = 0xffde - (11 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xc1: { - dp = 0xffde - (12 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xd1: { - dp = 0xffde - (13 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xe1: { - dp = 0xffde - (14 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0xf1: { - dp = 0xffde - (15 << 1); - rd = op_readaddr(dp); - rd |= op_readaddr(dp + 1) << 8; - op_io(3); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + break; + case 2: + rd |= op_readaddr(dp + 1) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_io(); + break; + case 6: + op_writestack(regs.pc >> 8); + break; + case 7: + op_writestack(regs.pc); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x0f: { - rd = op_readaddr(0xffde); - rd |= op_readaddr(0xffdf) << 8; - op_io(2); - op_writestack(regs.pc >> 8); - op_writestack(regs.pc); - op_writestack(regs.p); - regs.pc = rd; - regs.p.b = 1; - regs.p.i = 0; + switch(opcode_cycle++) { + case 1: + rd = op_readaddr(0xffde); + break; + case 2: + rd |= op_readaddr(0xffdf) << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + break; + case 5: + op_writestack(regs.pc >> 8); + break; + case 6: + op_writestack(regs.pc); + break; + case 7: + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + opcode_cycle = 0; + break; + } break; } case 0x6f: { - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(2); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + rd = op_readstack(); + break; + case 2: + rd |= op_readstack() << 8; + break; + case 3: + op_io(); + break; + case 4: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } case 0x7f: { - regs.p = op_readstack(); - rd = op_readstack(); - rd |= op_readstack() << 8; - op_io(2); - regs.pc = rd; + switch(opcode_cycle++) { + case 1: + regs.p = op_readstack(); + break; + case 2: + rd = op_readstack(); + break; + case 3: + rd |= op_readstack() << 8; + break; + case 4: + op_io(); + break; + case 5: + op_io(); + regs.pc = rd; + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/opcycle_read.cpp b/apu/bapu/smp/core/opcycle_read.cpp index 2a16a3c8..6c19f3a9 100644 --- a/apu/bapu/smp/core/opcycle_read.cpp +++ b/apu/bapu/smp/core/opcycle_read.cpp @@ -1,744 +1,1599 @@ case 0x88: { - rd = op_readpc(); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x28: { - rd = op_readpc(); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x68: { - rd = op_readpc(); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xc8: { - rd = op_readpc(); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0xad: { - rd = op_readpc(); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x48: { - rd = op_readpc(); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x08: { - rd = op_readpc(); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa8: { - rd = op_readpc(); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x86: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x26: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x66: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x46: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x06: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa6: { - op_io(); - rd = op_readdp(regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x84: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x24: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x64: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x3e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x7e: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x44: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x04: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa4: { - dp = op_readpc(); - rd = op_readdp(dp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x94: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x34: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x74: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x54: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x14: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb4: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x85: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x25: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x65: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x1e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.x = op_cmp(regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x5e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.y = op_cmp(regs.y, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + opcode_cycle = 0; + break; + } break; } case 0x45: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x05: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x95: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x96: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x35: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x36: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x75: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x76: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x55: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x56: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x15: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x16: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb5: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.x); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb6: { - dp = op_readpc(); - dp |= op_readpc() << 8; - op_io(); - rd = op_readaddr(dp + regs.y); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_io(); + break; + case 4: + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x87: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x27: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x67: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x47: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x07: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xa7: { - dp = op_readpc() + regs.x; - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc() + regs.x; + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x97: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_adc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x37: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_and(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x77: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_cmp(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x57: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_eor(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x17: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_or(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0xb7: { - dp = op_readpc(); - op_io(); - sp = op_readdp(dp); - sp |= op_readdp(dp + 1) << 8; - rd = op_readaddr(sp + regs.y); - regs.a = op_sbc(regs.a, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + sp = op_readdp(dp); + break; + case 4: + sp |= op_readdp(dp + 1) << 8; + break; + case 5: + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + opcode_cycle = 0; + break; + } break; } case 0x99: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_adc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x39: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_and(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x79: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_cmp(wr, rd); - (0) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + break; + case 4: + (0) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x59: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_eor(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x19: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_or(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xb9: { - op_io(); - rd = op_readdp(regs.y); - wr = op_readdp(regs.x); - wr = op_sbc(wr, rd); - (1) ? op_writedp(regs.x, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + op_io(); + break; + case 2: + rd = op_readdp(regs.y); + break; + case 3: + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + break; + case 4: + (1) ? op_writedp(regs.x, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x89: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x29: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x69: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x49: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x09: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xa9: { - sp = op_readpc(); - rd = op_readdp(sp); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + wr = op_readdp(dp); + break; + case 5: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x98: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_adc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x38: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_and(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x78: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_cmp(wr, rd); - (0) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x58: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_eor(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x18: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_or(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0xb8: { - rd = op_readpc(); - dp = op_readpc(); - wr = op_readdp(dp); - wr = op_sbc(wr, rd); - (1) ? op_writedp(dp, wr) : op_io(); + switch(opcode_cycle++) { + case 1: + rd = op_readpc(); + break; + case 2: + dp = op_readpc(); + break; + case 3: + wr = op_readdp(dp); + break; + case 4: + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + opcode_cycle = 0; + break; + } break; } case 0x7a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_addw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x9a: { - dp = op_readpc(); - rd = op_readdp(dp); - op_io(); - rd |= op_readdp(dp + 1) << 8; - regs.ya = op_subw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + op_io(); + break; + case 4: + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x5a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd |= op_readdp(dp + 1) << 8; - op_cmpw(regs.ya, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + opcode_cycle = 0; + break; + } break; } case 0x4a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x6a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - regs.p.c = regs.p.c & !(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x8a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0xea: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - rd ^= (1 << bit); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + break; + case 4: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !!(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } case 0x2a: { - dp = op_readpc(); - dp |= op_readpc() << 8; - bit = dp >> 13; - dp &= 0x1fff; - rd = op_readaddr(dp); - op_io(); - regs.p.c = regs.p.c | !(rd & (1 << bit)); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + break; + case 4: + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/opcycle_rmw.cpp b/apu/bapu/smp/core/opcycle_rmw.cpp index 9b0dd2fb..eca62f02 100644 --- a/apu/bapu/smp/core/opcycle_rmw.cpp +++ b/apu/bapu/smp/core/opcycle_rmw.cpp @@ -1,262 +1,550 @@ case 0xbc: { - op_io(); - regs.a = op_inc(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_inc(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3d: { - op_io(); - regs.x = op_inc(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_inc(regs.x); + opcode_cycle = 0; + break; + } break; } case 0xfc: { - op_io(); - regs.y = op_inc(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_inc(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x9c: { - op_io(); - regs.a = op_dec(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_dec(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x1d: { - op_io(); - regs.x = op_dec(regs.x); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.x = op_dec(regs.x); + opcode_cycle = 0; + break; + } break; } case 0xdc: { - op_io(); - regs.y = op_dec(regs.y); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.y = op_dec(regs.y); + opcode_cycle = 0; + break; + } break; } case 0x1c: { - op_io(); - regs.a = op_asl(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_asl(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x5c: { - op_io(); - regs.a = op_lsr(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_lsr(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3c: { - op_io(); - regs.a = op_rol(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_rol(regs.a); + opcode_cycle = 0; + break; + } break; } case 0x7c: { - op_io(); - regs.a = op_ror(regs.a); + switch(opcode_cycle++) { + case 1: + op_io(); + regs.a = op_ror(regs.a); + opcode_cycle = 0; break; + } + break; } case 0xab: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_inc(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_inc(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x8b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_dec(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_dec(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_asl(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_asl(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x4b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_lsr(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_lsr(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_rol(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_rol(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x6b: { - dp = op_readpc(); - rd = op_readdp(dp); - rd = op_ror(rd); - op_writedp(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + break; + case 3: + rd = op_ror(rd); + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0xbb: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_inc(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x9b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_dec(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x1b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_asl(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x5b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_lsr(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x3b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_rol(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0x7b: { - dp = op_readpc(); - op_io(); - rd = op_readdp(dp + regs.x); - rd = op_ror(rd); - op_writedp(dp + regs.x, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + op_io(); + break; + case 3: + rd = op_readdp(dp + regs.x); + break; + case 4: + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + opcode_cycle = 0; + break; + } break; } case 0xac: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_inc(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_inc(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x8c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_dec(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_dec(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_asl(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_asl(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x4c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_lsr(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_lsr(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x2c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_rol(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_rol(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x6c: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - rd = op_ror(rd); - op_writeaddr(dp, rd); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + break; + case 4: + rd = op_ror(rd); + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } break; } case 0x0e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd | regs.a); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd | regs.a); + opcode_cycle = 0; + break; + } break; } case 0x4e: { - dp = op_readpc(); - dp |= op_readpc() << 8; - rd = op_readaddr(dp); - regs.p.n = !!((regs.a - rd) & 0x80); - regs.p.z = ((regs.a - rd) == 0); - op_readaddr(dp); - op_writeaddr(dp, rd &~ regs.a); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, rd &~ regs.a); + opcode_cycle = 0; + break; + } break; } case 0x3a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd++; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd++; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } break; } case 0x1a: { - dp = op_readpc(); - rd = op_readdp(dp); - rd--; - op_writedp(dp++, rd); - rd += op_readdp(dp) << 8; - op_writedp(dp, rd >> 8); - regs.p.n = !!(rd & 0x8000); - regs.p.z = (rd == 0); + switch(opcode_cycle++) { + case 1: + dp = op_readpc(); + break; + case 2: + rd = op_readdp(dp); + rd--; + break; + case 3: + op_writedp(dp++, rd); + break; + case 4: + rd += op_readdp(dp) << 8; + break; + case 5: + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + opcode_cycle = 0; + break; + } break; } diff --git a/apu/bapu/smp/core/oppseudo_misc.cpp b/apu/bapu/smp/core/oppseudo_misc.cpp new file mode 100644 index 00000000..d266ef92 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_misc.cpp @@ -0,0 +1,311 @@ +case 0x00: { + op_io(); + break; +} + +case 0xef: { + op_io(2); + regs.pc--; + break; +} + +case 0xff: { + op_io(2); + regs.pc--; + break; +} + +case 0x9f: { + op_io(4); + regs.a = (regs.a >> 4) | (regs.a << 4); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdf: { + op_io(2); + if(regs.p.c || (regs.a) > 0x99) { + regs.a += 0x60; + regs.p.c = 1; + } + if(regs.p.h || (regs.a & 15) > 0x09) { + regs.a += 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xbe: { + op_io(2); + if(!regs.p.c || (regs.a) > 0x99) { + regs.a -= 0x60; + regs.p.c = 0; + } + if(!regs.p.h || (regs.a & 15) > 0x09) { + regs.a -= 0x06; + } + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x60: { + op_io(); + regs.p.c = 0; + break; +} + +case 0x20: { + op_io(); + regs.p.p = 0; + break; +} + +case 0x80: { + op_io(); + regs.p.c = 1; + break; +} + +case 0x40: { + op_io(); + regs.p.p = 1; + break; +} + +case 0xe0: { + op_io(); + regs.p.v = 0; + regs.p.h = 0; + break; +} + +case 0xed: { + op_io(2); + regs.p.c = !regs.p.c; + break; +} + +case 0xa0: { + op_io(2); + regs.p.i = 1; + break; +} + +case 0xc0: { + op_io(2); + regs.p.i = 0; + break; +} + +case 0x02: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x01; + op_writedp(dp, rd); + break; +} + +case 0x12: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x01; + op_writedp(dp, rd); + break; +} + +case 0x22: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x02; + op_writedp(dp, rd); + break; +} + +case 0x32: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x02; + op_writedp(dp, rd); + break; +} + +case 0x42: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x04; + op_writedp(dp, rd); + break; +} + +case 0x52: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x04; + op_writedp(dp, rd); + break; +} + +case 0x62: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x08; + op_writedp(dp, rd); + break; +} + +case 0x72: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x08; + op_writedp(dp, rd); + break; +} + +case 0x82: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x10; + op_writedp(dp, rd); + break; +} + +case 0x92: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x10; + op_writedp(dp, rd); + break; +} + +case 0xa2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x20; + op_writedp(dp, rd); + break; +} + +case 0xb2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x20; + op_writedp(dp, rd); + break; +} + +case 0xc2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x40; + op_writedp(dp, rd); + break; +} + +case 0xd2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x40; + op_writedp(dp, rd); + break; +} + +case 0xe2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= 0x80; + op_writedp(dp, rd); + break; +} + +case 0xf2: { + dp = op_readpc(); + rd = op_readdp(dp); + rd &= ~0x80; + op_writedp(dp, rd); + break; +} + +case 0x2d: { + op_io(2); + op_writestack(regs.a); + break; +} + +case 0x4d: { + op_io(2); + op_writestack(regs.x); + break; +} + +case 0x6d: { + op_io(2); + op_writestack(regs.y); + break; +} + +case 0x0d: { + op_io(2); + op_writestack(regs.p); + break; +} + +case 0xae: { + op_io(2); + regs.a = op_readstack(); + break; +} + +case 0xce: { + op_io(2); + regs.x = op_readstack(); + break; +} + +case 0xee: { + op_io(2); + regs.y = op_readstack(); + break; +} + +case 0x8e: { + op_io(2); + regs.p = op_readstack(); + break; +} + +case 0xcf: { + op_io(8); + ya = regs.y * regs.a; + regs.a = ya; + regs.y = ya >> 8; + //result is set based on y (high-byte) only + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9e: { + op_io(11); + ya = regs.ya; + //overflow set if quotient >= 256 + regs.p.v = !!(regs.y >= regs.x); + regs.p.h = !!((regs.y & 15) >= (regs.x & 15)); + if(regs.y < (regs.x << 1)) { + //if quotient is <= 511 (will fit into 9-bit result) + regs.a = ya / regs.x; + regs.y = ya % regs.x; + } else { + //otherwise, the quotient won't fit into regs.p.v + regs.a + //this emulates the odd behavior of the S-SMP in this case + regs.a = 255 - (ya - (regs.x << 9)) / (256 - regs.x); + regs.y = regs.x + (ya - (regs.x << 9)) % (256 - regs.x); + } + //result is set based on a (quotient) only + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_mov.cpp b/apu/bapu/smp/core/oppseudo_mov.cpp new file mode 100644 index 00000000..fd44ad29 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_mov.cpp @@ -0,0 +1,705 @@ +case 0x7d: { + op_io(); + regs.a = regs.x; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xdd: { + op_io(); + regs.a = regs.y; + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0x5d: { + op_io(); + regs.x = regs.a; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xfd: { + op_io(); + regs.y = regs.a; + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0x9d: { + op_io(); + regs.x = regs.sp; + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0xbd: { + op_io(); + regs.sp = regs.x; + break; +} + +case 0xe8: { + regs.a = op_readpc(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + break; +} + +case 0xcd: { + regs.x = op_readpc(); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + break; +} + +case 0x8d: { + regs.y = op_readpc(); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + break; +} + +case 0xe6: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xbf: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + regs.a = op_readdp(regs.x++); + op_io(); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe4: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf8: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.x = op_readdp(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xeb: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.y = op_readdp(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf4: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.a = op_readdp(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf9: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.x = op_readdp(sp + regs.y); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfb: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + break; + case 2: + regs.y = op_readdp(sp + regs.x); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe5: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + sp |= op_readpc() << 8; + break; + case 3: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe9: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + regs.x = op_readaddr(sp); + regs.p.n = !!(regs.x & 0x80); + regs.p.z = (regs.x == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xec: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + regs.y = op_readaddr(sp); + regs.p.n = !!(regs.y & 0x80); + regs.p.z = (regs.y == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf5: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + break; + case 2: + regs.a = op_readaddr(sp + regs.x); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf6: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + op_io(); + break; + case 2: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xe7: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc() + regs.x; + op_io(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + sp |= op_readdp(dp + 1) << 8; + break; + case 4: + regs.a = op_readaddr(sp); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xf7: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + break; + case 2: + sp = op_readdp(dp); + break; + case 3: + sp |= op_readdp(dp + 1) << 8; + break; + case 4: + regs.a = op_readaddr(sp + regs.y); + regs.p.n = !!(regs.a & 0x80); + regs.p.z = (regs.a == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xfa: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + rd = op_readdp(sp); + break; + case 3: + dp = op_readpc(); + break; + case 4: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0x8f: { + switch(++opcode_cycle) { + case 1: + rd = op_readpc(); + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc6: { + switch(++opcode_cycle) { + case 1: + op_io(); + break; + case 2: + op_readdp(regs.x); + break; + case 3: + op_writedp(regs.x, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaf: { + switch(++opcode_cycle) { + case 1: + op_io(2); + case 2: + op_writedp(regs.x++, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc4: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd8: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcb: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd4: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.x; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd9: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.y; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xdb: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + op_io(); + dp += regs.x; + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc5: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc9: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.x); + opcode_cycle = 0; + break; + } + break; +} + +case 0xcc: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + dp |= op_readpc() << 8; + break; + case 3: + op_readaddr(dp); + break; + case 4: + op_writeaddr(dp, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd5: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + break; + case 2: + op_readaddr(dp); + break; + case 3: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd6: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.y; + break; + case 2: + op_readaddr(dp); + break; + case 3: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xc7: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + op_io(); + sp += regs.x; + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xd7: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + dp = op_readdp(sp); + break; + case 3: + dp |= op_readdp(sp + 1) << 8; + op_io(); + dp += regs.y; + break; + case 4: + op_readaddr(dp); + break; + case 5: + op_writeaddr(dp, regs.a); + opcode_cycle = 0; + break; + } + break; +} + +case 0xba: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + break; + case 2: + regs.a = op_readdp(sp); + op_io(); + break; + case 3: + regs.y = op_readdp(sp + 1); + regs.p.n = !!(regs.ya & 0x8000); + regs.p.z = (regs.ya == 0); + opcode_cycle = 0; + break; + } + break; +} + +case 0xda: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + break; + case 2: + op_readdp(dp); + break; + case 3: + op_writedp(dp, regs.a); + break; + case 4: + op_writedp(dp + 1, regs.y); + opcode_cycle = 0; + break; + } + break; +} + +case 0xaa: { + switch(++opcode_cycle) { + case 1: + sp = op_readpc(); + sp |= op_readpc() << 8; + break; + case 2: + bit = sp >> 13; + sp &= 0x1fff; + rd = op_readaddr(sp); + regs.p.c = !!(rd & (1 << bit)); + opcode_cycle = 0; + break; + } + break; +} + +case 0xca: { + switch(++opcode_cycle) { + case 1: + dp = op_readpc(); + dp |= op_readpc() << 8; + break; + case 2: + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + if(regs.p.c)rd |= (1 << bit); + else rd &= ~(1 << bit); + op_io(); + break; + case 3: + op_writeaddr(dp, rd); + opcode_cycle = 0; + break; + } + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_pc.cpp b/apu/bapu/smp/core/oppseudo_pc.cpp new file mode 100644 index 00000000..022179d1 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_pc.cpp @@ -0,0 +1,536 @@ +case 0x2f: { + rd = op_readpc(); + if(0){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xf0: { + rd = op_readpc(); + if(!regs.p.z){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xd0: { + rd = op_readpc(); + if(regs.p.z){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xb0: { + rd = op_readpc(); + if(!regs.p.c){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x90: { + rd = op_readpc(); + if(regs.p.c){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x70: { + rd = op_readpc(); + if(!regs.p.v){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x50: { + rd = op_readpc(); + if(regs.p.v){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x30: { + rd = op_readpc(); + if(!regs.p.n){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x10: { + rd = op_readpc(); + if(regs.p.n){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x03: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) != 0x01){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x13: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x01) == 0x01){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x23: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) != 0x02){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x33: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x02) == 0x02){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x43: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) != 0x04){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x53: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x04) == 0x04){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x63: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) != 0x08){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x73: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x08) == 0x08){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x83: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) != 0x10){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x93: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x10) == 0x10){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xa3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) != 0x20){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xb3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x20) == 0x20){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xc3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) != 0x40){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xd3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x40) == 0x40){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xe3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) != 0x80){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xf3: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if((sp & 0x80) == 0x80){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x2e: { + dp = op_readpc(); + sp = op_readdp(dp); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xde: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp + regs.x); + rd = op_readpc(); + op_io(); + if(regs.a == sp){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x6e: { + dp = op_readpc(); + wr = op_readdp(dp); + op_writedp(dp, --wr); + rd = op_readpc(); + if(wr == 0x00){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0xfe: { + rd = op_readpc(); + op_io(); + regs.y--; + op_io(); + if(regs.y == 0x00){ break; } + op_io(2); + regs.pc += (int8)rd; + break; +} + +case 0x5f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + regs.pc = rd; + break; +} + +case 0x1f: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + dp += regs.x; + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + regs.pc = rd; + break; +} + +case 0x3f: { + rd = op_readpc(); + rd |= op_readpc() << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x4f: { + rd = op_readpc(); + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = 0xff00 | rd; + break; +} + +case 0x01: { + dp = 0xffde - (0 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x11: { + dp = 0xffde - (1 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x21: { + dp = 0xffde - (2 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x31: { + dp = 0xffde - (3 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x41: { + dp = 0xffde - (4 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x51: { + dp = 0xffde - (5 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x61: { + dp = 0xffde - (6 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x71: { + dp = 0xffde - (7 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x81: { + dp = 0xffde - (8 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x91: { + dp = 0xffde - (9 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xa1: { + dp = 0xffde - (10 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xb1: { + dp = 0xffde - (11 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xc1: { + dp = 0xffde - (12 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xd1: { + dp = 0xffde - (13 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xe1: { + dp = 0xffde - (14 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0xf1: { + dp = 0xffde - (15 << 1); + rd = op_readaddr(dp); + rd |= op_readaddr(dp + 1) << 8; + op_io(3); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + regs.pc = rd; + break; +} + +case 0x0f: { + rd = op_readaddr(0xffde); + rd |= op_readaddr(0xffdf) << 8; + op_io(2); + op_writestack(regs.pc >> 8); + op_writestack(regs.pc); + op_writestack(regs.p); + regs.pc = rd; + regs.p.b = 1; + regs.p.i = 0; + break; +} + +case 0x6f: { + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + break; +} + +case 0x7f: { + regs.p = op_readstack(); + rd = op_readstack(); + rd |= op_readstack() << 8; + op_io(2); + regs.pc = rd; + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_read.cpp b/apu/bapu/smp/core/oppseudo_read.cpp new file mode 100644 index 00000000..2a16a3c8 --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_read.cpp @@ -0,0 +1,744 @@ +case 0x88: { + rd = op_readpc(); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x28: { + rd = op_readpc(); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x68: { + rd = op_readpc(); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0xc8: { + rd = op_readpc(); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0xad: { + rd = op_readpc(); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x48: { + rd = op_readpc(); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x08: { + rd = op_readpc(); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa8: { + rd = op_readpc(); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x86: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x26: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x66: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x46: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x06: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa6: { + op_io(); + rd = op_readdp(regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x84: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x24: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x64: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x3e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x7e: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x44: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x04: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa4: { + dp = op_readpc(); + rd = op_readdp(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x94: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x34: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x74: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x54: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x14: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb4: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x85: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x25: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x65: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x1e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.x = op_cmp(regs.x, rd); + break; +} + +case 0x5e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.y = op_cmp(regs.y, rd); + break; +} + +case 0x45: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x05: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x95: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x96: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x35: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x36: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x75: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x76: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x55: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x56: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x15: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_or(regs.a, rd); + break; +} + +case 0x16: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb5: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.x); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0xb6: { + dp = op_readpc(); + dp |= op_readpc() << 8; + op_io(); + rd = op_readaddr(dp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x87: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x27: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x67: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x47: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x07: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xa7: { + dp = op_readpc() + regs.x; + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x97: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_adc(regs.a, rd); + break; +} + +case 0x37: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_and(regs.a, rd); + break; +} + +case 0x77: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_cmp(regs.a, rd); + break; +} + +case 0x57: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_eor(regs.a, rd); + break; +} + +case 0x17: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_or(regs.a, rd); + break; +} + +case 0xb7: { + dp = op_readpc(); + op_io(); + sp = op_readdp(dp); + sp |= op_readdp(dp + 1) << 8; + rd = op_readaddr(sp + regs.y); + regs.a = op_sbc(regs.a, rd); + break; +} + +case 0x99: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_adc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x39: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_and(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x79: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_cmp(wr, rd); + (0) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x59: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_eor(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x19: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_or(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0xb9: { + op_io(); + rd = op_readdp(regs.y); + wr = op_readdp(regs.x); + wr = op_sbc(wr, rd); + (1) ? op_writedp(regs.x, wr) : op_io(); + break; +} + +case 0x89: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x29: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x69: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x49: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x09: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xa9: { + sp = op_readpc(); + rd = op_readdp(sp); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x98: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_adc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x38: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_and(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x78: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_cmp(wr, rd); + (0) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x58: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_eor(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x18: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_or(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0xb8: { + rd = op_readpc(); + dp = op_readpc(); + wr = op_readdp(dp); + wr = op_sbc(wr, rd); + (1) ? op_writedp(dp, wr) : op_io(); + break; +} + +case 0x7a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_addw(regs.ya, rd); + break; +} + +case 0x9a: { + dp = op_readpc(); + rd = op_readdp(dp); + op_io(); + rd |= op_readdp(dp + 1) << 8; + regs.ya = op_subw(regs.ya, rd); + break; +} + +case 0x5a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd |= op_readdp(dp + 1) << 8; + op_cmpw(regs.ya, rd); + break; +} + +case 0x4a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !!(rd & (1 << bit)); + break; +} + +case 0x6a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + regs.p.c = regs.p.c & !(rd & (1 << bit)); + break; +} + +case 0x8a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c ^ !!(rd & (1 << bit)); + break; +} + +case 0xea: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + rd ^= (1 << bit); + op_writeaddr(dp, rd); + break; +} + +case 0x0a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !!(rd & (1 << bit)); + break; +} + +case 0x2a: { + dp = op_readpc(); + dp |= op_readpc() << 8; + bit = dp >> 13; + dp &= 0x1fff; + rd = op_readaddr(dp); + op_io(); + regs.p.c = regs.p.c | !(rd & (1 << bit)); + break; +} + diff --git a/apu/bapu/smp/core/oppseudo_rmw.cpp b/apu/bapu/smp/core/oppseudo_rmw.cpp new file mode 100644 index 00000000..9b0dd2fb --- /dev/null +++ b/apu/bapu/smp/core/oppseudo_rmw.cpp @@ -0,0 +1,262 @@ +case 0xbc: { + op_io(); + regs.a = op_inc(regs.a); + break; +} + +case 0x3d: { + op_io(); + regs.x = op_inc(regs.x); + break; +} + +case 0xfc: { + op_io(); + regs.y = op_inc(regs.y); + break; +} + +case 0x9c: { + op_io(); + regs.a = op_dec(regs.a); + break; +} + +case 0x1d: { + op_io(); + regs.x = op_dec(regs.x); + break; +} + +case 0xdc: { + op_io(); + regs.y = op_dec(regs.y); + break; +} + +case 0x1c: { + op_io(); + regs.a = op_asl(regs.a); + break; +} + +case 0x5c: { + op_io(); + regs.a = op_lsr(regs.a); + break; +} + +case 0x3c: { + op_io(); + regs.a = op_rol(regs.a); + break; +} + +case 0x7c: { + op_io(); + regs.a = op_ror(regs.a); + break; +} + +case 0xab: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_inc(rd); + op_writedp(dp, rd); + break; +} + +case 0x8b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_dec(rd); + op_writedp(dp, rd); + break; +} + +case 0x0b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_asl(rd); + op_writedp(dp, rd); + break; +} + +case 0x4b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_lsr(rd); + op_writedp(dp, rd); + break; +} + +case 0x2b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_rol(rd); + op_writedp(dp, rd); + break; +} + +case 0x6b: { + dp = op_readpc(); + rd = op_readdp(dp); + rd = op_ror(rd); + op_writedp(dp, rd); + break; +} + +case 0xbb: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_inc(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x9b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_dec(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x1b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_asl(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x5b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_lsr(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x3b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_rol(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0x7b: { + dp = op_readpc(); + op_io(); + rd = op_readdp(dp + regs.x); + rd = op_ror(rd); + op_writedp(dp + regs.x, rd); + break; +} + +case 0xac: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_inc(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x8c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_dec(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_asl(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x4c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_lsr(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x2c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_rol(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x6c: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + rd = op_ror(rd); + op_writeaddr(dp, rd); + break; +} + +case 0x0e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd | regs.a); + break; +} + +case 0x4e: { + dp = op_readpc(); + dp |= op_readpc() << 8; + rd = op_readaddr(dp); + regs.p.n = !!((regs.a - rd) & 0x80); + regs.p.z = ((regs.a - rd) == 0); + op_readaddr(dp); + op_writeaddr(dp, rd &~ regs.a); + break; +} + +case 0x3a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd++; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + +case 0x1a: { + dp = op_readpc(); + rd = op_readdp(dp); + rd--; + op_writedp(dp++, rd); + rd += op_readdp(dp) << 8; + op_writedp(dp, rd >> 8); + regs.p.n = !!(rd & 0x8000); + regs.p.z = (rd == 0); + break; +} + diff --git a/apu/bapu/smp/smp.cpp b/apu/bapu/smp/smp.cpp index a8092fcb..1a20b7ae 100644 --- a/apu/bapu/smp/smp.cpp +++ b/apu/bapu/smp/smp.cpp @@ -1,4 +1,5 @@ #define CYCLE_ACCURATE +#define PSEUDO_CYCLE #include From fe6b9f257f9474545bffd098a6dede5c0f40d5cc Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 15 Sep 2011 20:03:34 +0200 Subject: [PATCH 053/130] Win32: remove legacy snapshot extensions --- win32/wsnes9x.cpp | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index aa8252cb..88d5deda 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -3501,10 +3501,7 @@ loop_exit: void FreezeUnfreeze (int slot, bool8 freeze) { - static char filename [_MAX_PATH + 1]; - char drive [_MAX_DRIVE + 1]; - char dir [_MAX_DIR + 1]; - char fname [_MAX_FNAME + 1]; + const char *filename; char ext [_MAX_EXT + 1]; #ifdef NETPLAY_SUPPORT @@ -3516,30 +3513,8 @@ void FreezeUnfreeze (int slot, bool8 freeze) } #endif - _splitpath (Memory.ROMFilename, drive, dir, fname, ext); - static char *digits = "t123456789"; - for(int oldDir = 0; oldDir <= 1; oldDir++) - { - for(int zmv = 0; zmv <= 1; zmv++) - { - if((!oldDir && !zmv) || (!freeze && _taccess (_tFromChar(filename), 0) != 0 && slot < 10)) - { - if(!zmv) - sprintf (ext, ".%03d", slot); - else - sprintf (ext, ".zs%c", digits [slot]); - if (GUI.FreezeFileDir [0]) - { - strcpy (filename, oldDir ? S9xGetDirectory(ROMFILENAME_DIR) : S9xGetDirectory(SNAPSHOT_DIR)); - strcat (filename, "\\"); - strcat (filename, fname); - strcat (filename, ext); - } - else - _makepath (filename, drive, dir, fname, ext); - } - } - } + snprintf(ext, _MAX_EXT, ".%03d", slot); + filename = S9xGetFilename(ext,SNAPSHOT_DIR); S9xSetPause (PAUSE_FREEZE_FILE); From 2c3230a8da08f6b689a4a96cfaa19698ba0b84d3 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 23 Oct 2011 23:29:10 +0200 Subject: [PATCH 054/130] Rework mid-frame interlace handling (ASP briefing screen) --- gfx.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/gfx.cpp b/gfx.cpp index 0937852e..af5a2d08 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -709,7 +709,7 @@ void S9xUpdateScreen (void) IPPU.RenderedScreenWidth = 512; } - if (!IPPU.DoubleHeightPixels && IPPU.Interlace) + if (!IPPU.DoubleHeightPixels && IPPU.Interlace && (PPU.BGMode == 5 || PPU.BGMode == 6)) { IPPU.DoubleHeightPixels = TRUE; IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; @@ -719,16 +719,6 @@ void S9xUpdateScreen (void) for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) memmove(GFX.Screen + y * GFX.PPL, GFX.Screen + y * GFX.RealPPL, IPPU.RenderedScreenWidth * sizeof(uint16)); } - else if (IPPU.DoubleHeightPixels && !IPPU.Interlace) - { - for (register int32 y = 0; y < (int32) GFX.StartY; y++) - memmove(GFX.Screen + y * GFX.RealPPL, GFX.Screen + y * GFX.PPL, IPPU.RenderedScreenWidth * sizeof(uint16)); - - IPPU.DoubleHeightPixels = FALSE; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - GFX.PPL = GFX.RealPPL; - GFX.DoInterlace = 0; - } } if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f)) From c188725ee40cb2ce8c14ff214043ae50df6b261a Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 31 Oct 2011 22:36:17 +0100 Subject: [PATCH 055/130] Fix crash when drawing crosshair on screen edges (remove old workaround) --- gfx.cpp | 56 +++++++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/gfx.cpp b/gfx.cpp index af5a2d08..305a1e57 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -2242,43 +2242,37 @@ void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int1 fg = get_crosshair_color(fgcolor); bg = get_crosshair_color(bgcolor); - // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... -#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) - if (x >= 0 && y >= 0) -#endif + uint16 *s = GFX.Screen + y * (int32)GFX.RealPPL + x; + + for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx) { - uint16 *s = GFX.Screen + y * GFX.RealPPL + x; - - for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx) + if (y + r < 0) { - if (y + r < 0) - { - s += 15 * cx; + s += 15 * cx; + continue; + } + + if (y + r >= H) + break; + + for (c = 0; c < 15 * cx; c++, s++) + { + if (x + c < 0 || s < GFX.Screen) continue; - } - if (y + r >= H) - break; - - for (c = 0; c < 15 * cx; c++, s++) + if (x + c >= W) { - if (x + c < 0 || s < GFX.Screen) - continue; - - if (x + c >= W) - { - s += 15 * cx - c; - break; - } - - 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; + s += 15 * cx - c; + break; } + + 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; } } } From b0b176a126ee63e442ab68b0239eb9352d50c09a Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Wed, 2 Nov 2011 13:21:31 -0300 Subject: [PATCH 056/130] Updated the Snes9X EX description due to the Android Marketplace unfairly taking down Snes9X EX and including instructions on how to copy the ROMs and such to the iOS device --- docs/portsofsnes9x.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 35e2645a..41c59632 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -78,19 +78,17 @@ Gamecube: You might need a modchip. Name: Snes9X EX Latest Version: 1.4.2 Homepage/forum: http://www.explusalpha.com/home/snes9x-ex -Maintainer: Rakashazi (on the Snes9X forums) +Maintainer: Rakashazi HOW TO GET IT RUNNING: *DISCLAIMER* You will have to do some Googling, including but not limited to: * iOS (iPhone/iPod Touch) ONLY!!!: Jailbreaking your firmware -Android: It appears you can just download from the Android Marketplace and run -it from there :) Be sure to copy over your ROMs, saves, etc though. - -UPDATE from SparroHawc: Yup, the app store download works great - no need to root -the phone, and you can browse the contents of the phone's filesystem to find the -ROMs anywhere. The saves, I believe, will be put in the same directory as the -loaded ROM. +Android: Due to the Android Marketplace unfairly taking down Snes9X EX, you +will have to visit Rakashazi's website and download the apk either using your +PC (you'll have to connect the Android to your computer, mount the SD card, +then copy the apk to it) or using your Android, then run package installer +(or easy installer is fine too) to install the app. iOS: You’ll have to jailbreak your firmware and install the Cydia app installer. Then you’ll have to install the BigBoss repository within Cydia and @@ -99,6 +97,10 @@ stuff for that, as it’s the only way you can put the ROMs, saves, etc onto you iPhone/iPod Touch. After that you should be able to download and run from there :) +Hint: a more detailed description of copying your ROMs/saves/etc over to the +iOS device can be found here: +http://snes9x.com/phpbb2/viewtopic.php?t=5107 + *PS3 version of Snes9X* Name: Snes9X PS3 Latest Version: 4.4.9 From a5176752fd4dbc220624aa9923e674f625b7ee40 Mon Sep 17 00:00:00 2001 From: adventureoflink Date: Wed, 2 Nov 2011 13:46:17 -0300 Subject: [PATCH 057/130] forgot to edit in the latest Snes9X EX version number for Android and to reflect on the file being edited today, my bad! --- docs/portsofsnes9x.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/portsofsnes9x.txt b/docs/portsofsnes9x.txt index 41c59632..ae324f88 100644 --- a/docs/portsofsnes9x.txt +++ b/docs/portsofsnes9x.txt @@ -76,7 +76,7 @@ Gamecube: You might need a modchip. *Android and iOS (Apple iPhone/iPod Touch) version of Snes9X* Name: Snes9X EX -Latest Version: 1.4.2 +Latest Version: 1.4.2 (iOS); 1.4.7.1 (Android) Homepage/forum: http://www.explusalpha.com/home/snes9x-ex Maintainer: Rakashazi @@ -87,8 +87,8 @@ HOW TO GET IT RUNNING: Android: Due to the Android Marketplace unfairly taking down Snes9X EX, you will have to visit Rakashazi's website and download the apk either using your PC (you'll have to connect the Android to your computer, mount the SD card, -then copy the apk to it) or using your Android, then run package installer -(or easy installer is fine too) to install the app. +then copy the apk to it) or your Android, then run package installer +(or easy installer is fine too) on your Android to install the app. iOS: You’ll have to jailbreak your firmware and install the Cydia app installer. Then you’ll have to install the BigBoss repository within Cydia and @@ -132,4 +132,4 @@ Really, it's not hard. Read the readme, and use a softmod or modchip and a replacement dashboard. After that's installed, it should be as simple as copying over the emulator, ROMs, saves, etc to the X-Box and it should work. -Updated most recently by: 2011/8/28 adventure_of_link \ No newline at end of file +Updated most recently by: 2011/11/2 adventure_of_link \ No newline at end of file From 528689144151d2f4a2363f16e051993ac09adfaa Mon Sep 17 00:00:00 2001 From: Bl0ckeduser Date: Sun, 13 Nov 2011 13:07:34 -0500 Subject: [PATCH 058/130] Fix missing header (ctype.h for isalnum) --- controls.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/controls.cpp b/controls.cpp index 08aa3e8e..224ec88a 100644 --- a/controls.cpp +++ b/controls.cpp @@ -182,6 +182,7 @@ #include #include #include +#include #include "snes9x.h" #include "memmap.h" From d98ed475eb975e8d915c0d511b3de8a5f3bbcccd Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Mon, 14 Nov 2011 20:10:15 -0500 Subject: [PATCH 059/130] Win32: fix about dialog text layout --- win32/wlanguage.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/win32/wlanguage.h b/win32/wlanguage.h index e50402dd..05e9cf7a 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -187,21 +187,21 @@ //#define REG_KEY_VER "1.31" #define DISCLAIMER_TEXT TEXT("Snes9X v%s for Windows.\r\n\ - (c) Copyright 1996 - 2002 Gary Henderson and Jerremy Koot (jkoot@snes9x.com)\r\n\ - (c) Copyright 2002 - 2004 Matthew Kendora\r\n\ - (c) Copyright 2002 - 2005 Peter Bortas\r\n\ - (c) Copyright 2004 - 2005 Joel Yliluoma\r\n\ - (c) Copyright 2001 - 2006 John Weidman\r\n\ - (c) Copyright 2002 - 2010 Brad Jorsch, funkyass, Kris Bleakley, Nach, zones\r\n\ - (c) Copyright 2006 - 2007 nitsuja\r\n\ - (c) Copyright 2009 - 2011 BearOso, OV2\r\n\r\n\ - Windows Port Authors: Matthew Kendora, funkyass, nitsuja, Nach, blip, OV2.\r\n\r\n\ - Snes9X is a Super Nintendo Entertainment System\r\n\ - emulator that allows you to play most games designed\r\n\ - for the SNES on your PC.\r\n\r\n\ - Please visit http://www.snes9x.com for\r\n\ - up-to-the-minute information and help on Snes9X.\r\n\r\n\ - Nintendo is a trade mark.") +(c) Copyright 1996 - 2002 Gary Henderson and Jerremy Koot (jkoot@snes9x.com)\r\n\ +(c) Copyright 2002 - 2004 Matthew Kendora\r\n\ +(c) Copyright 2002 - 2005 Peter Bortas\r\n\ +(c) Copyright 2004 - 2005 Joel Yliluoma\r\n\ +(c) Copyright 2001 - 2006 John Weidman\r\n\ +(c) Copyright 2002 - 2010 Brad Jorsch, funkyass, Kris Bleakley, Nach, zones\r\n\ +(c) Copyright 2006 - 2007 nitsuja\r\n\ +(c) Copyright 2009 - 2011 BearOso, OV2\r\n\r\n\ +Windows Port Authors: Matthew Kendora, funkyass, nitsuja, Nach, blip, OV2.\r\n\r\n\ +Snes9X is a Super Nintendo Entertainment System\r\n\ +emulator that allows you to play most games designed\r\n\ +for the SNES on your PC.\r\n\r\n\ +Please visit http://www.snes9x.com for\r\n\ +up-to-the-minute information and help on Snes9X.\r\n\r\n\ +Nintendo is a trade mark.") #define APP_NAME TEXT("Snes9x") From f35b8005d582acadbe13c5159e85bf093c9439a2 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Mon, 14 Nov 2011 20:11:10 -0500 Subject: [PATCH 060/130] Win32: add scrollbar to accomodate large about dialog text --- win32/rsrc/snes9x.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index aad02cb6..e5e1b992 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -96,7 +96,7 @@ CAPTION "APP - About Dialog" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,90,160,50,14 - EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY,WS_EX_STATICEDGE + EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | WS_VSCROLL | ES_READONLY,WS_EX_STATICEDGE END IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 154 From 4e2d3854ab24697318e05863e99e26002bc7ecca Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Tue, 15 Nov 2011 15:09:29 -0500 Subject: [PATCH 061/130] Make Microsoft-specific enum code more portable --- memmap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/memmap.cpp b/memmap.cpp index 3b7ebce1..811518eb 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -3897,7 +3897,7 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) if(target_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; } //applying this patch will overflow Memory.ROM buffer - enum : uint32 { SourceRead, TargetRead, SourceCopy, TargetCopy }; + enum { SourceRead, TargetRead, SourceCopy, TargetCopy }; uint32 outputOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0; uint8 *patched_rom = new uint8[target_size]; @@ -3908,7 +3908,7 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) uint32 mode = length & 3; length = (length >> 2) + 1; - switch(mode) { + switch((int)mode) { case SourceRead: while(length--) patched_rom[outputOffset++] = Memory.ROM[outputOffset]; break; From 009276f9d0c16969fde6c27172931655f725d7ac Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Tue, 15 Nov 2011 20:10:58 -0500 Subject: [PATCH 062/130] Fix typos in French translation --- gtk/po/fr_FR.po | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gtk/po/fr_FR.po b/gtk/po/fr_FR.po index dafe7ce6..bb74e4fd 100644 --- a/gtk/po/fr_FR.po +++ b/gtk/po/fr_FR.po @@ -506,7 +506,7 @@ msgstr "Autoriser les filtres à utiliser plusieurs processeurs" #: ../src/snes9x.glade.h:61 msgid "Apply scaling filter:" -msgstr "Appliquer un filtre" +msgstr "Appliquer un filtre:" #: ../src/snes9x.glade.h:62 msgid "Artifacts:" @@ -547,7 +547,7 @@ msgid "" "Automatically save the game's SRAM at this interval. Setting this to 0 will " "only save when quitting or changing ROMs" msgstr "" -"Sauver automatiquement la SRAM à cet interval. Régler à 0 pour ne sauver " +"Sauver automatiquement la SRAM à cet intervalle. Régler à 0 pour ne sauver " "qu'en quittant ou en changeant de ROM" #: ../src/snes9x.glade.h:76 @@ -783,12 +783,12 @@ msgid "" "Host a game on this computer as Player 1, requiring extra throughput to " "support multitple users" msgstr "" -"Héberger une partie sur cet ordinateur en temps que 'Joueur 1', requiert un " +"Héberger une partie sur cet ordinateur en temps que 'Joueur 1' requiert un " "débit plus important pour supporter plusieurs utilisateurs" #: ../src/snes9x.glade.h:134 msgid "Hue:" -msgstr "Teinte" +msgstr "Teinte:" #: ../src/snes9x.glade.h:135 msgid "Increase frame rate" @@ -800,7 +800,7 @@ msgstr "Augmenter le temps entre chaque image" #: ../src/snes9x.glade.h:137 msgid "Input rate:" -msgstr "Fréquence d'entrée" +msgstr "Fréquence d'entrée:" #: ../src/snes9x.glade.h:138 msgid "Joypad" @@ -864,7 +864,7 @@ msgstr "Sourdine" #: ../src/snes9x.glade.h:153 msgid "Name or IP address:" -msgstr "Nom ou adresse IP" +msgstr "Nom ou adresse IP:" #: ../src/snes9x.glade.h:154 msgid "" @@ -1172,7 +1172,7 @@ msgstr "" #: ../src/snes9x.glade.h:234 msgid "Smoothens (blurs) the image" -msgstr "Adoucie (floute) l'image" +msgstr "Adoucit (floute) l'image" #: ../src/snes9x.glade.h:235 msgid "Snes9x" @@ -1208,7 +1208,7 @@ msgstr "Son" #: ../src/snes9x.glade.h:243 msgid "Sound driver:" -msgstr "Pilote audio" +msgstr "Pilote audio:" #: ../src/snes9x.glade.h:244 msgid "Start" @@ -1370,7 +1370,7 @@ msgstr "" #: ../src/snes9x.glade.h:283 msgid "Up" -msgstr "Haut:" +msgstr "Haut" #: ../src/snes9x.glade.h:284 msgid "Use " @@ -1547,7 +1547,7 @@ msgstr "threads pour le filtrage et le zoom" #~ msgid "Enable hacks that may improve performance, but can cause errors" #~ msgstr "" -#~ "Activer des hacks améliorant les performances, mais pouvant causer des " +#~ "Activer des hacks améliorant la performance, mais pouvant causer des " #~ "erreurs" #~ msgid "Enable speed hacks" @@ -1563,11 +1563,11 @@ msgstr "threads pour le filtrage et le zoom" #~ "Interpolates between samples. Smoothes the sound output to match the real " #~ "SNES" #~ msgstr "" -#~ "Interpole entre les samples. Fluidifie la sortie sonore pour correspondre " +#~ "Interpole entre les échantillons. Fluidifie la sortie sonore pour correspondre " #~ "au mieux à la SNES" #~ msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" -#~ msgstr "Sortie en 16 bits par sample au lieu de 8. Son plus précis" +#~ msgstr "Sortie en 16 bits par échantillon au lieu de 8. Son plus précis" #~ msgid "Reverse stereo" #~ msgstr "Stéréo inversée" From c2fa8a2cbf333e06e9503082e4c91a6e11e8d623 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Wed, 16 Nov 2011 13:07:25 -0500 Subject: [PATCH 063/130] Gtk: more improvements to French translation. --- gtk/po/fr_FR.po | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/gtk/po/fr_FR.po b/gtk/po/fr_FR.po index bb74e4fd..1076bf65 100644 --- a/gtk/po/fr_FR.po +++ b/gtk/po/fr_FR.po @@ -104,7 +104,7 @@ msgstr "" #: ../src/gtk_preferences.cpp:388 msgid " Only barebones features enabled" -msgstr "" +msgstr " Fonctionnalités de base seulement" #: ../src/gtk_preferences.cpp:391 msgid " OpenGL" @@ -179,7 +179,7 @@ msgstr "Erreur à l'ouverture de %s\n" #: ../src/gtk_s9xwindow.cpp:767 msgid "Couldn't load files." -msgstr "Impossible de charger les fichiers" +msgstr "Impossible de charger les fichiers." #: ../src/gtk_s9xwindow.cpp:799 msgid "Open SNES Movie" @@ -321,9 +321,9 @@ msgid "" "24-bit (GL_RGB)\n" "32-bit (GL_BGRA)" msgstr "" -"16-bit (GL_BVRA)\n" -"24-bit (GL_RVB)\n" -"32-bit (GL_BVRA)" +"16-bits (GL_BVRA)\n" +"24-bits (GL_RVB)\n" +"32-bits (GL_BVRA)" #: ../src/snes9x.glade.h:15 msgid "1x" @@ -506,7 +506,7 @@ msgstr "Autoriser les filtres à utiliser plusieurs processeurs" #: ../src/snes9x.glade.h:61 msgid "Apply scaling filter:" -msgstr "Appliquer un filtre:" +msgstr "Appliquer un filtre d'agrandissement:" #: ../src/snes9x.glade.h:62 msgid "Artifacts:" @@ -703,7 +703,7 @@ msgstr "Bas" #: ../src/snes9x.glade.h:113 msgid "Emulation" -msgstr "Emulation" +msgstr "Émulation" #: ../src/snes9x.glade.h:114 msgid "Enable HDMA" @@ -735,7 +735,7 @@ msgstr "Forcer la sortie Hires" #: ../src/snes9x.glade.h:121 msgid "Force an inverted byte-ordering" -msgstr "" +msgstr "Inverser l'ordre des octets" #: ../src/snes9x.glade.h:122 msgid "" @@ -783,7 +783,7 @@ msgid "" "Host a game on this computer as Player 1, requiring extra throughput to " "support multitple users" msgstr "" -"Héberger une partie sur cet ordinateur en temps que 'Joueur 1' requiert un " +"Héberger une partie sur cet ordinateur en tant que 'Joueur 1'; requiert un " "débit plus important pour supporter plusieurs utilisateurs" #: ../src/snes9x.glade.h:134 @@ -946,7 +946,7 @@ msgstr "Désactiver l'écran de veille" #: ../src/snes9x.glade.h:178 msgid "Prevents edge artifacts, but can slow performance" -msgstr "Empêche les artefacts des bords, mais peut ralentir le jeu" +msgstr "Empêche les artefacts de bords, mais peut ralentir le jeu" #: ../src/snes9x.glade.h:179 msgid "Quit Snes9x" @@ -1084,7 +1084,7 @@ msgstr "Raccourcis" #: ../src/snes9x.glade.h:212 msgid "Show ROM _Info..." -msgstr "Afficher les _Information de l'image ROM..." +msgstr "Afficher les _Informations de l'image ROM..." #: ../src/snes9x.glade.h:213 msgid "Show frame rate" @@ -1378,7 +1378,7 @@ msgstr "Utiliser " #: ../src/snes9x.glade.h:285 msgid "Use SNES extended height. Will probably cause letterboxing" -msgstr "" +msgstr "Utiliser la hauteur étendue SNES. Peut causer l'effet letterbox" #: ../src/snes9x.glade.h:286 msgid "Use fullscreen on ROM open" @@ -1567,7 +1567,7 @@ msgstr "threads pour le filtrage et le zoom" #~ "au mieux à la SNES" #~ msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" -#~ msgstr "Sortie en 16 bits par échantillon au lieu de 8. Son plus précis" +#~ msgstr "Sortie en 16 bits par échantillon plutôt que 8. Son plus précis" #~ msgid "Reverse stereo" #~ msgstr "Stéréo inversée" From 4f4e1de2d07ebcdc9c12d98cec2b8b51bd2208a1 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Wed, 16 Nov 2011 23:19:05 -0500 Subject: [PATCH 064/130] Win32: add notice on removal of DirectDraw in recent DX APIs --- win32/docs/how2compile.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win32/docs/how2compile.txt b/win32/docs/how2compile.txt index 0e50be36..5d7e5e67 100644 --- a/win32/docs/how2compile.txt +++ b/win32/docs/how2compile.txt @@ -8,6 +8,8 @@ NOTE: Unicode support requires a special zlib build - see the end of the zlib en your own project file for earlier MSVC versions - A recent DirectX SDK. The official binary is compiled against the June 2008 SDK. + Note that as of the June 2010 release of the DirectX SDK, DirectDraw (which is + necessary to compile) has been removed. - zlib(optional) - The release binaries are built against a static zlib compiled against VC's multi-threaded C runtime and renamed to zlibmt.lib, to avoid linker conflicts. From cd2715e3a47f4541b0f7c5d7c1d7b9e4b44db0cc Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Wed, 16 Nov 2011 23:23:03 -0500 Subject: [PATCH 065/130] Win32: only use zlib if it is turned on --- win32/wsnes9x.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 88d5deda..8f0a59ad 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -5104,6 +5104,7 @@ void rominfo(const TCHAR *filename, TCHAR *namebuffer, TCHAR *sizebuffer) lstrcpy(namebuffer, ROM_ITEM_DESCNOTAVAILABLE); lstrcpy(sizebuffer, TEXT("? Mbits")); +#ifdef ZLIB if(IsCompressed(filename)) { unzFile uf = unzOpen(_tToChar(filename)); @@ -5143,6 +5144,7 @@ void rominfo(const TCHAR *filename, TCHAR *namebuffer, TCHAR *sizebuffer) } return; } +#endif struct _stat filestats; _tstat(filename, &filestats); From bdc68a6283925f7152135192bbe065b000b0bd80 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Thu, 17 Nov 2011 00:01:48 -0500 Subject: [PATCH 066/130] Win32: handle lack of libpng --- win32/CGLCG.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 1667dfae..8ca7f4a2 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -525,6 +525,7 @@ void CGLCG::setShaderVars(int pass) } } +#ifdef HAVE_LIBPNG bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) { png_structp png_ptr; png_infop info_ptr; @@ -644,6 +645,12 @@ bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool /* That's it */ return true; } +#else +bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) { + /* No PNG support */ + return false; +} +#endif bool CGLCG::loadTGA(const TCHAR *filename, STGA& tgaFile) { From 2a939e6d9ba3145d5a43b23d2ae8fd4f5aa6593d Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Thu, 17 Nov 2011 14:00:30 -0500 Subject: [PATCH 067/130] Fix crash in config file loader --- conffile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conffile.cpp b/conffile.cpp index 2923ecc8..b7f60298 100644 --- a/conffile.cpp +++ b/conffile.cpp @@ -280,7 +280,7 @@ void ConfigFile::LoadFile(Reader *r, const char *name){ } key=l.substr(0,i); ConfigEntry::trim(key); val=l.substr(i+1); comment = ConfigEntry::trimCommented(val); - if(val[0]=='"' && *val.rbegin()=='"') val=val.substr(1, val.size()-2); + if(val.size() > 0 && val[0]=='"' && *val.rbegin()=='"') val=val.substr(1, val.size()-2); ConfigEntry e(line, section, key, val); e.comment = comment; From d53b71583cca5e7ba0deefe316d49903c2ceebe6 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Fri, 18 Nov 2011 16:30:47 -0500 Subject: [PATCH 068/130] Win32: Fix typos in Readme --- win32/docs/readme-windows.txt | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/win32/docs/readme-windows.txt b/win32/docs/readme-windows.txt index 193e8faa..24a264a9 100644 --- a/win32/docs/readme-windows.txt +++ b/win32/docs/readme-windows.txt @@ -46,13 +46,13 @@ The original Snes9x project was founded by Gary Henderson and Jerremy Koot as a collaboration of their earlier attempts at SNES emulation (Snes96 and Snes97.) Over the years the project has grown and has collected some of the greatest talent in the emulation community (at least of the SNES variety) some of which -have been listed in the credits section, others have helped but have been loss +have been listed in the credits section, others have helped but have been lost in the course of time. Why Emulate the SNES? --------------------- Well, there are many reasons for this. The main reason is for nostalgic -purposes. In this day and age, it's hard to find an SNES and many good games. +purposes. In this day and age, it's hard to find a SNES and many good games. Plus, many of us over the course of time have lost our beloved consoles (may they R.I.P) but still have our original carts. With no other means to play them, we turn to emulators. Besides this there are many conveniences of doing this on @@ -114,8 +114,8 @@ is displayed. This will help to find out what the problem is. These colors do NOT signify whether a game will work or not. It is just a means for reference so we can understand what may or may not be a problem. Most often -the problem with games that don't work it's because they are corrupt or are a -bad dump and should be redumped. +the problem with games that don't work is that they are corrupt or are a bad dump +and should be redumped. SNES Joypad Emulation --------------------- @@ -148,7 +148,7 @@ DirectX 6.1b or later. DirectSound capable sound card. Certain games use added hardware which will require a faster machine. The specs -listed above is the minimum to use Snes9x in any playable form. It is +listed above are the minimum to use Snes9x in any playable form. It is recommended that you get a semi-modern machine with a 800MHz CPU if you want good results. A 1GHz CPU is recommended for those that want a near perfect experience. @@ -255,7 +255,7 @@ intent - ideal for saving your game just before a tricky bit! Freeze files and SRAM files are normally written to and read from the folder called Saves where your snes9x.exe is located, but sometimes this is not -desirable or possible, especially if it’s a CD-ROM, which is of course is +desirable or possible, especially if it's a CD-ROM, which of course is usually read-only! You can change the folder where Snes9x saves and loads freeze and SRAM files using the Settings Dialog, available from the Options menu. @@ -349,7 +349,7 @@ Snes9x also allows new cheats to be found using the Search for New Cheats dialog, again available from the Cheats menu. The easiest way to describe the dialog is to walk through an example. -Let’s give ourselves infinite health and lives on Ocean's Addams Family platform +Let's give ourselves infinite health and lives on Ocean's Addams Family platform game: Load up the game; keep pressing the start button (Return key by default) to skip @@ -361,8 +361,8 @@ Launch the Cheat Search dialog for the first time; Alt+A is its accelerator. Press the Reset button just in case you've used the dialog before, leave the Search Type and Data Size radio boxes at their default values and press OK. -Play the game for a while until you loose a life by just keep walking into -baddies, when the game restarts and the life counter displays 4, launch the +Play the game for a while until you loose a life by just keeping walking into +baddies; when the game restarts and the life counter displays 4, launch the Cheat Search dialog again but this time press the Search button rather than Reset. The number of items in the list will reduce, each line shows a memory location, its current value and its previous value; what we're looking for is @@ -394,7 +394,7 @@ the counter back to the value you chose! If the memory location you add a cheat on proves to be wrong, just go to the Cheat Code Editor dialog and delete the incorrect entry. -Now let’s try and find the Addams Family health counter. While two hearts are +Now let's try and find the Addams Family health counter. While two hearts are displayed on the screen, visit the Cheat Search dialog and press the Reset button followed by OK. Play the game until you loose a heart by touching a baddie, then visit the Cheat Search dialog again. @@ -406,7 +406,7 @@ with. Look at address line 7E00C3, its current value is 1 and its previous value was 2. Scrolling through the list doesn't reveal any other likely memory locations, -so let’s try our luck. Click on the 7E00C3 line, press the Add Cheat button and +so let's try our luck. Click on the 7E00C3 line, press the Add Cheat button and type in a new value of say 4 into the dialog that appears and press OK. Press OK on the Search for New Cheats dialog to return to the game. @@ -428,9 +428,9 @@ Movie support allows you to record your actions while playing a game. This can be used for your own personal playback or to show other people that you can do something without them having to be around when you did it. -Recording the Movie -------------------- -Simply click File menu and click on Movie. Click the Record button. Here you can +Recording a Movie +----------------- +Simply click the File menu and click on Movie. Click the Record button. Here you can decide when to start recording. If you want to record from the very start of a game, click on 'Record from reset.' If you want to start recording from where you are already in a game, click 'Record from now.' You can also choose which @@ -438,14 +438,14 @@ controllers to record. If you are playing by yourself leave joypad 1 as the only one selected. The more controllers you choose to record the larger the file size will be. -Playing Back the Movie ----------------------- +Playing Back a Movie +-------------------- To play back a movie you recorded, click File menu, Movie, Play and select the file to play. Make sure the movie was recorded with the same ROM that you have loaded. -Re-recording the Movie ----------------------- +Re-recording a Movie +-------------------- If you make a mistake while recording a movie, there is a movie re-record function. Simply create a freeze file anytime while recording. If you want to re-record, load the freeze file and it will bring up the message 'movie @@ -625,8 +625,8 @@ Snes9x: Hayazashi Nidan Morita Shougi Seta-11 Hayazashi Nidan Morita Shougi 2 Seta-18 -Problems with Sounds --------------------- +Problems with Sound +------------------- No sound coming from any SNES game using Snes9x? Could be any or all of these: - If all sound menu options are grayed out, or an error dialog about Snes9x not From 9215fba45340b28ca5b0131b3e7046b24efac569 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 12 Nov 2011 21:01:46 +0100 Subject: [PATCH 069/130] Win32: add quit hotkey --- win32/wlanguage.h | 2 +- win32/wsnes9x.cpp | 12 ++++++++++-- win32/wsnes9x.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/win32/wlanguage.h b/win32/wlanguage.h index 05e9cf7a..77b12782 100644 --- a/win32/wlanguage.h +++ b/win32/wlanguage.h @@ -289,7 +289,7 @@ Nintendo is a trade mark.") #define HOTKEYS_LABEL_3_11 TEXT("Turbo Right mode") #define HOTKEYS_LABEL_3_12 TEXT("Turbo Down mode") //#define HOTKEYS_LABEL_4_12 "Interpolate Mode 7" -//#define HOTKEYS_LABEL_4_13 "BG Layering hack" +#define HOTKEYS_LABEL_4_13 TEXT("Quit Snes9x") // gaming buttons and axes #define GAMEDEVICE_JOYNUMPREFIX "(J%x)" // don't change this diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 8f0a59ad..06dfca2b 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -562,6 +562,7 @@ struct SCustomKeys CustomKeys = { {0,0}}, // Select save slot 9 {'R',CUSTKEY_CTRL_MASK|CUSTKEY_SHIFT_MASK}, // Reset Game {0,0}, // Toggle Cheats + {0,0}, }; @@ -1225,6 +1226,11 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) S9xReportControllers(); } } + if(wParam == CustomKeys.QuitS9X.key + && modifiers == CustomKeys.QuitS9X.modifiers) + { + PostMessage(GUI.hWnd,WM_CLOSE,(WPARAM)NULL,(LPARAM)(NULL)); + } //if(wParam == CustomKeys.BGLHack.key //&& modifiers == CustomKeys.BGLHack.modifiers) //{ @@ -7775,7 +7781,7 @@ static void set_hotkeyinfo(HWND hDlg) SendDlgItemMessage(hDlg,IDC_HOTKEY1+i,WM_USER+44,CustomKeys.SelectSave[i].key,CustomKeys.SelectSave[i].modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,0,0); SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,0,0); - SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,0,0); + SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.QuitS9X.key,CustomKeys.QuitS9X.modifiers); break; } @@ -7843,8 +7849,9 @@ static void set_hotkeyinfo(HWND hDlg) _stprintf(temp, TEXT("Select Slot %d"), i); SetDlgItemText(hDlg,IDC_LABEL_HK1+i,temp); } - for(int i = 10 ; i < 13 ; i++) + for(int i = 10 ; i < 12 ; i++) SetDlgItemText(hDlg,IDC_LABEL_HK1+i,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_4_13); break; } @@ -8003,6 +8010,7 @@ switch(msg) if(index == 0) CustomKeys.SaveScreenShot.key = wParam, CustomKeys.SaveScreenShot.modifiers = modifiers; if(index == 1) CustomKeys.ToggleCheats.key = wParam, CustomKeys.ToggleCheats.modifiers = modifiers; // if(index == 3) CustomKeys.BGLHack.key = wParam, CustomKeys.BGLHack.modifiers = modifiers; + if(index == 3) CustomKeys.QuitS9X.key = wParam, CustomKeys.QuitS9X.modifiers = modifiers; break; case IDC_SLOTPLUS: diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index c533c305..894f4c90 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -465,6 +465,7 @@ struct SCustomKeys { SCustomKey SelectSave [10]; SCustomKey ResetGame; SCustomKey ToggleCheats; + SCustomKey QuitS9X; }; struct SJoypad { From 6b17c7d3bd0ca9fcca8b62f18c285cb223bd81f1 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 30 Nov 2011 19:21:37 +0100 Subject: [PATCH 070/130] Win32: save quit hotkey to config --- win32/wconfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index 2d202535..95981ee2 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -1015,6 +1015,7 @@ void WinRegisterConfigItems() ADD(ClippingWindows); /*ADD(BGLHack);*/ ADD(Transparency); /*ADD(HDMA)*/; /*ADD(GLCube);*/ /*ADD(InterpMode7);*/ ADD(JoypadSwap); ADD(SwitchControllers); ADD(ResetGame); ADD(ToggleCheats); ADD(TurboA); ADD(TurboB); ADD(TurboY); ADD(TurboX); ADD(TurboL); ADD(TurboR); ADD(TurboStart); ADD(TurboSelect); ADD(TurboUp); ADD(TurboDown); ADD(TurboLeft); ADD(TurboRight); + ADD(QuitS9X); #undef ADD #undef ADDN #undef CATEGORY From e68a1e9786464c501f5596074bbcac5946606b7c Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 30 Nov 2011 19:31:27 +0100 Subject: [PATCH 071/130] Win32: only allow escape-menu in directdraw --- win32/wsnes9x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 06dfca2b..aaa21d5a 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -1316,7 +1316,7 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) switch (wParam) { case VK_ESCAPE: - if(GUI.outputMethod==DIRECT3D && GUI.FullScreen && !GUI.EmulateFullscreen) + if(GUI.outputMethod!=DIRECTDRAW && GUI.FullScreen && !GUI.EmulateFullscreen) ToggleFullScreen(); else if (GetMenu (GUI.hWnd) == NULL) From 01bf98aaaf8acefb3dfd1c4a6df1b3831e9b8f53 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 30 Nov 2011 19:31:59 +0100 Subject: [PATCH 072/130] Win32: only save window position if not in fullscreen --- win32/win32_display.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index 72afd1ea..0bf3498b 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -557,7 +557,8 @@ void SaveMainWinPos() wndPlacement.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(GUI.hWnd,&wndPlacement); GUI.window_maximized = wndPlacement.showCmd == SW_SHOWMAXIMIZED; - GUI.window_size = wndPlacement.rcNormalPosition; + if(!GUI.FullScreen && !GUI.EmulatedFullscreen) + GUI.window_size = wndPlacement.rcNormalPosition; } void RestoreMainWinPos() From 468275b2f2f21718826fbf43ed37c5294db8e8c0 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 10 Dec 2011 15:21:37 +0100 Subject: [PATCH 073/130] Win32: match D3D/OGL cg meta shader capability and update to latest spec --- win32/CCGShader.cpp | 180 ++++++++- win32/CCGShader.h | 176 +++++++++ win32/CD3DCG.cpp | 836 ++++++++++++++++++++++++++++++++++++++++++ win32/CD3DCG.h | 264 +++++++++++++ win32/CDirect3D.cpp | 174 ++++----- win32/CDirect3D.h | 15 +- win32/CGLCG.cpp | 279 ++++++++++++-- win32/CGLCG.h | 194 +++++++++- win32/cgFunctions.cpp | 59 ++- win32/cgFunctions.h | 29 +- win32/snes9xw.vcproj | 8 + 11 files changed, 2086 insertions(+), 128 deletions(-) create mode 100644 win32/CD3DCG.cpp create mode 100644 win32/CD3DCG.h diff --git a/win32/CCGShader.cpp b/win32/CCGShader.cpp index 8c589039..7789e321 100644 --- a/win32/CCGShader.cpp +++ b/win32/CCGShader.cpp @@ -1,3 +1,179 @@ +/*********************************************************************************** + 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 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + 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 used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + 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 emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + 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) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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 "CCGShader.h" #include "../conffile.h" @@ -79,11 +255,11 @@ bool CCGShader::LoadShader(const char *path) const char *scaleFloat = conf.GetString(keyName,""); int scaleInt = conf.GetInt(keyName,0); if(!strcasecmp(scaleFloat,"")) { - sprintf(keyName,"::scalex%u",i); + sprintf(keyName,"::scale_x%u",i); const char *scaleFloatX = conf.GetString(keyName,"1.0"); pass.scaleParams.scaleX = atof(scaleFloatX); pass.scaleParams.absX = conf.GetInt(keyName,1); - sprintf(keyName,"::scaley%u",i); + sprintf(keyName,"::scale_y%u",i); const char *scaleFloatY = conf.GetString(keyName,"1.0"); pass.scaleParams.scaleY = atof(scaleFloatY); pass.scaleParams.absY = conf.GetInt(keyName,1); diff --git a/win32/CCGShader.h b/win32/CCGShader.h index 9fe2f7fe..ab878bdf 100644 --- a/win32/CCGShader.h +++ b/win32/CCGShader.h @@ -1,3 +1,179 @@ +/*********************************************************************************** + 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 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + 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 used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + 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 emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + 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) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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 CCGSHADER_H #define CCGSHADER_H diff --git a/win32/CD3DCG.cpp b/win32/CD3DCG.cpp new file mode 100644 index 00000000..29dbfd8d --- /dev/null +++ b/win32/CD3DCG.cpp @@ -0,0 +1,836 @@ +/*********************************************************************************** + 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 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + 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 used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + 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 emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + 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) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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 "CD3DCG.h" +#include "wsnes9x.h" +#include "win32_display.h" +#include +#include +#include "CDirect3D.h" + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +static float npot(float desired) +{ + float out=512.0; + while(outcgContext = cgContext; + this->pDevice = pDevice; + ClearPasses(); + frameCnt=0; +} + +CD3DCG::~CD3DCG(void) +{ + LoadShader(NULL); +} + +void CD3DCG::ClearPasses() +{ + /* clean up cg programs, vertex buffers/declarations and textures + from all regular passes. pass 0 is the orignal texture, so ignore that + */ + if(shaderPasses.size()>1) { + for(std::vector::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { + if(it->cgFragmentProgram) + cgDestroyProgram(it->cgFragmentProgram); + if(it->cgVertexProgram) + cgDestroyProgram(it->cgVertexProgram); + if(it->tex) + it->tex->Release(); + if(it->vertexBuffer) + it->vertexBuffer->Release(); + if(it->vertexDeclaration) + it->vertexDeclaration->Release(); + } + } + for(std::vector::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) { + if(it->tex) + it->tex->Release(); + } + for(std::deque::iterator it=prevPasses.begin();it!=prevPasses.end();it++) { + if(it->tex) + it->tex->Release(); + if(it->vertexBuffer) + it->vertexBuffer->Release(); + } + prevPasses.clear(); + shaderPasses.clear(); + lookupTextures.clear(); + // prevPasses deque is always filled with PREV + PREV1-6 elements + prevPasses.resize(7); + shaderLoaded = false; +} + +void CD3DCG::OnLostDevice() +{ + /* release all non-managed textures so the device can reset - + will be recreated when required + */ + if(shaderPasses.size()>1) { + for(std::vector::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { + if(it->tex) { + it->tex->Release(); + it->tex = NULL; + } + } + } +} + +void CD3DCG::OnResetDevice() +{ + +} + +void CD3DCG::checkForCgError(const char *situation) +{ + char buffer[4096]; + CGerror error = cgGetError(); + const char *string = cgGetErrorString(error); + + if (error != CG_NO_ERROR) { + sprintf(buffer, + "Situation: %s\n" + "Error: %s\n\n" + "Cg compiler output...\n", situation, string); + MessageBoxA(0, buffer, + "Cg error", MB_OK|MB_ICONEXCLAMATION); + if (error == CG_COMPILER_ERROR) { + MessageBoxA(0, cgGetLastListing(cgContext), + "Cg compilation error", MB_OK|MB_ICONEXCLAMATION); + } + } +} + +#define IS_SLASH(x) ((x) == TEXT('\\') || (x) == TEXT('/')) + +bool CD3DCG::LoadShader(const TCHAR *shaderFile) +{ + CCGShader cgShader; + TCHAR shaderPath[MAX_PATH]; + TCHAR tempPath[MAX_PATH]; + HRESULT hr; + GLenum error; + + ClearPasses(); + + if (shaderFile == NULL || *shaderFile==TEXT('\0')) + return true; + + lstrcpy(shaderPath,shaderFile); + for(int i=lstrlen(shaderPath); i>=0; i--){ + if(IS_SLASH(shaderPath[i])){ + shaderPath[i]=TEXT('\0'); + break; + } + } + + SetCurrentDirectory(shaderPath); + if(!cgShader.LoadShader(_tToChar(shaderFile))) + return false; + + CGprofile vertexProfile = cgD3D9GetLatestVertexProfile(); + CGprofile pixelProfile = cgD3D9GetLatestPixelProfile(); + + const char** vertexOptions = cgD3D9GetOptimalOptions(vertexProfile); + const char** pixelOptions = cgD3D9GetOptimalOptions(pixelProfile); + + shaderPasses.push_back(shaderPass()); + + for(CCGShader::passVector::iterator it=cgShader.shaderPasses.begin(); + it!=cgShader.shaderPasses.end();it++) { + shaderPass pass; + + pass.scaleParams = it->scaleParams; + /* if this is the last pass (the only one that can have CG_SCALE_NONE) + and no filter has been set use the GUI setting + */ + if(pass.scaleParams.scaleTypeX==CG_SCALE_NONE && !it->filterSet) { + pass.linearFilter = GUI.BilinearFilter; + } else { + pass.linearFilter = it->linearFilter; + } + + // paths in the meta file can be relative + _tfullpath(tempPath,_tFromChar(it->cgShaderFile),MAX_PATH); + char *fileContents = ReadShaderFileContents(tempPath); + if(!fileContents) + return false; + + pass.cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + vertexProfile, "main_vertex", vertexOptions); + + checkForCgError("Compiling vertex program"); + + pass.cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + pixelProfile, "main_fragment", pixelOptions); + + checkForCgError("Compiling fragment program"); + + delete [] fileContents; + if(!pass.cgVertexProgram || !pass.cgFragmentProgram) { + return false; + } + if(pass.cgVertexProgram) { + hr = cgD3D9LoadProgram(pass.cgVertexProgram,false,0); + } + checkForCgError("Loading vertex program"); + if(pass.cgFragmentProgram) { + hr = cgD3D9LoadProgram(pass.cgFragmentProgram,false,0); + } + checkForCgError("Loading fragment program"); + + /* generate vertex buffer + */ + + hr = pDevice->CreateVertexBuffer(sizeof(VERTEX)*4,D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&pass.vertexBuffer,NULL); + if(FAILED(hr)) { + pass.vertexBuffer = NULL; + DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr); + return false; + } + + /* set up vertex declarations for the pass, + this also creates the vertex declaration + */ + setupVertexDeclaration(pass); + + shaderPasses.push_back(pass); + } + + for(std::vector::iterator it=cgShader.lookupTextures.begin();it!=cgShader.lookupTextures.end();it++) { + lookupTexture tex; + strcpy(tex.id,it->id); + tex.linearFilter = it->linearfilter; + + _tfullpath(tempPath,_tFromChar(it->texturePath),MAX_PATH); + + hr = D3DXCreateTextureFromFileEx( + pDevice, + tempPath, + D3DX_DEFAULT_NONPOW2, + D3DX_DEFAULT_NONPOW2, + 0, + 0, + D3DFMT_FROM_FILE, + D3DPOOL_MANAGED, + it->linearfilter?D3DX_FILTER_LINEAR:D3DX_FILTER_POINT, + 0, + 0, + NULL, + NULL, + &tex.tex); + if FAILED(hr){ + tex.tex = NULL; + } + lookupTextures.push_back(tex); + } + + shaderLoaded = true; + + return true; +} + +void CD3DCG::ensureTextureSize(LPDIRECT3DTEXTURE9 &tex, D3DXVECTOR2 &texSize, + D3DXVECTOR2 wantedSize,bool renderTarget) +{ + HRESULT hr; + + if(!tex || texSize != wantedSize) { + if(tex) + tex->Release(); + + hr = pDevice->CreateTexture( + wantedSize.x, wantedSize.y, + 1, // 1 level, no mipmaps + renderTarget?D3DUSAGE_RENDERTARGET:0, + renderTarget?D3DFMT_X8R8G8B8:D3DFMT_R5G6B5, + renderTarget?D3DPOOL_DEFAULT:D3DPOOL_MANAGED, // render targets cannot be managed + &tex, + NULL ); + + texSize = wantedSize; + + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error while creating texture"), hr); + return; + } + } +} + +void CD3DCG::setVertexStream(IDirect3DVertexBuffer9 *vertexBuffer, + D3DXVECTOR2 inputSize,D3DXVECTOR2 textureSize,D3DXVECTOR2 outputSize) +{ + float tX = inputSize.x / textureSize.x; + float tY = inputSize.y / textureSize.y; + VERTEX vertexStream[4]; + + /* vertex is POSITION, TEXCOORD, LUT TEXCOORD + */ + + vertexStream[0] = VERTEX(0.0f,0.0f,0.0f, + 0.0f,tY, + 0.0f,1.0f); + vertexStream[1] = VERTEX(0.0f,1.0f,0.0f, + 0.0f,0.0f, + 0.0f,0.0f); + vertexStream[2] = VERTEX(1.0f,0.0f,0.0f, + tX,tY, + 1.0f,1.0f); + vertexStream[3] = VERTEX(1.0f,1.0f,0.0f, + tX,0.0f, + 1.0f,0.0f); + // offset coordinates to correct pixel/texture alignment + for(int i=0;i<4;i++) { + vertexStream[i].x -= 0.5f / outputSize.x; + vertexStream[i].y += 0.5f / outputSize.y; + } + + void *pLockedVertexBuffer; + HRESULT hr = vertexBuffer->Lock(0,0,&pLockedVertexBuffer,NULL); + memcpy(pLockedVertexBuffer,vertexStream,sizeof(vertexStream)); + vertexBuffer->Unlock(); + + /* set vertex to stream 0-3, for POSITION,TEXCOORD0,TEXCOORD1,COLOR + if stream is used in parameter, this will be set in setShaderVars + */ + pDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERTEX)); + pDevice->SetStreamSource(1,vertexBuffer,0,sizeof(VERTEX)); + pDevice->SetStreamSource(2,vertexBuffer,0,sizeof(VERTEX)); + pDevice->SetStreamSource(3,vertexBuffer,0,sizeof(VERTEX)); +} + +void CD3DCG::Render(LPDIRECT3DTEXTURE9 &origTex, D3DXVECTOR2 textureSize, + D3DXVECTOR2 inputSize, D3DXVECTOR2 viewportSize, D3DXVECTOR2 windowSize) +{ + LPDIRECT3DSURFACE9 pRenderSurface = NULL,pBackBuffer = NULL; + frameCnt++; + + if(!shaderLoaded) + return; + + /* save back buffer render target + */ + pDevice->GetRenderTarget(0,&pBackBuffer); + + /* pass 0 represents the original texture + */ + shaderPasses[0].tex = origTex; + shaderPasses[0].outputSize = inputSize; + shaderPasses[0].textureSize = textureSize; + + calculateMatrix(); + + for(int i=1;iGetSurfaceLevel(0,&pRenderSurface); + pDevice->SetTexture(0, shaderPasses[i-1].tex); + pDevice->SetRenderTarget(0,pRenderSurface); + pRenderSurface->Release(); + + /* set vertex declaration of current pass, update vertex + buffer and set base streams + */ + pDevice->SetVertexDeclaration(shaderPasses[i].vertexDeclaration); + setVertexStream(shaderPasses[i].vertexBuffer, + shaderPasses[i-1].outputSize,shaderPasses[i-1].textureSize,shaderPasses[i].outputSize); + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); + + /* shader vars need to be set after the base vertex streams + have been set so they can override them + */ + setShaderVars(i); + + cgD3D9BindProgram(shaderPasses[i].cgVertexProgram); + checkForCgError("Binding vertex program"); + cgD3D9BindProgram(shaderPasses[i].cgFragmentProgram); + checkForCgError("Binding fragment program"); + + /* viewport defines output size + */ + setViewport(0,0,shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y); + + pDevice->BeginScene(); + pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); + pDevice->EndScene(); + } + + /* take oldes PREV out of deque, make sure it has + the same size as the current texture and + then set it up as new original texture + */ + prevPass &oldestPrev = prevPasses.back(); + ensureTextureSize(oldestPrev.tex,oldestPrev.textureSize,textureSize,false); + if(oldestPrev.vertexBuffer) + oldestPrev.vertexBuffer->Release(); + origTex = oldestPrev.tex; + prevPasses.pop_back(); + + /* push current original with corresponding vertex + buffer to front of PREV deque + */ + shaderPasses[0].vertexBuffer = shaderPasses[1].vertexBuffer; + prevPasses.push_front(prevPass(shaderPasses[0])); + + /* create new vertex buffer so that next render call + will not overwrite the PREV + */ + pDevice->CreateVertexBuffer(sizeof(VERTEX)*4,D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&shaderPasses[1].vertexBuffer,NULL); + + /* set up last pass texture, backbuffer and viewport + for final display pass without shaders + */ + pDevice->SetTexture(0, shaderPasses.back().tex); + pDevice->SetRenderTarget(0,pBackBuffer); + pBackBuffer->Release(); + RECT displayRect=CalculateDisplayRect(shaderPasses.back().outputSize.x,shaderPasses.back().outputSize.y,windowSize.x,windowSize.y); + setViewport(displayRect.left,displayRect.top,displayRect.right - displayRect.left,displayRect.bottom - displayRect.top); + setVertexStream(shaderPasses.back().vertexBuffer, + shaderPasses.back().outputSize,shaderPasses.back().textureSize, + D3DXVECTOR2(displayRect.right - displayRect.left,displayRect.bottom - displayRect.top)); + pDevice->SetVertexShader(NULL); + pDevice->SetPixelShader(NULL); +} + +void CD3DCG::calculateMatrix() +{ + D3DXMATRIX matWorld; + D3DXMATRIX matView; + D3DXMATRIX matProj; + + pDevice->GetTransform(D3DTS_WORLD,&matWorld); + pDevice->GetTransform(D3DTS_VIEW,&matView); + pDevice->GetTransform(D3DTS_PROJECTION,&matProj); + + mvp = matWorld * matView * matProj; + D3DXMatrixTranspose(&mvp,&mvp); +} + +void CD3DCG::setViewport(DWORD x, DWORD y, DWORD width, DWORD height) +{ + D3DVIEWPORT9 viewport; + viewport.X = x; + viewport.Y = y; + viewport.Height = height; + viewport.Width = width; + viewport.MinZ = 0.0f; + viewport.MaxZ = 1.0f; + HRESULT hr = pDevice->SetViewport(&viewport); +} + +void CD3DCG::setShaderVars(int pass) +{ + D3DXVECTOR2 inputSize = shaderPasses[pass-1].outputSize; + D3DXVECTOR2 textureSize = shaderPasses[pass-1].textureSize; + D3DXVECTOR2 outputSize = shaderPasses[pass].outputSize; + + /* mvp paramater + */ + CGparameter cgpModelViewProj = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, "modelViewProj"); + + if(cgpModelViewProj) + cgD3D9SetUniformMatrix(cgpModelViewProj,&mvp); + +#define setProgramUniform(pass,varname,floats)\ +{\ + CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\ + CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\ + if(cgpf)\ + cgD3D9SetUniform(cgpf,floats);\ + if(cgpv)\ + cgD3D9SetUniform(cgpv,floats);\ +}\ + +#define setTextureParameter(pass,varname,val,linear)\ +{\ + CGparameter cgpf = cgGetNamedParameter(shaderPasses[pass].cgFragmentProgram, varname);\ + if(cgpf) {\ + cgD3D9SetTexture(cgpf,val);\ + cgD3D9SetSamplerState(cgpf, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);\ + cgD3D9SetSamplerState(cgpf, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);\ + cgD3D9SetSamplerState(cgpf, D3DSAMP_MINFILTER, linear?D3DTEXF_LINEAR:D3DTEXF_POINT);\ + cgD3D9SetSamplerState(cgpf, D3DSAMP_MAGFILTER, linear?D3DTEXF_LINEAR:D3DTEXF_POINT);\ + }\ +}\ + +#define setTexCoordsParameter(pass,varname,val)\ +{\ + CGparameter cgpv = cgGetNamedParameter(shaderPasses[pass].cgVertexProgram, varname);\ + if(cgpv) {\ + unsigned long index = cgGetParameterResourceIndex(cgpv);\ + pDevice->SetStreamSource(shaderPasses[pass].parameterMap[index].streamNumber,val,0,sizeof(VERTEX));\ + }\ +}\ + + /* IN paramater + */ + setProgramUniform(pass,"IN.video_size",&inputSize); + setProgramUniform(pass,"IN.texture_size",&textureSize); + setProgramUniform(pass,"IN.output_size",&outputSize); + setProgramUniform(pass,"IN.frame_count",&frameCnt); + + /* ORIG parameter + */ + setProgramUniform(pass,"ORIG.video_size",shaderPasses[0].outputSize); + setProgramUniform(pass,"ORIG.texture_size",shaderPasses[0].textureSize); + setTextureParameter(pass,"ORIG.texture",shaderPasses[0].tex,shaderPasses[1].linearFilter); + setTexCoordsParameter(pass,"ORIG.tex_coord",shaderPasses[1].vertexBuffer); + + /* PREV parameter + */ + if(prevPasses[0].tex) { + setProgramUniform(pass,"PREV.video_size",prevPasses[0].imageSize); + setProgramUniform(pass,"PREV.texture_size",prevPasses[0].textureSize); + setTextureParameter(pass,"PREV.texture",prevPasses[0].tex,shaderPasses[1].linearFilter); + setTexCoordsParameter(pass,"PREV.tex_coord",prevPasses[0].vertexBuffer); + } + + /* PREV1-6 parameters + */ + for(int i=1;i2) { + for(int i=1;i &map, CGparameter param) +{ + parameterEntry mapEntry; + while (param) { + if(cgGetParameterType(param)==CG_STRUCT) + fillParameterMap(map,cgGetFirstStructParameter(param)); + else + if (cgGetParameterDirection(param) == CG_IN && cgGetParameterVariability(param) == CG_VARYING) { + mapEntry.rIndex = cgGetParameterResourceIndex(param); + mapEntry.semantic = cgGetParameterSemantic(param); + mapEntry.isKnownParam = isKnownParameter(cgGetParameterName(param)); + if(map.size()CreateVertexDeclaration(vElems,&vertexDeclaration); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex declaration"), hr); + } + if(pass.vertexDeclaration) + pass.vertexDeclaration->Release(); + pass.vertexDeclaration = vertexDeclaration; + delete [] vElems; +} diff --git a/win32/CD3DCG.h b/win32/CD3DCG.h new file mode 100644 index 00000000..f46d8aa6 --- /dev/null +++ b/win32/CD3DCG.h @@ -0,0 +1,264 @@ +/*********************************************************************************** + 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 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + 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 used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + 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 emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + 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) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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 CGD3DCG_H +#define CGD3DCG_H + +#include +#include +#include +#include +#include "CCGShader.h" +#include +#include + +class CD3DCG +{ +private: + typedef struct _parameterEntry { + unsigned long rIndex; + const char* semantic; + bool isKnownParam; + UINT streamNumber; + } parameterEntry; + typedef struct _shaderPass { + cgScaleParams scaleParams; + bool linearFilter; + CGprogram cgVertexProgram, cgFragmentProgram; + LPDIRECT3DTEXTURE9 tex; + LPDIRECT3DVERTEXBUFFER9 vertexBuffer; + LPDIRECT3DVERTEXDECLARATION9 vertexDeclaration; + std::vector parameterMap; + + D3DXVECTOR2 outputSize; + D3DXVECTOR2 textureSize; + + _shaderPass() {cgVertexProgram=NULL; + cgFragmentProgram=NULL; + tex=NULL; + vertexBuffer=NULL; + vertexDeclaration=NULL;} + } shaderPass; + typedef struct _prevPass { + LPDIRECT3DTEXTURE9 tex; + LPDIRECT3DVERTEXBUFFER9 vertexBuffer; + D3DXVECTOR2 imageSize; + D3DXVECTOR2 textureSize; + _prevPass() {tex=NULL; + vertexBuffer=NULL;} + _prevPass(const shaderPass &pass) {tex = pass.tex; + vertexBuffer = pass.vertexBuffer; + imageSize = pass.outputSize; + textureSize = pass.textureSize;} + } prevPass; + typedef struct _lookupTexture { + char id[PATH_MAX]; + LPDIRECT3DTEXTURE9 tex; + bool linearFilter; + _lookupTexture() {tex=NULL;} + } lookupTexture; + + std::vector shaderPasses; + std::vector lookupTextures; + std::deque prevPasses; + + bool shaderLoaded; + void checkForCgError(const char *situation); + void setVertexStream(IDirect3DVertexBuffer9 *vertexBuffer,D3DXVECTOR2 inputSize,D3DXVECTOR2 textureSize,D3DXVECTOR2 outputSize); + void setViewport(DWORD x, DWORD y, DWORD width, DWORD height); + void setShaderVars(int pass); + void ensureTextureSize(LPDIRECT3DTEXTURE9 &tex, D3DXVECTOR2 &texSize, D3DXVECTOR2 wantedSize,bool renderTarget); + void fillParameterMap(std::vector &map, CGparameter param); + void setupVertexDeclaration(shaderPass &pass); + void calculateMatrix(); + + LPDIRECT3DDEVICE9 pDevice; + CGcontext cgContext; + float frameCnt; + D3DXMATRIX mvp; + +public: + CD3DCG(CGcontext cgContext,LPDIRECT3DDEVICE9 pDevice); + ~CD3DCG(void); + + bool LoadShader(const TCHAR *shaderFile); + void Render(LPDIRECT3DTEXTURE9 &origTex, D3DXVECTOR2 textureSize, D3DXVECTOR2 inputSize, D3DXVECTOR2 viewportSize, D3DXVECTOR2 windowSize); + void ClearPasses(); + void OnLostDevice(); + void OnResetDevice(); +}; + +#endif diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index 5f5b3f49..a801c168 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -198,6 +198,13 @@ #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif +const D3DVERTEXELEMENT9 CDirect3D::vertexElems[4] = { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END() + }; + /* CDirect3D::CDirect3D() sets default values for the variables */ @@ -223,8 +230,9 @@ CDirect3D::CDirect3D() shaderTimeElapsed = 0; frameCount = 0; cgContext = NULL; - cgVertexProgram = cgFragmentProgram = NULL; cgAvailable = false; + cgShader = NULL; + vertexDeclaration = NULL; } /* CDirect3D::~CDirect3D() @@ -272,12 +280,18 @@ bool CDirect3D::Initialize(HWND hWnd) return false; } - hr = pDevice->CreateVertexBuffer(sizeof(triangleStripVertices),D3DUSAGE_WRITEONLY,FVF_COORDS_TEX,D3DPOOL_MANAGED,&vertexBuffer,NULL); + hr = pDevice->CreateVertexBuffer(sizeof(vertexStream),D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&vertexBuffer,NULL); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr); return false; } + hr = pDevice->CreateVertexDeclaration(vertexElems,&vertexDeclaration); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex declaration"), hr); + return false; + } + cgAvailable = loadCgFunctions(); if(cgAvailable) { @@ -286,9 +300,13 @@ bool CDirect3D::Initialize(HWND hWnd) if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); } + cgShader = new CD3DCG(cgContext,pDevice); } pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + pDevice->SetRenderState( D3DRS_ZENABLE, FALSE); + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); @@ -305,11 +323,14 @@ void CDirect3D::DeInitialize() DestroyDrawSurface(); SetShader(NULL); + if(cgShader) { + delete cgShader; + cgShader = NULL; + } if(cgContext) { cgDestroyContext(cgContext); cgContext = NULL; } - if(cgAvailable) cgD3D9SetDevice(NULL); @@ -318,6 +339,11 @@ void CDirect3D::DeInitialize() vertexBuffer = NULL; } + if(vertexDeclaration) { + vertexDeclaration->Release(); + vertexDeclaration = NULL; + } + if( pDevice ) { pDevice->Release(); pDevice = NULL; @@ -344,7 +370,9 @@ bool CDirect3D::SetShader(const TCHAR *file) SetShaderCG(NULL); SetShaderHLSL(NULL); shader_type = D3D_SHADER_NONE; - if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) { + if(file!=NULL && + (lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) || + (lstrlen(file)>4 && _tcsncicmp(&file[lstrlen(file)-4],TEXT(".cgp"),4)==0)){ return SetShaderCG(file); } else { return SetShaderHLSL(file); @@ -373,62 +401,16 @@ void CDirect3D::checkForCgError(const char *situation) bool CDirect3D::SetShaderCG(const TCHAR *file) { - TCHAR errorMsg[MAX_PATH + 50]; - HRESULT hr; - - if(cgFragmentProgram) { - cgDestroyProgram(cgFragmentProgram); - cgFragmentProgram = NULL; - } - if(cgVertexProgram) { - cgDestroyProgram(cgVertexProgram); - cgVertexProgram = NULL; - } - - if (file == NULL || *file==TEXT('\0')) - return true; - if(!cgAvailable) { - MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), - MB_OK|MB_ICONEXCLAMATION); + if(file) + MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), + MB_OK|MB_ICONEXCLAMATION); return false; } - CGprofile vertexProfile = cgD3D9GetLatestVertexProfile(); - CGprofile pixelProfile = cgD3D9GetLatestPixelProfile(); - - const char** vertexOptions = cgD3D9GetOptimalOptions(vertexProfile); - const char** pixelOptions = cgD3D9GetOptimalOptions(pixelProfile); - - char *fileContents = ReadShaderFileContents(file); - if(!fileContents) + if(!cgShader->LoadShader(file)) return false; - cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, - vertexProfile, "main_vertex", vertexOptions); - - checkForCgError("Compiling vertex program"); - - cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, - pixelProfile, "main_fragment", pixelOptions); - - checkForCgError("Compiling fragment program"); - - delete [] fileContents; - - if(!cgVertexProgram || !cgFragmentProgram) { - return false; - } - - if(cgVertexProgram) { - hr = cgD3D9LoadProgram(cgVertexProgram,true,0); - hr = cgD3D9BindProgram(cgVertexProgram); - } - if(cgFragmentProgram) { - hr = cgD3D9LoadProgram(cgFragmentProgram,false,0); - hr = cgD3D9BindProgram(cgFragmentProgram); - } - shader_type = D3D_SHADER_CG; return true; @@ -628,7 +610,7 @@ void CDirect3D::SetShaderVars(bool setMatrix) effect->SetTexture( rubyLUTName, rubyLUT[i] ); } } - } else if(shader_type == D3D_SHADER_CG) { + }/* else if(shader_type == D3D_SHADER_CG) { D3DXVECTOR2 videoSize; D3DXVECTOR2 textureSize; @@ -640,6 +622,7 @@ void CDirect3D::SetShaderVars(bool setMatrix) outputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; outputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; frameCnt = (float)++frameCount; + videoSize = textureSize; #define setProgramUniform(program,varname,floats)\ {\ @@ -676,7 +659,7 @@ void CDirect3D::SetShaderVars(bool setMatrix) if(cgpModelViewProj) cgD3D9SetUniformMatrix(cgpModelViewProj,&mvp); } - } + }*/ } /* CDirect3D::Render @@ -745,22 +728,16 @@ void CDirect3D::Render(SSurface Src) SetViewport(); } - pDevice->BeginScene(); - pDevice->SetTexture(0, drawSurface); - pDevice->SetFVF(FVF_COORDS_TEX); + pDevice->SetVertexDeclaration(vertexDeclaration); pDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERTEX)); - SetShaderVars(); - - if(shader_type == D3D_SHADER_CG) { - cgD3D9BindProgram(cgFragmentProgram); - cgD3D9BindProgram(cgVertexProgram); - } - if (shader_type == D3D_SHADER_HLSL) { - UINT passes; + SetShaderVars(); + SetFiltering(); + UINT passes; + pDevice->BeginScene(); hr = effect->Begin(&passes, 0); for(UINT pass = 0; pass < passes; pass++ ) { effect->BeginPass(pass); @@ -768,11 +745,30 @@ void CDirect3D::Render(SSurface Src) effect->EndPass(); } effect->End(); - } else { - pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); - } + pDevice->EndScene(); - pDevice->EndScene(); + } else { + if(shader_type == D3D_SHADER_CG) { + RECT displayRect; + //Get maximum rect respecting AR setting + displayRect=CalculateDisplayRect(dPresentParams.BackBufferWidth,dPresentParams.BackBufferHeight, + dPresentParams.BackBufferWidth,dPresentParams.BackBufferHeight); + cgShader->Render(drawSurface, + D3DXVECTOR2((float)quadTextureSize, (float)quadTextureSize), + D3DXVECTOR2((float)afterRenderWidth, (float)afterRenderHeight), + D3DXVECTOR2((float)(displayRect.right - displayRect.left), + (float)(displayRect.bottom - displayRect.top)), + D3DXVECTOR2((float)dPresentParams.BackBufferWidth, (float)dPresentParams.BackBufferHeight)); + } + + SetFiltering(); + + pDevice->SetVertexDeclaration(vertexDeclaration); + + pDevice->BeginScene(); + pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); + pDevice->EndScene(); + } pDevice->Present(NULL, NULL, NULL, NULL); @@ -876,13 +872,18 @@ void CDirect3D::SetupVertices() float tX = (float)afterRenderWidth / (float)quadTextureSize; float tY = (float)afterRenderHeight / (float)quadTextureSize; - triangleStripVertices[0] = VERTEX(0.0f,0.0f,0.0f,0.0f,tY); - triangleStripVertices[1] = VERTEX(0.0f,1.0f,0.0f,0.0f,0.0f); - triangleStripVertices[2] = VERTEX(1.0f,0.0f,0.0f,tX,tY); - triangleStripVertices[3] = VERTEX(1.0f,1.0f,0.0f,tX,0.0f); + vertexStream[0] = VERTEX(0.0f,0.0f,0.0f,0.0f,tY,0.0f,0.0f); + vertexStream[1] = VERTEX(0.0f,1.0f,0.0f,0.0f,0.0f,0.0f,0.0f); + vertexStream[2] = VERTEX(1.0f,0.0f,0.0f,tX,tY,0.0f,0.0f); + vertexStream[3] = VERTEX(1.0f,1.0f,0.0f,tX,0.0f,0.0f,0.0f); + for(int i=0;i<4;i++) { + vertexStream[i].x -= 0.5f / (float)dPresentParams.BackBufferWidth; + vertexStream[i].y += 0.5f / (float)dPresentParams.BackBufferHeight; + } + HRESULT hr = vertexBuffer->Lock(0,0,&pLockedVertexBuffer,NULL); - memcpy(pLockedVertexBuffer,triangleStripVertices,sizeof(triangleStripVertices)); + memcpy(pLockedVertexBuffer,vertexStream,sizeof(vertexStream)); vertexBuffer->Unlock(); } @@ -952,6 +953,7 @@ bool CDirect3D::ResetDevice() DestroyDrawSurface(); if(cgAvailable) { + cgShader->OnLostDevice(); cgD3D9SetDevice(NULL); } @@ -989,14 +991,7 @@ bool CDirect3D::ResetDevice() if(cgAvailable) { cgD3D9SetDevice(pDevice); - } - - if(GUI.BilinearFilter) { - pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - } else { - pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + cgShader->OnResetDevice(); } pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); @@ -1111,3 +1106,14 @@ bool CDirect3D::ApplyDisplayChanges(void) return ChangeRenderSize(0,0); } + +void CDirect3D::SetFiltering() +{ + if(GUI.BilinearFilter) { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + } else { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + } +} diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 54cd9e00..459184e7 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -185,6 +185,7 @@ #include #include "cgFunctions.h" +#include "CD3DCG.h" #include "render.h" #include "wsnes9x.h" @@ -195,9 +196,10 @@ typedef struct _VERTEX { float x, y, z; float tx, ty; + float lutx, luty; _VERTEX() {} - _VERTEX(float x,float y,float z,float tx,float ty) { - this->x=x;this->y=y;this->z=z;this->tx=tx;this->ty=ty; + _VERTEX(float x,float y,float z,float tx,float ty,float lutx, float luty) { + this->x=x;this->y=y;this->z=z;this->tx=tx;this->ty=ty;this->lutx=lutx;this->luty=luty; } } VERTEX; //our custom vertex with a constuctor for easier assignment @@ -218,15 +220,19 @@ private: unsigned int quadTextureSize; //size of the texture (only multiples of 2) bool fullscreen; //are we currently displaying in fullscreen mode - VERTEX triangleStripVertices[4]; //the 4 vertices that make up our display rectangle + VERTEX vertexStream[4]; //the 4 vertices that make up our display rectangle + + static const D3DVERTEXELEMENT9 vertexElems[4]; + LPDIRECT3DVERTEXDECLARATION9 vertexDeclaration; LPD3DXEFFECT effect; LPDIRECT3DTEXTURE9 rubyLUT[MAX_SHADER_TEXTURES]; CGcontext cgContext; - CGprogram cgVertexProgram, cgFragmentProgram; current_d3d_shader_type shader_type; bool cgAvailable; + CD3DCG *cgShader; + float shaderTimer; int shaderTimeStart; int shaderTimeElapsed; @@ -239,6 +245,7 @@ private: void SetViewport(); void SetupVertices(); bool ResetDevice(); + void SetFiltering(); void SetShaderVars(bool setMatrix = false); bool SetShader(const TCHAR *file); bool SetShaderHLSL(const TCHAR *file); diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 8ca7f4a2..7f0032a8 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -1,3 +1,179 @@ +/*********************************************************************************** + 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 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + + (c) Copyright 2002 - 2011 zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2011 BearOso, + OV2 + + + 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 used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + 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 emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + 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) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2011 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2011 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2011 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 "CGLCG.h" #include "wsnes9x.h" #include "win32_display.h" @@ -7,7 +183,7 @@ #define max(a, b) (((a) > (b)) ? (a) : (b)) #endif -float npot(float desired) +static float npot(float desired) { float out=512.0; while(outtex) glDeleteTextures(1,&it->tex); } + for(glPrevDeque::iterator it=prevPasses.begin();it!=prevPasses.end();it++) { + if(it->tex) + glDeleteTextures(1,&it->tex); + } shaderPasses.clear(); lookupTextures.clear(); + prevPasses.clear(); + // prevPasses deque is always filled with PREV + PREV1-6 elements + prevPasses.resize(7); shaderLoaded = false; } @@ -126,11 +308,6 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) ClearPasses(); - if(prevTex) { - glDeleteTextures(1,&prevTex); - prevTex=0; - } - if (shaderFile == NULL || *shaderFile==TEXT('\0')) return true; @@ -251,15 +428,16 @@ bool CGLCG::LoadShader(const TCHAR *shaderFile) glTexCoordPointer(2,GL_FLOAT,0,lut_coords); glClientActiveTexture(GL_TEXTURE0); - /* generate a texture that we can swap with the original texture - and pass back to the main opengl code + /* generate textures and set default values for the pref-filled PREV deque. */ - glGenTextures(1,&prevTex); - glBindTexture(GL_TEXTURE_2D,prevTex); - glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,512,512,0,GL_RGB,GL_UNSIGNED_SHORT_5_6_5,NULL); - glBindTexture(GL_TEXTURE_2D,0); - prevTexSize.x = prevTexSize.y = prevTexImageSize.x = prevTexImageSize.y = 0; - memset(prevTexCoords,0,sizeof(prevTexCoords)); + for(int i=0;i0) { + float prev_videoSize[2] = {prevPasses[0].videoSize.x,prevPasses[0].videoSize.y}; + float prev_textureSize[2] = {prevPasses[0].textureSize.x,prevPasses[0].textureSize.y}; - setProgram2fv(pass,"PREV.video_size",prev_videoSize); - setProgram2fv(pass,"PREV.texture_size",prev_textureSize); - setTextureParameter(pass,"PREV.texture",prevTex); - setTexCoordsParameter(pass,"PREV.tex_coord",prevTexCoords); + setProgram2fv(pass,"PREV.video_size",prev_videoSize); + setProgram2fv(pass,"PREV.texture_size",prev_textureSize); + setTextureParameter(pass,"PREV.texture",prevPasses[0].tex); + setTexCoordsParameter(pass,"PREV.tex_coord",prevPasses[0].texCoords); + } + + /* PREV1-6 parameters + */ + for(int i=1;i +#include typedef struct _xySize { double x; double y; + operator CONST FLOAT* () const; } xySize; class CGLCG @@ -45,6 +223,13 @@ private: fbo=NULL; tex=NULL;} } shaderPass; + typedef struct _prevPass { + GLuint tex; + xySize videoSize; + xySize textureSize; + GLfloat texCoords[8]; + _prevPass() {tex=0;} + } prevPass; typedef struct _lookupTexture { char id[PATH_MAX]; GLuint tex; @@ -53,8 +238,12 @@ private: typedef std::vector glPassVector; typedef std::vector glLutVector; + typedef std::deque glPrevDeque; + typedef std::vector glAttribParams; glPassVector shaderPasses; glLutVector lookupTextures; + glPrevDeque prevPasses; + glAttribParams cgAttribParams; bool fboFunctionsLoaded; bool shaderLoaded; @@ -62,16 +251,13 @@ private: void checkForCgError(const char *situation); void setTexCoords(int pass,xySize inputSize,xySize textureSize,bool topdown=false); void setShaderVars(int pass); + void resetAttribParams(); bool loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData); bool loadTGA(const TCHAR *filename, STGA& tgaFile); CGcontext cgContext; int frameCnt; static const GLfloat lut_coords[8]; - GLuint prevTex; - xySize prevTexSize; - xySize prevTexImageSize; - GLfloat prevTexCoords[8]; PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; diff --git a/win32/cgFunctions.cpp b/win32/cgFunctions.cpp index e458f486..0d19757d 100644 --- a/win32/cgFunctions.cpp +++ b/win32/cgFunctions.cpp @@ -192,6 +192,16 @@ CGGES cgGetErrorString = NULL; CGGLL cgGetLastListing = NULL; CGCP cgCreateProgram = NULL; CGDP cgDestroyProgram = NULL; +CGGPRI cgGetParameterResourceIndex = NULL; +CGGFP cgGetFirstParameter = NULL; +CGGNEP cgGetNextParameter = NULL; +CGGPD cgGetParameterDirection = NULL; +CGGPS cgGetParameterSemantic = NULL; +CGGRS cgGetResourceString = NULL; +CGGPV cgGetParameterVariability = NULL; +CGGPT cgGetParameterType = NULL; +CGGFSP cgGetFirstStructParameter = NULL; +CGGPN cgGetParameterName = NULL; //cgD3D9.dll CGD3DSD cgD3D9SetDevice = NULL; CGD3DBP cgD3D9BindProgram = NULL; @@ -201,6 +211,9 @@ CGD3DGOO cgD3D9GetOptimalOptions = NULL; CGD3DLP cgD3D9LoadProgram = NULL; CGD3DSUM cgD3D9SetUniformMatrix = NULL; CGD3DSU cgD3D9SetUniform = NULL; +CGD3DST cgD3D9SetTexture = NULL; +CGD3DGVD cgD3D9GetVertexDeclaration = NULL; +CGD3DSSS cgD3D9SetSamplerState = NULL; //cggl.dll CGGLSSMP cgGLSetStateMatrixParameter = NULL; CGGLSP2FV cgGLSetParameter2fv = NULL; @@ -215,6 +228,7 @@ CGGLSTP cgGLSetTextureParameter = NULL; CGGLETP cgGLEnableTextureParameter = NULL; CGGLSPP cgGLSetParameterPointer = NULL; CGGLECS cgGLEnableClientState = NULL; +CGGLDCS cgGLDisableClientState = NULL; bool loadCgFunctions() { @@ -241,6 +255,16 @@ bool loadCgFunctions() cgGetLastListing = (CGGLL)GetProcAddress(hCgDll,"cgGetLastListing"); cgCreateProgram = (CGCP)GetProcAddress(hCgDll,"cgCreateProgram"); cgDestroyProgram = (CGDP)GetProcAddress(hCgDll,"cgDestroyProgram"); + cgGetParameterResourceIndex = (CGGPRI)GetProcAddress(hCgDll,"cgGetParameterResourceIndex"); + cgGetFirstParameter = (CGGFP)GetProcAddress(hCgDll,"cgGetFirstParameter"); + cgGetNextParameter = (CGGNEP)GetProcAddress(hCgDll,"cgGetNextParameter"); + cgGetParameterDirection = (CGGPD)GetProcAddress(hCgDll,"cgGetParameterDirection"); + cgGetParameterSemantic = (CGGPS)GetProcAddress(hCgDll,"cgGetParameterSemantic"); + cgGetResourceString = (CGGRS)GetProcAddress(hCgDll,"cgGetResourceString"); + cgGetParameterVariability = (CGGPV)GetProcAddress(hCgDll,"cgGetParameterVariability"); + cgGetParameterType = (CGGPT)GetProcAddress(hCgDll,"cgGetParameterType"); + cgGetFirstStructParameter = (CGGFSP)GetProcAddress(hCgDll,"cgGetFirstStructParameter"); + cgGetParameterName = (CGGPN)GetProcAddress(hCgDll,"cgGetParameterName"); //cgD3D9.dll cgD3D9SetDevice = (CGD3DSD)GetProcAddress(hCgD3D9Dll,"cgD3D9SetDevice"); cgD3D9BindProgram = (CGD3DBP)GetProcAddress(hCgD3D9Dll,"cgD3D9BindProgram"); @@ -250,6 +274,9 @@ bool loadCgFunctions() cgD3D9LoadProgram = (CGD3DLP)GetProcAddress(hCgD3D9Dll,"cgD3D9LoadProgram"); cgD3D9SetUniformMatrix = (CGD3DSUM)GetProcAddress(hCgD3D9Dll,"cgD3D9SetUniformMatrix"); cgD3D9SetUniform = (CGD3DSU)GetProcAddress(hCgD3D9Dll,"cgD3D9SetUniform"); + cgD3D9SetTexture = (CGD3DST)GetProcAddress(hCgD3D9Dll,"cgD3D9SetTexture"); + cgD3D9GetVertexDeclaration = (CGD3DGVD)GetProcAddress(hCgD3D9Dll,"cgD3D9GetVertexDeclaration"); + cgD3D9SetSamplerState = (CGD3DSSS)GetProcAddress(hCgD3D9Dll,"cgD3D9SetSamplerState"); //cggl.dll cgGLSetStateMatrixParameter = (CGGLSSMP)GetProcAddress(hCgGLDll,"cgGLSetStateMatrixParameter"); cgGLSetParameter2fv = (CGGLSP2FV)GetProcAddress(hCgGLDll,"cgGLSetParameter2fv"); @@ -264,6 +291,7 @@ bool loadCgFunctions() cgGLEnableTextureParameter = (CGGLETP)GetProcAddress(hCgGLDll,"cgGLEnableTextureParameter"); cgGLSetParameterPointer = (CGGLSPP)GetProcAddress(hCgGLDll,"cgGLSetParameterPointer"); cgGLEnableClientState = (CGGLECS)GetProcAddress(hCgGLDll,"cgGLEnableClientState"); + cgGLDisableClientState = (CGGLDCS)GetProcAddress(hCgGLDll,"cgGLDisableClientState"); if( //cg.dll @@ -275,6 +303,16 @@ bool loadCgFunctions() !cgGetLastListing || !cgCreateProgram || !cgDestroyProgram || + !cgGetParameterResourceIndex || + !cgGetFirstParameter || + !cgGetNextParameter || + !cgGetParameterDirection || + !cgGetParameterSemantic || + !cgGetResourceString || + !cgGetParameterVariability || + !cgGetParameterType || + !cgGetFirstStructParameter || + !cgGetParameterName || //cgD3D9.dll !cgD3D9SetDevice || !cgD3D9BindProgram || @@ -284,6 +322,9 @@ bool loadCgFunctions() !cgD3D9LoadProgram || !cgD3D9SetUniformMatrix || !cgD3D9SetUniform || + !cgD3D9SetTexture || + !cgD3D9GetVertexDeclaration || + !cgD3D9SetSamplerState || //cggl.dll !cgGLSetStateMatrixParameter || !cgGLSetParameter2fv || @@ -297,7 +338,8 @@ bool loadCgFunctions() !cgGLSetTextureParameter || !cgGLEnableTextureParameter || !cgGLSetParameterPointer || - !cgGLEnableClientState) { + !cgGLEnableClientState || + !cgGLDisableClientState) { unloadCgLibrary(); return false; } @@ -325,6 +367,16 @@ void unloadCgLibrary() cgGetLastListing = NULL; cgCreateProgram = NULL; cgDestroyProgram = NULL; + cgGetParameterResourceIndex = NULL; + cgGetFirstParameter = NULL; + cgGetNextParameter = NULL; + cgGetParameterDirection = NULL; + cgGetParameterSemantic = NULL; + cgGetResourceString = NULL; + cgGetParameterVariability = NULL; + cgGetParameterType = NULL; + cgGetFirstStructParameter = NULL; + cgGetParameterName = NULL; //cgD3D9.dll cgD3D9SetDevice = NULL; cgD3D9BindProgram = NULL; @@ -334,6 +386,9 @@ void unloadCgLibrary() cgD3D9LoadProgram = NULL; cgD3D9SetUniformMatrix = NULL; cgD3D9SetUniform = NULL; + cgD3D9SetTexture = NULL; + cgD3D9GetVertexDeclaration = NULL; + cgD3D9SetSamplerState = NULL; //cggl.dll cgGLSetStateMatrixParameter = NULL; cgGLSetParameter2fv = NULL; @@ -343,4 +398,6 @@ void unloadCgLibrary() cgGLSetOptimalOptions = NULL; cgGLLoadProgram = NULL; cgGLBindProgram = NULL; + cgGLEnableClientState = NULL; + cgGLDisableClientState = NULL; } diff --git a/win32/cgFunctions.h b/win32/cgFunctions.h index 636dd833..500e5e41 100644 --- a/win32/cgFunctions.h +++ b/win32/cgFunctions.h @@ -205,6 +205,26 @@ typedef CG_API CGprogram (CGENTRY *CGCP)(CGcontext context, CGenum program_type, extern CGCP cgCreateProgram; typedef CG_API void (CGENTRY *CGDP)(CGprogram program); extern CGDP cgDestroyProgram; +typedef CG_API unsigned long (CGENTRY *CGGPRI)(CGparameter param); +extern CGGPRI cgGetParameterResourceIndex; +typedef CG_API CGparameter (CGENTRY *CGGFP)(CGprogram program, CGenum name_space); +extern CGGFP cgGetFirstParameter; +typedef CG_API CGparameter (CGENTRY *CGGNEP)(CGparameter current); +extern CGGNEP cgGetNextParameter; +typedef CG_API CGenum (CGENTRY *CGGPD)(CGparameter param); +extern CGGPD cgGetParameterDirection; +typedef CG_API const char * (CGENTRY *CGGPS)(CGparameter param); +extern CGGPS cgGetParameterSemantic; +typedef CG_API const char * (CGENTRY *CGGRS)(CGresource resource); +extern CGGRS cgGetResourceString; +typedef CG_API CGenum (CGENTRY *CGGPV)(CGparameter param); +extern CGGPV cgGetParameterVariability; +typedef CG_API CGtype (CGENTRY *CGGPT)(CGparameter param); +extern CGGPT cgGetParameterType; +typedef CG_API CGparameter (CGENTRY *CGGFSP)(CGparameter param); +extern CGGFSP cgGetFirstStructParameter; +typedef CG_API const char * (CGENTRY *CGGPN)(CGparameter param); +extern CGGPN cgGetParameterName; //cgD3D9.dll typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSD)(IDirect3DDevice9 *pDevice); @@ -223,6 +243,12 @@ typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSUM)(CGparameter param, const D extern CGD3DSUM cgD3D9SetUniformMatrix; typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSU)(CGparameter param, const void *floats); extern CGD3DSU cgD3D9SetUniform; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DST)(CGparameter param, IDirect3DBaseTexture9 *tex); +extern CGD3DST cgD3D9SetTexture; +typedef CGD3D9DLL_API CGbool (CGD3D9ENTRY *CGD3DGVD)(CGprogram prog, D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH]); +extern CGD3DGVD cgD3D9GetVertexDeclaration; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSSS)(CGparameter param, D3DSAMPLERSTATETYPE type, DWORD value); +extern CGD3DSSS cgD3D9SetSamplerState; //cggl.dll typedef CGGL_API void (CGGLENTRY *CGGLSSMP)(CGparameter param, CGGLenum matrix, CGGLenum transform); @@ -251,7 +277,8 @@ typedef CGGL_API void (CGGLENTRY *CGGLSPP)(CGparameter param, GLint fsize, GLenu extern CGGLSPP cgGLSetParameterPointer; typedef CGGL_API void (CGGLENTRY *CGGLECS)(CGparameter param); extern CGGLECS cgGLEnableClientState; - +typedef CGGL_API void (CGGLENTRY *CGGLDCS)(CGparameter param); +extern CGGLDCS cgGLDisableClientState; //cgfunctions.cpp bool loadCgFunctions(); diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 94d0dbb1..454e4439 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -3137,6 +3137,14 @@ RelativePath=".\CCGShader.h" > + + + + From 245364b7c1edfa5d35e11d6c17c9d686aff4ee11 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 10 Dec 2011 19:17:03 +0100 Subject: [PATCH 074/130] Win32: use D3DTADDRESS_BORDER in every pass --- win32/CD3DCG.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win32/CD3DCG.cpp b/win32/CD3DCG.cpp index 29dbfd8d..f15de2d1 100644 --- a/win32/CD3DCG.cpp +++ b/win32/CD3DCG.cpp @@ -546,6 +546,8 @@ void CD3DCG::Render(LPDIRECT3DTEXTURE9 &origTex, D3DXVECTOR2 textureSize, pDevice->SetVertexDeclaration(shaderPasses[i].vertexDeclaration); setVertexStream(shaderPasses[i].vertexBuffer, shaderPasses[i-1].outputSize,shaderPasses[i-1].textureSize,shaderPasses[i].outputSize); + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); + pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); From 1678b71d1e855e7204ab579b0a166f882c205859 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:46:12 -0600 Subject: [PATCH 075/130] Prioritize GLX_EXT_swap_control over GLX_SGI_swap_control. --- gtk/src/gtk_display_driver_opengl.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp index 5e692c43..153bfc17 100644 --- a/gtk/src/gtk_display_driver_opengl.cpp +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -905,16 +905,19 @@ S9xOpenGLDisplayDriver::swap_control (int enable) queried = TRUE; } - if (glSwapInterval) - { - glSwapInterval (enable); - } - if (glXSwapIntervalEXT) { + if (glSwapInterval) + glSwapInterval (0); + glXSwapIntervalEXT (display, xwindow, enable); } + else if (glSwapInterval) + { + glSwapInterval (enable); + } + return; } From 1b0c82ed3b2b5aaf1b120cf883fa24ba1dcd6031 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:47:28 -0600 Subject: [PATCH 076/130] Clean up configure.ac slightly. --- gtk/configure.ac | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/gtk/configure.ac b/gtk/configure.ac index f946b695..95024a23 100644 --- a/gtk/configure.ac +++ b/gtk/configure.ac @@ -342,15 +342,6 @@ if test yes = "$with_jma_decomp"; then JMA=yes fi -dnl FIXME: There is a third case (OLD) that is missed with this. -if test yes = "$with_newblend"; then - CFLAGS="$CFLAGS -DNEW_COLOUR_BLENDING" -else - #OLD_COLOUR_BLENDING hasn't been default for a while - # SYSDEFINES="$SYSDEFINES"' -DOLD_COLOUR_BLENDING' - : -fi - if test yes = "$with_zlib"; then AC_CHECK_HEADERS(zlib.h) AC_CHECK_LIB(z, gzread, [ @@ -432,7 +423,7 @@ if test $ac_cv_my_sar_int8 = yes && \ CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR" fi -CFLAGS="$CFLAGS -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DNO_INLINE_SET_GET -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" +CFLAGS="$CFLAGS -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" CXXFLAGS="$CFLAGS" From 2337ab3ed01e56bcdd77608319b732527788392c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 14 Dec 2011 02:47:44 -0600 Subject: [PATCH 077/130] Optimize hermite resampler slightly. The vtable lookup on read probably still hurts fine-granularity sound systems like OSS. --- apu/hermite_resampler.h | 46 ++++++++++++----------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 30ee1032..eda547f4 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,25 +14,20 @@ class HermiteResampler : public Resampler { protected: - double r_step; - double r_frac; - int r_left[4], r_right[4]; + float r_step; + float r_frac; + int r_left[4], r_right[4]; - double - hermite (double mu1, double a, double b, double c, double d) + static inline float + hermite (float mu1, float a, float b, float c, float d) { - const double tension = 0.0; //-1 = low, 0 = normal, 1 = high - const double bias = 0.0; //-1 = left, 0 = even, 1 = right - - double mu2, mu3, m0, m1, a0, a1, a2, a3; + float mu2, mu3, m0, m1, a0, a1, a2, a3; mu2 = mu1 * mu1; mu3 = mu2 * mu1; - m0 = (b - a) * (1 + bias) * (1 - tension) / 2; - m0 += (c - b) * (1 - bias) * (1 - tension) / 2; - m1 = (c - b) * (1 + bias) * (1 - tension) / 2; - m1 += (d - c) * (1 - bias) * (1 - tension) / 2; + m0 = (c - a) * 0.5; + m1 = (d - b) * 0.5; a0 = +2 * mu3 - 3 * mu2 + 1; a1 = mu3 - 2 * mu2 + mu1; @@ -72,6 +67,7 @@ class HermiteResampler : public Resampler read (short *data, int num_samples) { int i_position = start >> 1; + int max_samples = buffer_size >> 1; short *internal_buffer = (short *) buffer; int o_position = 0; int consumed = 0; @@ -80,22 +76,6 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - int max_samples = buffer_size >> 1; - const double margin_of_error = 1.0e-10; - - if (fabs(r_step - 1.0) < margin_of_error) - { - data[o_position] = (short) s_left; - data[o_position + 1] = (short) s_right; - - o_position += 2; - i_position += 2; - if (i_position >= max_samples) - i_position -= max_samples; - consumed += 2; - - continue; - } while (r_frac <= 1.0 && o_position < num_samples) { @@ -113,14 +93,14 @@ class HermiteResampler : public Resampler r_left [1] = r_left [2]; r_left [2] = r_left [3]; r_left [3] = s_left; - + r_right[0] = r_right[1]; r_right[1] = r_right[2]; r_right[2] = r_right[3]; - r_right[3] = s_right; - + r_right[3] = s_right; + r_frac -= 1.0; - + i_position += 2; if (i_position >= max_samples) i_position -= max_samples; From d6c81119556b6512221e8ad07ac26a86a5bf8e6a Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 29 Dec 2011 15:49:03 +0100 Subject: [PATCH 078/130] Win32: add missing outputmode description --- win32/wconfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index 95981ee2..bafa2130 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -861,7 +861,7 @@ void WinRegisterConfigItems() AddBoolC("DisplayFrameCount", Settings.DisplayMovieFrame, true, "true to show the frame count when a movie is playing"); #undef CATEGORY #define CATEGORY "Display\\Win" - AddUIntC("OutputMethod", GUI.outputMethod, 1, "0=DirectDraw, 1=Direct3D"); + AddUIntC("OutputMethod", GUI.outputMethod, 1, "0=DirectDraw, 1=Direct3D, 2=OpenGL"); AddUIntC("FilterType", GUI.Scale, 0, filterString); AddUIntC("FilterHiRes", GUI.ScaleHiRes, 0, filterString2); AddBoolC("BlendHiRes", GUI.BlendHiRes, true, "true to horizontally blend Hi-Res images (better transparency effect on filters that do not account for this)"); From 8a8d7b56469e169377f59955dc374112c159592a Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 29 Dec 2011 15:49:29 +0100 Subject: [PATCH 079/130] Display all netplay connection error messages --- netplay.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/netplay.cpp b/netplay.cpp index dff5d0a3..f0f15315 100644 --- a/netplay.cpp +++ b/netplay.cpp @@ -350,6 +350,7 @@ on the remote machine on this port?"); errno #endif ); + S9xNPSetError(buf); S9xNPDisconnect (); } return (FALSE); From dee8895db2ee59da1abe491228a029f9f28916be Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 2 Jan 2012 01:48:51 +0100 Subject: [PATCH 080/130] Allow membased rom/state load/save, add libsnes interface (Themaister) --- apu/SNES_SPC.h | 4 + conffile.cpp | 10 +- conffile.h | 3 +- gtk/Makefile.am | 2 +- libsnes/Makefile | 53 + libsnes/libsnes-win32.vcproj | 794 ++++++++++++++ libsnes/libsnes.cpp | 754 ++++++++++++++ libsnes/libsnes.def | 47 + libsnes/libsnes.hpp | 1264 +++++++++++++++++++++++ libsnes/link.T | 4 + loadzip.cpp | 11 +- macosx/snes9x.xcodeproj/project.pbxproj | 32 +- memmap.cpp | 191 ++-- memmap.h | 9 +- netplay.cpp | 3 +- port.h | 42 +- server.cpp | 3 +- snapshot.cpp | 23 + snapshot.h | 3 + snes9x.cpp | 8 +- snes9x.h | 53 +- reader.cpp => stream.cpp | 281 ++++- reader.h => stream.h | 97 +- unix/Makefile.in | 2 +- win32/snes9xw.vcproj | 72 +- 25 files changed, 3527 insertions(+), 238 deletions(-) create mode 100644 libsnes/Makefile create mode 100644 libsnes/libsnes-win32.vcproj create mode 100644 libsnes/libsnes.cpp create mode 100644 libsnes/libsnes.def create mode 100644 libsnes/libsnes.hpp create mode 100644 libsnes/link.T rename reader.cpp => stream.cpp (64%) rename reader.h => stream.h (73%) diff --git a/apu/SNES_SPC.h b/apu/SNES_SPC.h index baf90063..9655c929 100644 --- a/apu/SNES_SPC.h +++ b/apu/SNES_SPC.h @@ -120,6 +120,8 @@ public: uint8_t dsp_reg_value( int, int ); int dsp_envx_value( int ); + uint8_t *apuram(); + //// Snes9x Debugger #ifdef DEBUGGER @@ -313,4 +315,6 @@ inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; } +inline SNES_SPC::uint8_t * SNES_SPC::apuram() { return m.ram.ram; } + #endif diff --git a/conffile.cpp b/conffile.cpp index b7f60298..0582a9da 100644 --- a/conffile.cpp +++ b/conffile.cpp @@ -209,16 +209,16 @@ void ConfigFile::Clear(void){ } bool ConfigFile::LoadFile(const char *filename){ - STREAM s; + FSTREAM s; bool ret=false; const char *n, *n2; - if((s=OPEN_STREAM(filename, "r"))){ + if((s=OPEN_FSTREAM(filename, "r"))){ n=filename; n2=strrchr(n, '/'); if(n2!=NULL) n=n2+1; n2=strrchr(n, '\\'); if(n2!=NULL) n=n2+1; - LoadFile(new fReader(s), n); - CLOSE_STREAM(s); + LoadFile(new fStream(s), n); + CLOSE_FSTREAM(s); ret = true; } else { fprintf(stderr, "Couldn't open conffile "); @@ -228,7 +228,7 @@ bool ConfigFile::LoadFile(const char *filename){ } -void ConfigFile::LoadFile(Reader *r, const char *name){ +void ConfigFile::LoadFile(Stream *r, const char *name){ curConfigFile = this; string l, key, val; string section; diff --git a/conffile.h b/conffile.h index 24c8c20e..54339fd0 100644 --- a/conffile.h +++ b/conffile.h @@ -188,7 +188,6 @@ #include "unzip/unzip.h" #endif #include "snes9x.h" -#include "reader.h" #ifndef MAX # define MAX(a,b) ((a) > (b)? (a) : (b)) @@ -203,7 +202,7 @@ class ConfigFile { // return false on failure bool LoadFile(const char *filename); - void LoadFile(Reader *r, const char *name=NULL); + void LoadFile(Stream *r, const char *name=NULL); // return false if key does not exist or is empty bool Exists(const char *key); diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 14d99899..f5f08f45 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -157,7 +157,7 @@ snes9x_gtk_SOURCES += \ ../dma.cpp \ ../snes9x.cpp \ ../globals.cpp \ - ../reader.cpp \ + ../stream.cpp \ ../conffile.cpp \ ../bsx.cpp \ ../logger.cpp \ diff --git a/libsnes/Makefile b/libsnes/Makefile new file mode 100644 index 00000000..b72f8819 --- /dev/null +++ b/libsnes/Makefile @@ -0,0 +1,53 @@ +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx +endif +endif + +ifeq ($(platform), unix) + TARGET := libsnes.so + fpic := -fPIC + SHARED := -shared -Wl,--version-script=link.T +else ifeq ($(platform), osx) + TARGET := libsnes.dylib + fpic := -fPIC + SHARED := -dynamiclib +else + TARGET := snes.dll + CC = gcc + CXX = g++ + SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T + CXXFLAGS += -D__WIN32__ -D__WIN32_LIBSNES__ +endif + +OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libsnes.o + +CXX = g++ +CC = gcc +INCLUDES = -I. -I.. -I../apu/ + +CXXFLAGS += -O3 -fomit-frame-pointer -fno-exceptions -fno-rtti -pedantic -Wall -W -Wno-unused-parameter $(fpic) +CXXFLAGS += -DHAVE_STRINGS_H -DHAVE_STDINT_H -DRIGHTSHIFT_IS_SAR +CFLAGS = $(CXXFLAGS) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CXX) $(fpic) $(SHARED) $(INCLUDES) -o $@ $(OBJECTS) -lm + +%.o: %.cpp + $(CXX) $(INCLUDES) $(CXXFLAGS) -c -o $@ $< + +%.o: %.c + $(CC) $(INCLUDES) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(OBJECTS) $(TARGET) + diff --git a/libsnes/libsnes-win32.vcproj b/libsnes/libsnes-win32.vcproj new file mode 100644 index 00000000..a278a6d6 --- /dev/null +++ b/libsnes/libsnes-win32.vcproj @@ -0,0 +1,794 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libsnes/libsnes.cpp b/libsnes/libsnes.cpp new file mode 100644 index 00000000..7c47ede1 --- /dev/null +++ b/libsnes/libsnes.cpp @@ -0,0 +1,754 @@ +#include "libsnes.hpp" + +#include "snes9x.h" +#include "memmap.h" +#include "srtc.h" +#include "apu/apu.h" +#include "gfx.h" +#include "snapshot.h" +#include "controls.h" +#include "cheats.h" +#include "movie.h" +#include "logger.h" +#include "display.h" +#include "conffile.h" +#include +#ifndef __WIN32__ +#include +#endif +#include +#include +#include + + +static snes_video_refresh_t s9x_video_cb = NULL; +static snes_audio_sample_t s9x_audio_cb = NULL; +static snes_input_poll_t s9x_poller_cb = NULL; +static snes_input_state_t s9x_input_state_cb = NULL; + +void snes_set_video_refresh(snes_video_refresh_t cb) +{ + s9x_video_cb = cb; +} + +void snes_set_audio_sample(snes_audio_sample_t cb) +{ + s9x_audio_cb = cb; +} + +void snes_set_input_poll(snes_input_poll_t cb) +{ + s9x_poller_cb = cb; +} + +void snes_set_input_state(snes_input_state_t cb) +{ + s9x_input_state_cb = cb; +} + +static snes_environment_t environ_cb; +static bool use_overscan; +void snes_set_environment(snes_environment_t cb) +{ + environ_cb = cb; +} + +static void S9xAudioCallback(void*) +{ + // Just pick a big buffer. We won't use it all. + static int16_t audio_buf[0x10000]; + + S9xFinalizeSamples(); + size_t avail = S9xGetSampleCount(); + S9xMixSamples((uint8*)audio_buf, avail); + for (size_t i = 0; i < avail; i+=2) + s9x_audio_cb((uint16_t)audio_buf[i], (uint16_t)audio_buf[i + 1]); +} + +const char *snes_library_id() +{ + return "SNES9x v" VERSION; +} + +unsigned snes_library_revision_major() +{ + return 1; +} + +unsigned snes_library_revision_minor() +{ + return 3; +} + +void snes_power() +{ + S9xReset(); +} + +void snes_reset() +{ + S9xMovieUpdateOnReset(); + if (S9xMoviePlaying()) + { + S9xMovieStop(true); + } + S9xSoftReset(); +} + +static unsigned snes_devices[2]; +void snes_set_controller_port_device(bool in_port, unsigned device) +{ + int port = in_port == SNES_PORT_1 ? 0 : 1; + switch (device) + { + case SNES_DEVICE_JOYPAD: + S9xSetController(port, CTL_JOYPAD, 0, 0, 0, 0); + snes_devices[port] = SNES_DEVICE_JOYPAD; + break; + case SNES_DEVICE_MULTITAP: + S9xSetController(port, CTL_MP5, 1, 2, 3, 4); + snes_devices[port] = SNES_DEVICE_MULTITAP; + break; + case SNES_DEVICE_MOUSE: + S9xSetController(port, CTL_MOUSE, 0, 0, 0, 0); + snes_devices[port] = SNES_DEVICE_MOUSE; + break; + case SNES_DEVICE_SUPER_SCOPE: + S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0); + snes_devices[port] = SNES_DEVICE_SUPER_SCOPE; + break; + case SNES_DEVICE_JUSTIFIER: + S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0); + snes_devices[port] = SNES_DEVICE_JUSTIFIER; + break; + case SNES_DEVICE_JUSTIFIERS: + S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0); + snes_devices[port] = SNES_DEVICE_JUSTIFIERS; + break; + default: + fprintf(stderr, "[libsnes]: Invalid device!\n"); + } +} + +void snes_cheat_reset() +{} + +void snes_cheat_set(unsigned, bool, const char*) +{} + +bool snes_load_cartridge_bsx_slotted( + const char *, const uint8_t *, unsigned, + const char *, const uint8_t *, unsigned + ) +{ + return false; +} + +bool snes_load_cartridge_bsx( + const char *, const uint8_t *, unsigned, + const char *, const uint8_t *, unsigned + ) +{ + return false; +} + +bool snes_load_cartridge_sufami_turbo( + const char *, const uint8_t *, unsigned, + const char *, const uint8_t *, unsigned, + const char *, const uint8_t *, unsigned + ) +{ + return false; +} + +bool snes_load_cartridge_super_game_boy( + const char *, const uint8_t *, unsigned, + const char *, const uint8_t *, unsigned + ) +{ + return false; +} + +static void map_buttons(); + + +void snes_init() +{ + if (environ_cb) + { + if (!environ_cb(SNES_ENVIRONMENT_GET_OVERSCAN, &use_overscan)) + use_overscan = false; + + if (use_overscan) + { + snes_geometry geom = {256, 239, 512, 512}; + environ_cb(SNES_ENVIRONMENT_SET_GEOMETRY, &geom); + unsigned pitch = 1024; + environ_cb(SNES_ENVIRONMENT_SET_PITCH, &pitch); + } + } + + memset(&Settings, 0, sizeof(Settings)); + Settings.MouseMaster = TRUE; + Settings.SuperScopeMaster = TRUE; + Settings.JustifierMaster = TRUE; + Settings.MultiPlayer5Master = TRUE; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.SixteenBitSound = TRUE; + Settings.Stereo = TRUE; + Settings.SoundPlaybackRate = 32000; + Settings.SoundInputRate = 32000; + Settings.SupportHiRes = TRUE; + Settings.Transparency = TRUE; + Settings.AutoDisplayMessages = TRUE; + Settings.InitialInfoStringTimeout = 120; + Settings.HDMATimingHack = 100; + Settings.BlockInvalidVRAMAccessMaster = TRUE; + Settings.StopEmulation = TRUE; + Settings.WrongMovieStateProtection = TRUE; + Settings.DumpStreamsMaxFrames = -1; + Settings.StretchScreenshots = 0; + Settings.SnapshotScreenshots = FALSE; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.TurboSkipFrames = 15; + Settings.CartAName[0] = 0; + Settings.CartBName[0] = 0; + Settings.AutoSaveDelay = 1; + + CPU.Flags = 0; + + if (!Memory.Init() || !S9xInitAPU()) + { + Memory.Deinit(); + S9xDeinitAPU(); + fprintf(stderr, "[libsnes]: Failed to init Memory or APU.\n"); + exit(1); + } + + S9xInitSound(16, 0); + S9xSetSoundMute(FALSE); + S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL); + + S9xSetRenderPixelFormat(RGB555); + GFX.Pitch = use_overscan ? 1024 : 2048; + GFX.Screen = (uint16*) calloc(1, GFX.Pitch * 512 * sizeof(uint16)); + S9xGraphicsInit(); + + S9xInitInputDevices(); + for (int i = 0; i < 2; i++) + { + S9xSetController(i, CTL_JOYPAD, i, 0, 0, 0); + snes_devices[i] = SNES_DEVICE_JOYPAD; + } + + S9xUnmapAllControls(); + map_buttons(); + +} + +#define MAP_BUTTON(id, name) S9xMapButton((id), S9xGetCommandT((name)), false) +#define MAKE_BUTTON(pad, btn) (((pad)<<4)|(btn)) + +#define PAD_1 1 +#define PAD_2 2 +#define PAD_3 3 +#define PAD_4 4 +#define PAD_5 5 + +#define BTN_B SNES_DEVICE_ID_JOYPAD_B +#define BTN_Y SNES_DEVICE_ID_JOYPAD_Y +#define BTN_SELECT SNES_DEVICE_ID_JOYPAD_SELECT +#define BTN_START SNES_DEVICE_ID_JOYPAD_START +#define BTN_UP SNES_DEVICE_ID_JOYPAD_UP +#define BTN_DOWN SNES_DEVICE_ID_JOYPAD_DOWN +#define BTN_LEFT SNES_DEVICE_ID_JOYPAD_LEFT +#define BTN_RIGHT SNES_DEVICE_ID_JOYPAD_RIGHT +#define BTN_A SNES_DEVICE_ID_JOYPAD_A +#define BTN_X SNES_DEVICE_ID_JOYPAD_X +#define BTN_L SNES_DEVICE_ID_JOYPAD_L +#define BTN_R SNES_DEVICE_ID_JOYPAD_R +#define BTN_FIRST BTN_B +#define BTN_LAST BTN_R + +#define MOUSE_X SNES_DEVICE_ID_MOUSE_X +#define MOUSE_Y SNES_DEVICE_ID_MOUSE_Y +#define MOUSE_LEFT SNES_DEVICE_ID_MOUSE_LEFT +#define MOUSE_RIGHT SNES_DEVICE_ID_MOUSE_RIGHT +#define MOUSE_FIRST MOUSE_X +#define MOUSE_LAST MOUSE_RIGHT + +#define SCOPE_X SNES_DEVICE_ID_SUPER_SCOPE_X +#define SCOPE_Y SNES_DEVICE_ID_SUPER_SCOPE_Y +#define SCOPE_TRIGGER SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER +#define SCOPE_CURSOR SNES_DEVICE_ID_SUPER_SCOPE_CURSOR +#define SCOPE_TURBO SNES_DEVICE_ID_SUPER_SCOPE_TURBO +#define SCOPE_PAUSE SNES_DEVICE_ID_SUPER_SCOPE_PAUSE +#define SCOPE_FIRST SCOPE_X +#define SCOPE_LAST SCOPE_PAUSE + +#define JUSTIFIER_X SNES_DEVICE_ID_JUSTIFIER_X +#define JUSTIFIER_Y SNES_DEVICE_ID_JUSTIFIER_Y +#define JUSTIFIER_TRIGGER SNES_DEVICE_ID_JUSTIFIER_TRIGGER +#define JUSTIFIER_START SNES_DEVICE_ID_JUSTIFIER_START +#define JUSTIFIER_FIRST JUSTIFIER_X +#define JUSTIFIER_LAST JUSTIFIER_START + +#define BTN_POINTER (BTN_LAST + 1) +#define BTN_POINTER2 (BTN_POINTER + 1) + +static void map_buttons() +{ + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_A), "Joypad1 A"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_B), "Joypad1 B"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_X), "Joypad1 X"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_Y), "Joypad1 Y"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_SELECT), "{Joypad1 Select,Mouse1 L}"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_START), "{Joypad1 Start,Mouse1 R}"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_L), "Joypad1 L"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_R), "Joypad1 R"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_LEFT), "Joypad1 Left"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_RIGHT), "Joypad1 Right"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_UP), "Joypad1 Up"); + MAP_BUTTON(MAKE_BUTTON(PAD_1, BTN_DOWN), "Joypad1 Down"); + S9xMapPointer((BTN_POINTER), S9xGetCommandT("Pointer Mouse1+Superscope+Justifier1"), false); + S9xMapPointer((BTN_POINTER2), S9xGetCommandT("Pointer Mouse2"), false); + + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_A), "Joypad2 A"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_B), "Joypad2 B"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_X), "Joypad2 X"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_Y), "Joypad2 Y"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_SELECT), "{Joypad2 Select,Mouse2 L,Superscope Fire,Justifier1 Trigger}"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_START), "{Joypad2 Start,Mouse2 R,Superscope Cursor,Justifier1 Start}"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_L), "Joypad2 L"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_R), "Joypad2 R"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_LEFT), "Joypad2 Left"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_RIGHT), "Joypad2 Right"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_UP), "{Joypad2 Up,Superscope ToggleTurbo}"); + MAP_BUTTON(MAKE_BUTTON(PAD_2, BTN_DOWN), "{Joypad2 Down,Superscope Pause}"); + + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_A), "Joypad3 A"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_B), "Joypad3 B"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_X), "Joypad3 X"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_Y), "Joypad3 Y"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_SELECT), "Joypad3 Select"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_START), "Joypad3 Start"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_L), "Joypad3 L"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_R), "Joypad3 R"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_LEFT), "Joypad3 Left"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_RIGHT), "Joypad3 Right"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_UP), "Joypad3 Up"); + MAP_BUTTON(MAKE_BUTTON(PAD_3, BTN_DOWN), "Joypad3 Down"); + + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_A), "Joypad4 A"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_B), "Joypad4 B"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_X), "Joypad4 X"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_Y), "Joypad4 Y"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_SELECT), "Joypad4 Select"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_START), "Joypad4 Start"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_L), "Joypad4 L"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_R), "Joypad4 R"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_LEFT), "Joypad4 Left"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_RIGHT), "Joypad4 Right"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_UP), "Joypad4 Up"); + MAP_BUTTON(MAKE_BUTTON(PAD_4, BTN_DOWN), "Joypad4 Down"); + + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_A), "Joypad5 A"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_B), "Joypad5 B"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_X), "Joypad5 X"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_Y), "Joypad5 Y"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_SELECT), "Joypad5 Select"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_START), "Joypad5 Start"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_L), "Joypad5 L"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_R), "Joypad5 R"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_LEFT), "Joypad5 Left"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_RIGHT), "Joypad5 Right"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_UP), "Joypad5 Up"); + MAP_BUTTON(MAKE_BUTTON(PAD_5, BTN_DOWN), "Joypad5 Down"); + +} + +// libsnes uses relative values for analogue devices. +// S9x seems to use absolute values, but do convert these into relative values in the core. (Why?!) +// Hack around it. :) +static int16_t snes_mouse_state[2][2] = {{0}, {0}}; +static int16_t snes_scope_state[2] = {0}; +static int16_t snes_justifier_state[2][2] = {{0}, {0}}; +static void report_buttons() +{ + int _x, _y; + for (int port = SNES_PORT_1; port <= SNES_PORT_2; port++) + { + switch (snes_devices[port]) + { + case SNES_DEVICE_JOYPAD: + for (int i = BTN_FIRST; i <= BTN_LAST; i++) + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JOYPAD, 0, i)); + break; + + case SNES_DEVICE_MULTITAP: + for (int j = 0; j < 4; j++) + for (int i = BTN_FIRST; i <= BTN_LAST; i++) + S9xReportButton(MAKE_BUTTON(j + 2, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MULTITAP, j, i)); + break; + + case SNES_DEVICE_MOUSE: + _x = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_X); + _y = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_Y); + snes_mouse_state[port][0] += _x; + snes_mouse_state[port][1] += _y; + S9xReportPointer(BTN_POINTER + port, snes_mouse_state[port][0], snes_mouse_state[port][1]); + for (int i = MOUSE_LEFT; i <= MOUSE_LAST; i++) + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, i)); + break; + + case SNES_DEVICE_SUPER_SCOPE: + snes_scope_state[0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_X); + snes_scope_state[1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_Y); + S9xReportPointer(BTN_POINTER, snes_scope_state[0], snes_scope_state[1]); + for (int i = SCOPE_TRIGGER; i <= SCOPE_LAST; i++) + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, i)); + break; + + case SNES_DEVICE_JUSTIFIER: + case SNES_DEVICE_JUSTIFIERS: + snes_justifier_state[0][0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_X); + snes_justifier_state[0][1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_Y); + S9xReportPointer(BTN_POINTER, snes_justifier_state[0][0], snes_justifier_state[0][1]); + for (int i = JUSTIFIER_TRIGGER; i <= JUSTIFIER_LAST; i++) + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, i)); + break; + + default: + fprintf(stderr, "[libsnes]: Unknown device...\n"); + + } + } +} + +bool snes_load_cartridge_normal(const char *, const uint8_t *rom_data, unsigned rom_size) +{ + int loaded = Memory.LoadROMMem(rom_data,rom_size); + if (!loaded) + { + fprintf(stderr, "[libsnes]: Rom loading failed...\n"); + return false; + } + + if (environ_cb) + { + snes_system_timing timing; + timing.sample_rate = 32040.5; + if (!Settings.PAL) + timing.fps = 21477272.0 / 357366.0; + else + timing.fps = 21281370.0 / 425568.0; + + environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); + } + + return true; +} + +void snes_run() +{ + s9x_poller_cb(); + report_buttons(); + S9xMainLoop(); +} + +void snes_term() +{ + S9xDeinitAPU(); + Memory.Deinit(); + S9xGraphicsDeinit(); + S9xUnmapAllControls(); +} + + +bool snes_get_region() +{ + return Settings.PAL ? SNES_REGION_PAL : SNES_REGION_NTSC; +} + +uint8_t* snes_get_memory_data(unsigned type) +{ + uint8_t* data; + + switch(type) { + case SNES_MEMORY_CARTRIDGE_RAM: + data = Memory.SRAM; + break; + case SNES_MEMORY_CARTRIDGE_RTC: + data = RTCData.reg; + break; + case SNES_MEMORY_WRAM: + data = Memory.RAM; + break; + case SNES_MEMORY_APURAM: + data = spc_core->apuram(); + break; + case SNES_MEMORY_VRAM: + data = Memory.VRAM; + break; + case SNES_MEMORY_CGRAM: + data = (uint8_t*)PPU.CGDATA; + break; + case SNES_MEMORY_OAM: + data = PPU.OAMData; + break; + default: + data = NULL; + break; + } + + return data; +} + +void snes_unload_cartridge() +{ + +} + +unsigned snes_get_memory_size(unsigned type) +{ + unsigned size; + + switch(type) { + case SNES_MEMORY_CARTRIDGE_RAM: + size = (unsigned) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0); + if (size > 0x20000) + size = 0x20000; + break; + case SNES_MEMORY_CARTRIDGE_RTC: + size = (Settings.SRTC || Settings.SPC7110RTC)?20:0; + break; + case SNES_MEMORY_WRAM: + size = 128 * 1024; + break; + case SNES_MEMORY_VRAM: + case SNES_MEMORY_APURAM: + size = 64 * 1024; + break; + case SNES_MEMORY_CGRAM: + size = 512; + break; + case SNES_MEMORY_OAM: + size = 512 + 32; + break; + default: + size = 0; + break; + } + + return size; +} + +void snes_set_cartridge_basename(const char*) +{} + +unsigned snes_serialize_size() +{ + return S9xFreezeSize(); +} + +bool snes_serialize(uint8_t *data, unsigned size) +{ + if (S9xFreezeGameMem(data,size) == FALSE) + return false; + + return true; +} + +bool snes_unserialize(const uint8_t* data, unsigned size) +{ + if (S9xUnfreezeGameMem(data,size) != SUCCESS) + return false; + return true; +} + +// Pitch 2048 -> 1024, only done once per res-change. +static void pack_frame(uint16_t *frame, int width, int height) +{ + for (int y = 1; y < height; y++) + { + uint16_t *src = frame + y * 1024; + uint16_t *dst = frame + y * 512; + + memcpy(dst, src, width * sizeof(uint16_t)); + } +} + +// Pitch 1024 -> 2048, only done once per res-change. +static void stretch_frame(uint16_t *frame, int width, int height) +{ + for (int y = height - 1; y >= 0; y--) + { + uint16_t *src = frame + y * 512; + uint16_t *dst = frame + y * 1024; + + memcpy(dst, src, width * sizeof(uint16_t)); + } +} + +bool8 S9xDeinitUpdate(int width, int height) +{ + if (use_overscan) + { + if (height == 224) + { + memmove(GFX.Screen + (GFX.Pitch / 2) * 7, GFX.Screen, GFX.Pitch * height); + memset(GFX.Screen, 0x00, GFX.Pitch * 7); + memset(GFX.Screen + (GFX.Pitch / 2) * (7 + 224), 0, GFX.Pitch * 8); + height = 239; + } + else if (height == 448) + { + memmove(GFX.Screen + (GFX.Pitch / 2) * 15, GFX.Screen, GFX.Pitch * height); + memset(GFX.Screen, 0x00, GFX.Pitch * 15); + memset(GFX.Screen + (GFX.Pitch / 2) * (15 + 224), 0x00, GFX.Pitch * 17); + height = 478; + } + } + else // libsnes classic behavior + { + if (height == 448 || height == 478) + { + if (GFX.Pitch == 2048) + pack_frame(GFX.Screen, width, height); + GFX.Pitch = 1024; + } + else + { + if (GFX.Pitch == 1024) + stretch_frame(GFX.Screen, width, height); + GFX.Pitch = 2048; + } + } + + s9x_video_cb(GFX.Screen, width, height); + return TRUE; +} + +bool8 S9xContinueUpdate(int width, int height) +{ + return S9xDeinitUpdate(width, height); +} + + +// Dummy functions that should probably be implemented correctly later. +void S9xParsePortConfig(ConfigFile&, int) {} +void S9xSyncSpeed() {} +//void S9xPollPointer(int, short*, short*) {} +const char* S9xStringInput(const char* in) { return in; } +const char* S9xGetFilename(const char* in, s9x_getdirtype) { return in; } +const char* S9xGetDirectory(s9x_getdirtype) { return NULL; } +void S9xInitInputDevices() {} +const char* S9xChooseFilename(unsigned char) { return NULL; } +void S9xHandlePortCommand(s9xcommand_t, short, short) {} +bool S9xPollButton(unsigned int, bool*) { return false; } +void S9xToggleSoundChannel(int) {} +const char* S9xGetFilenameInc(const char* in, s9x_getdirtype) { return NULL; } +const char* S9xBasename(const char* in) { return in; } +bool8 S9xInitUpdate() { return TRUE; } +void S9xExtraUsage() {} +bool8 S9xOpenSoundDevice() { return TRUE; } +void S9xMessage(int, int, const char*) {} +bool S9xPollAxis(unsigned int, short*) { return FALSE; } +void S9xSetPalette() {} +void S9xParseArg(char**, int&, int) {} +void S9xExit() {} +bool S9xPollPointer(unsigned int, short*, short*) { return false; } +const char *S9xChooseMovieFilename(unsigned char) { return NULL; } + +bool8 S9xOpenSnapshotFile(const char* filepath, bool8 read_only, STREAM *file) +{ + if(read_only) + { + if((*file = OPEN_STREAM(filepath, "rb")) != 0) + { + return (TRUE); + } + } + else + { + if((*file = OPEN_STREAM(filepath, "wb")) != 0) + { + return (TRUE); + } + } + return (FALSE); +} + +void S9xCloseSnapshotFile(STREAM file) +{ + CLOSE_STREAM(file); +} + +void S9xAutoSaveSRAM() +{ + return; +} + +#ifndef __WIN32__ +// S9x weirdness. +void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +{ + *drive = 0; + + const char *slash = strrchr(path, SLASH_CHAR), + *dot = strrchr(path, '.'); + + if (dot && slash && dot < slash) + dot = NULL; + + if (!slash) + { + *dir = 0; + + strcpy(fname, path); + + if (dot) + { + fname[dot - path] = 0; + strcpy(ext, dot + 1); + } + else + *ext = 0; + } + else + { + strcpy(dir, path); + dir[slash - path] = 0; + + strcpy(fname, slash + 1); + + if (dot) + { + fname[dot - slash - 1] = 0; + strcpy(ext, dot + 1); + } + else + *ext = 0; + } +} + +void _makepath (char *path, const char *, const char *dir, const char *fname, const char *ext) +{ + if (dir && *dir) + { + strcpy(path, dir); + strcat(path, SLASH_STR); + } + else + *path = 0; + + strcat(path, fname); + + if (ext && *ext) + { + strcat(path, "."); + strcat(path, ext); + } +} +#endif // __WIN32__ diff --git a/libsnes/libsnes.def b/libsnes/libsnes.def new file mode 100644 index 00000000..c1017351 --- /dev/null +++ b/libsnes/libsnes.def @@ -0,0 +1,47 @@ +LIBRARY snes + +EXPORTS + +snes_library_id + +snes_library_revision_major +snes_library_revision_minor + +snes_set_video_refresh +snes_set_audio_sample +snes_set_input_poll +snes_set_input_state + +snes_set_environment + +snes_set_controller_port_device +snes_set_cartridge_basename + +snes_init +snes_term +snes_power +snes_reset +snes_run + +snes_serialize_size +snes_serialize +snes_unserialize + +snes_cheat_reset +snes_cheat_set + +snes_load_cartridge_normal + +snes_load_cartridge_bsx_slotted + +snes_load_cartridge_bsx + +snes_load_cartridge_sufami_turbo + +snes_load_cartridge_super_game_boy + +snes_unload_cartridge + +snes_get_region +snes_get_memory_data +snes_get_memory_size \ No newline at end of file diff --git a/libsnes/libsnes.hpp b/libsnes/libsnes.hpp new file mode 100644 index 00000000..78a49816 --- /dev/null +++ b/libsnes/libsnes.hpp @@ -0,0 +1,1264 @@ +#ifndef LIBSNES_HPP +#define LIBSNES_HPP + +#include "port.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////// +// LIBSNES Super Nintendo emulation API +// +// Things you should know: +// - Linking against libsnes requires a C++ compiler. It can be compiled with +// a C99 compiler if you #include and if your C99 compiler's +// bool type is compatible with the bool type used by the C++ compiler used +// to compile libsnes. +// - libsnes supports exactly one emulated SNES; if you want to run two SNESes +// in a single process, you'll need to link against or dlopen() two +// different copies of the library. +// +// Typical usage of the libsnes API looks like this: +// +// 1. Call snes_init() to initialize the library. +// 2. Tell libsnes which callback should be called for each event (see the +// documentation on the individual callback types below. +// 3. Call one of the snes_load_cartridge_* functions to load cartridge data +// into the emulated SNES. +// 4. If the physical cart had any non-volatile storage, there may be data from +// a previous emulation run that needs to be loaded. Find the storage buffer +// by calling the snes_get_memory_* functions and load any saved data into +// it. +// 5. Call snes_set_controller_port_device() to connect appropriate controllers +// to the emulated SNES. +// 6. Call snes_get_region() to determine the intended screen refresh rate for +// this cartridge.. +// 7. Call snes_run() to emulate a single frame. Before snes_run() returns, the +// installed callbacks will be called - possibly multiple times. +// 8. When you're done, call snes_term() to free all memory allocated +// associated with the emulated SNES. +// +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constants {{{ + +// These constants represent the two controller ports on the front of the SNES, +// for use with the snes_set_controller_port_device() function and the +// snes_input_state_t callback. +#define SNES_PORT_1 0 +#define SNES_PORT_2 1 + +// These constants represent the different kinds of controllers that can be +// connected to a controller port, for use with the +// snes_set_controller_port_device() function and the snes_input_state_t +// callback. +#define SNES_DEVICE_NONE 0 +#define SNES_DEVICE_JOYPAD 1 +#define SNES_DEVICE_MULTITAP 2 +#define SNES_DEVICE_MOUSE 3 +#define SNES_DEVICE_SUPER_SCOPE 4 +#define SNES_DEVICE_JUSTIFIER 5 +#define SNES_DEVICE_JUSTIFIERS 6 + +// These constants represent the button and axis inputs on various controllers, +// for use with the snes_input_state_t callback. +#define SNES_DEVICE_ID_JOYPAD_B 0 +#define SNES_DEVICE_ID_JOYPAD_Y 1 +#define SNES_DEVICE_ID_JOYPAD_SELECT 2 +#define SNES_DEVICE_ID_JOYPAD_START 3 +#define SNES_DEVICE_ID_JOYPAD_UP 4 +#define SNES_DEVICE_ID_JOYPAD_DOWN 5 +#define SNES_DEVICE_ID_JOYPAD_LEFT 6 +#define SNES_DEVICE_ID_JOYPAD_RIGHT 7 +#define SNES_DEVICE_ID_JOYPAD_A 8 +#define SNES_DEVICE_ID_JOYPAD_X 9 +#define SNES_DEVICE_ID_JOYPAD_L 10 +#define SNES_DEVICE_ID_JOYPAD_R 11 + +#define SNES_DEVICE_ID_MOUSE_X 0 +#define SNES_DEVICE_ID_MOUSE_Y 1 +#define SNES_DEVICE_ID_MOUSE_LEFT 2 +#define SNES_DEVICE_ID_MOUSE_RIGHT 3 + +#define SNES_DEVICE_ID_SUPER_SCOPE_X 0 +#define SNES_DEVICE_ID_SUPER_SCOPE_Y 1 +#define SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER 2 +#define SNES_DEVICE_ID_SUPER_SCOPE_CURSOR 3 +#define SNES_DEVICE_ID_SUPER_SCOPE_TURBO 4 +#define SNES_DEVICE_ID_SUPER_SCOPE_PAUSE 5 + +#define SNES_DEVICE_ID_JUSTIFIER_X 0 +#define SNES_DEVICE_ID_JUSTIFIER_Y 1 +#define SNES_DEVICE_ID_JUSTIFIER_TRIGGER 2 +#define SNES_DEVICE_ID_JUSTIFIER_START 3 + +// These constants will be returned by snes_get_region(), representing the +// region of the last loaded cartridge. +#define SNES_REGION_NTSC 0 +#define SNES_REGION_PAL 1 + +// These constants represent the kinds of non-volatile memory a SNES cartridge +// might have, for use with the snes_get_memory_* functions. +#define SNES_MEMORY_CARTRIDGE_RAM 0 +#define SNES_MEMORY_CARTRIDGE_RTC 1 +#define SNES_MEMORY_BSX_RAM 2 +#define SNES_MEMORY_BSX_PRAM 3 +#define SNES_MEMORY_SUFAMI_TURBO_A_RAM 4 +#define SNES_MEMORY_SUFAMI_TURBO_B_RAM 5 +#define SNES_MEMORY_GAME_BOY_RAM 6 +#define SNES_MEMORY_GAME_BOY_RTC 7 + +// These constants represent the various kinds of volatile storage the SNES +// offers, to allow libsnes clients to implement things like cheat-searching +// and certain kinds of debugging. They are for use with the snes_get_memory_* +// functions. +#define SNES_MEMORY_WRAM 100 +#define SNES_MEMORY_APURAM 101 +#define SNES_MEMORY_VRAM 102 +#define SNES_MEMORY_OAM 103 +#define SNES_MEMORY_CGRAM 104 + +// SSNES extension. Not required to be implemented for a working implementation. +#define SNES_ENVIRONMENT_GET_FULLPATH 0 // const char ** -- Full path of game loaded. +#define SNES_ENVIRONMENT_SET_GEOMETRY 1 // const struct snes_geometry * -- Window geometry information for the system/game. +#define SNES_ENVIRONMENT_SET_PITCH 2 // const unsigned * -- Pitch of game image. +#define SNES_ENVIRONMENT_GET_OVERSCAN 3 // bool * -- Boolean value whether or not the implementation should use overscan. +#define SNES_ENVIRONMENT_SET_TIMING 4 // const struct snes_system_timing * -- Set exact timings of the system. + // Used primarily for video recording. + +struct snes_geometry +{ + unsigned base_width; // Nominal video width of system. + unsigned base_height; // Nominal video height of system. + unsigned max_width; // Maximum possible width of system. + unsigned max_height; // Maximum possible height of system. +}; + +struct snes_system_timing +{ + double fps; + double sample_rate; +}; + +typedef bool (*snes_environment_t)(unsigned cmd, void *data); + +// Must be called before calling snes_init(). +void snes_set_environment(snes_environment_t); +//// + + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Callback types {{{ +// +// In order to deliver controller input to the emulated SNES, and retrieve +// video frames and audio samples, you will need to register callbacks. + +// snes_audio_sample_t: +// +// This callback delivers a stereo audio sample pair generated by the +// emulated SNES. +// +// This function is called once for every audio frame (one sample from left +// and right channels). The SNES generates audio samples at a rate of about +// 32040Hz (varies from unit to unit). +// +// Because the SNES generates video at exactly 59.94fps and most computer +// monitors only support a 60fps refresh rate, real-time emulation needs to +// run slightly fast so that each computer frame displays one emulated SNES +// frame. Because the emulation runs slightly fast, and because most +// consumer audio hardware does not play audio at precisely the requested +// sample rate, you'll likely need to let the end-user tweak the effective +// sample rate by 100Hz or so in either direction. +// +// Although the parameters are declared as unsigned for historical reasons, +// the data they contain is actually signed. To work with the audio (e.g. +// resample), you will need to reinterpret the sample value: +// +// int16_t real_left = *(int16_t*)(&left); +// +// Parameters: +// +// left: +// A signed 16-bit integer containing the next audio sample from the +// left audio channel. Yes, it's declared as unsigned for historical +// reasons. +// +// right: +// A signed 16-bit integer containing the next audio sample from the +// right audio channel. Yes, it's declared as unsigned for historical +// reasons. +// + +typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right); + + +// snes_video_refresh_t: +// +// This callback delivers a single SNES frame, generated by the emulated +// SNES. The same memory buffer may be re-used later, so take a copy of the +// data if you want to refer to it after your callback returns. +// +// The framebuffer is an array of unsigned 16-bit pixels, in a somewhat +// complicated format. A quick refresher on SNES video modes: +// - The basic SNES video-mode renders 256 pixels per scanline for a total +// of 224 scanlines. +// - When "overscan" mode is enabled, the SNES renders a few extra +// scanlines at the end of the frame, for a total of 239 scanlines. +// - When "hi-res" mode is enabled, the SNES speeds up its pixel rendering +// to fit 512 pixels per scanline. +// - Normally the SNES renders its pixels to one field of the interlaced +// NTSC signal, but if "interlaced" mode is enabled the SNES renders +// a second set of scanlines inbetween the regular set, for a total of +// 448 (normal) or 478 (overscan) scanlines. +// +// Thus, the framebuffer memory layout for a standard 256x240 frame looks +// something like this (note that 'height' has been reduced to 4 or 8 for +// these examples): +// +// 0 1024b +// ,---------------------------------------. +// |====== width ======|...................| -. +// |.......................................| | +// |===================|...................| | +// |.......................................| +- height = 4 +// |===================|...................| | +// |.......................................| | +// |===================|...................| | +// |.......................................| -' +// `---------------------------------------' +// +// A hi-res frame would look like this: +// +// 0 1024b +// ,---------------------------------------. +// |================ width ================| -. +// |.......................................| | +// |=======================================| | +// |.......................................| +- height = 4 +// |=======================================| | +// |.......................................| | +// |=======================================| | +// |.......................................| -' +// `---------------------------------------' +// +// An interlaced frame would look like this: +// +// 0 1024b +// ,---------------------------------------. +// |====== width ======|...................| -. +// |===================|...................| | +// |===================|...................| | +// |===================|...................| +- height = 8 +// |===================|...................| | +// |===================|...................| | +// |===================|...................| | +// |===================|...................| -' +// `---------------------------------------' +// +// And of course a hi-res, interlaced frame would look like this: +// +// 0 1024b +// ,---------------------------------------. +// |================ width ================| -. +// |=======================================| | +// |=======================================| | +// |=======================================| |+- height = 8 +// |=======================================| | +// |=======================================| | +// |=======================================| | +// |=======================================| -' +// `---------------------------------------' +// +// More succinctly: +// - the buffer begins at the top-left of the frame +// - the first "width" bytes contain the first scanline. +// - if the emulated SNES is in an interlaced video-mode (that is, if the +// "height" parameter" is 448 or 478) then the second scanline begins at +// an offset of 1024 bytes (512 pixels) after the first. +// - otherwise the second scanline begins at an offset of 2048 bytes (1024 +// pixels) after the first. +// - there are "height" scanlines in total. +// +// Each pixel contains a 15-bit RGB tuple: 0RRRRRGGGGGBBBBB (XRGB1555) +// +// Example code: +// +// void pack_frame (uint16_t * restrict out, const uint16_t * restrict in, +// unsigned width, unsigned height) +// { +// // Normally our pitch is 2048 bytes. +// int pitch_pixels = 1024; +// // If we have an interlaced mode, pitch is 1024 bytes. +// if ( height == 448 || height == 478 ) +// pitch_pixels = 512; +// +// for ( int y = 0; y < height; y++ ) +// { +// const uint16_t *src = in + y * pitch_pixels; +// uint16_t *dst = out + y * width; +// +// memcpy(dst, src, width * sizeof(uint16_t)); +// } +// } +// +// Parameters: +// +// data: +// a pointer to the beginning of the framebuffer described above. +// +// width: +// the width of the frame, in pixels. +// +// height: +// the number of scanlines in the frame. + +typedef void (*snes_video_refresh_t)(const uint16_t *data, unsigned width, + unsigned height); + +// snes_input_poll_t: +// +// This callback requests that you poll your input devices for events, if +// required. +// +// Generally called once per frame before the snes_input_state_t callback is +// called. +// + +typedef void (*snes_input_poll_t)(void); + +// snes_input_state_t: +// +// This callback asks for information about the state of a particular input. +// +// The callback may be called multiple times per frame with the same +// parameters. +// +// The callback might not be called at all, if the software running in the +// emulated SNES does not try to probe the controllers. +// +// The callback will not be called for a particular port if DEVICE_NONE is +// connected to it. +// +// If you wish to emulate any kind of turbo-fire, etc. then you will need to +// put that logic into this callback. +// +// Parameters: +// +// port: +// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which +// controller port you should report. +// +// device: +// One of the SNES_DEVICE_* constants describing which type of device +// is currently connected to the given port. +// +// index: +// A number describing which of the devices connected to the port is +// being reported. It's only useful for SNES_DEVICE_MULTITAP and +// SNES_DEVICE_JUSTIFIERS - for other device types, this parameter is +// always 0. +// +// id: +// One of the SNES_DEVICE_ID_* constants for the given device, +// describing which button or axis is being reported (for +// SNES_DEVICE_MULTITAP, use the SNES_DEVICE_ID_JOYPAD_* IDs; for +// SNES_DEVICE_JUSTIFIERS use the SNES_DEVICE_ID_JUSTIFIER_* IDs.). +// +// Returns: +// +// An integer representing the state of the described button or axis. +// +// - If it represents a digital input such as SNES_DEVICE_ID_JOYPAD_B or +// SNES_DEVICE_ID_MOUSE_LEFT), return 1 if the button is pressed, and +// 0 otherwise. +// - If "id" is SNES_DEVICE_ID_MOUSE_X or SNES_DEVICE_ID_MOUSE_Y then +// return the relative movement of the mouse during the current frame; +// values outside the range -127 to +127 will be clamped. +// - If "id" is one of the light-gun axes (such as +// SNES_DEVICE_ID_JUSTIFIER_Y or SNES_DEVICE_ID_SUPER_SCOPE_X), you +// should return the relative movement of the pointing device during the +// current frame. + +typedef int16_t (*snes_input_state_t)(bool port, unsigned device, + unsigned index, unsigned id); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// libsnes setup {{{ +// +// These functions are used to get information about and manipulate the libsnes +// library itself, not the emulated SNES it implements. + +// snes_library_id: +// +// Returns a human readable string describing this libsnes implementation. +// It is not supposed to be parsed or used in any other way than being +// printed to screen on request by user or otherwise. +// +// Returns: +// +// A human-readable string describing this implementation. + +const char* snes_library_id(void); + + +// snes_library_revision_major: +// +// Returns the major API version of this libsnes implementation. +// +// This number is increased every time there is a compatibility-breaking +// change to the libsnes API. At startup, your program should call this +// function and compare the return value to the major API version the +// program was designed to work with. If they are different, your program +// will (very likely) not work with this libsnes implementation. +// +// For example, if your program was designed to work with the libsnes API +// whose major.minor revision was 1.5, and this function returns a major +// version of 2, you have a problem. +// +// Returns: +// +// An integer, the major API version of this libsnes implementation. + +unsigned snes_library_revision_major(void); + +// snes_library_revision_minor: +// +// Returns the minor API version of this libsnes implementation. +// +// This number is increased every time there is a backwards-compatible +// change to the libsnes API. At startup, your program should call this +// function and compare the return value to the minor API version the +// program was designed to work with. If the return value is less than the +// expected minor version, your program will (very likely) not work with +// this libsnes implementation. +// +// For example, if your program was designed to work with the libsnes API +// whose major.minor revision was 1.5, and this libsnes implementation's +// major.minor version is 1.3, it's probably missing features you require. +// On the other hand, if this libsnes implementation's major.minor version +// is 1.9, it probably has extra fancy features you don't need to worry +// about. +// +// Returns: +// +// An integer, the minor API version of this libsnes implementation. + +unsigned snes_library_revision_minor(void); + +// snes_init: +// +// Initializes the libsnes implementation. +// +// This function must be called exactly once before any other library +// functions are called. + +void snes_init(void); + +// snes_term: +// +// Shuts down the libsnes implementation. +// +// This function must be called exactly once. Once called, you should not +// call any other libsnes functions besides (perhaps) snes_init(). + +void snes_term(void); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Callback registration {{{ +// +// Note that all callbacks should be set up before snes_run() is called for the +// first time. + +// snes_set_video_refresh: +// +// Sets the callback that will receive new video frames. +// +// See the documentation for snes_video_refresh_t for details. +// +// Parameters: +// +// A pointer to a function matching the snes_video_refresh_t call +// signature. + +void snes_set_video_refresh(snes_video_refresh_t); + +// snes_set_audio_sample +// +// Sets the callback that will receive new audio sample pairs. +// +// See the documentation for snes_audio_sample_t for details. +// +// Parameters: +// +// A pointer to a function matching the snes_audio_sample_t call +// signature. + +void snes_set_audio_sample(snes_audio_sample_t); + +// snes_set_input_poll: +// +// Sets the callback that will be notified to poll input devices. +// +// See the documentation for snes_input_poll_t for details. +// +// Parameters: +// +// A pointer to a function matching the snes_input_poll_t call signature. + +void snes_set_input_poll(snes_input_poll_t); + +// snes_set_input_state: +// +// Sets the callback that will be used to read input device state. +// +// See the documentation for snes_input_state_t for details. +// +// Parameters: +// +// A pointer to a function matching the snes_input_state_t call signature. + +void snes_set_input_state(snes_input_state_t); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// SNES operation {{{ +// +// Functions for manipulating the emulated SNES. + +// snes_set_controller_port_device: +// +// Sets the input device connected to a given controller port. +// +// Connecting a device to a port implicitly removes any device previously +// connected to that port. To remove a device without connecting a new one, +// pass DEVICE_NONE as the device parameter. From this point onward, the +// callback passed to set_input_state_cb() will be called with the +// appropriate device, index and id parameters. +// +// If this function is never called, the default is to have a DEVICE_JOYPAD +// connected to both ports. +// +// Calling this callback from inside the set_input_state_cb() has undefined +// results, so don't do that. +// +// Parameters: +// +// port: +// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which +// controller port is being configured. +// +// device: +// One of the SNES_DEVICE_* constants describing which type of device +// should be connected to the given port. Note that some devices can +// only be connected to SNES_PORT_2. Attempting to connect +// a port-2-only device to SNES_PORT_1 has undefined results. +// +// These devices work in either port: +// - SNES_DEVICE_NONE: No device is connected to this port. +// - SNES_DEVICE_JOYPAD: A standard SNES gamepad. +// - SNES_DEVICE_MULTITAP: A multitap controller, which acts like +// 4 SNES_DEVICE_JOYPADs. Your input state callback will be +// passed "id" parameters between 0 and 3, inclusive. +// - SNES_DEVICE_MOUSE: A SNES mouse controller, as shipped with +// Mario Paint. +// +// These devices only work properly when connected to port 2: +// - SNES_DEVICE_SUPER_SCOPE: A Nintendo Super Scope light-gun +// device. +// - SNES_DEVICE_JUSTIFIER: A Konami Justifier light-gun device. +// - SNES_DEVICE_JUSTIFIERS: Two Konami Justifier light-gun +// devices, daisy-chained together. Your input state callback +// will be passed "id" parameters 0 and 1. + +void snes_set_controller_port_device(bool port, unsigned device); + +// snes_power: +// +// Turns the emulated console off and back on. +// +// This functionality is sometimes called "hard reset" and guarantees that +// all hardware state is reset to a reasonable default. +// +// Before bsnes v070r07, this resets the controller ports to both contain +// SNES_DEVICE_JOYPADs. +// +// This requires that a cartridge is loaded. + +void snes_power(void); + +// snes_reset: +// +// Presses the "reset" button on the emulated SNES. +// +// This functionality is sometimes called "soft reset". Most hardware state +// is reset to a reasonable befault, but not all. +// +// As of bsnes v073r01, this function (as a side-effect) resets the +// controller ports to both contain SNES_DEVICE_JOYPADs. +// +// This requires that a cartridge is loaded. + +void snes_reset(void); + +// snes_run(): +// +// Runs the emulated SNES until the end of the next video frame. +// +// Usually causes each registered callback to be called before returning. +// +// This function will run as fast as possible. It is up to the caller to +// make sure that the game runs at the intended speed. +// +// For optimal A/V sync, make sure that the audio callback never blocks for +// longer than a frame (approx 16ms for NTSC, 20ms for PAL) +// +// Optimally, it should never block for more than a few ms at a time. + +void snes_run(void); + +// snes_get_region(): +// +// Determines the intended frame-rate of the loaded cartridge. +// +// The two main SNES hardware variants are the US/Japan variant, designed +// for NTSC output, and the European variant, designed for PAL output. +// However, the world is not quite so tidy as that, and there are countries +// like Brazil that use PAL output at NTSC frame-rates. +// +// For historical reasons this function is named snes_get_region(), but +// effectively the only information you can reliably infer is the +// frame-rate. +// +// Returns: +// +// One of the SNES_REGION_* constants. SNES_REGION_PAL means 50fps, +// SNES_REGION_NTSC means 60fps. + +bool snes_get_region(void); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Save state support {{{ +// +// libsnes has the ability to save the current emulation state and restore it +// at a later time. +// +// Note 1: It is impossible to reliably restore the *exact* state, although the +// difference is only a few cycles. If you demand the ability to reliably +// restore state, call snes_serialize() after each frame to ensure the emulated +// SNES is in a state that can be reliably restored. +// +// Note 2: The save state information is specific to a particular cartridge +// loaded into a particular version of a particular libsnes implementation. +// Unfortunately, there is not yet a way to determine whether a given save +// state is compatible with a given libsnes implementation, other than by +// loading it. However, if snes_serialize_size() does not match the size of an +// old save state, that's a strong hint that something has incompatibly +// changed. + +// snes_serialize_size: +// +// Determines the minimum size of a save state. +// +// This value can change depending on the features used by the loaded +// cartridge, and the version of the libsnes implementation used. +// +// Returns: +// +// An integer representing the number of bytes required to store the +// current emulation state. + +unsigned snes_serialize_size(void); + +// snes_serialize: +// +// Serialize the current emulation state to a buffer. +// +// If the allocated buffer is smaller than the size returned by +// snes_serialize_size(), serialization will fail. If the allocated buffer +// is larger, only the first snes_serialize_size() bytes will be written to. +// +// The resulting buffer may be stored, and later passed to +// snes_unserialize() to restore the saved emulation state. +// +// Parameters: +// +// data: +// A pointer to an allocated buffer of memory. +// +// size: +// The size of the buffer pointed to by "data". Should be greater than +// or equal to the value returned by snes_serialize_size(). +// +// Returns: +// +// A boolean; True means the emulation state was serialized successfully, +// False means a problem was encountered. + +bool snes_serialize(uint8_t *data, unsigned size); + +// snes_unserialize: +// +// Unserialize the emulation state from a buffer. +// +// If the serialization data in the buffer does not appear to be compatible +// with the current libsnes implementation, the function returns False and +// the current emulation state is not modified. +// +// Parameters: +// +// data: +// A pointer to an allocated buffer of memory. +// +// size: +// The size of the buffer pointed to by "data". Should be greater than +// or equal to the value returned by snes_serialize_size(). +// +// Returns: +// +// A boolean; True means the emulation state was loaded successfully, +// False means a problem was encountered. + +bool snes_unserialize(const uint8_t *data, unsigned size); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Cheat support {{{ +// +// libsnes does not include any kind of cheat management API; the intention is +// that any change to the set of applied cheats will cause the containing +// application to call snes_cheat_reset() then apply the new set of cheats with +// snes_cheat_set(). +// +// Any currently-applied cheats are discarded when a new cartridge is loaded. + +// snes_cheat_reset: +// +// Discards all cheat codes applied to the emulated SNES. + +void snes_cheat_reset(void); + +// snes_cheat_set: +// +// Apply a sequence of cheat codes to the emulated SNES. +// +// Since a "cheat code" is basically an instruction to override the value of +// a particular byte in the SNES' memory, more complex cheats may require +// several individual codes applied at once. There's no effective difference +// between applying these codes in a group with one call to +// snes_cheat_set(), or applying them one at a time with individual calls. +// However, most cheat databases will have a collection of available cheats +// for each game, where each item in the collection has a description and +// a sequence of codes to be applied as a unit. This API makes it easy to +// present the list of descriptions to the user, and apply each cheat the +// user selects. +// +// Parameters: +// +// index: +// The given cheat code will be stored at this index in the array of +// applied cheats. If a cheat already exists at this location, it will +// be replaced by the new cheat. If the index is larger than any +// previously specififed index, the array will be resized to +// accommodate. +// +// enabled: +// True means that the cheat will actually be applied, False means +// that the cheat will have no effect. There is no way to enable or +// disable a cheat after it has been added, other than to call +// snes_cheat_set() a second time with the same values for "index" and +// "code". +// +// code: +// A string containing a sequence of cheat codes separated by '+' +// characters. Any spaces in the string will be removed before +// parsing. +// +// Each code in the sequence must be in either GameGenie format +// ("1234-ABCD") or ProActionReplay format ("1234AB:CD" or +// "1234ABCD"). + +void snes_cheat_set(unsigned index, bool enabled, const char *code); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Cartridge loading and unloading {{{ +// +// Before calling snes_run(), a cartridge must be loaded into the emulated SNES +// so that it has code to run. +// +// Loading a cartridge of any kind calls snes_cheat_reset() as a side-effect. + +// snes_load_cartridge_normal: +// +// Load a normal ROM image into the emulated SNES. +// +// Parameters: +// +// rom_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes where the ROM image is mapped into the SNES address +// space, what special chips it uses (and where they're mapped), etc. +// +// If NULL, libsnes will guess a memory map. The guessed memory map +// should be correct for all licenced games in all regions. +// +// rom_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image. +// +// rom_size: +// The length of the rom_data array, in bytes. +// +// Returns: +// +// A boolean; True means the cartridge was loaded correctly, False means +// an error occurred. + +bool snes_load_cartridge_normal( + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size +); + +// snes_load_cartridge_bsx: +// +// Load a BS-X base cart image, optionally with a memory pack. +// +// The Satellaview system, abbreviated "BS-X" for unclear reasons, was an +// addon for the Super Famicom that connected it to the St. GIGA satellite +// network. The network would broadcast games at a particular time, and +// users could download them to replaceable memory packs. +// +// For more information, see http://en.wikipedia.org/wiki/Satellaview +// +// Parameters: +// +// rom_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes where the BS-X base cartridge ROM image is mapped +// into the SNES address space. +// +// If NULL, libsnes will guess a memory map. The guessed memory map +// should be correct for all known BS-X base cartridge images. +// +// rom_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image of the BS-X base cartridge. +// +// The BS-X base cartridge is named "BS-X - Sore wa Namae o Nusumareta +// Machi no Monogatari" in some SNES game databases. +// +// rom_size: +// The length of the rom_data array, in bytes. +// +// bsx_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes the BS-X memory pack. +// +// This parameter is currently ignored and should be passed as NULL. +// +// bsx_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless image of the BS-X memory-pack. +// +// If NULL, libsnes will behave as though no memory-pack were inserted +// into the base cartridge. +// +// bsx_size: +// The length of the bsx_data array, in bytes. +// +// Returns: +// +// A boolean; True means the cartridge was loaded correctly, False means +// an error occurred. + +bool snes_load_cartridge_bsx( + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, + const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size +); + +// snes_load_cartridge_bsx_slotted: +// +// Load a BS-X slotted cartridge, optionally with a memory pack. +// +// A BS-X slotted cartridge is an ordinary SNES cartridge, with a slot in +// the top that accepts the same memory packs used by the BS-X base +// cartridge. +// +// Parameters: +// +// rom_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes where the ROM image is mapped into the SNES address +// space, what special chips it uses (and where they're mapped), etc. +// +// If NULL, libsnes will guess a memory map. The guessed memory map +// should be correct for all licenced games in all regions. +// +// rom_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image. +// +// rom_size: +// The length of the rom_data array, in bytes. +// +// bsx_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes the BS-X memory pack. +// +// This parameter is currently ignored and should be passed as NULL. +// +// bsx_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless image of the BS-X memory-pack. +// +// If NULL, libsnes will behave as though no memory-pack were inserted +// into the base cartridge. +// +// bsx_size: +// The length of the bsx_data array, in bytes. +// +// Returns: +// +// A boolean; True means the cartridge was loaded correctly, False means +// an error occurred. + +bool snes_load_cartridge_bsx_slotted( + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, + const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size +); + +// snes_load_cartridge_sufami_turbo: +// +// Load a SuFami Turbo base cart image, optionally with game packs. +// +// The SuFami Turbo was a cartridge available for the Super Famicom, created +// by Bandai, with two slots in the top designed to accept special +// mini-cartridges. The cartridge in Slot A was the cartridge that actually +// ran, while the cartridge in Slot B was made available to the Slot +// A cartridge, enabling sharing of save-game data or using characters from +// one game in another. +// +// For more information, see: http://en.wikipedia.org/wiki/Sufami_Turbo +// +// Parameters: +// +// rom_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes where the SuFami Turbo base cartridge ROM image is +// mapped into the SNES address space. +// +// If NULL, libsnes will guess a memory map. The guessed memory map +// should be correct for all known SuFami Turbo base cartridge images. +// +// rom_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image of the SuFami Turbo base +// cartridge. +// +// The SuFami Turbo base cartridge is named "Sufami Turbo" in some +// SNES game databases. +// +// rom_size: +// The length of the rom_data array, in bytes. +// +// sta_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes the Sufami Turbo cartridge in Slot A. +// +// This parameter is currently ignored and should be passed as NULL. +// +// sta_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image of the SuFami Turbo cartridge +// in Slot A. +// +// This is the cartridge that will be executed by the SNES. +// +// If NULL, libsnes will behave as though no cartridge were inserted +// into the Slot A. +// +// sta_size: +// The length of the sta_data array, in bytes. +// +// stb_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes the Sufami Turbo cartridge in Slot B. +// +// This parameter is currently ignored and should be passed as NULL. +// +// stb_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image of the SuFami Turbo cartridge +// in Slot B. +// +// The data in this cartridge will be made available to the cartridge +// in Slot A. +// +// If NULL, libsnes will behave as though no cartridge were inserted +// into Slot B. +// +// stb_size: +// The length of the stb_data array, in bytes. +// +// Returns: +// +// A boolean; True means the cartridge was loaded correctly, False means +// an error occurred. + +bool snes_load_cartridge_sufami_turbo( + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, + const char *sta_xml, const uint8_t *sta_data, unsigned sta_size, + const char *stb_xml, const uint8_t *stb_data, unsigned stb_size +); + +// snes_load_cartridge_super_game_boy: +// +// Load a Super Game Boy base cart, optionally with a Gameboy cartridge. +// +// The Super Game Boy was a cartridge available for the Super Famicom and +// Super Nintendo that accepted ordinary (original) Gameboy cartridges and +// allowed the user to play them with a Super Nintendo controller, on a TV. +// It extended the orginal Gameboy hardware in a few ways, including the +// ability to display games in various palettes (rather than strictly +// monochrome), to display a full-colour border image around the Gameboy +// video output, or even run native SNES code to enhance the game. +// +// For more information, see: http://en.wikipedia.org/wiki/Super_Game_Boy +// +// Up until bsnes v073, loading Super Game Boy cartridges only works if the +// libsupergameboy library from the bsnes release is installed. bsnes v074 +// includes a custom Gameboy emulation core, and external code is no longer +// required. +// +// Parameters: +// +// rom_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes where the Super Game Boy base cartridge ROM image is +// mapped into the SNES address space. +// +// If NULL, libsnes will guess a memory map. The guessed memory map +// should be correct for all known Super Game Boy base cartridge +// images. +// +// rom_data: +// A pointer to a byte array containing the uncompressed, +// de-interleaved, headerless ROM image of the Super Game Boy base +// cartridge. +// +// Appropriate base cartridge images are named "Super Game Boy" or +// "Super Game Boy 2" in some SNES game databases. +// +// rom_size: +// The length of the rom_data array, in bytes. +// +// dmg_xml: +// A pointer to a null-terminated string containing an XML memory map +// that describes the inserted Gameboy cartridge. +// +// If NULL, libsnes will guess a memory map. The guesed memory map +// should be correct for all licensed original Gameboy games in all +// regions. +// +// dmg_data: +// A pointer to a byte array containing the uncompressed, headerless +// ROM image of the inserted Gameboy cartridge. +// +// If NULL, libsnes will behave as though no cartridge were inserted. +// +// dmg_size: +// The length of the dmg_size array, in bytes. +// +// Returns: +// +// A boolean; True means the cartridge was loaded correctly, False means +// an error occurred. + +bool snes_load_cartridge_super_game_boy( + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, + const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size +); + +// snes_set_cartridge_basename: +// +// Set the location and name of the loaded cartridge. +// +// libsnes uses this information to locate additional resources the +// cartridge might require. Currently, these resources include: +// +// - The MSU-1 data pack and associated audio tracks, if the cartridge makes +// use of bsnes' MSU-1 special-chip. +// - The serial-port data receiving library, if the cartridge makes uses of +// bsnes' serial-data-over-controller-port feature. +// +// Parameters: +// +// basename: +// The path and basename of the loaded cartridge. For example, if the +// full path to the loaded cartridge is "/path/to/filename.sfc", this +// parameter should be set to "/path/to/filename". + +void snes_set_cartridge_basename(const char *basename); + +// snes_unload_cartridge: +// +// Unloads the currently loaded cartridge from the emulated SNES. +// +// You will be unable to call snes_run() until another cartridge is loaded. + +void snes_unload_cartridge(void); + +////////////////////////////////////////////////////////////////////////////}}} + +/////////////////////////////////////////////////////////////////////////////// +// Volatile and non-volatile storage {{{ +// +// Certain SNES cartridges include non-volatile storage or other kinds of data +// that would persist after the SNES is turned off. libsnes exposes this +// information via the snes_get_memory_data() and snes_get_memory_size() +// functions. Since version 1.2 of the libsnes API, libsnes also exposes the +// contents of volatile storage such as WRAM and VRAM. +// +// After a cartridge is loaded, call snes_get_memory_size() and +// snes_get_memory_data() with the various SNES_MEMORY_* constants to determine +// which kinds of non-volatile storage the cartridge supports - unsupported +// storage types will have a size of 0 and the data pointer NULL. +// +// If you have non-volatile storage data from a previous run, you can memcpy() +// the data from your storage into the buffer described by the data and size +// values before calling snes_run(). Do not load non-volatile storage data if +// the size of the data you have is different from the size returned by +// snes_get_memory_size(). +// +// Before calling snes_unload_cartridge(), you should copy the contents of the +// relevant storage buffers into a file (or some non-volatile storage of your +// own) so that you can load it the next time you load the same cartridge into +// the emulated SNES. Do not call free() on the storage buffers; they will be +// handled by libsnes. Note: It is not necessary to store the contents of +// volatile storage; the emulated SNES expects information in volatile storage +// to be lost (hence the name 'volatile'). +// +// Because non-volatile storage is read and written by the software running on +// the emulated SNES, it should be compatible between different versions of +// different emulators running on different platforms, unlike save states. +// +// The various kinds of non-volatile storage and their uses are: +// +// SNES_MEMORY_CARTRIDGE_RAM: +// Standard battery-backed static RAM (SRAM). Traditionally, the SRAM for +// a ROM image named "foo.sfc" is stored in a file named "foo.srm" beside +// it. +// +// SNES_MEMORY_CARTRIDGE_RTC: +// Real-time clock data. Traditionally, the RTC data for a ROM image named +// "foo.sfc" is stored in a file named "foo.rtc" beside it. +// +// SNES_MEMORY_BSX_RAM: +// RAM data used with the BS-X base cartridge. +// +// SNES_MEMORY_BSX_PRAM: +// PRAM data used with the BS-X base cartridge. +// +// SNES_MEMORY_SUFAMI_TURBO_A_RAM: +// RAM data stored in the mini-cartridge inserted into Slot A of the +// SuFami Turbo base cartridge. +// +// SNES_MEMORY_SUFAMI_TURBO_B_RAM: +// RAM data stored in the mini-cartridge inserted into Slot B of the +// SuFami Turbo base cartridge. +// +// SNES_MEMORY_GAME_BOY_RAM: +// Standard battery-backed static RAM (SRAM) in the Gameboy cartridge +// inserted into the Super Game Boy base cartridge. Not all Gameboy games +// have SRAM. +// +// SNES_MEMORY_GAME_BOY_RTC: +// Real-time clock data in the Gameboy cartridge inserted into the Super +// Game Boy base cartridge. Not all Gameboy games have an RTC. +// +// The various kinds of volatile storage are: +// +// SNES_MEMORY_WRAM: +// Working RAM, accessible by the CPU. SNES software tends to keep runtime +// information in here; games' life-bars and inventory contents and so +// forth are in here somewhere. +// +// SNES_MEMORY_APURAM: +// RAM accessible by the Audio Processing Unit. Contains audio samples, +// music data and the code responsible for feeding the right notes to the +// DSP at the right times. +// +// SNES_MEMORY_VRAM: +// Video RAM. Stores almost everything related to video output, including +// the patterns used for each tile and sprite, tilemaps for each +// background. The exact format used depends on the current video mode of +// the emulated SNES. +// +// SNES_MEMORY_OAM: +// Object Attribute Memory. Stores the location, orientation and priority +// of all the sprites the SNES displays. +// +// SNES_MEMORY_CGRAM: +// Color Generator RAM. Contains the colour palettes used by tiles and +// sprites. Each palette entry is stored in a 16-bit int, in the standard +// XBGR1555 format. + +// snes_get_memory_data: +// +// Returns a pointer to the given non-volatile storage buffer. +// +// This requires that a cartridge is loaded. +// +// Parameters: +// +// id: +// One of the SNES_MEMORY_* constants. +// +// Returns: +// +// A pointer to the memory buffer used for storing the given type of data. +// The size of the buffer can be obtained from snes_get_memory_size(). +// +// If NULL, the loaded cartridge does not store the given type of data. + +uint8_t* snes_get_memory_data(unsigned id); + +// snes_get_memory_size: +// +// Returns the size of the given non-volatile storage buffer. +// +// This requires that a cartridge is loaded. +// +// Parameters: +// +// id: +// One of the SNES_MEMORY_* constants. +// +// Returns: +// +// The size of the memory buffer used for storing the given type of data. +// A pointer to the buffer can be obtained from snes_get_memory_data(). +// +// If 0, the loaded cartridge does not store the given type of data. + +unsigned snes_get_memory_size(unsigned id); + +////////////////////////////////////////////////////////////////////////////}}} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libsnes/link.T b/libsnes/link.T new file mode 100644 index 00000000..432292c1 --- /dev/null +++ b/libsnes/link.T @@ -0,0 +1,4 @@ +{ + global: snes_*; + local: *; +}; diff --git a/loadzip.cpp b/loadzip.cpp index 6ce8e7c8..1a92828a 100644 --- a/loadzip.cpp +++ b/loadzip.cpp @@ -185,10 +185,9 @@ #include "memmap.h" -bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 *buffer) +bool8 LoadZip (const char *zipname, uint32 *TotalFileSize, uint8 *buffer) { *TotalFileSize = 0; - *headers = 0; unzFile file = unzOpen(zipname); if (file == NULL) @@ -196,7 +195,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 // find largest file in zip file (under MAX_ROM_SIZE) or a file with extension .1 char filename[132]; - int filesize = 0; + uint32 filesize = 0; int port = unzGoToFirstFile(file); unz_file_info info; @@ -212,7 +211,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 continue; } - if ((int) info.uncompressed_size > filesize) + if (info.uncompressed_size > filesize) { strcpy(filename, name); filesize = info.uncompressed_size; @@ -259,7 +258,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 { assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512); - int FileSize = info.uncompressed_size; + uint32 FileSize = info.uncompressed_size; int l = unzReadCurrentFile(file, ptr, FileSize); if (unzCloseCurrentFile(file) == UNZ_CRCERROR) @@ -274,7 +273,7 @@ bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 return (FALSE); } - FileSize = (int) Memory.HeaderRemove((uint32) FileSize, *headers, ptr); + FileSize = Memory.HeaderRemove(FileSize, ptr); ptr += FileSize; *TotalFileSize += FileSize; diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj index 176f07e6..37ab5032 100755 --- a/macosx/snes9x.xcodeproj/project.pbxproj +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -36,7 +36,7 @@ CF047D54109D0E0600FD0754 /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; CF047D55109D0E0600FD0754 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; CF047D56109D0E0600FD0754 /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; - CF047D57109D0E0600FD0754 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF047D57109D0E0600FD0754 /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; }; CF047D58109D0E0600FD0754 /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; CF047D59109D0E0600FD0754 /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; @@ -145,7 +145,7 @@ CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; - CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF047DCC109D0E0600FD0754 /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; }; CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; @@ -237,7 +237,7 @@ CF0566A90CF98E7E00C7877C /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; CF0566AA0CF98E7E00C7877C /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; - CF0566AC0CF98E7E00C7877C /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF0566AC0CF98E7E00C7877C /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; }; CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; CF0566AE0CF98E7E00C7877C /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; @@ -333,7 +333,7 @@ CF0567180CF98E7E00C7877C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; - CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF05671B0CF98E7E00C7877C /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; }; CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; @@ -424,7 +424,7 @@ CF2F462E1095EE72007D33FA /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; CF2F462F1095EE72007D33FA /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; CF2F46301095EE72007D33FA /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; - CF2F46311095EE72007D33FA /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF2F46311095EE72007D33FA /* stream.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* stream.h */; }; CF2F46321095EE72007D33FA /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; CF2F46331095EE72007D33FA /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; CF2F46341095EE72007D33FA /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; @@ -533,7 +533,7 @@ CF2F46A31095EE72007D33FA /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; - CF2F46A61095EE72007D33FA /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF2F46A61095EE72007D33FA /* stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* stream.cpp */; }; CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; @@ -817,11 +817,11 @@ EA6E6C0E08F9734500CB3555 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; EA809E9308F8D6C40072CDFB /* controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controls.h; sourceTree = ""; }; EA809E9508F8D6E00072CDFB /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = language.h; sourceTree = ""; }; - EA809E9708F8D70D0072CDFB /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + EA809E9708F8D70D0072CDFB /* stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stream.h; sourceTree = ""; }; EA809E9908F8D7240072CDFB /* controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = controls.cpp; sourceTree = ""; }; EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crosshairs.cpp; sourceTree = ""; }; EA809E9D08F8D73A0072CDFB /* crosshairs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crosshairs.h; sourceTree = ""; }; - EA809E9F08F8D7530072CDFB /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + EA809E9F08F8D7530072CDFB /* stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stream.cpp; sourceTree = ""; }; EA809F9D08F8F2190072CDFB /* mac-controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-controls.h"; sourceTree = ""; }; EA809FA108F8F2420072CDFB /* mac-controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-controls.cpp"; sourceTree = ""; }; EA813E86066F5076004F99B5 /* movie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = movie.h; sourceTree = ""; }; @@ -1179,7 +1179,7 @@ EAE061C60526CCB900A80003 /* pixform.h */, EAE061C70526CCB900A80003 /* port.h */, EAE061C90526CCB900A80003 /* ppu.h */, - EA809E9708F8D70D0072CDFB /* reader.h */, + EA809E9708F8D70D0072CDFB /* stream.h */, EAE061CC0526CCB900A80003 /* sa1.h */, EAE061CE0526CCB900A80003 /* sar.h */, EAE061D00526CCB900A80003 /* screenshot.h */, @@ -1222,7 +1222,7 @@ EA813E9A066F50A5004F99B5 /* movie.cpp */, EAE061C30526CCB900A80003 /* obc1.cpp */, EAE061C80526CCB900A80003 /* ppu.cpp */, - EA809E9F08F8D7530072CDFB /* reader.cpp */, + EA809E9F08F8D7530072CDFB /* stream.cpp */, EAE061CB0526CCB900A80003 /* sa1.cpp */, EAE061CD0526CCB900A80003 /* sa1cpu.cpp */, EAE061D10526CCB900A80003 /* sdd1.cpp */, @@ -1384,7 +1384,7 @@ CF047D54109D0E0600FD0754 /* pixform.h in Headers */, CF047D55109D0E0600FD0754 /* port.h in Headers */, CF047D56109D0E0600FD0754 /* ppu.h in Headers */, - CF047D57109D0E0600FD0754 /* reader.h in Headers */, + CF047D57109D0E0600FD0754 /* stream.h in Headers */, CF047D58109D0E0600FD0754 /* sa1.h in Headers */, CF047D59109D0E0600FD0754 /* sar.h in Headers */, CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */, @@ -1503,7 +1503,7 @@ CF0566A90CF98E7E00C7877C /* pixform.h in Headers */, CF0566AA0CF98E7E00C7877C /* port.h in Headers */, CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */, - CF0566AC0CF98E7E00C7877C /* reader.h in Headers */, + CF0566AC0CF98E7E00C7877C /* stream.h in Headers */, CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */, CF0566AE0CF98E7E00C7877C /* sar.h in Headers */, CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */, @@ -1622,7 +1622,7 @@ CF2F462E1095EE72007D33FA /* pixform.h in Headers */, CF2F462F1095EE72007D33FA /* port.h in Headers */, CF2F46301095EE72007D33FA /* ppu.h in Headers */, - CF2F46311095EE72007D33FA /* reader.h in Headers */, + CF2F46311095EE72007D33FA /* stream.h in Headers */, CF2F46321095EE72007D33FA /* sa1.h in Headers */, CF2F46331095EE72007D33FA /* sar.h in Headers */, CF2F46341095EE72007D33FA /* screenshot.h in Headers */, @@ -1938,7 +1938,7 @@ CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */, CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */, CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */, - CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */, + CF047DCC109D0E0600FD0754 /* stream.cpp in Sources */, CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */, CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */, CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */, @@ -2033,7 +2033,7 @@ CF0567180CF98E7E00C7877C /* movie.cpp in Sources */, CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */, CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */, - CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */, + CF05671B0CF98E7E00C7877C /* stream.cpp in Sources */, CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */, CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */, CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */, @@ -2128,7 +2128,7 @@ CF2F46A31095EE72007D33FA /* movie.cpp in Sources */, CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */, CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */, - CF2F46A61095EE72007D33FA /* reader.cpp in Sources */, + CF2F46A61095EE72007D33FA /* stream.cpp in Sources */, CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */, CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */, CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */, diff --git a/memmap.cpp b/memmap.cpp index 811518eb..83effdbf 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -197,7 +197,6 @@ #include "controls.h" #include "cheats.h" #include "movie.h" -#include "reader.h" #include "display.h" #ifndef SET_UI_COLOR @@ -945,9 +944,9 @@ static bool8 is_GNEXT_BIOS (uint8 *, uint32); static bool8 is_GNEXT_Add_On (uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); -static bool8 ReadUPSPatch (Reader *, long, int32 &); -static long ReadInt (Reader *, unsigned); -static bool8 ReadIPSPatch (Reader *, long, int32 &); +static bool8 ReadUPSPatch (Stream *, long, int32 &); +static long ReadInt (Stream *, unsigned); +static bool8 ReadIPSPatch (Stream *, long, int32 &); #ifdef UNZIP_SUPPORT static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE); #endif @@ -1352,7 +1351,7 @@ int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) return (score); } -uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) +uint32 CMemory::HeaderRemove (uint32 size, uint8 *buf) { uint32 calc_size = (size / 0x2000) * 0x2000; @@ -1373,20 +1372,20 @@ uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) } memmove(buf, buf + 512, calc_size); - headerCount++; + HeaderCount++; size -= 512; } return (size); } -uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) +uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, uint32 maxsize) { // <- ROM size without header // ** Memory.HeaderCount // ** Memory.ROMFilename - int32 totalSize = 0; + uint32 totalSize = 0; char fname[PATH_MAX + 1]; char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; char *ext; @@ -1415,7 +1414,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) case FILE_ZIP: { #ifdef UNZIP_SUPPORT - if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) + if (!LoadZip(fname, &totalSize, buffer)) { S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); return (0); @@ -1439,7 +1438,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) return (0); } - totalSize = HeaderRemove(size, HeaderCount, buffer); + totalSize = HeaderRemove(size, buffer); strcpy(ROMFilename, fname); #else @@ -1468,7 +1467,7 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); CLOSE_STREAM(fp); - size = HeaderRemove(size, HeaderCount, ptr); + size = HeaderRemove(size, ptr); totalSize += size; ptr += size; @@ -1511,31 +1510,55 @@ uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) return ((uint32) totalSize); } +bool8 CMemory::LoadROMMem (const uint8 *source, uint32 sourceSize) +{ + if(!source || sourceSize > MAX_ROM_SIZE) + return FALSE; + + strcpy(ROMFilename,"MemoryROM"); + + do + { + memset(ROM,0, MAX_ROM_SIZE); + memset(&Multi, 0,sizeof(Multi)); + memcpy(ROM,source,sourceSize); + } + while(!LoadROMInt(sourceSize)); + + return TRUE; +} + bool8 CMemory::LoadROM (const char *filename) { - int retry_count = 0; + if(!filename || !*filename) + return FALSE; - if (!filename || !*filename) - return (FALSE); + int32 totalFileSize; - ZeroMemory(ROM, MAX_ROM_SIZE); - ZeroMemory(&Multi, sizeof(Multi)); - -again: + do + { + memset(ROM,0, MAX_ROM_SIZE); + memset(&Multi, 0,sizeof(Multi)); + totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); + + if (!totalFileSize) + return (FALSE); + } + while(!LoadROMInt(totalFileSize)); + + return TRUE; +} + +bool8 CMemory::LoadROMInt (int32 ROMfillSize) +{ Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); CalculatedSize = 0; ExtendedFormat = NOPE; - int32 totalFileSize; - - totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); - if (!totalFileSize) - return (FALSE); - if (!Settings.NoPatch) - CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize); + CheckForAnyPatch(ROMFilename, HeaderCount != 0, ROMfillSize); int hi_score, lo_score; @@ -1546,15 +1569,15 @@ again: ((hi_score > lo_score && ScoreHiROM(TRUE) > hi_score) || (hi_score <= lo_score && ScoreLoROM(TRUE) > lo_score))) { - memmove(ROM, ROM + 512, totalFileSize - 512); - totalFileSize -= 512; + memmove(ROM, ROM + 512, ROMfillSize - 512); + ROMfillSize -= 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); } - CalculatedSize = (totalFileSize / 0x2000) * 0x2000; + CalculatedSize = (ROMfillSize / 0x2000) * 0x2000; if (CalculatedSize > 0x400000 && (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x3423 && // exclude SA-1 @@ -1571,7 +1594,7 @@ again: ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) { if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved) - S9xDeinterleaveType1(totalFileSize, ROM); + S9xDeinterleaveType1(ROMfillSize, ROM); } // CalculatedSize is now set, so rescore @@ -1699,14 +1722,10 @@ again: 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."); - Settings.ForceNotInterleaved = TRUE; - Settings.ForceInterleaved = FALSE; - retry_count++; - goto again; - } + S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again."); + Settings.ForceNotInterleaved = TRUE; + Settings.ForceInterleaved = FALSE; + return (FALSE); } } @@ -1726,9 +1745,9 @@ again: } } - if (strncmp(LastRomFilename, filename, PATH_MAX + 1)) + if (strncmp(LastRomFilename, ROMFilename, PATH_MAX + 1)) { - strncpy(LastRomFilename, filename, PATH_MAX + 1); + strncpy(LastRomFilename, ROMFilename, PATH_MAX + 1); LastRomFilename[PATH_MAX] = 0; } @@ -3775,7 +3794,7 @@ static uint32 XPSdecode (const uint8 *data, unsigned &addr, unsigned size) //no-header patching errors that result in IPS patches having a 50/50 chance of //being applied correctly. -static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) +static bool8 ReadUPSPatch (Stream *r, long, int32 &rom_size) { //Reader lacks size() and rewind(), so we need to read in the file to get its size uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ... @@ -3857,7 +3876,7 @@ static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) // // logic taken from http://byuu.org/programming/bps and the accompanying source // -static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) +static bool8 ReadBPSPatch (Stream *r, long, int32 &rom_size) { uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ... uint32 size = 0; @@ -3948,7 +3967,7 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) } } -static long ReadInt (Reader *r, unsigned nbytes) +static long ReadInt (Stream *r, unsigned nbytes) { long v = 0; @@ -3963,7 +3982,7 @@ static long ReadInt (Reader *r, unsigned nbytes) return (v); } -static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) +static bool8 ReadIPSPatch (Stream *r, long offset, int32 &rom_size) { const int32 IPS_EOF = 0x00454F46l; int32 ofs; @@ -4082,7 +4101,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r if (Settings.NoPatch) return; - STREAM patch_file = NULL; + FSTREAM patch_file = NULL; uint32 i; long offset = header ? 512 : 0; int ret; @@ -4095,12 +4114,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r // BPS _makepath(fname, drive, dir, name, "bps"); - if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL) { printf("Using BPS patch %s", fname); - ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4122,7 +4141,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadBPSPatch(new unzReader(file), offset, rom_size); + ret = ReadBPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4136,12 +4155,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r n = S9xGetFilename(".bps", IPS_DIR); - if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL) { printf("Using BPS patch %s", n); - ret = ReadBPSPatch(new fReader(patch_file), 0, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadBPSPatch(new fStream(patch_file), 0, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4156,12 +4175,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r _makepath(fname, drive, dir, name, "ups"); - if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL) { printf("Using UPS patch %s", fname); - ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4183,7 +4202,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadUPSPatch(new unzReader(file), offset, rom_size); + ret = ReadUPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4197,12 +4216,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r n = S9xGetFilename(".ups", IPS_DIR); - if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL) { printf("Using UPS patch %s", n); - ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadUPSPatch(new fStream(patch_file), 0, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4217,12 +4236,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r _makepath(fname, drive, dir, name, "ips"); - if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL) { printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4243,13 +4262,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r snprintf(ips, 8, "%03d.ips", i); _makepath(fname, drive, dir, name, ips); - if (!(patch_file = OPEN_STREAM(fname, "rb"))) + if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) break; printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4279,13 +4298,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r break; _makepath(fname, drive, dir, name, ips); - if (!(patch_file = OPEN_STREAM(fname, "rb"))) + if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) break; printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4313,13 +4332,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r snprintf(ips, 4, "ip%d", i); _makepath(fname, drive, dir, name, ips); - if (!(patch_file = OPEN_STREAM(fname, "rb"))) + if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) break; printf("Using IPS patch %s", fname); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4348,7 +4367,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + ret = ReadIPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4375,7 +4394,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + ret = ReadIPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4409,7 +4428,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + ret = ReadIPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4441,7 +4460,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r printf(" in %s", rom_filename); - ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + ret = ReadIPSPatch(new unzStream(file), offset, rom_size); unzCloseCurrentFile(file); if (ret) @@ -4470,12 +4489,12 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r n = S9xGetFilename(".ips", IPS_DIR); - if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL) { printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4496,13 +4515,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r snprintf(ips, 9, ".%03d.ips", i); n = S9xGetFilename(ips, IPS_DIR); - if (!(patch_file = OPEN_STREAM(n, "rb"))) + if (!(patch_file = OPEN_FSTREAM(n, "rb"))) break; printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4532,13 +4551,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r break; n = S9xGetFilename(ips, IPS_DIR); - if (!(patch_file = OPEN_STREAM(n, "rb"))) + if (!(patch_file = OPEN_FSTREAM(n, "rb"))) break; printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { @@ -4566,13 +4585,13 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r snprintf(ips, 5, ".ip%d", i); n = S9xGetFilename(ips, IPS_DIR); - if (!(patch_file = OPEN_STREAM(n, "rb"))) + if (!(patch_file = OPEN_FSTREAM(n, "rb"))) break; printf("Using IPS patch %s", n); - ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); - CLOSE_STREAM(patch_file); + ret = ReadIPSPatch(new fStream(patch_file), offset, rom_size); + CLOSE_FSTREAM(patch_file); if (ret) { diff --git a/memmap.h b/memmap.h index 4991ae83..4bf43d36 100644 --- a/memmap.h +++ b/memmap.h @@ -271,9 +271,12 @@ struct CMemory int ScoreHiROM (bool8, int32 romoff = 0); int ScoreLoROM (bool8, int32 romoff = 0); - uint32 HeaderRemove (uint32, int32 &, uint8 *); - uint32 FileLoader (uint8 *, const char *, int32); + uint32 HeaderRemove (uint32, uint8 *); + uint32 FileLoader (uint8 *, const char *, uint32); + uint32 MemLoader (uint8 *, const char*, uint32); + bool8 LoadROMMem (const uint8 *, uint32); bool8 LoadROM (const char *); + bool8 LoadROMInt (int32); bool8 LoadMultiCart (const char *, const char *); bool8 LoadSufamiTurbo (const char *, const char *); bool8 LoadSameGame (const char *, const char *); @@ -361,7 +364,7 @@ extern CMemory Memory; extern SMulti Multi; void S9xAutoSaveSRAM (void); -bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); +bool8 LoadZip(const char *, uint32 *, uint8 *); enum s9xwrap_t { diff --git a/netplay.cpp b/netplay.cpp index f0f15315..6e18291c 100644 --- a/netplay.cpp +++ b/netplay.cpp @@ -189,6 +189,8 @@ #include #include +#include "snes9x.h" + #ifdef __WIN32__ #include #include @@ -222,7 +224,6 @@ #include #endif -#include "snes9x.h" #include "memmap.h" #include "netplay.h" #include "snapshot.h" diff --git a/port.h b/port.h index 0e8192e5..a4d07330 100644 --- a/port.h +++ b/port.h @@ -202,7 +202,9 @@ #define RIGHTSHIFT_int8_IS_SAR #define RIGHTSHIFT_int16_IS_SAR #define RIGHTSHIFT_int32_IS_SAR +#ifndef __WIN32_LIBSNES__ #define SNES_JOY_READ_CALLBACKS +#endif //__WIN32_LIBSNES__ #endif #ifdef __MACOSX__ @@ -227,31 +229,22 @@ typedef uint64_t uint64; #else // HAVE_STDINT_H #ifdef __WIN32__ typedef intptr_t pint; -#else // __WIN32__ -#ifdef PTR_NOT_INT -typedef long pint; -#else -typedef int pint; -#endif -#endif // __WIN32__ -#ifdef __WIN32__ -#ifdef __BORLANDC__ -#include -#else typedef signed char int8; typedef unsigned char uint8; typedef signed short int16; typedef unsigned short uint16; -#ifndef WSAAP -// winsock2.h typedefs int32 as well -typedef signed int int32; -#endif +typedef signed int int32; typedef unsigned int uint32; -#endif -typedef unsigned char uint8_t; -typedef signed char int8_t; typedef signed __int64 int64; typedef unsigned __int64 uint64; +typedef int8 int8_t; +typedef uint8 uint8_t; +typedef int16 int16_t; +typedef uint16 uint16_t; +typedef int32 int32_t; +typedef uint32 uint32_t; +typedef int64 int64_t; +typedef uint64 uint64_t; typedef int socklen_t; #else // __WIN32__ typedef signed char int8; @@ -266,6 +259,11 @@ __extension__ #endif typedef long long int64; typedef unsigned long long uint64; +#ifdef PTR_NOT_INT +typedef long pint; +#else // __PTR_NOT_INT +typedef int pint; +#endif // __PTR_NOT_INT #endif // __WIN32__ #endif // HAVE_STDINT_H #endif // snes9x_types_defined @@ -300,15 +298,19 @@ typedef unsigned long long uint64; void _splitpath (const char *, char *, char *, char *, char *); void _makepath (char *, const char *, const char *, const char *, const char *); #define S9xDisplayString DisplayStringFromBottom -#else +#else // __WIN32__ #define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp +#ifndef __WIN32_LIBSNES__ void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); #define S9xDisplayString WinDisplayStringFromBottom void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); #define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) -#endif +#else // __WIN32_LIBSNES__ +#define S9xDisplayString DisplayStringFromBottom +#endif // __WIN32_LIBSNES__ +#endif // __WIN32__ #ifdef __DJGPP #define SLASH_STR "\\" diff --git a/server.cpp b/server.cpp index fc2f3fa4..6a376132 100644 --- a/server.cpp +++ b/server.cpp @@ -190,6 +190,8 @@ #include #endif +#include "snes9x.h" + #ifdef __WIN32__ #include @@ -219,7 +221,6 @@ #endif // !__WIN32__ -#include "snes9x.h" #include "memmap.h" #include "snapshot.h" #include "netplay.h" diff --git a/snapshot.cpp b/snapshot.cpp index 7b758b42..86dbdbc0 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1169,6 +1169,21 @@ void S9xResetSaveTimer (bool8 dontsave) t = time(NULL); } +uint32 S9xFreezeSize() +{ + nulStream stream; + S9xFreezeToStream(&stream); + return stream.size(); +} + +bool8 S9xFreezeGameMem (uint8 *buf, uint32 bufSize) +{ + memStream mStream(buf, bufSize); + S9xFreezeToStream(&mStream); + + return (TRUE); +} + bool8 S9xFreezeGame (const char *filename) { STREAM stream = NULL; @@ -1194,6 +1209,14 @@ bool8 S9xFreezeGame (const char *filename) return (FALSE); } +int S9xUnfreezeGameMem (const uint8 *buf, uint32 bufSize) +{ + memStream stream(buf, bufSize); + int result = S9xUnfreezeFromStream(&stream); + + return result; +} + bool8 S9xUnfreezeGame (const char *filename) { STREAM stream = NULL; diff --git a/snapshot.h b/snapshot.h index d55b8b7e..d5ce8958 100644 --- a/snapshot.h +++ b/snapshot.h @@ -192,7 +192,10 @@ void S9xResetSaveTimer (bool8); bool8 S9xFreezeGame (const char *); +uint32 S9xFreezeSize (void); +bool8 S9xFreezeGameMem (uint8 *,uint32); bool8 S9xUnfreezeGame (const char *); +int S9xUnfreezeGameMem (const uint8 *,uint32); void S9xFreezeToStream (STREAM); int S9xUnfreezeFromStream (STREAM); bool8 S9xSPCDump (const char *); diff --git a/snes9x.cpp b/snes9x.cpp index 148073e8..4a84e70b 100644 --- a/snes9x.cpp +++ b/snes9x.cpp @@ -315,14 +315,14 @@ static void parse_crosshair_spec (enum crosscontrols ctl, const char *spec) static bool try_load_config_file (const char *fname, ConfigFile &conf) { - STREAM fp; + FSTREAM fp; - fp = OPEN_STREAM(fname, "r"); + fp = OPEN_FSTREAM(fname, "r"); if (fp) { fprintf(stdout, "Reading config file %s.\n", fname); - conf.LoadFile(new fReader(fp)); - CLOSE_STREAM(fp); + conf.LoadFile(new fStream(fp)); + CLOSE_FSTREAM(fp); return (true); } diff --git a/snes9x.h b/snes9x.h index 4e09c0dd..97689baf 100644 --- a/snes9x.h +++ b/snes9x.h @@ -189,29 +189,42 @@ #ifdef ZLIB #include -#define STREAM gzFile -#define READ_STREAM(p, l, s) gzread(s, p, l) -#define WRITE_STREAM(p, l, s) gzwrite(s, p, l) -#define GETS_STREAM(p, l, s) gzgets(s, p, l) -#define GETC_STREAM(s) gzgetc(s) -#define OPEN_STREAM(f, m) gzopen(f, m) -#define REOPEN_STREAM(f, m) gzdopen(f, m) -#define FIND_STREAM(f) gztell(f) -#define REVERT_STREAM(f, o, s) gzseek(f, o, s) -#define CLOSE_STREAM(s) gzclose(s) +#define FSTREAM gzFile +#define READ_FSTREAM(p, l, s) gzread(s, p, l) +#define WRITE_FSTREAM(p, l, s) gzwrite(s, p, l) +#define GETS_FSTREAM(p, l, s) gzgets(s, p, l) +#define GETC_FSTREAM(s) gzgetc(s) +#define OPEN_FSTREAM(f, m) gzopen(f, m) +#define REOPEN_FSTREAM(f, m) gzdopen(f, m) +#define FIND_FSTREAM(f) gztell(f) +#define REVERT_FSTREAM(s, o, p) gzseek(s, o, p) +#define CLOSE_FSTREAM(s) gzclose(s) #else -#define STREAM FILE * -#define READ_STREAM(p, l, s) fread(p, 1, l, s) -#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s) -#define GETS_STREAM(p, l, s) fgets(p, l, s) -#define GETC_STREAM(s) fgetc(s) -#define OPEN_STREAM(f, m) fopen(f, m) -#define REOPEN_STREAM(f, m) fdopen(f, m) -#define FIND_STREAM(f) ftell(f) -#define REVERT_STREAM(f, o, s) fseek(f, o, s) -#define CLOSE_STREAM(s) fclose(s) +#define FSTREAM FILE * +#define READ_FSTREAM(p, l, s) fread(p, 1, l, s) +#define WRITE_FSTREAM(p, l, s) fwrite(p, 1, l, s) +#define GETS_FSTREAM(p, l, s) fgets(p, l, s) +#define GETC_FSTREAM(s) fgetc(s) +#define OPEN_FSTREAM(f, m) fopen(f, m) +#define REOPEN_FSTREAM(f, m) fdopen(f, m) +#define FIND_FSTREAM(s) ftell(s) +#define REVERT_FSTREAM(s, o, p) fseek(s, o, p) +#define CLOSE_FSTREAM(s) fclose(s) #endif +#include "stream.h" + +#define STREAM Stream * +#define READ_STREAM(p, l, s) s->read(p,l) +#define WRITE_STREAM(p, l, s) s->write(p,l) +#define GETS_STREAM(p, l, s) s->gets(p,l) +#define GETC_STREAM(s) s->get_char() +#define OPEN_STREAM(f, m) openStreamFromFSTREAM(f, m) +#define REOPEN_STREAM(f, m) reopenStreamFromFd(f, m) +#define FIND_STREAM(s) s->pos() +#define REVERT_STREAM(s, o, p) s->revert(p, o) +#define CLOSE_STREAM(s) s->closeStream() + #define SNES_WIDTH 256 #define SNES_HEIGHT 224 #define SNES_HEIGHT_EXTENDED 239 diff --git a/reader.cpp b/stream.cpp similarity index 64% rename from reader.cpp rename to stream.cpp index 8ad1ed44..84f9424a 100644 --- a/reader.cpp +++ b/stream.cpp @@ -183,24 +183,24 @@ #include "unzip.h" #endif #include "snes9x.h" -#include "reader.h" +#include "stream.h" // Generic constructor/destructor -Reader::Reader (void) +Stream::Stream (void) { return; } -Reader::~Reader (void) +Stream::~Stream (void) { return; } // Generic getline function, based on gets. Reimlpement if you can do better. -char * Reader::getline (void) +char * Stream::getline (void) { bool eof; std::string ret; @@ -212,7 +212,7 @@ char * Reader::getline (void) return (strdup(ret.c_str())); } -std::string Reader::getline (bool &eof) +std::string Stream::getline (bool &eof) { char buf[1024]; std::string ret; @@ -235,50 +235,81 @@ std::string Reader::getline (bool &eof) return (ret); } -// snes9x.h STREAM reader +// snes9x.h FSTREAM Stream -fReader::fReader (STREAM f) +fStream::fStream (FSTREAM f) { fp = f; } -fReader::~fReader (void) +fStream::~fStream (void) { + CLOSE_FSTREAM(fp); return; } -int fReader::get_char (void) +int fStream::get_char (void) { - return (GETC_STREAM(fp)); + return (GETC_FSTREAM(fp)); } -char * fReader::gets (char *buf, size_t len) +char * fStream::gets (char *buf, size_t len) { - return (GETS_STREAM(buf, len, fp)); + return (GETS_FSTREAM(buf, len, fp)); } -size_t fReader::read (char *buf, size_t len) +size_t fStream::read (void *buf, size_t len) { - return (READ_STREAM(buf, len, fp)); + return (READ_FSTREAM(buf, len, fp)); } -// unzip reader +size_t fStream::write (void *buf, size_t len) +{ + return (WRITE_FSTREAM(buf, len, fp)); +} + +size_t fStream::pos (void) +{ + return (FIND_FSTREAM(fp)); +} + +size_t fStream::size (void) +{ + size_t sz; + REVERT_FSTREAM(fp,0L,SEEK_END); + sz = FIND_FSTREAM(fp); + REVERT_FSTREAM(fp,0L,SEEK_SET); + return sz; +} + +int fStream::revert (size_t from, size_t offset) +{ + return (REVERT_FSTREAM(fp, from, offset)); +} + +void fStream::closeStream() +{ + CLOSE_FSTREAM(fp); + delete this; +} + +// unzip Stream #ifdef UNZIP_SUPPORT -unzReader::unzReader (unzFile &v) +unzStream::unzStream (unzFile &v) { file = v; head = NULL; numbytes = 0; } -unzReader::~unzReader (void) +unzStream::~unzStream (void) { return; } -int unzReader::get_char (void) +int unzStream::get_char (void) { unsigned char c; @@ -297,7 +328,7 @@ int unzReader::get_char (void) return ((int) c); } -char * unzReader::gets (char *buf, size_t len) +char * unzStream::gets (char *buf, size_t len) { size_t i; int c; @@ -322,7 +353,7 @@ char * unzReader::gets (char *buf, size_t len) return (buf); } -size_t unzReader::read (char *buf, size_t len) +size_t unzStream::read (void *buf, size_t len) { if (len == 0) return (len); @@ -344,11 +375,219 @@ size_t unzReader::read (char *buf, size_t len) numbytes = 0; } - int l = unzReadCurrentFile(file, buf + numread, len - numread); + int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread); if (l > 0) numread += l; return (numread); } +// not supported +size_t unzStream::write (void *buf, size_t len) +{ + return (0); +} + +size_t unzStream::pos (void) +{ + return (unztell(file)); +} + +size_t unzStream::size (void) +{ + unz_file_info info; + unzGetCurrentFileInfo(file,&info,NULL,0,NULL,0,NULL,0); + return info.uncompressed_size; +} + +// not supported +int unzStream::revert (size_t from, size_t offset) +{ + return -1; +} + +void unzStream::closeStream() +{ + unzCloseCurrentFile(file); + delete this; +} + #endif + +// memory Stream + +memStream::memStream (uint8 *source, size_t sourceSize) +{ + mem = head = source; + msize = remaining = sourceSize; + readonly = false; +} + +memStream::memStream (const uint8 *source, size_t sourceSize) +{ + mem = head = const_cast(source); + msize = remaining = sourceSize; + readonly = true; +} + +memStream::~memStream (void) +{ + return; +} + +int memStream::get_char (void) +{ + if(!remaining) + return EOF; + + remaining--; + return *head++; +} + +char * memStream::gets (char *buf, size_t len) +{ + size_t i; + int c; + + for (i = 0; i < len - 1; i++) + { + c = get_char(); + if (c == EOF) + { + if (i == 0) + return (NULL); + break; + } + + buf[i] = (char) c; + if (buf[i] == '\n') + break; + } + + buf[i] = '\0'; + + return (buf); +} + +size_t memStream::read (void *buf, size_t len) +{ + size_t bytes = len < remaining ? len : remaining; + memcpy(buf,head,bytes); + head += bytes; + remaining -= bytes; + + return bytes; +} + +size_t memStream::write (void *buf, size_t len) +{ + if(readonly) + return 0; + + size_t bytes = len < remaining ? len : remaining; + memcpy(head,buf,bytes); + head += bytes; + remaining -= bytes; + + return bytes; +} + +size_t memStream::pos (void) +{ + return msize - remaining; +} + +size_t memStream::size (void) +{ + return msize; +} + +int memStream::revert (size_t from, size_t offset) +{ + size_t pos = from + offset; + + if(pos > msize) + return -1; + + head = mem + pos; + remaining = msize - pos; + + return 0; +} + +void memStream::closeStream() +{ + delete [] mem; + delete this; +} + +// dummy Stream + +nulStream::nulStream (void) +{ + bytes_written = 0; +} + +nulStream::~nulStream (void) +{ + return; +} + +int nulStream::get_char (void) +{ + return 0; +} + +char * nulStream::gets (char *buf, size_t len) +{ + *buf = '\0'; + return NULL; +} + +size_t nulStream::read (void *buf, size_t len) +{ + return 0; +} + +size_t nulStream::write (void *buf, size_t len) +{ + bytes_written += len; + return len; +} + +size_t nulStream::pos (void) +{ + return 0; +} + +size_t nulStream::size (void) +{ + return bytes_written; +} + +int nulStream::revert (size_t from, size_t offset) +{ + bytes_written = from + offset; + return 0; +} + +void nulStream::closeStream() +{ + delete this; +} + +Stream *openStreamFromFSTREAM(const char* filename, const char* mode) +{ + FSTREAM f = OPEN_FSTREAM(filename,mode); + if(!f) + return NULL; + return new fStream(f); +} + +Stream *reopenStreamFromFd(int fd, const char* mode) +{ + FSTREAM f = REOPEN_FSTREAM(fd,mode); + if(!f) + return NULL; + return new fStream(f); +} diff --git a/reader.h b/stream.h similarity index 73% rename from reader.h rename to stream.h index 80e92e4d..7a0e509a 100644 --- a/reader.h +++ b/stream.h @@ -176,46 +176,65 @@ ***********************************************************************************/ -#ifndef _READER_H_ -#define _READER_H_ +#ifndef _STREAM_H_ +#define _STREAM_H_ -class Reader +#include + +class Stream { public: - Reader (void); - virtual ~Reader (void); + Stream (void); + virtual ~Stream (void); virtual int get_char (void) = 0; virtual char * gets (char *, size_t) = 0; virtual char * getline (void); // free() when done virtual std::string getline (bool &); - virtual size_t read (char *, size_t) = 0; + virtual size_t read (void *, size_t) = 0; + virtual size_t write (void *, size_t) = 0; + virtual size_t pos (void) = 0; + virtual size_t size (void) = 0; + virtual int revert (size_t from, size_t offset) = 0; + virtual void closeStream() = 0; }; -class fReader : public Reader +class fStream : public Stream { public: - fReader (STREAM); - virtual ~fReader (void); + fStream (FSTREAM); + virtual ~fStream (void); virtual int get_char (void); virtual char * gets (char *, size_t); - virtual size_t read (char *, size_t); + virtual size_t read (void *, size_t); + virtual size_t write (void *, size_t); + virtual size_t pos (void); + virtual size_t size (void); + virtual int revert (size_t from, size_t offset); + virtual void closeStream(); private: - STREAM fp; + FSTREAM fp; }; #ifdef UNZIP_SUPPORT +#include "unzip.h" + #define unz_BUFFSIZ 1024 -class unzReader : public Reader +class unzStream : public Stream { public: - unzReader (unzFile &); - virtual ~unzReader (void); + unzStream (unzFile &); + virtual ~unzStream (void); virtual int get_char (void); virtual char * gets (char *, size_t); - virtual size_t read (char *, size_t); + virtual size_t read (void *, size_t); + virtual size_t write (void *, size_t); + virtual size_t pos (void); + virtual size_t size (void); + virtual int revert (size_t from, size_t offset); + virtual void closeStream(); private: unzFile file; @@ -226,4 +245,52 @@ class unzReader : public Reader #endif +class memStream : public Stream +{ + public: + memStream (uint8 *,size_t); + memStream (const uint8 *,size_t); + virtual ~memStream (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (void *, size_t); + virtual size_t write (void *, size_t); + virtual size_t pos (void); + virtual size_t size (void); + virtual int revert (size_t from, size_t offset); + virtual void closeStream(); + + private: + uint8 *mem; + size_t msize; + size_t remaining; + uint8 *head; + bool readonly; +}; + +/* dummy stream that always reads 0 and writes nowhere + but counts bytes written +*/ +class nulStream : public Stream +{ + public: + nulStream (void); + virtual ~nulStream (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (void *, size_t); + virtual size_t write (void *, size_t); + virtual size_t pos (void); + virtual size_t size (void); + virtual int revert (size_t from, size_t offset); + virtual void closeStream(); + + private: + size_t bytes_written; +}; + +Stream *openStreamFromFSTREAM(const char* filename, const char* mode); +Stream *reopenStreamFromFd(int fd, const char* mode); + + #endif diff --git a/unix/Makefile.in b/unix/Makefile.in index 36cf6050..ed12ed4b 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -7,7 +7,7 @@ OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 454e4439..558c9b09 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -2082,42 +2082,6 @@ /> - - - - - - - - - - - - - - - - @@ -2902,6 +2866,42 @@ /> + + + + + + + + + + + + + + + + From 3368fd68833e94381e062d9a704b7034debedbcb Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 6 Jan 2012 20:13:16 +0100 Subject: [PATCH 081/130] Add multicart memory function, add sufami turbo to libsnes --- libsnes/libsnes.cpp | 67 ++++++++---- memmap.cpp | 241 +++++++++++++++++++++++--------------------- memmap.h | 8 +- 3 files changed, 183 insertions(+), 133 deletions(-) diff --git a/libsnes/libsnes.cpp b/libsnes/libsnes.cpp index 7c47ede1..3a9fa9b9 100644 --- a/libsnes/libsnes.cpp +++ b/libsnes/libsnes.cpp @@ -53,6 +53,21 @@ void snes_set_environment(snes_environment_t cb) environ_cb = cb; } +static void set_environ_timing() +{ + if (environ_cb) + { + snes_system_timing timing; + timing.sample_rate = 32040.5; + if (!Settings.PAL) + timing.fps = 21477272.0 / 357366.0; + else + timing.fps = 21281370.0 / 425568.0; + + environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); + } +} + static void S9xAudioCallback(void*) { // Just pick a big buffer. We won't use it all. @@ -137,10 +152,20 @@ void snes_cheat_set(unsigned, bool, const char*) {} bool snes_load_cartridge_bsx_slotted( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned + const char *, const uint8_t *rom_data, unsigned rom_size, + const char *, const uint8_t *bsx_data, unsigned bsx_size ) { + int loaded = Memory.LoadMultiCartMem(rom_data, rom_size, bsx_data, bsx_size, NULL, NULL); + + if (!loaded) + { + fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); + return false; + } + + set_environ_timing(); + return false; } @@ -153,12 +178,22 @@ bool snes_load_cartridge_bsx( } bool snes_load_cartridge_sufami_turbo( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned + const char *, const uint8_t *rom_data, unsigned rom_size, + const char *, const uint8_t *sta_data, unsigned sta_size, + const char *, const uint8_t *stb_data, unsigned stb_size ) { - return false; + int loaded = Memory.LoadMultiCartMem(sta_data, sta_size, stb_data, stb_size, rom_data, rom_size); + + if (!loaded) + { + fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); + return false; + } + + set_environ_timing(); + + return true; } bool snes_load_cartridge_super_game_boy( @@ -435,17 +470,7 @@ bool snes_load_cartridge_normal(const char *, const uint8_t *rom_data, unsigned return false; } - if (environ_cb) - { - snes_system_timing timing; - timing.sample_rate = 32040.5; - if (!Settings.PAL) - timing.fps = 21477272.0 / 357366.0; - else - timing.fps = 21281370.0 / 425568.0; - - environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); - } + set_environ_timing(); return true; } @@ -476,9 +501,13 @@ uint8_t* snes_get_memory_data(unsigned type) uint8_t* data; switch(type) { + case SNES_MEMORY_SUFAMI_TURBO_A_RAM: case SNES_MEMORY_CARTRIDGE_RAM: data = Memory.SRAM; break; + case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + data = Multi.sramB; + break; case SNES_MEMORY_CARTRIDGE_RTC: data = RTCData.reg; break; @@ -515,11 +544,15 @@ unsigned snes_get_memory_size(unsigned type) unsigned size; switch(type) { + case SNES_MEMORY_SUFAMI_TURBO_A_RAM: case SNES_MEMORY_CARTRIDGE_RAM: size = (unsigned) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0); if (size > 0x20000) size = 0x20000; break; + case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + size = (unsigned) (Multi.cartType && Multi.sramSizeB ? (1 << (Multi.sramSizeB + 3)) * 128 : 0); + break; case SNES_MEMORY_CARTRIDGE_RTC: size = (Settings.SRTC || Settings.SPC7110RTC)?20:0; break; diff --git a/memmap.cpp b/memmap.cpp index 83effdbf..8eb52aec 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -936,12 +936,12 @@ 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 bool8 is_GNEXT_BIOS (uint8 *, uint32); -static bool8 is_GNEXT_Add_On (uint8 *, uint32); +static bool8 is_SufamiTurbo_BIOS (const uint8 *, uint32); +static bool8 is_SufamiTurbo_Cart (const uint8 *, uint32); +static bool8 is_SameGame_BIOS (const uint8 *, uint32); +static bool8 is_SameGame_Add_On (const uint8 *, uint32); +static bool8 is_GNEXT_BIOS (const uint8 *, uint32); +static bool8 is_GNEXT_Add_On (const uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); static bool8 ReadUPSPatch (Stream *, long, int32 &); @@ -1206,7 +1206,7 @@ static bool8 allASCII (uint8 *b, int size) return (TRUE); } -static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) +static bool8 is_SufamiTurbo_BIOS (const uint8 *data, uint32 size) { if (size == 0x40000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0) @@ -1215,7 +1215,7 @@ static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) +static bool8 is_SufamiTurbo_Cart (const 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) @@ -1224,7 +1224,7 @@ static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) +static bool8 is_SameGame_BIOS (const uint8 *data, uint32 size) { if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) return (TRUE); @@ -1232,7 +1232,7 @@ static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) +static bool8 is_SameGame_Add_On (const uint8 *data, uint32 size) { if (size == 0x80000) return (TRUE); @@ -1240,7 +1240,7 @@ static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_GNEXT_BIOS (uint8 *data, uint32 size) +static bool8 is_GNEXT_BIOS (const uint8 *data, uint32 size) { if (size == 0x180000 && strncmp((char *) (data + 0x7fc0), "SFC SDGUNDAMGNEXT", 17) == 0) return (TRUE); @@ -1248,7 +1248,7 @@ static bool8 is_GNEXT_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_GNEXT_Add_On (uint8 *data, uint32 size) +static bool8 is_GNEXT_Add_On (const uint8 *data, uint32 size) { if (size == 0x80000) return (TRUE); @@ -1543,6 +1543,9 @@ bool8 CMemory::LoadROM (const char *filename) if (!totalFileSize) return (FALSE); + + if (!Settings.NoPatch) + CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize); } while(!LoadROMInt(totalFileSize)); @@ -1557,9 +1560,6 @@ bool8 CMemory::LoadROMInt (int32 ROMfillSize) CalculatedSize = 0; ExtendedFormat = NOPE; - if (!Settings.NoPatch) - CheckForAnyPatch(ROMFilename, HeaderCount != 0, ROMfillSize); - int hi_score, lo_score; hi_score = ScoreHiROM(FALSE); @@ -1766,60 +1766,144 @@ bool8 CMemory::LoadROMInt (int32 ROMfillSize) return (TRUE); } +bool8 CMemory::LoadMultiCartMem (const uint8 *sourceA, uint32 sourceASize, + const uint8 *sourceB, uint32 sourceBSize, + const uint8 *bios, uint32 biosSize) +{ + uint32 offset = 0; + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + + if(bios) { + if(!is_SufamiTurbo_BIOS(bios,biosSize)) + return FALSE; + + memcpy(ROM,bios,biosSize); + offset+=biosSize; + } + + if(sourceA) { + memcpy(ROM + offset,sourceA,sourceASize); + Multi.cartOffsetA = offset; + Multi.cartSizeA = sourceASize; + offset += sourceASize; + strcpy(Multi.fileNameA,"MemCartA"); + } + + if(sourceB) { + memcpy(ROM + offset,sourceB,sourceBSize); + Multi.cartOffsetB = offset; + Multi.cartSizeB = sourceBSize; + offset += sourceBSize; + strcpy(Multi.fileNameB,"MemCartB"); + } + + return LoadMultiCartInt(); +} + bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) { - bool8 r = TRUE; - - ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); - CalculatedSize = 0; - ExtendedFormat = NOPE; + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + + if (Multi.cartSizeB) { + strcpy(Multi.fileNameB, cartB); + + if(!Settings.NoPatch) + CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); + + Multi.cartOffsetB = 0x400000; + memcpy(ROM + Multi.cartOffsetB,ROM,Multi.cartSizeB); + } 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) { + strcpy(Multi.fileNameA, cartA); + + if(!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + } + + return LoadMultiCartInt(); +} + +bool8 CMemory::LoadMultiCartInt () +{ + bool8 r = TRUE; + + CalculatedSize = 0; + ExtendedFormat = NOPE; if (Multi.cartSizeA) { - if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA)) + if (is_SufamiTurbo_Cart(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 4; else - if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) + if (is_SameGame_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 3; else - if (is_GNEXT_BIOS(ROM, Multi.cartSizeA)) + if (is_GNEXT_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 5; } else if (Multi.cartSizeB) { - if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + if (is_SufamiTurbo_Cart(ROM + Multi.cartOffsetB, Multi.cartSizeB)) Multi.cartType = 4; } else Multi.cartType = 4; // assuming BIOS only + + if(Multi.cartType == 4 && Multi.cartOffsetA == 0) { // try to load bios from file + Multi.cartOffsetA = 0x40000; + if(Multi.cartSizeA) + memmove(ROM + Multi.cartOffsetA,ROM,Multi.cartOffsetB - Multi.cartOffsetA); + else // clear cart A so the bios can detect that it's not present + memset(ROM,0,Multi.cartOffsetB); + + FILE *fp; + size_t size; + char path[PATH_MAX + 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); + + strcpy(ROMFilename, path); + } + switch (Multi.cartType) { case 4: - r = LoadSufamiTurbo(cartA, cartB); + r = LoadSufamiTurbo(); break; case 3: - r = LoadSameGame(cartA, cartB); + r = LoadSameGame(); break; case 5: - r = LoadGNEXT(cartA, cartB); + r = LoadGNEXT(); break; default: @@ -1832,6 +1916,12 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (FALSE); } + if (Multi.cartSizeA) + strcpy(ROMFilename, Multi.fileNameA); + else + if (Multi.cartSizeB) + strcpy(ROMFilename, Multi.fileNameB); + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; @@ -1847,10 +1937,8 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) +bool8 CMemory::LoadSufamiTurbo () { - Multi.cartOffsetA = 0x100000; - Multi.cartOffsetB = 0x200000; Multi.sramA = SRAM; Multi.sramB = SRAM + 0x10000; @@ -1858,65 +1946,20 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) { Multi.sramSizeA = 4; // ROM[0x37]? Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; - - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - strcpy(Multi.fileNameA, cartA); - memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); } - if (Multi.cartSizeA && !Multi.cartSizeB) + if (Multi.cartSizeB) { - if (cartB && cartB[0]) - Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); - - if (Multi.cartSizeB) - { - if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) - Multi.cartSizeB = 0; - } + if (!is_SufamiTurbo_Cart(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; } if (Multi.cartSizeB) { Multi.sramSizeB = 4; // ROM[0x37]? Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; - - if (!Settings.NoPatch) - CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); - - strcpy(Multi.fileNameB, cartB); - memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); } - FILE *fp; - size_t size; - char path[PATH_MAX + 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; @@ -1924,10 +1967,8 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) +bool8 CMemory::LoadSameGame () { - Multi.cartOffsetA = 0; - Multi.cartOffsetB = 0x200000; Multi.sramA = SRAM; Multi.sramB = NULL; @@ -1936,24 +1977,12 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) Multi.sramSizeB = 0; Multi.sramMaskB = 0; - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - 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; @@ -1961,10 +1990,8 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadGNEXT (const char *cartA, const char *cartB) +bool8 CMemory::LoadGNEXT () { - Multi.cartOffsetA = 0; - Multi.cartOffsetB = 0x400000; Multi.sramA = SRAM; Multi.sramB = NULL; @@ -1973,24 +2000,12 @@ bool8 CMemory::LoadGNEXT (const char *cartA, const char *cartB) Multi.sramSizeB = 0; Multi.sramMaskB = 0; - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - 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_GNEXT_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) Multi.cartSizeB = 0; - else - strcpy(Multi.fileNameB, cartB); } - strcpy(ROMFilename, Multi.fileNameA); - LoROM = TRUE; HiROM = FALSE; CalculatedSize = Multi.cartSizeA; diff --git a/memmap.h b/memmap.h index 4bf43d36..0f943542 100644 --- a/memmap.h +++ b/memmap.h @@ -277,10 +277,12 @@ struct CMemory bool8 LoadROMMem (const uint8 *, uint32); bool8 LoadROM (const char *); bool8 LoadROMInt (int32); + bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32); bool8 LoadMultiCart (const char *, const char *); - bool8 LoadSufamiTurbo (const char *, const char *); - bool8 LoadSameGame (const char *, const char *); - bool8 LoadGNEXT (const char *, const char *); + bool8 LoadMultiCartInt (); + bool8 LoadSufamiTurbo (); + bool8 LoadSameGame (); + bool8 LoadGNEXT (); bool8 LoadSRAM (const char *); bool8 SaveSRAM (const char *); void ClearSRAM (bool8 onlyNonSavedSRAM = 0); From 0f69665d175913209ed9fdd218af7cd08ef64188 Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 9 Jan 2012 17:33:42 +0100 Subject: [PATCH 082/130] Fix double stream close --- stream.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stream.cpp b/stream.cpp index 84f9424a..0d4082c4 100644 --- a/stream.cpp +++ b/stream.cpp @@ -244,7 +244,6 @@ fStream::fStream (FSTREAM f) fStream::~fStream (void) { - CLOSE_FSTREAM(fp); return; } From 0a7c84e7672fd6ebbfc17e0fa6ae57b44c85da01 Mon Sep 17 00:00:00 2001 From: Alex Rosario Date: Wed, 11 Jan 2012 17:07:22 -0500 Subject: [PATCH 083/130] reorder OS detection --- libsnes/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsnes/Makefile b/libsnes/Makefile index b72f8819..2038181d 100644 --- a/libsnes/Makefile +++ b/libsnes/Makefile @@ -2,12 +2,12 @@ ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win else ifneq ($(findstring win,$(shell uname -a)),) platform = win -else ifneq ($(findstring Darwin,$(shell uname -a)),) - platform = osx endif endif From a66f10d9e405e3545100c27f11dc3c2d06d0b475 Mon Sep 17 00:00:00 2001 From: OV2 Date: Fri, 20 Jan 2012 04:24:36 +0100 Subject: [PATCH 084/130] Convert old savestates for new smp --- apu/apu.cpp | 112 ++++++++++++ apu/apu.h | 1 + port.h | 10 +- snapshot.cpp | 8 +- snapshot.h | 4 +- win32/snes9xw.vcproj | 402 ++++++------------------------------------- 6 files changed, 179 insertions(+), 358 deletions(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index 237f3939..bc9f616a 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -637,6 +637,118 @@ void S9xAPULoadState (uint8 *block) memcpy (SNES::cpu.registers, ptr, 4); } +static void to_var_from_buf (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +#undef IF_0_THEN_256 +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) +void S9xAPULoadBlarggState(uint8 *oldblock) +{ + uint8 *ptr = oldblock; + + SNES::SPC_State_Copier copier(&ptr,to_var_from_buf); + + copier.copy(SNES::smp.apuram,0x10000); // RAM + + uint8_t regs_in [0x10]; + uint8_t regs [0x10]; + uint16_t pc, spc_time, dsp_time; + uint8_t a,x,y,psw,sp; + + copier.copy(regs,0x10); // REGS + copier.copy(regs_in,0x10); // REGS_IN + + // CPU Regs + pc = copier.copy_int( 0, sizeof(uint16_t) ); + a = copier.copy_int( 0, sizeof(uint8_t) ); + x = copier.copy_int( 0, sizeof(uint8_t) ); + y = copier.copy_int( 0, sizeof(uint8_t) ); + psw = copier.copy_int( 0, sizeof(uint8_t) ); + sp = copier.copy_int( 0, sizeof(uint8_t) ); + copier.extra(); + + // times + spc_time = copier.copy_int( 0, sizeof(uint16_t) ); + dsp_time = copier.copy_int( 0, sizeof(uint16_t) ); + + int cur_time = S9xAPUGetClock(CPU.Cycles); + + // spc_time is absolute, dsp_time is relative + // smp.clock is relative, dsp.clock relative but counting upwards + SNES::smp.clock = spc_time - cur_time; + SNES::dsp.clock = -1 * dsp_time; + + // DSP + SNES::dsp.load_state(&ptr); + + // Timers + uint16_t next_time[3]; + uint8_t divider[3], counter[3]; + for ( int i = 0; i < 3; i++ ) + { + next_time[i] = copier.copy_int( 0, sizeof(uint16_t) ); + divider[i] = copier.copy_int( 0, sizeof(uint8_t) ); + counter[i] = copier.copy_int( 0, sizeof(uint8_t) ); + copier.extra(); + } + // construct timers out of available parts from blargg smp + SNES::smp.timer0.enable = regs[1] >> 0 & 1; // regs[1] = CONTROL + SNES::smp.timer0.target = IF_0_THEN_256(regs[10]); // regs[10+i] = TiTARGET + // blargg counts time, get ticks through timer frequency + // (assume tempo = 256) + SNES::smp.timer0.stage1_ticks = 128 - (next_time[0] - cur_time) / 128; + SNES::smp.timer0.stage2_ticks = divider[0]; + SNES::smp.timer0.stage3_ticks = counter[0]; + + SNES::smp.timer1.enable = regs[1] >> 1 & 1; + SNES::smp.timer1.target = IF_0_THEN_256(regs[11]); + SNES::smp.timer1.stage1_ticks = 128 - (next_time[1] - cur_time) / 128; + SNES::smp.timer1.stage2_ticks = divider[0]; + SNES::smp.timer1.stage3_ticks = counter[0]; + + SNES::smp.timer2.enable = regs[1] >> 2 & 1; + SNES::smp.timer2.target = IF_0_THEN_256(regs[12]); + SNES::smp.timer2.stage1_ticks = 16 - (next_time[2] - cur_time) / 16; + SNES::smp.timer2.stage2_ticks = divider[0]; + SNES::smp.timer2.stage3_ticks = counter[0]; + + copier.extra(); + + SNES::smp.opcode_number = 0; + SNES::smp.opcode_cycle = 0; + + SNES::smp.regs.pc = pc; + SNES::smp.regs.sp = sp; + SNES::smp.regs.a = a; + SNES::smp.regs.x = x; + SNES::smp.regs.y = y; + + // blargg's psw has same layout as byuu's flags + SNES::smp.regs.p = psw; + + // blargg doesn't explicitly store iplrom_enable + SNES::smp.status.iplrom_enable = regs[1] & 0x80; + + SNES::smp.status.dsp_addr = regs[2]; + + SNES::smp.status.ram00f8 = regs_in[8]; + SNES::smp.status.ram00f9 = regs_in[9]; + + // default to 0 - we are on an opcode boundary, shouldn't matter + SNES::smp.rd=SNES::smp.wr=SNES::smp.dp=SNES::smp.sp=SNES::smp.ya=SNES::smp.bit=0; + + spc::reference_time = SNES::get_le32(ptr); + ptr += sizeof(int32); + spc::remainder = SNES::get_le32(ptr); + ptr += sizeof(int32); + + // blargg stores CPUIx in regs_in + memcpy (SNES::cpu.registers, regs_in + 4, 4); +} + bool8 S9xSPCDump (const char *filename) { FILE *fs; diff --git a/apu/apu.h b/apu/apu.h index 44b183a8..61575dae 100644 --- a/apu/apu.h +++ b/apu/apu.h @@ -198,6 +198,7 @@ void S9xAPUSetReferenceTime (int32); void S9xAPUTimingSetSpeedup (int); void S9xAPUAllowTimeOverflow (bool); void S9xAPULoadState (uint8 *); +void S9xAPULoadBlarggState(uint8 *oldblock); void S9xAPUSaveState (uint8 *); void S9xDumpSPCSnapshot (void); bool8 S9xSPCDump (const char *); diff --git a/port.h b/port.h index 0e8192e5..bd43353c 100644 --- a/port.h +++ b/port.h @@ -248,10 +248,16 @@ typedef signed int int32; #endif typedef unsigned int uint32; #endif -typedef unsigned char uint8_t; -typedef signed char int8_t; typedef signed __int64 int64; typedef unsigned __int64 uint64; +typedef int8 int8_t; +typedef uint8 uint8_t; +typedef int16 int16_t; +typedef uint16 uint16_t; +typedef int32 int32_t; +typedef uint32 uint32_t; +typedef int64 int64_t; +typedef uint64 uint64_t; typedef int socklen_t; #else // __WIN32__ typedef signed char int8; diff --git a/snapshot.cpp b/snapshot.cpp index e6cd879a..8c9a434e 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1626,7 +1626,11 @@ int S9xUnfreezeFromStream (STREAM stream) memcpy(Memory.FillRAM, local_fillram, 0x8000); - S9xAPULoadState(local_apu_sound); + if(version < SNAPSHOT_VERSION_BAPU) { + printf("Using Blargg APU snapshot loading (snapshot version %d, current is %d)\n...", version, SNAPSHOT_VERSION); + S9xAPULoadBlarggState(local_apu_sound); + } else + S9xAPULoadState(local_apu_sound); struct SControlSnapshot ctl_snap; UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version); @@ -1678,7 +1682,7 @@ int S9xUnfreezeFromStream (STREAM stream) if (local_bsx_data) UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); - if (version < SNAPSHOT_VERSION) + if (version < SNAPSHOT_VERSION_IRQ) { printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION); diff --git a/snapshot.h b/snapshot.h index 1cb4bd8c..a522abae 100644 --- a/snapshot.h +++ b/snapshot.h @@ -180,7 +180,9 @@ #define _SNAPSHOT_H_ #define SNAPSHOT_MAGIC "#!s9xsnp" -#define SNAPSHOT_VERSION 7 +#define SNAPSHOT_VERSION_IRQ 7 +#define SNAPSHOT_VERSION_BAPU 8 +#define SNAPSHOT_VERSION 8 #define SUCCESS 1 #define WRONG_FORMAT (-1) diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 4b5bda35..06e38e15 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -158,7 +158,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="$(ProjectDir),$(ProjectDir)..\,$(ProjectDir)..\..\,$(ProjectDir)..\..\zLib,$(ProjectDir)..\unzip,$(ProjectDir)..\..\FMOD\api\inc,$(ProjectDir)..\..\libPNG\src,$(ProjectDir)..\snes9x" + AdditionalIncludeDirectories="$(ProjectDir),$(ProjectDir)..\,$(ProjectDir)..\..\,$(ProjectDir)..\..\zLib,$(ProjectDir)..\unzip,$(ProjectDir)..\..\FMOD\api\inc,$(ProjectDir)..\..\libPNG\src,$(ProjectDir)..\apu\bapu" PreprocessorDefinitions="NDEBUG;HAVE_LIBPNG;JMA_SUPPORT;ZLIB;UNZIP_SUPPORT;__WIN32__;FMODEX_SUPPORT;NETPLAY_SUPPORT" StringPooling="true" RuntimeLibrary="0" @@ -255,7 +255,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + - - - + - - - - + + + + + + + + + + - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Date: Sun, 22 Jan 2012 20:18:15 +0100 Subject: [PATCH 085/130] Win32: use event for soundsync --- win32/CDirectSound.cpp | 3 ++- win32/CFMOD.cpp | 4 +++- win32/CFMODEx.cpp | 4 +++- win32/CXAudio2.cpp | 1 + win32/render.cpp | 2 +- win32/win32.cpp | 2 ++ win32/wsnes9x.cpp | 12 +++--------- win32/wsnes9x.h | 1 + 8 files changed, 16 insertions(+), 13 deletions(-) diff --git a/win32/CDirectSound.cpp b/win32/CDirectSound.cpp index 8dc6c948..bd640a92 100644 --- a/win32/CDirectSound.cpp +++ b/win32/CDirectSound.cpp @@ -489,7 +489,8 @@ void CDirectSound::MixSound() S9xMixSamples(B2,(Settings.SixteenBitSound?S2>>1:S2)); } LeaveCriticalSection(&GUI.SoundCritSect); - + + SetEvent(GUI.SoundSyncEvent); hResult = lpDSB -> Unlock (B1, S1, B2, S2); if (!SUCCEEDED(hResult)) diff --git a/win32/CFMOD.cpp b/win32/CFMOD.cpp index 2c2c9a14..ffd93daf 100644 --- a/win32/CFMOD.cpp +++ b/win32/CFMOD.cpp @@ -357,6 +357,8 @@ F_CALLBACKAPI CFMOD::FMODStreamCallback (FSOUND_STREAM *stream, void *buff, int LeaveCriticalSection(&GUI.SoundCritSect); + SetEvent(GUI.SoundSyncEvent); + #if defined (FSOUND_LOADRAW) @@ -364,4 +366,4 @@ F_CALLBACKAPI CFMOD::FMODStreamCallback (FSOUND_STREAM *stream, void *buff, int #endif } -#endif \ No newline at end of file +#endif diff --git a/win32/CFMODEx.cpp b/win32/CFMODEx.cpp index 09f9035e..b5a6b4d9 100644 --- a/win32/CFMODEx.cpp +++ b/win32/CFMODEx.cpp @@ -135,7 +135,9 @@ FMOD_RESULT F_CALLBACK CFMODEx::FMODExStreamCallback( LeaveCriticalSection(&GUI.SoundCritSect); + SetEvent(GUI.SoundSyncEvent); + return FMOD_OK; } #endif -#endif \ No newline at end of file +#endif diff --git a/win32/CXAudio2.cpp b/win32/CXAudio2.cpp index ba4297be..90286f1b 100644 --- a/win32/CXAudio2.cpp +++ b/win32/CXAudio2.cpp @@ -308,6 +308,7 @@ pBufferContext - unused void CXAudio2::OnBufferEnd(void *pBufferContext) { InterlockedDecrement(&bufferCount); + SetEvent(GUI.SoundSyncEvent); } /* CXAudio2::PushBuffer diff --git a/win32/render.cpp b/win32/render.cpp index f565de08..a5ac894b 100644 --- a/win32/render.cpp +++ b/win32/render.cpp @@ -2624,7 +2624,7 @@ void RenderBlarggNTSCRgb( SSurface Src, SSurface Dst, RECT *rect) void RenderBlarggNTSC( SSurface Src, SSurface Dst, RECT *rect) { SetRect(rect, 256, 239, 2); - rect->right = 604; + rect->right = SNES_NTSC_OUT_WIDTH(256); const unsigned int srcRowPixels = Src.Pitch/2; diff --git a/win32/win32.cpp b/win32/win32.cpp index aba6d171..7d4a52fb 100644 --- a/win32/win32.cpp +++ b/win32/win32.cpp @@ -986,6 +986,7 @@ void InitSnes9X( void) GFX.Screen = (uint16*)(ScreenBuffer); InitializeCriticalSection(&GUI.SoundCritSect); + GUI.SoundSyncEvent = CreateEvent(NULL,TRUE,TRUE,NULL); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); S9xInitAPU(); @@ -1005,6 +1006,7 @@ void DeinitS9x() delete [] ScreenBuf; DeleteCriticalSection(&GUI.SoundCritSect); + CloseHandle(GUI.SoundSyncEvent); CoUninitialize(); if(GUI.GunSight) DestroyCursor(GUI.GunSight);//= LoadCursor (hInstance, MAKEINTRESOURCE (IDC_CURSOR_SCOPE)); diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index aaa21d5a..85d737db 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -3304,7 +3304,6 @@ int WINAPI WinMain( ChangeInputDevice(); DWORD lastTime = timeGetTime(); - DWORD sSyncTime,sSyncWaited; MSG msg; @@ -3421,15 +3420,10 @@ int WINAPI WinMain( { ProcessInput(); - sSyncTime=timeGetTime(); - while(!S9xSyncSound()) { - Sleep(2); - sSyncWaited=timeGetTime(); - if(sSyncWaited-sSyncTime > 1000) { - S9xClearSamples(); - break; - } + ResetEvent(GUI.SoundSyncEvent); + if(WaitForSingleObject(GUI.SoundSyncEvent,1000) != WAIT_OBJECT_0) + S9xClearSamples(); } S9xMainLoop(); diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 894f4c90..4a49f3cd 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -369,6 +369,7 @@ struct sGUI { bool Mute; // used for sync sound synchronization CRITICAL_SECTION SoundCritSect; + HANDLE SoundSyncEvent; TCHAR RomDir [_MAX_PATH]; TCHAR ScreensDir [_MAX_PATH]; From faee2859b5cb14593362fe2234056e4bb1a6a517 Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 23 Jan 2012 18:12:47 +0100 Subject: [PATCH 086/130] Change ZeroMemory to memset --- cheats2.cpp | 2 +- conffile.cpp | 2 +- controls.cpp | 6 +- cpu.cpp | 4 +- gfx.cpp | 14 ++--- macosx/mac-controls.cpp | 2 +- memmap.cpp | 50 +++++++-------- movie.cpp | 12 ++-- port.h | 1 - ppu.cpp | 24 +++---- snapshot.cpp | 2 +- unix/unix.cpp | 4 +- win32/CDirect3D.cpp | 2 +- win32/CDirectDraw.cpp | 4 +- win32/COpenGL.cpp | 2 +- win32/wsnes9x.cpp | 134 ++++++++++++++++++++-------------------- 16 files changed, 132 insertions(+), 133 deletions(-) diff --git a/cheats2.cpp b/cheats2.cpp index ce1d153a..aeef2cc6 100644 --- a/cheats2.cpp +++ b/cheats2.cpp @@ -368,7 +368,7 @@ bool8 S9xSaveCheatFile (const char *filename) for (uint32 i = 0; i < Cheat.num_cheats; i++) { - ZeroMemory(data, 28); + memset(data, 0, 28); if (i == 0) { diff --git a/conffile.cpp b/conffile.cpp index b7f60298..dde03227 100644 --- a/conffile.cpp +++ b/conffile.cpp @@ -427,7 +427,7 @@ string ConfigFile::GetString(const char *key, string def){ char *ConfigFile::GetString(const char *key, char *out, uint32 outlen){ if(!Exists(key)) return NULL; - ZeroMemory(out, outlen); + memset(out, 0, outlen); string o=Get(key); if(outlen>0){ outlen--; diff --git a/controls.cpp b/controls.cpp index 224ec88a..714bb206 100644 --- a/controls.cpp +++ b/controls.cpp @@ -624,7 +624,7 @@ void S9xUnmapAllControls (void) if (!(superscope.crosshair.set & 4)) superscope.crosshair.bg = 1; - ZeroMemory(pseudobuttons, sizeof(pseudobuttons)); + memset(pseudobuttons, 0, sizeof(pseudobuttons)); turbo_time = 1; } @@ -1241,7 +1241,7 @@ s9xcommand_t S9xGetCommandT (const char *name) int i, j; const char *s; - ZeroMemory(&cmd, sizeof(cmd)); + memset(&cmd, 0, sizeof(cmd)); cmd.type = S9xBadMapping; cmd.multi_press = 0; cmd.button_norpt = 0; @@ -3450,7 +3450,7 @@ void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char ** void S9xControlPreSaveState (struct SControlSnapshot *s) { - ZeroMemory(s, sizeof(*s)); + memset(s, 0, sizeof(*s)); s->ver = 3; for (int j = 0; j < 2; j++) diff --git a/cpu.cpp b/cpu.cpp index 575bc59b..4bdb92b2 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -274,7 +274,7 @@ void S9xReset (void) memset(Memory.RAM, 0x55, 0x20000); memset(Memory.VRAM, 0x00, 0x10000); - ZeroMemory(Memory.FillRAM, 0x8000); + memset(Memory.FillRAM, 0, 0x8000); if (Settings.BS) S9xResetBSX(); @@ -308,7 +308,7 @@ void S9xSoftReset (void) { S9xResetSaveTimer(FALSE); - ZeroMemory(Memory.FillRAM, 0x8000); + memset(Memory.FillRAM, 0, 0x8000); if (Settings.BS) S9xResetBSX(); diff --git a/gfx.cpp b/gfx.cpp index 305a1e57..040a1e8d 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -216,7 +216,7 @@ static uint16 get_crosshair_color (uint8); bool8 S9xGraphicsInit (void) { S9xInitTileRenderer(); - ZeroMemory(BlackColourMap, 256 * sizeof(uint16)); + memset(BlackColourMap, 0, 256 * sizeof(uint16)); #ifdef GFX_MULTI_FORMAT if (GFX.BuildPixel == NULL) @@ -246,7 +246,7 @@ bool8 S9xGraphicsInit (void) } // Lookup table for color addition - ZeroMemory(GFX.X2, 0x10000 * sizeof(uint16)); + memset(GFX.X2, 0, 0x10000 * sizeof(uint16)); for (uint32 r = 0; r <= MAX_RED; r++) { uint32 r2 = r << 1; @@ -272,7 +272,7 @@ bool8 S9xGraphicsInit (void) } // Lookup table for 1/2 color subtraction - ZeroMemory(GFX.ZERO, 0x10000 * sizeof(uint16)); + memset(GFX.ZERO, 0, 0x10000 * sizeof(uint16)); for (uint32 r = 0; r <= MAX_RED; r++) { uint32 r2 = r; @@ -387,8 +387,8 @@ void S9xStartScreenRefresh (void) PPU.RecomputeClipWindows = TRUE; IPPU.PreviousLine = IPPU.CurrentLine = 0; - ZeroMemory(GFX.ZBuffer, GFX.ScreenSize); - ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize); + memset(GFX.ZBuffer, 0, GFX.ScreenSize); + memset(GFX.SubZBuffer, 0, GFX.ScreenSize); } if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) @@ -810,7 +810,7 @@ static void SetupOBJ (void) if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case { uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; - ZeroMemory(LineOBJ, sizeof(LineOBJ)); + memset(LineOBJ, 0, sizeof(LineOBJ)); for (int i = 0; i < SNES_HEIGHT_EXTENDED; i++) { @@ -887,7 +887,7 @@ static void SetupOBJ (void) { // First, find out which sprites are on which lines uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128]; - ZeroMemory(OBJOnLine, sizeof(OBJOnLine)); + memset(OBJOnLine, 0, sizeof(OBJOnLine)); for (S = 0; S < 128; S++) { diff --git a/macosx/mac-controls.cpp b/macosx/mac-controls.cpp index 26e0d5b4..46a5d4ab 100644 --- a/macosx/mac-controls.cpp +++ b/macosx/mac-controls.cpp @@ -424,7 +424,7 @@ s9xcommand_t S9xGetPortCommandT (const char *name) { s9xcommand_t cmd; - ZeroMemory(&cmd, sizeof(cmd)); + memset(&cmd, 0, sizeof(cmd)); cmd.type = S9xBadMapping; return (cmd); diff --git a/memmap.cpp b/memmap.cpp index 811518eb..20b9d2ff 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -1101,26 +1101,26 @@ bool8 CMemory::Init (void) return (FALSE); } - ZeroMemory(RAM, 0x20000); - ZeroMemory(SRAM, 0x20000); - ZeroMemory(VRAM, 0x10000); - ZeroMemory(ROM, 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); - 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); + memset(IPPU.TileCache[TILE_2BIT], 0, MAX_2BIT_TILES * 64); + memset(IPPU.TileCache[TILE_4BIT], 0, MAX_4BIT_TILES * 64); + memset(IPPU.TileCache[TILE_8BIT], 0, MAX_8BIT_TILES * 64); + memset(IPPU.TileCache[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES * 64); + memset(IPPU.TileCache[TILE_2BIT_ODD], 0, MAX_2BIT_TILES * 64); + memset(IPPU.TileCache[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES * 64); + memset(IPPU.TileCache[TILE_4BIT_ODD], 0, MAX_4BIT_TILES * 64); - 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); + memset(IPPU.TileCached[TILE_2BIT], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT], 0, MAX_4BIT_TILES); + memset(IPPU.TileCached[TILE_8BIT], 0, MAX_8BIT_TILES); + memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_2BIT_ODD], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES); // FillRAM uses first 32K of ROM image area, otherwise space just // wasted. Might be read by the SuperFX code. @@ -1518,8 +1518,8 @@ bool8 CMemory::LoadROM (const char *filename) if (!filename || !*filename) return (FALSE); - ZeroMemory(ROM, MAX_ROM_SIZE); - ZeroMemory(&Multi, sizeof(Multi)); + memset(ROM, 0, MAX_ROM_SIZE); + memset(&Multi, 0, sizeof(Multi)); again: Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); @@ -1732,7 +1732,7 @@ again: LastRomFilename[PATH_MAX] = 0; } - ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + memset(&SNESGameFixes, 0, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); @@ -1751,8 +1751,8 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) { bool8 r = TRUE; - ZeroMemory(ROM, MAX_ROM_SIZE); - ZeroMemory(&Multi, sizeof(Multi)); + memset(ROM, 0, MAX_ROM_SIZE); + memset(&Multi, 0, sizeof(Multi)); Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); @@ -1809,11 +1809,11 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) if (!r) { - ZeroMemory(&Multi, sizeof(Multi)); + memset(&Multi, 0, sizeof(Multi)); return (FALSE); } - ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + memset(&SNESGameFixes, 0, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); diff --git a/movie.cpp b/movie.cpp index 982b9ebd..6b42745a 100644 --- a/movie.cpp +++ b/movie.cpp @@ -412,14 +412,14 @@ static void reset_controllers (void) MovieSetJoypad(i, 0); uint8 clearedMouse[MOUSE_DATA_SIZE]; - ZeroMemory(clearedMouse, MOUSE_DATA_SIZE); + memset(clearedMouse, 0, MOUSE_DATA_SIZE); clearedMouse[4] = 1; uint8 clearedScope[SCOPE_DATA_SIZE]; - ZeroMemory(clearedScope, SCOPE_DATA_SIZE); + memset(clearedScope, 0, SCOPE_DATA_SIZE); uint8 clearedJustifier[JUSTIFIER_DATA_SIZE]; - ZeroMemory(clearedJustifier, JUSTIFIER_DATA_SIZE); + memset(clearedJustifier, 0, JUSTIFIER_DATA_SIZE); for (int p = 0; p < 2; p++) { @@ -614,7 +614,7 @@ static void write_movie_header (FILE *fd, SMovie *movie) { uint8 buf[SMV_HEADER_SIZE], *ptr = buf; - ZeroMemory(buf, sizeof(buf)); + memset(buf, 0, sizeof(buf)); Write32(SMV_MAGIC, ptr); Write32(SMV_VERSION, ptr); @@ -963,7 +963,7 @@ int S9xMovieGetInfo (const char *filename, struct MovieInfo *info) flush_movie(); - ZeroMemory(info, sizeof(*info)); + memset(info, 0, sizeof(*info)); if (!(fd = fopen(filename, "rb"))) return (FILE_NOT_FOUND); @@ -1092,7 +1092,7 @@ void S9xMovieUpdateOnReset (void) void S9xMovieInit (void) { - ZeroMemory(&Movie, sizeof(Movie)); + memset(&Movie, 0, sizeof(Movie)); Movie.State = MOVIE_STATE_NONE; } diff --git a/port.h b/port.h index 0e8192e5..e00b6059 100644 --- a/port.h +++ b/port.h @@ -296,7 +296,6 @@ typedef unsigned long long uint64; #endif #ifndef __WIN32__ -#define ZeroMemory(a, b) memset((a), 0, (b)) void _splitpath (const char *, char *, char *, char *, char *); void _makepath (char *, const char *, const char *, const char *, const char *); #define S9xDisplayString DisplayStringFromBottom diff --git a/ppu.cpp b/ppu.cpp index 7733baaf..0907021b 100644 --- a/ppu.cpp +++ b/ppu.cpp @@ -1872,7 +1872,7 @@ void S9xSoftResetPPU (void) PPU.OAMReadFlip = 0; PPU.OAMTileAddress = 0; PPU.OAMWriteRegister = 0; - ZeroMemory(PPU.OAMData, 512 + 32); + memset(PPU.OAMData, 0, 512 + 32); PPU.FirstSprite = 0; PPU.LastSprite = 127; @@ -1947,13 +1947,13 @@ void S9xSoftResetPPU (void) IPPU.ColorsChanged = TRUE; IPPU.OBJChanged = TRUE; IPPU.DirectColourMapsNeedRebuild = TRUE; - 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); + memset(IPPU.TileCached[TILE_2BIT], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT], 0, MAX_4BIT_TILES); + memset(IPPU.TileCached[TILE_8BIT], 0, MAX_8BIT_TILES); + memset(IPPU.TileCached[TILE_2BIT_EVEN], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_2BIT_ODD], 0, MAX_2BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT_EVEN], 0, MAX_4BIT_TILES); + memset(IPPU.TileCached[TILE_4BIT_ODD], 0, MAX_4BIT_TILES); IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? IPPU.Interlace = FALSE; IPPU.InterlaceOBJ = FALSE; @@ -1978,11 +1978,11 @@ void S9xSoftResetPPU (void) for (int c = 0; c < 0x8000; c += 0x100) memset(&Memory.FillRAM[c], c >> 8, 0x100); - ZeroMemory(&Memory.FillRAM[0x2100], 0x100); - ZeroMemory(&Memory.FillRAM[0x4200], 0x100); - ZeroMemory(&Memory.FillRAM[0x4000], 0x100); + memset(&Memory.FillRAM[0x2100], 0, 0x100); + memset(&Memory.FillRAM[0x4200], 0, 0x100); + memset(&Memory.FillRAM[0x4000], 0, 0x100); // For BS Suttehakkun 2... - ZeroMemory(&Memory.FillRAM[0x1000], 0x1000); + memset(&Memory.FillRAM[0x1000], 0, 0x1000); Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff; } diff --git a/snapshot.cpp b/snapshot.cpp index 7b758b42..164cda38 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2061,7 +2061,7 @@ static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int siz len = size; } - ZeroMemory(block, size); + memset(block, 0, size); if (READ_STREAM(block, len, stream) != len) { diff --git a/unix/unix.cpp b/unix/unix.cpp index c5f6da26..c16d04aa 100644 --- a/unix/unix.cpp +++ b/unix/unix.cpp @@ -1555,7 +1555,7 @@ int main (int argc, char **argv) snprintf(default_dir, PATH_MAX + 1, "%s%s%s", getenv("HOME"), SLASH_STR, ".snes9x"); s9x_base_dir = default_dir; - ZeroMemory(&Settings, sizeof(Settings)); + memset(&Settings, 0, sizeof(Settings)); Settings.MouseMaster = TRUE; Settings.SuperScopeMaster = TRUE; Settings.JustifierMaster = TRUE; @@ -1594,7 +1594,7 @@ int main (int argc, char **argv) unixSettings.SoundBufferSize = 100; unixSettings.SoundFragmentSize = 2048; - ZeroMemory(&so, sizeof(so)); + memset(&so, 0, sizeof(so)); CPU.Flags = 0; diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index a801c168..56d16b9b 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -262,7 +262,7 @@ bool CDirect3D::Initialize(HWND hWnd) return false; } - ZeroMemory(&dPresentParams, sizeof(dPresentParams)); + memset(&dPresentParams, 0, sizeof(dPresentParams)); dPresentParams.hDeviceWindow = hWnd; dPresentParams.Windowed = true; dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; diff --git a/win32/CDirectDraw.cpp b/win32/CDirectDraw.cpp index 4943a226..99f5efbd 100644 --- a/win32/CDirectDraw.cpp +++ b/win32/CDirectDraw.cpp @@ -554,7 +554,7 @@ void CDirectDraw::Render(SSurface Src) if(!dDinitialized) return; - ZeroMemory(&caps,sizeof(DDSCAPS)); + memset(&caps, 0,sizeof(DDSCAPS)); caps.dwCaps = DDSCAPS_BACKBUFFER; if (lpDDSPrimary2->GetAttachedSurface (&caps, &pDDSurface) != DD_OK || @@ -676,7 +676,7 @@ void CDirectDraw::Render(SSurface Src) lpDDSurface2->Unlock (Dst.Surface); - ZeroMemory(&caps,sizeof(DDSCAPS)); + memset(&caps, 0,sizeof(DDSCAPS)); caps.dwCaps = DDSCAPS_BACKBUFFER; if (lpDDSPrimary2->GetAttachedSurface (&caps, &pDDSurface) != DD_OK || diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index c5beb828..04557484 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -596,7 +596,7 @@ void COpenGL::EnumModes(std::vector *modeVector) if (!(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) && (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) { DEVMODE dm; - ZeroMemory(&dm, sizeof(dm)); + memset(&dm, 0, sizeof(dm)); dm.dmSize = sizeof(dm); iMode = 0; while(EnumDisplaySettings(dd.DeviceName,iMode,&dm)) { diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 85d737db..3c405860 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -1400,7 +1400,7 @@ static bool DoOpenRomDialog(TCHAR filename [_MAX_PATH], bool noCustomDlg = false strcat0(lpfilterptr, FILE_INFO_ANY_FILE_TYPE); strcat0(lpfilterptr, TEXT("\0*.*\0\0")); - ZeroMemory((LPVOID)&ofn, sizeof(OPENFILENAME)); + memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = GUI.hWnd; ofn.lpstrFilter = lpfilter; @@ -1523,7 +1523,7 @@ LRESULT CALLBACK WinProc( szFileName[0] = TEXT('\0'); - ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = GUI.hWnd; ofn.lpstrFilter = FILE_INFO_AVI_FILE_TYPE TEXT("\0*.avi\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0"); @@ -2564,7 +2564,7 @@ LRESULT CALLBACK WinProc( BOOL WinInit( HINSTANCE hInstance) { WNDCLASSEX wndclass; - ZeroMemory(&wndclass, sizeof(wndclass)); + memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; @@ -3568,7 +3568,7 @@ static void CheckMenuStates () MENUITEMINFO mii; unsigned int i; - ZeroMemory( &mii, sizeof( mii)); + memset( &mii, 0, sizeof( mii)); mii.cbSize = sizeof( mii); mii.fMask = MIIM_STATE; @@ -3818,7 +3818,7 @@ static void CheckMenuStates () mii.fState = !Settings.StopEmulation ? MFS_ENABLED : MFS_DISABLED; SetMenuItemInfo (GUI.hMenu, ID_FILE_AVI_RECORDING, FALSE, &mii); - ZeroMemory(&mii, sizeof(mii)); + memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING; @@ -4955,7 +4955,7 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar LPMALLOC lpm=NULL; LPITEMIDLIST iidl=NULL; BROWSEINFO bi; - ZeroMemory(&bi, sizeof(BROWSEINFO)); + memset(&bi, 0, sizeof(BROWSEINFO)); TCHAR path[MAX_PATH]; _tfullpath(path, paths[which], MAX_PATH); TCHAR title[]=SETTINGS_TITLE_SELECTFOLDER; @@ -5283,7 +5283,7 @@ void GetPathFromTree( HWND hDlg, UINT tree, TCHAR* selected, HTREEITEM hItem) TVITEM tv; TCHAR temp[MAX_PATH]; temp[0]=('\0'); - ZeroMemory(&tv, sizeof(TVITEM)); + memset(&tv, 0, sizeof(TVITEM)); HTREEITEM hTreeTemp=hItem; if(tv.iImage==7) @@ -5292,7 +5292,7 @@ void GetPathFromTree( HWND hDlg, UINT tree, TCHAR* selected, HTREEITEM hItem) tv.hItem=hTreeTemp; tv.iImage=6; TreeView_SetItem(GetDlgItem(hDlg, tree),&tv); - ZeroMemory(&tv, sizeof(TVITEM)); + memset(&tv, 0, sizeof(TVITEM)); } tv.mask=TVIF_HANDLE|TVIF_TEXT; @@ -5350,7 +5350,7 @@ void ExpandDir(TCHAR * selected, HTREEITEM hParent, HWND hDlg) { TCHAR temp[MAX_PATH]; WIN32_FIND_DATA wfd; - ZeroMemory(&wfd, sizeof(WIN32_FIND_DATA)); + memset(&wfd, 0, sizeof(WIN32_FIND_DATA)); lstrcat(selected, TEXT("\\*")); HANDLE hFind=FindFirstFile(selected,&wfd); selected[(lstrlen(selected)-1)]=TEXT('\0'); @@ -5363,7 +5363,7 @@ void ExpandDir(TCHAR * selected, HTREEITEM hParent, HWND hDlg) { //skip these, add the rest. TV_INSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + memset(&tvis, 0, sizeof(TV_INSERTSTRUCT)); tvis.hParent=hParent; tvis.hInsertAfter=TVI_SORT; tvis.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; @@ -5381,7 +5381,7 @@ void ExpandDir(TCHAR * selected, HTREEITEM hParent, HWND hDlg) bool subdir=false; WIN32_FIND_DATA wfd2; - ZeroMemory(&wfd2, sizeof(WIN32_FIND_DATA)); + memset(&wfd2, 0, sizeof(WIN32_FIND_DATA)); HANDLE hFind2=FindFirstFile(temp,&wfd2); do { @@ -5398,7 +5398,7 @@ void ExpandDir(TCHAR * selected, HTREEITEM hParent, HWND hDlg) if(subdir) { TV_INSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + memset(&tvis, 0, sizeof(TV_INSERTSTRUCT)); tvis.hParent=hNewTree; tvis.hInsertAfter=TVI_SORT; TreeView_InsertItem(GetDlgItem(hDlg, IDC_ROM_DIR),&tvis); @@ -5426,7 +5426,7 @@ void ListFilesFromFolder(HWND hDlg, RomDataList** prdl) TCHAR temp[MAX_PATH]; TCHAR selected[MAX_PATH]; // directory path temp[0]='\0'; - ZeroMemory(&tv, sizeof(TVITEM)); + memset(&tv, 0, sizeof(TVITEM)); HTREEITEM hTreeItem=TreeView_GetSelection(GetDlgItem(hDlg, IDC_ROM_DIR)); GetPathFromTree(hDlg, IDC_ROM_DIR, selected, hTreeItem); @@ -5438,7 +5438,7 @@ void ListFilesFromFolder(HWND hDlg, RomDataList** prdl) //Add items here. WIN32_FIND_DATA wfd; - ZeroMemory(&wfd, sizeof(WIN32_FIND_DATA)); + memset(&wfd, 0, sizeof(WIN32_FIND_DATA)); lstrcat(selected, TEXT("\\*")); @@ -5451,7 +5451,7 @@ void ListFilesFromFolder(HWND hDlg, RomDataList** prdl) if(ExtensionIsValid(wfd.cFileName)) { RomDataList* newitem=new RomDataList; - ZeroMemory(newitem, sizeof(RomDataList)); + memset(newitem, 0, sizeof(RomDataList)); newitem->fname=new TCHAR[1+lstrlen(wfd.cFileName)]; lstrcpy(newitem->fname, wfd.cFileName); @@ -5595,7 +5595,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara RECT listRect; WNDCLASSEX wcex; TCHAR tempclassname[]=TEXT("S9xSplitter"); - ZeroMemory(&wcex, sizeof(WNDCLASSEX)); + memset(&wcex, 0, sizeof(WNDCLASSEX)); wcex.cbSize=sizeof(WNDCLASSEX); wcex.hInstance=g_hInst; wcex.lpfnWndProc=DlgChildSplitProc; @@ -5617,7 +5617,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara LVCOLUMN col; static const LPTSTR temp1 = ROM_COLUMN_FILENAME; - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; col.fmt=LVCFMT_LEFT; col.iOrder=0; @@ -5628,7 +5628,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara ListView_InsertColumn(romList, 0, &col); static const LPTSTR temp2 = ROM_COLUMN_DESCRIPTION; - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=1; @@ -5641,7 +5641,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara static const LPTSTR temp3 = ROM_COLUMN_SIZE; - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=2; @@ -5729,7 +5729,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara driveName[2]='\0'; TVINSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TVINSERTSTRUCT)); + memset(&tvis, 0, sizeof(TVINSERTSTRUCT)); tvis.hParent=NULL; tvis.hInsertAfter=TVI_ROOT; @@ -5760,7 +5760,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara if(driveType==DRIVE_REMOVABLE || driveType == DRIVE_CDROM || driveType == DRIVE_UNKNOWN) { TV_INSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + memset(&tvis, 0, sizeof(TV_INSERTSTRUCT)); tvis.hParent=hTwee; tvis.hInsertAfter=TVI_SORT; TreeView_InsertItem(dirList,&tvis); @@ -5769,7 +5769,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara else { WIN32_FIND_DATA wfd2; - ZeroMemory(&wfd2, sizeof(WIN32_FIND_DATA)); + memset(&wfd2, 0, sizeof(WIN32_FIND_DATA)); HANDLE hFind2=FindFirstFile(temp,&wfd2); do { @@ -5786,7 +5786,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara if(subdir) { TV_INSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + memset(&tvis, 0, sizeof(TV_INSERTSTRUCT)); tvis.hParent=hTwee; tvis.hInsertAfter=TVI_SORT; TreeView_InsertItem(dirList,&tvis); @@ -5816,7 +5816,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara temp2 = temp3; TVITEM tvi; - ZeroMemory(&tvi, sizeof(TVITEM)); + memset(&tvi, 0, sizeof(TVITEM)); tvi.mask=TVIF_TEXT; tvi.pszText=blah; tvi.cchTextMax=MAX_PATH; @@ -5872,7 +5872,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara if(Memory.ROMFilename[0]!='\0') { LVFINDINFO lvfi; - ZeroMemory(&lvfi, sizeof(LVFINDINFO)); + memset(&lvfi, 0, sizeof(LVFINDINFO)); TCHAR filename[_MAX_PATH]; TCHAR *tmp, *tmp2; lstrcpy(filename,_tFromChar(Memory.ROMFilename)); @@ -5995,7 +5995,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara case IDOK: { LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); //get selections int list_index = selectionMarkOverride == -1 ? ListView_GetSelectionMark(romList) : selectionMarkOverride; if(list_index!=-1 && (int)SendMessage(romList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED)!=-1) @@ -6013,7 +6013,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara HTREEITEM hTreeTemp=TreeView_GetSelection(dirList); TVITEM tv; - ZeroMemory(&tv, sizeof(TVITEM)); + memset(&tv, 0, sizeof(TVITEM)); tv.mask=TVIF_HANDLE|TVIF_TEXT; tv.hItem=hTreeTemp; @@ -6309,7 +6309,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara else { TVITEM tv; - ZeroMemory(&tv, sizeof(TVITEM)); + memset(&tv, 0, sizeof(TVITEM)); HTREEITEM hTreeTemp=nmTv->itemNew.hItem; if(tv.iImage==6) @@ -6322,7 +6322,7 @@ INT_PTR CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara TV_INSERTSTRUCT tvis; - ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + memset(&tvis, 0, sizeof(TV_INSERTSTRUCT)); tvis.hParent=nmTv->itemNew.hItem; tvis.hInsertAfter=TVI_SORT; TreeView_InsertItem(dirList,&tvis); @@ -6696,7 +6696,7 @@ void LoadExts(void) ExtList* curr; valid_ext=new ExtList; curr=valid_ext; - ZeroMemory(curr, sizeof(ExtList)); + memset(curr, 0, sizeof(ExtList)); ifstream in; #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) @@ -6728,7 +6728,7 @@ void LoadExts(void) { curr->next=new ExtList; curr=curr->next; - ZeroMemory(curr, sizeof(ExtList)); + memset(curr, 0, sizeof(ExtList)); if(_strnicmp(buffer+strlen(buffer)-1, "Y", 1)==0) curr->compressed=true; if(strlen(buffer)>1) @@ -7232,7 +7232,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) break; case IDC_SHADER_HLSL_BROWSE: GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,openFileName,MAX_PATH); - ZeroMemory((LPVOID)&ofn, sizeof(OPENFILENAME)); + memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; @@ -7251,7 +7251,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) break; case IDC_SHADER_GLSL_BROWSE: GetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,openFileName,MAX_PATH); - ZeroMemory((LPVOID)&ofn, sizeof(OPENFILENAME)); + memset((LPVOID)&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; @@ -8108,7 +8108,7 @@ int* index; DWORD* state; }CheatTracker; -#define ITEM_QUERY(a, b, c, d, e) ZeroMemory(&a, sizeof(LV_ITEM)); \ +#define ITEM_QUERY(a, b, c, d, e) memset(&a, 0, sizeof(LV_ITEM)); \ a.iItem= ListView_GetSelectionMark(GetDlgItem(hDlg, b)); \ a.iSubItem=c; \ a.mask=LVIF_TEXT; \ @@ -8138,7 +8138,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) LVCOLUMN col; TCHAR temp[32]; lstrcpy(temp,SEARCH_COLUMN_ADDRESS); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; col.fmt=LVCFMT_LEFT; col.iOrder=0; @@ -8149,7 +8149,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 0, &col); lstrcpy(temp,SEARCH_COLUMN_VALUE); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=1; @@ -8161,7 +8161,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 1, &col); lstrcpy(temp,SEARCH_COLUMN_DESCRIPTION); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=2; @@ -8182,7 +8182,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) int curr_idx=-1; _stprintf(buffer, TEXT("%06X"), Cheat.c[counter].address); LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.mask=LVIF_TEXT; lvi.pszText=buffer; lvi.cchTextMax=7; @@ -8199,7 +8199,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ct.state[counter]=Untouched; _stprintf(buffer, TEXT("%02X"), Cheat.c[counter].byte); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8208,7 +8208,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); lstrcpy(buffer,_tFromChar(Cheat.c[counter].name)); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8336,7 +8336,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) int curr_idx=-1; _stprintf(buffer, TEXT("%06X"), addy); LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.mask=LVIF_TEXT; lvi.pszText=buffer; lvi.cchTextMax=6; @@ -8352,7 +8352,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) _stprintf(buffer, TEXT("%02X"), byte[j]); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8363,7 +8363,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, tempDesc, 23); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8387,7 +8387,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) int curr_idx=-1; LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.mask=LVIF_TEXT; lvi.pszText=buffer; lvi.cchTextMax=6; @@ -8402,7 +8402,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) _stprintf(buffer2, TEXT("%02X"), byte); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8412,7 +8412,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, tempDesc, 23); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=curr_idx; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8465,7 +8465,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) // int curr_idx=-1; _stprintf(buffer, TEXT("%06X"), addy); LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.mask=LVIF_TEXT; lvi.pszText=buffer; lvi.cchTextMax=6; @@ -8473,7 +8473,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ListView_SetItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi); _stprintf(buffer, TEXT("%02X"), byte[j]); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=sel_idx; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8483,7 +8483,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=sel_idx; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8511,7 +8511,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) // int curr_idx=-1; LVITEM lvi; - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.mask=LVIF_TEXT; lvi.pszText=buffer; lvi.cchTextMax=6; @@ -8529,7 +8529,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) _stprintf(buffer, TEXT("%02X"), byte); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=sel_idx; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8539,7 +8539,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23); - ZeroMemory(&lvi, sizeof(LVITEM)); + memset(&lvi, 0, sizeof(LVITEM)); lvi.iItem=sel_idx; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8794,7 +8794,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) TCHAR buf[25]; LV_ITEM lvi; - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.mask=LVIF_TEXT; lvi.pszText=buf; @@ -8805,7 +8805,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ScanAddress(lvi.pszText, scanned); Cheat.c[l].address = scanned; - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8817,7 +8817,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) _stscanf(lvi.pszText, TEXT("%02X"), &scanned); Cheat.c[l].byte = (uint8)(scanned & 0xff); - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -8843,7 +8843,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) bool8 enabled; TCHAR buf[25]; LV_ITEM lvi; - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.mask=LVIF_TEXT; lvi.pszText=buf; @@ -8854,7 +8854,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ScanAddress(lvi.pszText, scanned); address = scanned; - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.iSubItem=1; lvi.mask=LVIF_TEXT; @@ -8870,7 +8870,7 @@ INT_PTR CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) S9xAddCheat(enabled,true,address,byte); - ZeroMemory(&lvi, sizeof(LV_ITEM)); + memset(&lvi, 0, sizeof(LV_ITEM)); lvi.iItem= k; lvi.iSubItem=2; lvi.mask=LVIF_TEXT; @@ -9080,7 +9080,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara LVCOLUMN col; TCHAR temp[32]; lstrcpy(temp,TEXT("Address")); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; col.fmt=LVCFMT_LEFT; col.iOrder=0; @@ -9091,7 +9091,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 0, &col); lstrcpy(temp,TEXT("Curr. Value")); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=1; @@ -9103,7 +9103,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 1, &col); lstrcpy(temp,TEXT("Prev. Value")); - ZeroMemory(&col, sizeof(LVCOLUMN)); + memset(&col, 0, sizeof(LVCOLUMN)); col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; col.fmt=LVCFMT_LEFT; col.iOrder=2; @@ -9495,7 +9495,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara // int idx=-1; LVITEM lvi; static TCHAR buf[12]; // the following code assumes this variable is static, I think - ZeroMemory(&cht, sizeof(struct SCheat)); + memset(&cht, 0, sizeof(struct SCheat)); //retrieve and convert to SCheat @@ -9652,7 +9652,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara lstrcpy(szFileName, TEXT("watches")); _tfullpath(szPathName, S9xGetDirectoryT(CHEAT_DIR), MAX_PATH); - ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = GUI.hWnd; ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE TEXT("\0*.txt\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0"); @@ -9711,7 +9711,7 @@ INT_PTR CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara lstrcpy(szFileName, TEXT("watches")); _tfullpath(szPathName, S9xGetDirectoryT(CHEAT_DIR), MAX_PATH); - ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = GUI.hWnd; ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE TEXT("\0*.txt\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0"); @@ -10002,7 +10002,7 @@ INT_PTR CALLBACK DlgCheatSearchAdd(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP TCHAR buf[23]; int temp=new_cheat->size; S9xCheatDataSize tmp = S9X_8_BITS; - ZeroMemory(new_cheat, sizeof(struct SCheat)); + memset(new_cheat, 0, sizeof(struct SCheat)); new_cheat->size=temp; GetDlgItemText(hDlg, IDC_NC_ADDRESS, buf, 7); ScanAddress(buf, new_cheat->address); @@ -10321,7 +10321,7 @@ INT_PTR CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) szFileName[0] = TEXT('\0'); - ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION TEXT("\0*.smv\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0"); @@ -10468,7 +10468,7 @@ INT_PTR CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara szFileName[0] = TEXT('\0'); - ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + memset( (LPVOID)&ofn, 0, sizeof(OPENFILENAME) ); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION TEXT("\0*.smv\0") FILE_INFO_ANY_FILE_TYPE TEXT("\0*.*\0\0"); From 804d419b399276b1cdbb14a5a2f718147a7673c0 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 26 Jan 2012 13:42:27 -0600 Subject: [PATCH 087/130] Inline some functions to avoid vtable lookups. --- apu/bapu/smp/smp.hpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index 0a17cb8f..ed3a4767 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -107,21 +107,21 @@ public: unsigned cycle_table_dsp[256]; uint64 cycle_step_cpu; - uint8 op_adc (uint8 x, uint8 y); - uint16 op_addw(uint16 x, uint16 y); - uint8 op_and (uint8 x, uint8 y); - uint8 op_cmp (uint8 x, uint8 y); - uint16 op_cmpw(uint16 x, uint16 y); - uint8 op_eor (uint8 x, uint8 y); - uint8 op_inc (uint8 x); - uint8 op_dec (uint8 x); - uint8 op_or (uint8 x, uint8 y); - uint8 op_sbc (uint8 x, uint8 y); - uint16 op_subw(uint16 x, uint16 y); - uint8 op_asl (uint8 x); - uint8 op_lsr (uint8 x); - uint8 op_rol (uint8 x); - uint8 op_ror (uint8 x); + inline uint8 op_adc (uint8 x, uint8 y); + inline uint16 op_addw(uint16 x, uint16 y); + inline uint8 op_and (uint8 x, uint8 y); + inline uint8 op_cmp (uint8 x, uint8 y); + inline uint16 op_cmpw(uint16 x, uint16 y); + inline uint8 op_eor (uint8 x, uint8 y); + inline uint8 op_inc (uint8 x); + inline uint8 op_dec (uint8 x); + inline uint8 op_or (uint8 x, uint8 y); + inline uint8 op_sbc (uint8 x, uint8 y); + inline uint16 op_subw(uint16 x, uint16 y); + inline uint8 op_asl (uint8 x); + inline uint8 op_lsr (uint8 x); + inline uint8 op_rol (uint8 x); + inline uint8 op_ror (uint8 x); }; #if defined(DEBUGGER) From dc773bb6bec1b6c5f4b20d714a8bd65d00e3a515 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 26 Jan 2012 14:07:12 -0600 Subject: [PATCH 088/130] Fix ZeroMemory reference. --- gtk/src/gtk_s9x.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index a2f354c9..30adb261 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -51,7 +51,7 @@ main (int argc, char *argv[]) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - ZeroMemory (&Settings, sizeof (Settings)); + memset (&Settings, 0, sizeof (Settings)); /* Allow original config file for backend settings */ S9xLoadConfigFiles (argv, argc); From 668f8becb795a9808f84245790d4dfd785465f34 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 28 Jan 2012 01:52:28 +0100 Subject: [PATCH 089/130] Add bsx loading to libsnes --- bsx.cpp | 12 ++++++++++-- libsnes/libsnes.cpp | 16 +++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/bsx.cpp b/bsx.cpp index d55b346c..88f27dc3 100644 --- a/bsx.cpp +++ b/bsx.cpp @@ -1023,11 +1023,19 @@ static bool8 BSX_LoadBIOS (void) return (r); } +static bool8 is_BSX_BIOS (const uint8 *data, uint32 size) +{ + if (size == BIOS_SIZE && strncmp((char *) (data + 0x7FC0), "Satellaview BS-X ", 21) == 0) + return (TRUE); + else + return (FALSE); +} + void S9xInitBSX (void) { Settings.BS = FALSE; - if (!memcmp(&Memory.ROM[0x7FC0], "Satellaview BS-X ", 21)) + if (is_BSX_BIOS(Memory.ROM,Memory.CalculatedSize)) { // BS-X itself @@ -1074,7 +1082,7 @@ void S9xInitBSX (void) BSX.bootup = Settings.BSXBootup; - if (!BSX_LoadBIOS()) + if (!BSX_LoadBIOS() && !is_BSX_BIOS(BIOSROM,BIOS_SIZE)) { BSX.bootup = FALSE; memset(BIOSROM, 0, BIOS_SIZE); diff --git a/libsnes/libsnes.cpp b/libsnes/libsnes.cpp index 3a9fa9b9..e6216717 100644 --- a/libsnes/libsnes.cpp +++ b/libsnes/libsnes.cpp @@ -170,11 +170,14 @@ bool snes_load_cartridge_bsx_slotted( } bool snes_load_cartridge_bsx( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned + const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, + const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size ) { - return false; + if(bsx_data==NULL) + return snes_load_cartridge_normal(rom_xml,rom_data,rom_size); + memcpy(Memory.BIOSROM,rom_data,rom_size); + return snes_load_cartridge_normal(bsx_xml,bsx_data,bsx_size); } bool snes_load_cartridge_sufami_turbo( @@ -668,20 +671,19 @@ bool8 S9xContinueUpdate(int width, int height) return S9xDeinitUpdate(width, height); } - // Dummy functions that should probably be implemented correctly later. void S9xParsePortConfig(ConfigFile&, int) {} void S9xSyncSpeed() {} //void S9xPollPointer(int, short*, short*) {} const char* S9xStringInput(const char* in) { return in; } const char* S9xGetFilename(const char* in, s9x_getdirtype) { return in; } -const char* S9xGetDirectory(s9x_getdirtype) { return NULL; } +const char* S9xGetDirectory(s9x_getdirtype) { return ""; } void S9xInitInputDevices() {} -const char* S9xChooseFilename(unsigned char) { return NULL; } +const char* S9xChooseFilename(unsigned char) { return ""; } void S9xHandlePortCommand(s9xcommand_t, short, short) {} bool S9xPollButton(unsigned int, bool*) { return false; } void S9xToggleSoundChannel(int) {} -const char* S9xGetFilenameInc(const char* in, s9x_getdirtype) { return NULL; } +const char* S9xGetFilenameInc(const char* in, s9x_getdirtype) { return ""; } const char* S9xBasename(const char* in) { return in; } bool8 S9xInitUpdate() { return TRUE; } void S9xExtraUsage() {} From f6c9ea8de3ba1db601c02d7996a555ae0d02c22f Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 30 Jan 2012 13:29:01 -0600 Subject: [PATCH 090/130] Don't call hermite twice per sample for clamping. Adjust so compiler auto-SIMDs. --- apu/hermite_resampler.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index eda547f4..8c7dd96b 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -76,11 +76,14 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; + float hermite_val[2]; while (r_frac <= 1.0 && o_position < num_samples) { - data[o_position] = SHORT_CLAMP (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); - data[o_position + 1] = SHORT_CLAMP (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); + hermite_val[0] = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + hermite_val[1] = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + data[o_position] = SHORT_CLAMP (hermite_val[0]); + data[o_position + 1] = SHORT_CLAMP (hermite_val[1]); o_position += 2; From 54a83400c6799d085f74e6eba85b7a89cf0bbb49 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 30 Jan 2012 13:37:47 -0600 Subject: [PATCH 091/130] Change GL constants back in fr_FR translation. These macros, when translated, wouldn't actually be valid GL header values. --- gtk/po/fr_FR.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gtk/po/fr_FR.po b/gtk/po/fr_FR.po index 1076bf65..66946fe8 100644 --- a/gtk/po/fr_FR.po +++ b/gtk/po/fr_FR.po @@ -321,9 +321,9 @@ msgid "" "24-bit (GL_RGB)\n" "32-bit (GL_BGRA)" msgstr "" -"16-bits (GL_BVRA)\n" -"24-bits (GL_RVB)\n" -"32-bits (GL_BVRA)" +"16-bits (GL_BGRA)\n" +"24-bits (GL_RGB)\n" +"32-bits (GL_BGRA)" #: ../src/snes9x.glade.h:15 msgid "1x" From 2411daa2e773914797dc1553c3bd34ca4a5d8f15 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 30 Jan 2012 15:59:19 -0600 Subject: [PATCH 092/130] Change hermite resampler to use fixed-point arithmetic for speed on slower FPU systems. --- apu/hermite_resampler.h | 55 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 8c7dd96b..394ecee5 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,27 +14,32 @@ class HermiteResampler : public Resampler { protected: - float r_step; - float r_frac; + uint32 r_step; + uint32 r_frac; int r_left[4], r_right[4]; - static inline float - hermite (float mu1, float a, float b, float c, float d) + static inline int32 + hermite (uint32 mu1, int32 a, int32 b, int32 c, int32 d) { - float mu2, mu3, m0, m1, a0, a1, a2, a3; + uint32 mu2, mu3, m0, m1, a0, a1, a2, a3; - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; + mu2 = (mu1 * mu1) >> 15; + mu3 = (mu2 * mu1) >> 15; - m0 = (c - a) * 0.5; - m1 = (d - b) * 0.5; + m0 = (c - a + 32768) << 14; + m1 = (d - b + 32768) << 14; - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; + a0 = (mu3 << 1) - (3 * mu2) + (1 << 15); + a1 = mu3 - (mu2 << 1) + mu1; + a2 = mu3 - mu2; + a3 = 3 * mu2 - (mu3 << 1); - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + return (int32) (( + (a0 * (b + 32768)) + + ((a1 * m0) >> 15) + + ((a2 * m1) >> 15) + + (a3 * (c + 32768)) + ) >> 15) - 32768; } public: @@ -50,7 +55,7 @@ class HermiteResampler : public Resampler void time_ratio (double ratio) { - r_step = ratio; + r_step = (1 << 15) * ratio; clear (); } @@ -58,7 +63,7 @@ class HermiteResampler : public Resampler clear (void) { ring_buffer::clear (); - r_frac = 1.0; + r_frac = (1 << 15); r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; } @@ -76,21 +81,21 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - float hermite_val[2]; + int hermite_val; - while (r_frac <= 1.0 && o_position < num_samples) + while (r_frac <= (1 << 15) && o_position < num_samples) { - hermite_val[0] = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); - hermite_val[1] = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); - data[o_position] = SHORT_CLAMP (hermite_val[0]); - data[o_position + 1] = SHORT_CLAMP (hermite_val[1]); + hermite_val = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + data[o_position] = SHORT_CLAMP (hermite_val); + hermite_val = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + data[o_position + 1] = SHORT_CLAMP (hermite_val); o_position += 2; r_frac += r_step; } - if (r_frac > 1.0) + if (r_frac > (1 << 15)) { r_left [0] = r_left [1]; r_left [1] = r_left [2]; @@ -102,7 +107,7 @@ class HermiteResampler : public Resampler r_right[2] = r_right[3]; r_right[3] = s_right; - r_frac -= 1.0; + r_frac -= (1 << 15); i_position += 2; if (i_position >= max_samples) @@ -120,7 +125,7 @@ class HermiteResampler : public Resampler inline int avail (void) { - return (int) floor (((size >> 2) - r_frac) / r_step) * 2; + return ((((uint32) size) << 13) - r_frac) / r_step * 2; } }; From b66f00d6f46448cdf3e99a6e9e0dbebde447431a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 1 Feb 2012 09:33:04 -0600 Subject: [PATCH 093/130] Change type of temporary vars to properly clip. Fixes SMT problem. --- apu/bapu/smp/smp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apu/bapu/smp/smp.hpp b/apu/bapu/smp/smp.hpp index ed3a4767..c96ebea9 100644 --- a/apu/bapu/smp/smp.hpp +++ b/apu/bapu/smp/smp.hpp @@ -50,7 +50,7 @@ public: unsigned opcode_number; unsigned opcode_cycle; - unsigned rd, wr, dp, sp, ya, bit; + uint16 rd, wr, dp, sp, ya, bit; struct Regs { uint16 pc; From 986289a96c064173cf4c12091441c5bbe7fa72cf Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Wed, 1 Feb 2012 14:45:31 -0600 Subject: [PATCH 094/130] Revert "Change hermite resampler to use fixed-point arithmetic for speed on" This reverts commit 2411daa2e773914797dc1553c3bd34ca4a5d8f15. --- apu/hermite_resampler.h | 55 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 394ecee5..8c7dd96b 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,32 +14,27 @@ class HermiteResampler : public Resampler { protected: - uint32 r_step; - uint32 r_frac; + float r_step; + float r_frac; int r_left[4], r_right[4]; - static inline int32 - hermite (uint32 mu1, int32 a, int32 b, int32 c, int32 d) + static inline float + hermite (float mu1, float a, float b, float c, float d) { - uint32 mu2, mu3, m0, m1, a0, a1, a2, a3; + float mu2, mu3, m0, m1, a0, a1, a2, a3; - mu2 = (mu1 * mu1) >> 15; - mu3 = (mu2 * mu1) >> 15; + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; - m0 = (c - a + 32768) << 14; - m1 = (d - b + 32768) << 14; + m0 = (c - a) * 0.5; + m1 = (d - b) * 0.5; - a0 = (mu3 << 1) - (3 * mu2) + (1 << 15); - a1 = mu3 - (mu2 << 1) + mu1; - a2 = mu3 - mu2; - a3 = 3 * mu2 - (mu3 << 1); + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; - return (int32) (( - (a0 * (b + 32768)) + - ((a1 * m0) >> 15) + - ((a2 * m1) >> 15) + - (a3 * (c + 32768)) - ) >> 15) - 32768; + return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); } public: @@ -55,7 +50,7 @@ class HermiteResampler : public Resampler void time_ratio (double ratio) { - r_step = (1 << 15) * ratio; + r_step = ratio; clear (); } @@ -63,7 +58,7 @@ class HermiteResampler : public Resampler clear (void) { ring_buffer::clear (); - r_frac = (1 << 15); + r_frac = 1.0; r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; } @@ -81,21 +76,21 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - int hermite_val; + float hermite_val[2]; - while (r_frac <= (1 << 15) && o_position < num_samples) + while (r_frac <= 1.0 && o_position < num_samples) { - hermite_val = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); - data[o_position] = SHORT_CLAMP (hermite_val); - hermite_val = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); - data[o_position + 1] = SHORT_CLAMP (hermite_val); + hermite_val[0] = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + hermite_val[1] = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + data[o_position] = SHORT_CLAMP (hermite_val[0]); + data[o_position + 1] = SHORT_CLAMP (hermite_val[1]); o_position += 2; r_frac += r_step; } - if (r_frac > (1 << 15)) + if (r_frac > 1.0) { r_left [0] = r_left [1]; r_left [1] = r_left [2]; @@ -107,7 +102,7 @@ class HermiteResampler : public Resampler r_right[2] = r_right[3]; r_right[3] = s_right; - r_frac -= (1 << 15); + r_frac -= 1.0; i_position += 2; if (i_position >= max_samples) @@ -125,7 +120,7 @@ class HermiteResampler : public Resampler inline int avail (void) { - return ((((uint32) size) << 13) - r_frac) / r_step * 2; + return (int) floor (((size >> 2) - r_frac) / r_step) * 2; } }; From 93cf0a77b9e3a8f30e7d2b816eacf7b8a43194ff Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 2 Feb 2012 15:47:44 -0600 Subject: [PATCH 095/130] Revert "Revert "Change hermite resampler to use fixed-point arithmetic for speed on"" This reverts commit 986289a96c064173cf4c12091441c5bbe7fa72cf. --- apu/hermite_resampler.h | 55 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 8c7dd96b..394ecee5 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,27 +14,32 @@ class HermiteResampler : public Resampler { protected: - float r_step; - float r_frac; + uint32 r_step; + uint32 r_frac; int r_left[4], r_right[4]; - static inline float - hermite (float mu1, float a, float b, float c, float d) + static inline int32 + hermite (uint32 mu1, int32 a, int32 b, int32 c, int32 d) { - float mu2, mu3, m0, m1, a0, a1, a2, a3; + uint32 mu2, mu3, m0, m1, a0, a1, a2, a3; - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; + mu2 = (mu1 * mu1) >> 15; + mu3 = (mu2 * mu1) >> 15; - m0 = (c - a) * 0.5; - m1 = (d - b) * 0.5; + m0 = (c - a + 32768) << 14; + m1 = (d - b + 32768) << 14; - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; + a0 = (mu3 << 1) - (3 * mu2) + (1 << 15); + a1 = mu3 - (mu2 << 1) + mu1; + a2 = mu3 - mu2; + a3 = 3 * mu2 - (mu3 << 1); - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + return (int32) (( + (a0 * (b + 32768)) + + ((a1 * m0) >> 15) + + ((a2 * m1) >> 15) + + (a3 * (c + 32768)) + ) >> 15) - 32768; } public: @@ -50,7 +55,7 @@ class HermiteResampler : public Resampler void time_ratio (double ratio) { - r_step = ratio; + r_step = (1 << 15) * ratio; clear (); } @@ -58,7 +63,7 @@ class HermiteResampler : public Resampler clear (void) { ring_buffer::clear (); - r_frac = 1.0; + r_frac = (1 << 15); r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; } @@ -76,21 +81,21 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - float hermite_val[2]; + int hermite_val; - while (r_frac <= 1.0 && o_position < num_samples) + while (r_frac <= (1 << 15) && o_position < num_samples) { - hermite_val[0] = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); - hermite_val[1] = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); - data[o_position] = SHORT_CLAMP (hermite_val[0]); - data[o_position + 1] = SHORT_CLAMP (hermite_val[1]); + hermite_val = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + data[o_position] = SHORT_CLAMP (hermite_val); + hermite_val = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + data[o_position + 1] = SHORT_CLAMP (hermite_val); o_position += 2; r_frac += r_step; } - if (r_frac > 1.0) + if (r_frac > (1 << 15)) { r_left [0] = r_left [1]; r_left [1] = r_left [2]; @@ -102,7 +107,7 @@ class HermiteResampler : public Resampler r_right[2] = r_right[3]; r_right[3] = s_right; - r_frac -= 1.0; + r_frac -= (1 << 15); i_position += 2; if (i_position >= max_samples) @@ -120,7 +125,7 @@ class HermiteResampler : public Resampler inline int avail (void) { - return (int) floor (((size >> 2) - r_frac) / r_step) * 2; + return ((((uint32) size) << 13) - r_frac) / r_step * 2; } }; From 8db1c467ac7ada2d27584da1b72d9efcd5458f4c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 2 Feb 2012 15:48:17 -0600 Subject: [PATCH 096/130] Adjust fixed-point hermite resampler. Use signed arithmetic. --- apu/hermite_resampler.h | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 394ecee5..e3fdbb36 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -19,27 +19,25 @@ class HermiteResampler : public Resampler int r_left[4], r_right[4]; static inline int32 - hermite (uint32 mu1, int32 a, int32 b, int32 c, int32 d) + hermite (int32 mu1, int32 a, int32 b, int32 c, int32 d) { - uint32 mu2, mu3, m0, m1, a0, a1, a2, a3; + int32 mu2, mu3, m0, m1, a0, a1, a2, a3; mu2 = (mu1 * mu1) >> 15; mu3 = (mu2 * mu1) >> 15; - m0 = (c - a + 32768) << 14; - m1 = (d - b + 32768) << 14; + m0 = (c - a) << 14; + m1 = (d - b) << 14; a0 = (mu3 << 1) - (3 * mu2) + (1 << 15); a1 = mu3 - (mu2 << 1) + mu1; a2 = mu3 - mu2; a3 = 3 * mu2 - (mu3 << 1); - return (int32) (( - (a0 * (b + 32768)) + - ((a1 * m0) >> 15) + - ((a2 * m1) >> 15) + - (a3 * (c + 32768)) - ) >> 15) - 32768; + return (a0 * b) + + ((a1 * m0) >> 15) + + ((a2 * m1) >> 15) + + (a3 * c) >> 15; } public: @@ -55,7 +53,7 @@ class HermiteResampler : public Resampler void time_ratio (double ratio) { - r_step = (1 << 15) * ratio; + r_step = (1 << 16) * ratio; clear (); } @@ -63,7 +61,7 @@ class HermiteResampler : public Resampler clear (void) { ring_buffer::clear (); - r_frac = (1 << 15); + r_frac = (1 << 16); r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; } @@ -83,11 +81,11 @@ class HermiteResampler : public Resampler int s_right = internal_buffer[i_position + 1]; int hermite_val; - while (r_frac <= (1 << 15) && o_position < num_samples) + while (r_frac <= (1 << 16) && o_position < num_samples) { - hermite_val = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + hermite_val = hermite (r_frac >> 1, r_left [0], r_left [1], r_left [2], r_left [3]); data[o_position] = SHORT_CLAMP (hermite_val); - hermite_val = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + hermite_val = hermite (r_frac >> 1, r_right[0], r_right[1], r_right[2], r_right[3]); data[o_position + 1] = SHORT_CLAMP (hermite_val); o_position += 2; @@ -95,7 +93,7 @@ class HermiteResampler : public Resampler r_frac += r_step; } - if (r_frac > (1 << 15)) + if (r_frac > (1 << 16)) { r_left [0] = r_left [1]; r_left [1] = r_left [2]; @@ -107,7 +105,7 @@ class HermiteResampler : public Resampler r_right[2] = r_right[3]; r_right[3] = s_right; - r_frac -= (1 << 15); + r_frac -= (1 << 16); i_position += 2; if (i_position >= max_samples) @@ -125,7 +123,7 @@ class HermiteResampler : public Resampler inline int avail (void) { - return ((((uint32) size) << 13) - r_frac) / r_step * 2; + return ((((uint32) size) << 14) - r_frac) / r_step * 2; } }; From 1aeb1c8f3e2c3801959f4f9de0132e7ae0a02515 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 2 Feb 2012 15:57:42 -0600 Subject: [PATCH 097/130] Fix warning about operation order. --- apu/hermite_resampler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index e3fdbb36..3c872da0 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -34,10 +34,10 @@ class HermiteResampler : public Resampler a2 = mu3 - mu2; a3 = 3 * mu2 - (mu3 << 1); - return (a0 * b) + + return ((a0 * b) + ((a1 * m0) >> 15) + ((a2 * m1) >> 15) + - (a3 * c) >> 15; + (a3 * c)) >> 15; } public: From ef41a96c576190f2bbdbbf3f5a0cd469da7740f5 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Fri, 3 Feb 2012 17:43:32 -0500 Subject: [PATCH 098/130] Fix header path in apu/apu.cpp --- apu/apu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apu/apu.cpp b/apu/apu.cpp index bc9f616a..5c04cbe5 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -194,7 +194,7 @@ namespace SNES { -#include "dsp/blargg_endian.h" +#include "bapu/dsp/blargg_endian.h" CPU cpu; } From f699d21d12e91f2fed75ccff4afa875ec1d49938 Mon Sep 17 00:00:00 2001 From: bl0ckeduser Date: Fri, 3 Feb 2012 17:44:58 -0500 Subject: [PATCH 099/130] Fix header paths in apu/bapu/snes/snes.hpp --- apu/bapu/snes/snes.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apu/bapu/snes/snes.hpp b/apu/bapu/snes/snes.hpp index 3e8cd2b3..017856b8 100644 --- a/apu/bapu/snes/snes.hpp +++ b/apu/bapu/snes/snes.hpp @@ -27,8 +27,8 @@ struct Processor int32 clock; }; -#include "smp/smp.hpp" -#include "dsp/sdsp.hpp" +#include "../smp/smp.hpp" +#include "../dsp/sdsp.hpp" class CPU { From 4ce12c93c858a138819ef4aad2373f3ea63b6c75 Mon Sep 17 00:00:00 2001 From: Bl0ckeduser Date: Wed, 8 Feb 2012 20:15:23 -0500 Subject: [PATCH 100/130] Update unix build scripts for new apu code --- unix/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index 36cf6050..b19773bc 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -7,7 +7,7 @@ OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER @@ -29,7 +29,7 @@ endif CCC = @CXX@ CC = @CC@ GASM = @CXX@ -INCLUDES = -I. -I.. -I../apu/ -I../unzip/ -I../jma/ -I../filter/ +INCLUDES = -I. -I.. -I../apu/ -I../apu/bapu -I../unzip/ -I../jma/ -I../filter/ CCFLAGS = @S9XFLGS@ @S9XDEFS@ $(DEFS) CFLAGS = $(CCFLAGS) From da4829ec90ae4c9a71764549e2aa4657296bfb9d Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 27 Mar 2012 16:40:34 +0200 Subject: [PATCH 101/130] Prevent HWEvents from firing when setting cheats --- cheats2.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cheats2.cpp b/cheats2.cpp index aeef2cc6..c3558efe 100644 --- a/cheats2.cpp +++ b/cheats2.cpp @@ -186,10 +186,13 @@ static void S9xSetByteFree (uint8, uint32); static uint8 S9xGetByteFree (uint32 address) { - uint32 Cycles = CPU.Cycles; + int32 Cycles = CPU.Cycles; + int32 NextEvent = CPU.NextEvent; uint8 byte; + CPU.NextEvent = 0x7FFFFFFF; byte = S9xGetByte(address); + CPU.NextEvent = NextEvent; CPU.Cycles = Cycles; return (byte); @@ -197,9 +200,12 @@ static uint8 S9xGetByteFree (uint32 address) static void S9xSetByteFree (uint8 byte, uint32 address) { - uint32 Cycles = CPU.Cycles; + int32 Cycles = CPU.Cycles; + int32 NextEvent = CPU.NextEvent; + CPU.NextEvent = 0x7FFFFFFF; S9xSetByte(byte, address); + CPU.NextEvent = NextEvent; CPU.Cycles = Cycles; } From f7a1a99e2548b23bc318271c22d6ad53c2977aae Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 28 Mar 2012 00:17:18 +0200 Subject: [PATCH 102/130] Return zero state size if emulation is stopped --- snapshot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/snapshot.cpp b/snapshot.cpp index 0f2cc960..ba6a11c8 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1171,6 +1171,7 @@ void S9xResetSaveTimer (bool8 dontsave) uint32 S9xFreezeSize() { + if(Settings.StopEmulation) return 0; nulStream stream; S9xFreezeToStream(&stream); return stream.size(); From 486cde43913fca34e3cf3100b689984f571b43e9 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 28 Mar 2012 00:18:03 +0200 Subject: [PATCH 103/130] Win32: add rewind support --- win32/CD3DCG.cpp | 2 + win32/CGLCG.cpp | 1 + win32/InputCustom.cpp | 2 + win32/StateManager.cpp | 191 +++++++++++++++++++++++++++++++++++++++++ win32/StateManager.h | 35 ++++++++ win32/rsrc/resource.h | 11 ++- win32/rsrc/snes9x.rc | 32 ++++--- win32/snes9xw.vcproj | 8 ++ win32/wconfig.cpp | 5 +- win32/wlanguage.h | 3 + win32/wsnes9x.cpp | 50 ++++++++++- win32/wsnes9x.h | 8 +- 12 files changed, 329 insertions(+), 19 deletions(-) create mode 100644 win32/StateManager.cpp create mode 100644 win32/StateManager.h diff --git a/win32/CD3DCG.cpp b/win32/CD3DCG.cpp index f15de2d1..1d51dc24 100644 --- a/win32/CD3DCG.cpp +++ b/win32/CD3DCG.cpp @@ -683,6 +683,8 @@ void CD3DCG::setShaderVars(int pass) setProgramUniform(pass,"IN.texture_size",&textureSize); setProgramUniform(pass,"IN.output_size",&outputSize); setProgramUniform(pass,"IN.frame_count",&frameCnt); + float frameDirection = GUI.rewinding?-1.0f:1.0f; + setProgramUniform(pass,"IN.frame_direction",&frameDirection); /* ORIG parameter */ diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 7f0032a8..0d75a999 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -667,6 +667,7 @@ void CGLCG::setShaderVars(int pass) setProgram2fv(pass,"IN.texture_size",textureSize); setProgram2fv(pass,"IN.output_size",outputSize); setProgram1f(pass,"IN.frame_count",(float)frameCnt); + setProgram1f(pass,"IN.frame_direction",GUI.rewinding?-1.0f:1.0f); /* ORIG parameter */ diff --git a/win32/InputCustom.cpp b/win32/InputCustom.cpp index d86813ad..39f2cc0c 100644 --- a/win32/InputCustom.cpp +++ b/win32/InputCustom.cpp @@ -688,6 +688,8 @@ int GetNumHotKeysAssignedTo (WORD Key, int modifiers) if(MATCHES_KEY(TurboDown)) count++; if(MATCHES_KEY(ResetGame)) count++; if(MATCHES_KEY(ToggleCheats)) count++; + if(MATCHES_KEY(QuitS9X)) count++; + if(MATCHES_KEY(Rewind)) count++; #undef MATCHES_KEY } diff --git a/win32/StateManager.cpp b/win32/StateManager.cpp new file mode 100644 index 00000000..dcef99f8 --- /dev/null +++ b/win32/StateManager.cpp @@ -0,0 +1,191 @@ +#include "statemanager.h" +#include "snapshot.h" + +/* Snapshot Manager Class that records snapshot data for rewinding + mostly based on SSNES's rewind code by Themaister +*/ + +static inline size_t nearest_pow2_size(size_t v) +{ + size_t orig = v; + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; +#if SIZE_MAX >= 0xffff + v |= v >> 8; +#endif +#if SIZE_MAX >= 0xffffffff + v |= v >> 16; +#endif +#if SIZE_MAX >= 0xffffffffffffffff + v |= v >> 32; +#endif + v++; + + size_t next = v; + size_t prev = v >> 1; + + if ((next - orig) < (orig - prev)) + return next; + else + return prev; +} + +void StateManager::deallocate() { + if(buffer) { + delete [] buffer; + buffer = NULL; + } + if(tmp_state) { + delete [] tmp_state; + tmp_state = NULL; + } + if(in_state) { + delete [] in_state; + in_state = NULL; + } +} + +StateManager::StateManager() +{ + buffer = NULL; + tmp_state = NULL; + in_state = NULL; + init_done = false; +} + +StateManager::~StateManager() { + deallocate(); +} + +bool StateManager::init(size_t buffer_size) { + + init_done = false; + + deallocate(); + + real_state_size = S9xFreezeSize(); + state_size = real_state_size / sizeof(uint32_t); // Works in multiple of 4. + + // We need 4-byte aligned state_size to avoid having to enforce this with unneeded memcpy's! + if(real_state_size % sizeof(uint32_t)) state_size ++; + + if (buffer_size <= real_state_size) // Need a sufficient buffer size. + return false; + + top_ptr = 1; + + + buf_size = nearest_pow2_size(buffer_size) / sizeof(uint64_t); // Works in multiple of 8. + buf_size_mask = buf_size - 1; + + if (!(buffer = new uint64_t[buf_size])) + return false; + if (!(tmp_state = new uint32_t[state_size])) + return false; + if (!(in_state = new uint32_t[state_size])) + return false; + + memset(tmp_state,0,state_size * sizeof(uint32_t)); + memset(in_state,0,state_size * sizeof(uint32_t)); + + init_done = true; + + return true; +} + +int StateManager::pop() +{ + if(!init_done) + return 0; + + if (first_pop) + { + first_pop = false; + return S9xUnfreezeGameMem((uint8 *)tmp_state,real_state_size); + } + + top_ptr = (top_ptr - 1) & buf_size_mask; + + if (top_ptr == bottom_ptr) // Our stack is completely empty... :v + { + top_ptr = (top_ptr + 1) & buf_size_mask; + return 0; + } + + while (buffer[top_ptr]) + { + // Apply the xor patch. + uint32_t addr = buffer[top_ptr] >> 32; + uint32_t xor_ = buffer[top_ptr] & 0xFFFFFFFFU; + tmp_state[addr] ^= xor_; + + top_ptr = (top_ptr - 1) & buf_size_mask; + } + + if (top_ptr == bottom_ptr) // Our stack is completely empty... :v + { + top_ptr = (top_ptr + 1) & buf_size_mask; + } + + return S9xUnfreezeGameMem((uint8 *)tmp_state,real_state_size); +} + +void StateManager::reassign_bottom() +{ + bottom_ptr = (top_ptr + 1) & buf_size_mask; + while (buffer[bottom_ptr]) // Skip ahead until we find the first 0 (boundary for state delta). + bottom_ptr = (bottom_ptr + 1) & buf_size_mask; +} + +void StateManager::generate_delta(const void *data) +{ + bool crossed = false; + const uint32_t *old_state = tmp_state; + const uint32_t *new_state = (const uint32_t*)data; + + buffer[top_ptr++] = 0; // For each separate delta, we have a 0 value sentinel in between. + top_ptr &= buf_size_mask; + + // Check if top_ptr and bottom_ptr crossed each other, which means we need to delete old cruft. + if (top_ptr == bottom_ptr) + crossed = true; + + for (uint64_t i = 0; i < state_size; i++) + { + uint64_t xor_ = old_state[i] ^ new_state[i]; + + // If the data differs (xor != 0), we push that xor on the stack with index and xor. + // This can be reversed by reapplying the xor. + // This, if states don't really differ much, we'll save lots of space :) + // Hopefully this will work really well with save states. + if (xor_) + { + buffer[top_ptr] = (i << 32) | xor_; + top_ptr = (top_ptr + 1) & buf_size_mask; + + if (top_ptr == bottom_ptr) + crossed = true; + } + } + + if (crossed) + reassign_bottom(); +} + +bool StateManager::push() +{ + if(!init_done) + return false; + if(!S9xFreezeGameMem((uint8 *)in_state,real_state_size)) + return false; + generate_delta(in_state); + uint32 *tmp = tmp_state; + tmp_state = in_state; + in_state = tmp; + + first_pop = true; + + return true; +} diff --git a/win32/StateManager.h b/win32/StateManager.h new file mode 100644 index 00000000..65aabb30 --- /dev/null +++ b/win32/StateManager.h @@ -0,0 +1,35 @@ +#ifndef STATEMANAGER_H +#define STATEMANAGER_H + +/* Snapshot Manager Class that records snapshot data for rewinding + mostly based on SSNES's rewind code by Themaister +*/ + +#include "snes9x.h" + +class StateManager { +private: + uint64_t *buffer; + size_t buf_size; + size_t buf_size_mask; + uint32_t *tmp_state; + uint32_t *in_state; + size_t top_ptr; + size_t bottom_ptr; + size_t state_size; + size_t real_state_size; + bool init_done; + bool first_pop; + + void reassign_bottom(); + void generate_delta(const void *data); + void deallocate(); +public: + StateManager(); + ~StateManager(); + bool init(size_t buffer_size); + int pop(); + bool push(); +}; + +#endif // STATEMANAGER_H diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h index 90d5997f..04b0b0e8 100644 --- a/win32/rsrc/resource.h +++ b/win32/rsrc/resource.h @@ -81,7 +81,11 @@ #define IDC_HEADER 1067 #define IDC_HIRESAVI 1067 #define IDC_ROMLIST 1068 +#define IDC_REWIND_BUFFER 1068 #define IDC_MEM_TYPE 1069 +#define IDC_REWIND_BUFFER_SPIN 1069 +#define IDC_REWIND_GRANULARITY 1070 +#define IDC_REWIND_GRANULARITY_SPIN 1071 #define IDC_HOSTNAME 1086 #define IDC_PORTNUMBER 1087 #define IDC_CLEARHISTORY 1088 @@ -226,12 +230,17 @@ #define IDC_LABEL_UP4 1183 #define IDC_PORTNUMBLOCK 1184 #define IDC_LABEL_UP5 1184 +#define IDC_LABEL_RBUFFER 1184 #define IDC_CLIENTSETTINGSBLOCK 1185 #define IDC_LABEL_UP6 1185 +#define IDC_LABEL_RBUFFER_TEXT 1185 #define IDC_SERVERSETTINGSBLOCK 1186 #define IDC_LABEL_UP7 1186 +#define IDC_LABEL_RGRANU 1186 #define IDC_LABEL_PORTNUM 1187 #define IDC_LABEL_UP8 1187 +#define IDC_LABEL_RBUFFER_TEXT2 1187 +#define IDC_LABEL_GRANU_TEXT 1187 #define IDC_LABEL_PAUSEINTERVAL 1188 #define IDC_LABEL_UP9 1188 #define IDC_LABEL_PAUSEINTERVAL_TEXT 1189 @@ -485,7 +494,7 @@ #define ID_WINDOW_SIZE_3X 40171 #define ID_WINDOW_SIZE_4X 40172 #define ID_DEBUG_APU_TRACE 40173 -#define ID_EMULATION_BACKGROUNDINPUT 40174 +#define ID_EMULATION_BACKGROUNDINPUT 40174 // Next default values for new objects // diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index e5e1b992..2aa4637f 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -96,10 +96,10 @@ CAPTION "APP - About Dialog" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,90,160,50,14 - EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | WS_VSCROLL | ES_READONLY,WS_EX_STATICEDGE + EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY | WS_VSCROLL,WS_EX_STATICEDGE END -IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 154 +IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 184 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU CAPTION "APP - Emulator Settings" FONT 8, "MS Sans Serif", 0, 0, 0x0 @@ -112,9 +112,17 @@ BEGIN CONTROL "Spin3",IDC_SPIN_MAX_SKIP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,298,70,11,13 EDITTEXT IDC_TURBO_SKIP,91,85,49,14,ES_AUTOHSCROLL | ES_NUMBER CONTROL "Spin4",IDC_SPIN_TURBO_SKIP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,296,94,11,13 - CONTROL "Toggled Turbo Mode",IDC_TOGGLE_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,103,123,12 - DEFPUSHBUTTON "&OK",IDOK,215,136,46,14 - PUSHBUTTON "&Cancel",IDCANCEL,266,135,46,14 + EDITTEXT IDC_REWIND_BUFFER,91,102,49,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_REWIND_BUFFER_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,294,114,11,13 + EDITTEXT IDC_REWIND_GRANULARITY,91,120,49,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_REWIND_GRANULARITY_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,293,131,11,13 + CONTROL "Toggled Turbo Mode",IDC_TOGGLE_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,136,123,12 + CONTROL "Pause When Inactive",IDC_INACTIVE_PAUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,147,100,12 + CONTROL "Custom ROM Open Dialog",IDC_CUSTOMROMOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,158,117,12 + CONTROL "Hi-Res AVI Recording",IDC_HIRESAVI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,169,117,12 + DEFPUSHBUTTON "&OK",IDOK,215,168,46,14 + PUSHBUTTON "&Cancel",IDCANCEL,266,168,46,14 + COMBOBOX IDC_DIRCOMBO,7,29,44,30,CBS_DROPDOWNLIST | WS_TABSTOP RTEXT "Directory",IDC_LABEL_FREEZE,53,28,32,14,SS_CENTERIMAGE RTEXT "Auto-Save S-RAM",IDC_LABEL_ASRAM,21,47,64,14,SS_CENTERIMAGE RTEXT "Skip at most",IDC_LABEL_SMAX,40,66,45,14,SS_CENTERIMAGE @@ -122,13 +130,13 @@ BEGIN LTEXT "seconds after last change (0 disables auto-save)",IDC_LABEL_ASRAM_TEXT,146,47,161,14,SS_CENTERIMAGE LTEXT "frames in auto-frame rate mode",IDC_LABEL_SMAX_TEXT,146,66,138,14,SS_CENTERIMAGE LTEXT "frames in Turbo mode",IDC_LABEL_STURBO_TEXT,146,85,92,14,SS_CENTERIMAGE - CONTROL "Pause When Inactive",IDC_INACTIVE_PAUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,114,100,12 LTEXT "Config file",IDC_STATIC,54,11,34,11 EDITTEXT IDC_CONFIG_NAME_BOX,91,9,49,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER LTEXT "all of Snes9x's settings are stored in this file",IDC_STATIC,147,11,160,11 - COMBOBOX IDC_DIRCOMBO,7,29,44,30,CBS_DROPDOWNLIST | WS_TABSTOP - CONTROL "Custom ROM Open Dialog",IDC_CUSTOMROMOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,125,117,12 - CONTROL "Hi-Res AVI Recording",IDC_HIRESAVI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,136,117,12 + RTEXT "Rewind Buffer",IDC_LABEL_RBUFFER,31,102,51,14,SS_CENTERIMAGE + LTEXT "MB (set to 0 to disable rewind support)",IDC_LABEL_RBUFFER_TEXT,145,102,131,14,SS_CENTERIMAGE + RTEXT "Rewind Granularity",IDC_LABEL_RGRANU,18,120,64,14,SS_CENTERIMAGE + LTEXT "frames",IDC_LABEL_GRANU_TEXT,145,120,131,14,SS_CENTERIMAGE END IDD_OPEN_ROM DIALOGEX 0, 0, 430, 223 @@ -580,7 +588,7 @@ BEGIN BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 312 - BOTTOMMARGIN, 147 + BOTTOMMARGIN, 177 END IDD_OPEN_ROM, DIALOG @@ -842,8 +850,8 @@ BEGIN MENUITEM "&Input Configuration...\tAlt+F7", 40022 MENUITEM "&Customize Hotkeys...\tAlt+F9", ID_OPTIONS_KEYCUSTOM MENUITEM SEPARATOR - MENUITEM "Enable Background Input", ID_EMULATION_BACKGROUNDINPUT - MENUITEM SEPARATOR + MENUITEM "Enable Background Input", ID_EMULATION_BACKGROUNDINPUT + MENUITEM SEPARATOR MENUITEM "Use SNES Joypad(s)", IDM_SNES_JOYPAD MENUITEM "Use SNES Mouse", IDM_MOUSE_TOGGLE MENUITEM "Use Super Scope", IDM_SCOPE_TOGGLE diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 27ea8e7c..3437de14 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -3022,6 +3022,14 @@ RelativePath=".\render.h" > + + + + diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index bafa2130..896922dd 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -798,6 +798,7 @@ void WinPostLoad(ConfigFile& conf) for(i=0;i<8;i++) Joypad[i+8].Enabled = Joypad[i].Enabled; if(GUI.MaxRecentGames < 1) GUI.MaxRecentGames = 1; if(GUI.MaxRecentGames > MAX_RECENT_GAMES_LIST_SIZE) GUI.MaxRecentGames = MAX_RECENT_GAMES_LIST_SIZE; + if(GUI.rewindGranularity==0) GUI.rewindGranularity = 1; bool gap = false; for(i=0;i #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) @@ -563,6 +564,7 @@ struct SCustomKeys CustomKeys = { {'R',CUSTKEY_CTRL_MASK|CUSTKEY_SHIFT_MASK}, // Reset Game {0,0}, // Toggle Cheats {0,0}, + {'R',0}, // Rewind }; @@ -610,7 +612,7 @@ struct OpenMovieParams - +StateManager stateMan; std::vector dm; /*****************************************************************************/ @@ -1231,6 +1233,13 @@ int HandleKeyMessage(WPARAM wParam, LPARAM lParam) { PostMessage(GUI.hWnd,WM_CLOSE,(WPARAM)NULL,(LPARAM)(NULL)); } + if(wParam == CustomKeys.Rewind.key + && modifiers == CustomKeys.Rewind.modifiers) + { + if(!GUI.rewinding) + S9xMessage (S9X_INFO, 0, GUI.rewindBufferSize?WINPROC_REWINDING_TEXT:WINPROC_REWINDING_DISABLED); + GUI.rewinding = true; + } //if(wParam == CustomKeys.BGLHack.key //&& modifiers == CustomKeys.BGLHack.modifiers) //{ @@ -1479,6 +1488,12 @@ LRESULT CALLBACK WinProc( { GUI.superscope_pause = 0; } + if(wParam == CustomKeys.Rewind.key + && modifiers == CustomKeys.Rewind.modifiers) + { + GUI.rewinding = false; + } + } break; @@ -3242,6 +3257,7 @@ int WINAPI WinMain( InitRenderFilters(); GUI.ControlForced = 0xff; + GUI.rewinding = false; S9xSetRecentGames (); @@ -3426,6 +3442,19 @@ int WINAPI WinMain( S9xClearSamples(); } + if(GUI.rewindBufferSize +#ifdef NETPLAY_SUPPORT + &&!Settings.NetPlay +#endif + ) { + if(GUI.rewinding) { + GUI.rewinding = stateMan.pop(); + } else { + if(IPPU.TotalEmulatedFrames % GUI.rewindGranularity == 0) + stateMan.push(); + } + } + S9xMainLoop(); GUI.FrameCount++; } @@ -3887,6 +3916,8 @@ static bool LoadROM(const TCHAR *filename) { else S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName); #endif + if(GUI.rewindBufferSize) + stateMan.init(GUI.rewindBufferSize * 1024 * 1024); } if(GUI.ControllerOption == SNES_SUPERSCOPE) @@ -4909,6 +4940,10 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP,UDM_SETPOS,0, Settings.AutoMaxSkipFrames); SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_SETRANGE, 0, MAKELPARAM((short)600, (short)0)); SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP,UDM_SETPOS,0, Settings.TurboSkipFrames); + SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)4000, (short)0)); + SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN,UDM_SETPOS,0, GUI.rewindBufferSize); + SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)300, (short)1)); + SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN,UDM_SETPOS,0, GUI.rewindGranularity); CheckDlgButton(hDlg,IDC_TOGGLE_TURBO,GUI.TurboModeToggle ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg,IDC_INACTIVE_PAUSE,GUI.InactivePause ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg,IDC_CUSTOMROMOPEN,GUI.CustomRomOpen ? BST_CHECKED : BST_UNCHECKED); @@ -5001,6 +5036,13 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar Settings.TurboSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_GETPOS, 0,0); Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_GETPOS, 0,0); Settings.AutoSaveDelay=SendDlgItemMessage(hDlg, IDC_SRAM_SPIN, UDM_GETPOS, 0,0); + GUI.rewindGranularity = SendDlgItemMessage(hDlg, IDC_REWIND_GRANULARITY_SPIN, UDM_GETPOS, 0,0); + if(GUI.rewindGranularity==0) GUI.rewindGranularity = 1; + unsigned int newRewindBufSize = SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN, UDM_GETPOS, 0,0); + if(GUI.rewindBufferSize != newRewindBufSize) { + GUI.rewindBufferSize = newRewindBufSize; + stateMan.init(GUI.rewindBufferSize * 1024 * 1024); + } WinSaveConfigFile(); } @@ -7749,7 +7791,7 @@ static void set_hotkeyinfo(HWND hDlg) SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.ClippingWindows.key,CustomKeys.ClippingWindows.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.Transparency.key,CustomKeys.Transparency.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,0,0); - SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,0,0); + SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.Rewind.key,CustomKeys.Rewind.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.SwitchControllers.key,CustomKeys.SwitchControllers.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.JoypadSwap.key,CustomKeys.JoypadSwap.modifiers); SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ResetGame.key,CustomKeys.ResetGame.modifiers); @@ -7814,7 +7856,7 @@ static void set_hotkeyinfo(HWND hDlg) SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_2_6); SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_2_7); SetDlgItemText(hDlg,IDC_LABEL_HK8,INPUTCONFIG_LABEL_UNUSED); - SetDlgItemText(hDlg,IDC_LABEL_HK9,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_2_9); SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_2_10); SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_2_11); SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_2_12); @@ -7979,7 +8021,7 @@ switch(msg) break; case IDC_HOTKEY9: if(index == 0) CustomKeys.ScopePause.key = wParam, CustomKeys.ScopePause.modifiers = modifiers; - //if(index == 1) CustomKeys.GLCube.key = wParam, CustomKeys.GLCube.modifiers = modifiers; + if(index == 1) CustomKeys.Rewind.key = wParam, CustomKeys.Rewind.modifiers = modifiers; if(index == 2) CustomKeys.TurboLeft.key = wParam, CustomKeys.TurboLeft.modifiers = modifiers; if(index == 3) CustomKeys.SelectSave[8].key = wParam, CustomKeys.SelectSave[8].modifiers = modifiers; break; diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 4a49f3cd..fb7c81c6 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -339,7 +339,7 @@ struct sGUI { HACCEL Accelerators; bool NeedDepthConvert; bool DepthConverted; - bool BGR; + bool TurboModeToggle; bool InactivePause; bool CustomRomOpen; @@ -395,6 +395,11 @@ struct sGUI { long FrameCount; long LastFrameCount; unsigned long IdleCount; + + // rewinding + bool rewinding; + unsigned int rewindBufferSize; + unsigned int rewindGranularity; }; //TURBO masks @@ -467,6 +472,7 @@ struct SCustomKeys { SCustomKey ResetGame; SCustomKey ToggleCheats; SCustomKey QuitS9X; + SCustomKey Rewind; }; struct SJoypad { From 34a813cab0b8f9c69bbb6467b0a1a4244c152a66 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 28 Mar 2012 21:10:40 +0200 Subject: [PATCH 104/130] Remove ZeroMemory references from memstream merge --- memmap.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/memmap.cpp b/memmap.cpp index c2bbfed4..54f83587 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -1771,8 +1771,8 @@ bool8 CMemory::LoadMultiCartMem (const uint8 *sourceA, uint32 sourceASize, const uint8 *bios, uint32 biosSize) { uint32 offset = 0; - ZeroMemory(ROM, MAX_ROM_SIZE); - ZeroMemory(&Multi, sizeof(Multi)); + memset(ROM, 0, MAX_ROM_SIZE); + memset(&Multi, 0, sizeof(Multi)); if(bios) { if(!is_SufamiTurbo_BIOS(bios,biosSize)) @@ -1803,8 +1803,8 @@ bool8 CMemory::LoadMultiCartMem (const uint8 *sourceA, uint32 sourceASize, bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) { - ZeroMemory(ROM, MAX_ROM_SIZE); - ZeroMemory(&Multi, sizeof(Multi)); + memset(ROM, 0, MAX_ROM_SIZE); + memset(&Multi, 0, sizeof(Multi)); Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); @@ -1922,7 +1922,7 @@ bool8 CMemory::LoadMultiCartInt () if (Multi.cartSizeB) strcpy(ROMFilename, Multi.fileNameB); - ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + memset(&SNESGameFixes, 0, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); From 34088e033e294340a15dd40120f9fa6707f86326 Mon Sep 17 00:00:00 2001 From: OV2 Date: Wed, 28 Mar 2012 21:14:57 +0200 Subject: [PATCH 105/130] libsnes: update makefile for bapu --- libsnes/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsnes/Makefile b/libsnes/Makefile index 2038181d..7ffce8bf 100644 --- a/libsnes/Makefile +++ b/libsnes/Makefile @@ -27,11 +27,11 @@ else CXXFLAGS += -D__WIN32__ -D__WIN32_LIBSNES__ endif -OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libsnes.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libsnes.o CXX = g++ CC = gcc -INCLUDES = -I. -I.. -I../apu/ +INCLUDES = -I. -I.. -I../apu/ -I../apu/bapu CXXFLAGS += -O3 -fomit-frame-pointer -fno-exceptions -fno-rtti -pedantic -Wall -W -Wno-unused-parameter $(fpic) CXXFLAGS += -DHAVE_STRINGS_H -DHAVE_STDINT_H -DRIGHTSHIFT_IS_SAR From 8e1b726b6b743c60af1e401d7dff1b9c49313394 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 29 Mar 2012 15:23:04 +0200 Subject: [PATCH 106/130] Move statemanager to s9x folder, add rewind support to unix port --- win32/StateManager.cpp => statemanager.cpp | 2 +- win32/StateManager.h => statemanager.h | 2 +- unix/Makefile.in | 2 +- unix/unix.cpp | 71 ++++++++++++++++++++-- unix/x11.cpp | 2 + win32/snes9xw.vcproj | 16 ++--- win32/wsnes9x.cpp | 2 +- 7 files changed, 80 insertions(+), 17 deletions(-) rename win32/StateManager.cpp => statemanager.cpp (98%) rename win32/StateManager.h => statemanager.h (90%) diff --git a/win32/StateManager.cpp b/statemanager.cpp similarity index 98% rename from win32/StateManager.cpp rename to statemanager.cpp index dcef99f8..7280ec89 100644 --- a/win32/StateManager.cpp +++ b/statemanager.cpp @@ -1,7 +1,7 @@ #include "statemanager.h" #include "snapshot.h" -/* Snapshot Manager Class that records snapshot data for rewinding +/* State Manager Class that records snapshot data for rewinding mostly based on SSNES's rewind code by Themaister */ diff --git a/win32/StateManager.h b/statemanager.h similarity index 90% rename from win32/StateManager.h rename to statemanager.h index 65aabb30..38f3c0d7 100644 --- a/win32/StateManager.h +++ b/statemanager.h @@ -1,7 +1,7 @@ #ifndef STATEMANAGER_H #define STATEMANAGER_H -/* Snapshot Manager Class that records snapshot data for rewinding +/* State Manager Class that records snapshot data for rewinding mostly based on SSNES's rewind code by Themaister */ diff --git a/unix/Makefile.in b/unix/Makefile.in index c7525aa5..58495689 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -7,7 +7,7 @@ OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` BUILDDIR = . -OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../statemanager.o unix.o x11.o DEFS = -DMITSHM ifdef S9XDEBUGGER diff --git a/unix/unix.cpp b/unix/unix.cpp index c16d04aa..938e5698 100644 --- a/unix/unix.cpp +++ b/unix/unix.cpp @@ -222,6 +222,7 @@ #ifdef DEBUGGER #include "debug.h" #endif +#include "statemanager.h" #ifdef NETPLAY_SUPPORT #ifdef _DEBUG @@ -233,6 +234,8 @@ typedef std::pair strpair_t; ConfigFile::secvec_t keymaps; +StateManager stateMan; + #define FIXED_POINT 0x10000 #define FIXED_POINT_SHIFT 16 #define FIXED_POINT_REMAINDER 0xffff @@ -275,6 +278,8 @@ struct SUnixSettings bool8 ThreadSound; uint32 SoundBufferSize; uint32 SoundFragmentSize; + uint32 rewindBufferSize; + uint32 rewindGranularity; }; struct SoundStatus @@ -290,6 +295,8 @@ struct SoundStatus static SUnixSettings unixSettings; static SoundStatus so; +static bool8 rewinding; + #ifndef NOSOUND static uint8 Buf[SOUND_BUFFER_SIZE]; #endif @@ -436,6 +443,10 @@ void S9xExtraUsage (void) S9xMessage(S9X_INFO, S9X_USAGE, " frames (use with -dumpstreams)"); S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xMessage(S9X_INFO, S9X_USAGE, "-rwbuffersize Rewind buffer size in MB"); + S9xMessage(S9X_INFO, S9X_USAGE, "-rwgranularity Rewind granularity in frames"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xExtraDisplayUsage(); } @@ -534,6 +545,22 @@ void S9xParseArg (char **argv, int &i, int argc) else if (!strcasecmp(argv[i], "-dumpmaxframes")) Settings.DumpStreamsMaxFrames = atoi(argv[++i]); + else + if (!strcasecmp(argv[i], "-rwbuffersize")) + { + if (i + 1 < argc) + unixSettings.rewindBufferSize = atoi(argv[++i]); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-rwgranularity")) + { + if (i + 1 < argc) + unixSettings.rewindGranularity = atoi(argv[++i]); + else + S9xUsage(); + } else S9xParseDisplayArg(argv, i, argc); } @@ -1138,6 +1165,13 @@ s9xcommand_t S9xGetPortCommandT (const char *n) return (cmd); } + } else + if (!strcmp(n,"Rewind")) + { + cmd.type = S9xButtonPort; + cmd.port[1] = 2; + + return (cmd); } return (S9xGetDisplayCommandT(n)); @@ -1168,6 +1202,9 @@ char * S9xGetPortCommandName (s9xcommand_t cmd) x += " ToggleMeta"; x += (int) cmd.port[3]; return (strdup(x.c_str())); + + case 2: + return (strdup("Rewind")); } break; @@ -1204,6 +1241,10 @@ void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) if (data1) js_mod[cmd.port[2]] ^= cmd.port[3]; break; + + case 2: + rewinding = (bool8) data1; + break; } break; @@ -1594,8 +1635,13 @@ int main (int argc, char **argv) unixSettings.SoundBufferSize = 100; unixSettings.SoundFragmentSize = 2048; + unixSettings.rewindBufferSize = 0; + unixSettings.rewindGranularity = 1; + memset(&so, 0, sizeof(so)); + rewinding = false; + CPU.Flags = 0; S9xLoadConfigFiles(argv, argc); @@ -1733,6 +1779,8 @@ int main (int argc, char **argv) { NetPlay.MaxFrameSkip = 10; + unixSettings.rewindBufferSize = 0; + if (!S9xNPConnectToServer(Settings.ServerName, Settings.Port, Memory.ROMName)) { fprintf(stderr, "Failed to connect to server %s on port %d.\n", Settings.ServerName, Settings.Port); @@ -1759,12 +1807,18 @@ int main (int argc, char **argv) CPU.Flags |= flags; } else - if (snapshot_filename) { - uint32 flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); - if (!S9xUnfreezeGame(snapshot_filename)) - exit(1); - CPU.Flags |= flags; + if (snapshot_filename) + { + uint32 flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + if (!S9xUnfreezeGame(snapshot_filename)) + exit(1); + CPU.Flags |= flags; + } + if (unixSettings.rewindBufferSize) + { + stateMan.init(unixSettings.rewindBufferSize * 1024 * 1024); + } } S9xGraphicsMode(); @@ -1822,7 +1876,14 @@ int main (int argc, char **argv) #else if (!Settings.Paused) #endif + { + if(rewinding) + rewinding = stateMan.pop(); + else if(IPPU.TotalEmulatedFrames % unixSettings.rewindGranularity == 0) + stateMan.push(); + S9xMainLoop(); + } #ifdef NETPLAY_SUPPORT if (NP_Activated) diff --git a/unix/x11.cpp b/unix/x11.cpp index cb76f82d..d510464a 100644 --- a/unix/x11.cpp +++ b/unix/x11.cpp @@ -462,6 +462,8 @@ const char * S9xParseDisplayConfig (ConfigFile &conf, int pass) keymaps.push_back(strpair_t("M00:Pointer", "Pointer Mouse1+Superscope+Justifier1")); keymaps.push_back(strpair_t("K00:grave", "Superscope ToggleTurbo")); keymaps.push_back(strpair_t("K00:slash", "Superscope Pause")); + + keymaps.push_back(strpair_t("K00:r", "Rewind")); } GUI.no_repeat = !conf.GetBool("Unix/X11::SetKeyRepeat", TRUE); diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 3437de14..c8c38d2c 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -2866,6 +2866,14 @@ /> + + + + @@ -3022,14 +3030,6 @@ RelativePath=".\render.h" > - - - - diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 6baa90bf..cb8c8883 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -211,9 +211,9 @@ #include "../movie.h" #include "../controls.h" #include "../conffile.h" +#include "../statemanager.h" #include "AVIOutput.h" #include "InputCustom.h" -#include "StateManager.h" #include #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) From 5bf62c9d2f5d9ec9082bb7cfa337d05ff920b489 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 29 Mar 2012 15:58:40 +0200 Subject: [PATCH 107/130] Restrict "absent" messages during snapshot loading to DEBUGGER --- snapshot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/snapshot.cpp b/snapshot.cpp index ba6a11c8..282198f5 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -2065,7 +2065,9 @@ static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int siz if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':') { err: +#ifdef DEBUGGER fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); +#endif REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0); return (WRONG_FORMAT); } From 63ec714739f058bd7886cecb43b6e0107667f50a Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 7 Apr 2012 16:24:12 -0500 Subject: [PATCH 108/130] Add full-time blending function for high resolution mode. --- gtk/src/gtk_display.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index 2b4d6cf2..4729a765 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -718,6 +718,40 @@ S9xMergeHires (void *buffer, return; } +static void +S9xBlendHires (void *buffer, int pitch, int &width, int &height) +{ + uint16 tmp[512]; + + if (width < 512) + { + width <<= 1; + + for (int y = 0; y < height; y++) + { + uint16 *input = (uint16 *) ((uint8 *) buffer + y * pitch); + + tmp[0] = input[0]; + for (int x = 1; x < width; x++) + tmp[x] = AVERAGE_1555 (input[(x - 1) >> 1], input[(x >> 1)]); + + memcpy (input, tmp, width << 1); + } + } + else for (int y = 0; y < height; y++) + { + uint16 *input = (uint16 *) ((uint8 *) buffer + y * pitch); + + tmp[0] = input[0]; + for (int x = 1; x < width; x++) + tmp[x] = AVERAGE_1555 (input[x - 1], input[x]); + + memcpy (input, tmp, pitch); + } + + return; +} + void filter_2x (void *src, int src_pitch, From 4f551d3d29b94b96b9404cd51bf1133e4a8ab30c Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 7 Apr 2012 16:43:34 -0500 Subject: [PATCH 109/130] Fix crash on opening nonexistent file. Keep shaders from appearing in the recent files menu. --- gtk/src/gtk_s9x.cpp | 2 -- gtk/src/gtk_s9xwindow.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index 30adb261..03e1c812 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -207,8 +207,6 @@ S9xOpenROM (const char *rom_filename) } else { - S9xReset (); - CPU.Flags = flags; Settings.Paused = 1; diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index f58d934f..21e5ea34 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -976,6 +976,8 @@ Snes9xWindow::try_open_rom (const char *filename) } else { + const char *groups[] = { "cartridge", NULL }; + GtkRecentData recent_data = { NULL, @@ -983,7 +985,7 @@ Snes9xWindow::try_open_rom (const char *filename) (gchar *) "application/x-snes-rom", (gchar *) "Snes9x", NULL, - NULL, + (gchar **) groups, FALSE }; gchar *u_filename; @@ -1833,7 +1835,7 @@ Snes9xWindow::show (void) GtkRecentFilter *filter = gtk_recent_filter_new (); GtkRecentChooser *chooser = GTK_RECENT_CHOOSER (recent_menu); - gtk_recent_filter_add_application (filter, "Snes9x"); + gtk_recent_filter_add_group (filter, "cartridge"); gtk_recent_chooser_set_local_only (chooser, TRUE); gtk_recent_chooser_set_show_icons (chooser, FALSE); gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU); From 53defb5b111d29f830366592251e829400f191f5 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 7 Apr 2012 16:49:55 -0500 Subject: [PATCH 110/130] Go back to floating point hermite resampler. 16-bit fixed point doesn't have enough accuracy for a decent SNR with hermite. --- apu/hermite_resampler.h | 53 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h index 3c872da0..8c7dd96b 100644 --- a/apu/hermite_resampler.h +++ b/apu/hermite_resampler.h @@ -14,30 +14,27 @@ class HermiteResampler : public Resampler { protected: - uint32 r_step; - uint32 r_frac; + float r_step; + float r_frac; int r_left[4], r_right[4]; - static inline int32 - hermite (int32 mu1, int32 a, int32 b, int32 c, int32 d) + static inline float + hermite (float mu1, float a, float b, float c, float d) { - int32 mu2, mu3, m0, m1, a0, a1, a2, a3; + float mu2, mu3, m0, m1, a0, a1, a2, a3; - mu2 = (mu1 * mu1) >> 15; - mu3 = (mu2 * mu1) >> 15; + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; - m0 = (c - a) << 14; - m1 = (d - b) << 14; + m0 = (c - a) * 0.5; + m1 = (d - b) * 0.5; - a0 = (mu3 << 1) - (3 * mu2) + (1 << 15); - a1 = mu3 - (mu2 << 1) + mu1; - a2 = mu3 - mu2; - a3 = 3 * mu2 - (mu3 << 1); + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; - return ((a0 * b) + - ((a1 * m0) >> 15) + - ((a2 * m1) >> 15) + - (a3 * c)) >> 15; + return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); } public: @@ -53,7 +50,7 @@ class HermiteResampler : public Resampler void time_ratio (double ratio) { - r_step = (1 << 16) * ratio; + r_step = ratio; clear (); } @@ -61,7 +58,7 @@ class HermiteResampler : public Resampler clear (void) { ring_buffer::clear (); - r_frac = (1 << 16); + r_frac = 1.0; r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; } @@ -79,21 +76,21 @@ class HermiteResampler : public Resampler { int s_left = internal_buffer[i_position]; int s_right = internal_buffer[i_position + 1]; - int hermite_val; + float hermite_val[2]; - while (r_frac <= (1 << 16) && o_position < num_samples) + while (r_frac <= 1.0 && o_position < num_samples) { - hermite_val = hermite (r_frac >> 1, r_left [0], r_left [1], r_left [2], r_left [3]); - data[o_position] = SHORT_CLAMP (hermite_val); - hermite_val = hermite (r_frac >> 1, r_right[0], r_right[1], r_right[2], r_right[3]); - data[o_position + 1] = SHORT_CLAMP (hermite_val); + hermite_val[0] = hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]); + hermite_val[1] = hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]); + data[o_position] = SHORT_CLAMP (hermite_val[0]); + data[o_position + 1] = SHORT_CLAMP (hermite_val[1]); o_position += 2; r_frac += r_step; } - if (r_frac > (1 << 16)) + if (r_frac > 1.0) { r_left [0] = r_left [1]; r_left [1] = r_left [2]; @@ -105,7 +102,7 @@ class HermiteResampler : public Resampler r_right[2] = r_right[3]; r_right[3] = s_right; - r_frac -= (1 << 16); + r_frac -= 1.0; i_position += 2; if (i_position >= max_samples) @@ -123,7 +120,7 @@ class HermiteResampler : public Resampler inline int avail (void) { - return ((((uint32) size) << 14) - r_frac) / r_step * 2; + return (int) floor (((size >> 2) - r_frac) / r_step) * 2; } }; From 17fe17b4e206fbad9202bedde38d94f6295b77dc Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Sat, 7 Apr 2012 20:04:02 -0500 Subject: [PATCH 111/130] Fix a couple of warnings/gdk_pixbuf_unref deprecation. --- gtk/src/gtk_display_driver_gtk.cpp | 4 ++-- gtk/src/gtk_display_driver_xv.cpp | 6 ------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/gtk/src/gtk_display_driver_gtk.cpp b/gtk/src/gtk_display_driver_gtk.cpp index 234d5410..36ce8b35 100644 --- a/gtk/src/gtk_display_driver_gtk.cpp +++ b/gtk/src/gtk_display_driver_gtk.cpp @@ -83,7 +83,7 @@ S9xGTKDisplayDriver::output (void *src, gdk_buffer_width = width; gdk_buffer_height = height; - gdk_pixbuf_unref (pixbuf); + g_object_unref (pixbuf); padded_buffer[2] = realloc (padded_buffer[2], gdk_buffer_width * gdk_buffer_height * 3); @@ -195,7 +195,7 @@ S9xGTKDisplayDriver::deinit (void) free (buffer[0]); free (buffer[1]); - gdk_pixbuf_unref (pixbuf); + g_object_unref (pixbuf); free (padded_buffer[2]); return; diff --git a/gtk/src/gtk_display_driver_xv.cpp b/gtk/src/gtk_display_driver_xv.cpp index d6046aab..1333a705 100644 --- a/gtk/src/gtk_display_driver_xv.cpp +++ b/gtk/src/gtk_display_driver_xv.cpp @@ -443,17 +443,11 @@ S9xXVDisplayDriver::init (void) } } - XSetWindowAttributes window_attr; xcolormap = XCreateColormap (display, GDK_COMPAT_WINDOW_XID (gtk_widget_get_window (drawing_area)), vi->visual, AllocNone); - window_attr.colormap = xcolormap; - window_attr.border_pixel = 0; - window_attr.event_mask = StructureNotifyMask | ExposureMask | PropertyChangeMask; - window_attr.background_pixmap = None; - create_window (1, 1); gdk_window_hide (gdk_window); From 81e12d533cee984f199f0f27f7c05e27ba21d28f Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 10 Apr 2012 22:59:54 +0200 Subject: [PATCH 112/130] Win32: use asm in custom zlib proj --- win32/zlib/zlib.vcproj | 64 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/win32/zlib/zlib.vcproj b/win32/zlib/zlib.vcproj index 979ff284..d14adf81 100644 --- a/win32/zlib/zlib.vcproj +++ b/win32/zlib/zlib.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + From 50013f9a19650b890a8650131b3dd03d27bac08c Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 10 Apr 2012 23:06:17 +0200 Subject: [PATCH 113/130] libretro: rename from libsnes and adapt new interface --- {libsnes => libretro}/Makefile | 8 +- .../libretro-win32.vcproj | 26 +- libsnes/libsnes.cpp => libretro/libretro.cpp | 471 +++--- libretro/libretro.def | 41 + libretro/libretro.h | 218 +++ libretro/link.T | 4 + libsnes/libsnes.def | 47 - libsnes/libsnes.hpp | 1264 ----------------- libsnes/link.T | 4 - 9 files changed, 489 insertions(+), 1594 deletions(-) rename {libsnes => libretro}/Makefile (93%) rename libsnes/libsnes-win32.vcproj => libretro/libretro-win32.vcproj (96%) rename libsnes/libsnes.cpp => libretro/libretro.cpp (59%) create mode 100644 libretro/libretro.def create mode 100644 libretro/libretro.h create mode 100644 libretro/link.T delete mode 100644 libsnes/libsnes.def delete mode 100644 libsnes/libsnes.hpp delete mode 100644 libsnes/link.T diff --git a/libsnes/Makefile b/libretro/Makefile similarity index 93% rename from libsnes/Makefile rename to libretro/Makefile index 7ffce8bf..5958bd7e 100644 --- a/libsnes/Makefile +++ b/libretro/Makefile @@ -12,22 +12,22 @@ endif endif ifeq ($(platform), unix) - TARGET := libsnes.so + TARGET := libretro.so fpic := -fPIC SHARED := -shared -Wl,--version-script=link.T else ifeq ($(platform), osx) - TARGET := libsnes.dylib + TARGET := libretro.dylib fpic := -fPIC SHARED := -dynamiclib else - TARGET := snes.dll + TARGET := libretro.dll CC = gcc CXX = g++ SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T CXXFLAGS += -D__WIN32__ -D__WIN32_LIBSNES__ endif -OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libsnes.o +OBJECTS = ../apu/apu.o ../apu/bapu/dsp/sdsp.o ../apu/bapu/dsp/SPC_DSP.o ../apu/bapu/smp/smp.o ../apu/bapu/smp/smp_state.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../stream.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o libretro.o CXX = g++ CC = gcc diff --git a/libsnes/libsnes-win32.vcproj b/libretro/libretro-win32.vcproj similarity index 96% rename from libsnes/libsnes-win32.vcproj rename to libretro/libretro-win32.vcproj index ee4f1dff..3063f48c 100644 --- a/libsnes/libsnes-win32.vcproj +++ b/libretro/libretro-win32.vcproj @@ -2,7 +2,7 @@ diff --git a/libsnes/libsnes.cpp b/libretro/libretro.cpp similarity index 59% rename from libsnes/libsnes.cpp rename to libretro/libretro.cpp index 3cf5b2ce..50a6a875 100644 --- a/libsnes/libsnes.cpp +++ b/libretro/libretro.cpp @@ -1,4 +1,4 @@ -#include "libsnes.hpp" +#include "libretro.h" #include "snes9x.h" #include "memmap.h" @@ -22,53 +22,44 @@ #include -static snes_video_refresh_t s9x_video_cb = NULL; -static snes_audio_sample_t s9x_audio_cb = NULL; -static snes_input_poll_t s9x_poller_cb = NULL; -static snes_input_state_t s9x_input_state_cb = NULL; +static retro_video_refresh_t s9x_video_cb = NULL; +static retro_audio_sample_t s9x_audio_cb = NULL; +static retro_audio_sample_batch_t s9x_audio_batch_cb = NULL; +static retro_input_poll_t s9x_poller_cb = NULL; +static retro_input_state_t s9x_input_state_cb = NULL; -void snes_set_video_refresh(snes_video_refresh_t cb) +void retro_set_video_refresh(retro_video_refresh_t cb) { s9x_video_cb = cb; } -void snes_set_audio_sample(snes_audio_sample_t cb) +void retro_set_audio_sample(retro_audio_sample_t cb) { s9x_audio_cb = cb; } -void snes_set_input_poll(snes_input_poll_t cb) +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) +{ + s9x_audio_batch_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) { s9x_poller_cb = cb; } -void snes_set_input_state(snes_input_state_t cb) +void retro_set_input_state(retro_input_state_t cb) { s9x_input_state_cb = cb; } -static snes_environment_t environ_cb; +static retro_environment_t environ_cb; static bool use_overscan; -void snes_set_environment(snes_environment_t cb) +void retro_set_environment(retro_environment_t cb) { environ_cb = cb; } -static void set_environ_timing() -{ - if (environ_cb) - { - snes_system_timing timing; - timing.sample_rate = 32040.5; - if (!Settings.PAL) - timing.fps = 21477272.0 / 357366.0; - else - timing.fps = 21281370.0 / 425568.0; - - environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); - } -} - static void S9xAudioCallback(void*) { // Just pick a big buffer. We won't use it all. @@ -77,154 +68,172 @@ static void S9xAudioCallback(void*) S9xFinalizeSamples(); size_t avail = S9xGetSampleCount(); S9xMixSamples((uint8*)audio_buf, avail); - for (size_t i = 0; i < avail; i+=2) - s9x_audio_cb((uint16_t)audio_buf[i], (uint16_t)audio_buf[i + 1]); + s9x_audio_batch_cb(audio_buf,avail >> 1); + + /*for (size_t i = 0; i < avail; i+=2) + s9x_audio_cb((uint16_t)audio_buf[i], (uint16_t)audio_buf[i + 1]);*/ } -const char *snes_library_id() +void retro_get_system_info(struct retro_system_info *info) +{ + memset(info,0,sizeof(retro_system_info)); + + info->library_name = "SNES9x"; + info->library_version = VERSION; + info->valid_extensions = "smc|sfc|zip|gz|swc|fig|jma"; + info->need_fullpath = false; + info->block_extract = false; +} + +void retro_get_system_av_info(struct retro_system_av_info *info) +{ + memset(info,0,sizeof(retro_system_av_info)); + + info->geometry.base_width = SNES_WIDTH; + info->geometry.base_height = SNES_HEIGHT; + info->geometry.max_width = MAX_SNES_WIDTH; + info->geometry.max_height = MAX_SNES_HEIGHT; + info->timing.sample_rate = 32040.5; + info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0; +} + +const char *retro_library_id() { return "SNES9x v" VERSION; } -unsigned snes_library_revision_major() +unsigned retro_api_version() { - return 1; + return RETRO_API_VERSION; } -unsigned snes_library_revision_minor() -{ - return 3; -} -void snes_power() +void retro_reset() { - S9xReset(); -} - -void snes_reset() -{ - S9xMovieUpdateOnReset(); - if (S9xMoviePlaying()) - { - S9xMovieStop(true); - } S9xSoftReset(); } static unsigned snes_devices[2]; -void snes_set_controller_port_device(bool in_port, unsigned device) +void retro_set_controller_port_device(unsigned port, unsigned device) { - int port = in_port == SNES_PORT_1 ? 0 : 1; switch (device) { - case SNES_DEVICE_JOYPAD: + case RETRO_DEVICE_JOYPAD: S9xSetController(port, CTL_JOYPAD, 0, 0, 0, 0); - snes_devices[port] = SNES_DEVICE_JOYPAD; + snes_devices[port] = RETRO_DEVICE_JOYPAD; break; - case SNES_DEVICE_MULTITAP: + case RETRO_DEVICE_JOYPAD_MULTITAP: S9xSetController(port, CTL_MP5, 1, 2, 3, 4); - snes_devices[port] = SNES_DEVICE_MULTITAP; + snes_devices[port] = RETRO_DEVICE_JOYPAD_MULTITAP; break; - case SNES_DEVICE_MOUSE: + case RETRO_DEVICE_MOUSE: S9xSetController(port, CTL_MOUSE, 0, 0, 0, 0); - snes_devices[port] = SNES_DEVICE_MOUSE; + snes_devices[port] = RETRO_DEVICE_MOUSE; break; - case SNES_DEVICE_SUPER_SCOPE: + case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE: S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0); - snes_devices[port] = SNES_DEVICE_SUPER_SCOPE; + snes_devices[port] = RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE; break; - case SNES_DEVICE_JUSTIFIER: + case RETRO_DEVICE_LIGHTGUN_JUSTIFIER: S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0); - snes_devices[port] = SNES_DEVICE_JUSTIFIER; + snes_devices[port] = RETRO_DEVICE_LIGHTGUN_JUSTIFIER; break; - case SNES_DEVICE_JUSTIFIERS: + case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS: S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0); - snes_devices[port] = SNES_DEVICE_JUSTIFIERS; + snes_devices[port] = RETRO_DEVICE_LIGHTGUN_JUSTIFIERS; break; default: - fprintf(stderr, "[libsnes]: Invalid device!\n"); + fprintf(stderr, "[libretro]: Invalid device!\n"); } } -void snes_cheat_reset() +void retro_cheat_reset() {} -void snes_cheat_set(unsigned, bool, const char*) +void retro_cheat_set(unsigned, bool, const char*) {} -bool snes_load_cartridge_bsx_slotted( - const char *, const uint8_t *rom_data, unsigned rom_size, - const char *, const uint8_t *bsx_data, unsigned bsx_size - ) +bool retro_load_game(const struct retro_game_info *game) { - int loaded = Memory.LoadMultiCartMem(rom_data, rom_size, bsx_data, bsx_size, NULL, NULL); + int loaded = 0; + + if(game->data == NULL && game->size == NULL && game->path != NULL) + loaded = Memory.LoadROM(game->path); + else + loaded = Memory.LoadROMMem((const uint8_t*)game->data ,game->size); if (!loaded) { - fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); - return false; + fprintf(stderr, "[libretro]: Rom loading failed...\n"); } - - set_environ_timing(); - - return false; -} - -bool snes_load_cartridge_bsx( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size - ) -{ - if(bsx_data==NULL) - return snes_load_cartridge_normal(rom_xml,rom_data,rom_size); - memcpy(Memory.BIOSROM,rom_data,rom_size); - return snes_load_cartridge_normal(bsx_xml,bsx_data,bsx_size); -} - -bool snes_load_cartridge_sufami_turbo( - const char *, const uint8_t *rom_data, unsigned rom_size, - const char *, const uint8_t *sta_data, unsigned sta_size, - const char *, const uint8_t *stb_data, unsigned stb_size - ) -{ - int loaded = Memory.LoadMultiCartMem(sta_data, sta_size, stb_data, stb_size, rom_data, rom_size); - - if (!loaded) - { - fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); - return false; - } - - set_environ_timing(); - return true; + return loaded; } -bool snes_load_cartridge_super_game_boy( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned - ) -{ - return false; +void retro_unload_game(void) +{} + +bool retro_load_game_special(unsigned game_type, + const struct retro_game_info *info, size_t num_info) { + + int loaded = 0; + switch (game_type) { + case RETRO_GAME_TYPE_BSX: + + if(num_info == 1) { + loaded = Memory.LoadROMMem((const uint8_t*)info[0].data,info[0].size); + } else if(num_info == 2) { + memcpy(Memory.BIOSROM,(const uint8_t*)info[0].data,info[0].size); + loaded = Memory.LoadROMMem((const uint8_t*)info[1].data,info[1].size); + } + + if (!loaded) + { + fprintf(stderr, "[libretro]: BSX Rom loading failed...\n"); + } + + return loaded; + + case RETRO_GAME_TYPE_BSX_SLOTTED: + + if(num_info == 2) + loaded = Memory.LoadMultiCartMem((const uint8_t*)info[0].data, info[0].size, + (const uint8_t*)info[1].data, info[1].size, NULL, NULL); + + if (!loaded) + { + fprintf(stderr, "[libretro]: Multirom loading failed...\n"); + } + + return loaded; + + case RETRO_GAME_TYPE_SUFAMI_TURBO: + + if(num_info == 3) + loaded = Memory.LoadMultiCartMem((const uint8_t*)info[1].data, info[1].size, + (const uint8_t*)info[2].data, info[2].size, (const uint8_t*)info[0].data, info[0].size); + + if (!loaded) + { + fprintf(stderr, "[libretro]: Sufami Turbo Rom loading failed...\n"); + } + + return loaded; + + default: + return false; + } } static void map_buttons(); -void snes_init() +void retro_init() { if (environ_cb) { - if (!environ_cb(SNES_ENVIRONMENT_GET_OVERSCAN, &use_overscan)) + if (!environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &use_overscan)) use_overscan = false; - - if (use_overscan) - { - snes_geometry geom = {256, 239, 512, 512}; - environ_cb(SNES_ENVIRONMENT_SET_GEOMETRY, &geom); - unsigned pitch = 1024; - environ_cb(SNES_ENVIRONMENT_SET_PITCH, &pitch); - } } memset(&Settings, 0, sizeof(Settings)); @@ -261,7 +270,7 @@ void snes_init() { Memory.Deinit(); S9xDeinitAPU(); - fprintf(stderr, "[libsnes]: Failed to init Memory or APU.\n"); + fprintf(stderr, "[libretro]: Failed to init Memory or APU.\n"); exit(1); } @@ -270,15 +279,15 @@ void snes_init() S9xSetSamplesAvailableCallback(S9xAudioCallback, NULL); S9xSetRenderPixelFormat(RGB555); - GFX.Pitch = use_overscan ? 1024 : 2048; - GFX.Screen = (uint16*) calloc(1, GFX.Pitch * 512 * sizeof(uint16)); + GFX.Pitch = MAX_SNES_WIDTH * sizeof(uint16); + GFX.Screen = (uint16*) calloc(1, GFX.Pitch * MAX_SNES_HEIGHT); S9xGraphicsInit(); S9xInitInputDevices(); for (int i = 0; i < 2; i++) { S9xSetController(i, CTL_JOYPAD, i, 0, 0, 0); - snes_devices[i] = SNES_DEVICE_JOYPAD; + snes_devices[i] = RETRO_DEVICE_JOYPAD; } S9xUnmapAllControls(); @@ -295,41 +304,41 @@ void snes_init() #define PAD_4 4 #define PAD_5 5 -#define BTN_B SNES_DEVICE_ID_JOYPAD_B -#define BTN_Y SNES_DEVICE_ID_JOYPAD_Y -#define BTN_SELECT SNES_DEVICE_ID_JOYPAD_SELECT -#define BTN_START SNES_DEVICE_ID_JOYPAD_START -#define BTN_UP SNES_DEVICE_ID_JOYPAD_UP -#define BTN_DOWN SNES_DEVICE_ID_JOYPAD_DOWN -#define BTN_LEFT SNES_DEVICE_ID_JOYPAD_LEFT -#define BTN_RIGHT SNES_DEVICE_ID_JOYPAD_RIGHT -#define BTN_A SNES_DEVICE_ID_JOYPAD_A -#define BTN_X SNES_DEVICE_ID_JOYPAD_X -#define BTN_L SNES_DEVICE_ID_JOYPAD_L -#define BTN_R SNES_DEVICE_ID_JOYPAD_R +#define BTN_B RETRO_DEVICE_ID_JOYPAD_B +#define BTN_Y RETRO_DEVICE_ID_JOYPAD_Y +#define BTN_SELECT RETRO_DEVICE_ID_JOYPAD_SELECT +#define BTN_START RETRO_DEVICE_ID_JOYPAD_START +#define BTN_UP RETRO_DEVICE_ID_JOYPAD_UP +#define BTN_DOWN RETRO_DEVICE_ID_JOYPAD_DOWN +#define BTN_LEFT RETRO_DEVICE_ID_JOYPAD_LEFT +#define BTN_RIGHT RETRO_DEVICE_ID_JOYPAD_RIGHT +#define BTN_A RETRO_DEVICE_ID_JOYPAD_A +#define BTN_X RETRO_DEVICE_ID_JOYPAD_X +#define BTN_L RETRO_DEVICE_ID_JOYPAD_L +#define BTN_R RETRO_DEVICE_ID_JOYPAD_R #define BTN_FIRST BTN_B #define BTN_LAST BTN_R -#define MOUSE_X SNES_DEVICE_ID_MOUSE_X -#define MOUSE_Y SNES_DEVICE_ID_MOUSE_Y -#define MOUSE_LEFT SNES_DEVICE_ID_MOUSE_LEFT -#define MOUSE_RIGHT SNES_DEVICE_ID_MOUSE_RIGHT +#define MOUSE_X RETRO_DEVICE_ID_MOUSE_X +#define MOUSE_Y RETRO_DEVICE_ID_MOUSE_Y +#define MOUSE_LEFT RETRO_DEVICE_ID_MOUSE_LEFT +#define MOUSE_RIGHT RETRO_DEVICE_ID_MOUSE_RIGHT #define MOUSE_FIRST MOUSE_X #define MOUSE_LAST MOUSE_RIGHT -#define SCOPE_X SNES_DEVICE_ID_SUPER_SCOPE_X -#define SCOPE_Y SNES_DEVICE_ID_SUPER_SCOPE_Y -#define SCOPE_TRIGGER SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER -#define SCOPE_CURSOR SNES_DEVICE_ID_SUPER_SCOPE_CURSOR -#define SCOPE_TURBO SNES_DEVICE_ID_SUPER_SCOPE_TURBO -#define SCOPE_PAUSE SNES_DEVICE_ID_SUPER_SCOPE_PAUSE +#define SCOPE_X RETRO_DEVICE_ID_SUPER_SCOPE_X +#define SCOPE_Y RETRO_DEVICE_ID_SUPER_SCOPE_Y +#define SCOPE_TRIGGER RETRO_DEVICE_ID_LIGHTGUN_TRIGGER +#define SCOPE_CURSOR RETRO_DEVICE_ID_LIGHTGUN_CURSOR +#define SCOPE_TURBO RETRO_DEVICE_ID_LIGHTGUN_TURBO +#define SCOPE_PAUSE RETRO_DEVICE_ID_LIGHTGUN_PAUSE #define SCOPE_FIRST SCOPE_X #define SCOPE_LAST SCOPE_PAUSE -#define JUSTIFIER_X SNES_DEVICE_ID_JUSTIFIER_X -#define JUSTIFIER_Y SNES_DEVICE_ID_JUSTIFIER_Y -#define JUSTIFIER_TRIGGER SNES_DEVICE_ID_JUSTIFIER_TRIGGER -#define JUSTIFIER_START SNES_DEVICE_ID_JUSTIFIER_START +#define JUSTIFIER_X RETRO_DEVICE_ID_JUSTIFIER_X +#define JUSTIFIER_Y RETRO_DEVICE_ID_JUSTIFIER_Y +#define JUSTIFIER_TRIGGER RETRO_DEVICE_ID_LIGHTGUN_TRIGGER +#define JUSTIFIER_START RETRO_DEVICE_ID_LIGHTGUN_PAUSE #define JUSTIFIER_FIRST JUSTIFIER_X #define JUSTIFIER_LAST JUSTIFIER_START @@ -407,7 +416,7 @@ static void map_buttons() } -// libsnes uses relative values for analogue devices. +// libretro uses relative values for analogue devices. // S9x seems to use absolute values, but do convert these into relative values in the core. (Why?!) // Hack around it. :) static int16_t snes_mouse_state[2][2] = {{0}, {0}}; @@ -416,77 +425,63 @@ static int16_t snes_justifier_state[2][2] = {{0}, {0}}; static void report_buttons() { int _x, _y; - for (int port = SNES_PORT_1; port <= SNES_PORT_2; port++) + for (int port = 0; port <= 1; port++) { switch (snes_devices[port]) { - case SNES_DEVICE_JOYPAD: + case RETRO_DEVICE_JOYPAD: for (int i = BTN_FIRST; i <= BTN_LAST; i++) - S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JOYPAD, 0, i)); + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_JOYPAD, 0, i)); break; - case SNES_DEVICE_MULTITAP: + case RETRO_DEVICE_JOYPAD_MULTITAP: for (int j = 0; j < 4; j++) for (int i = BTN_FIRST; i <= BTN_LAST; i++) - S9xReportButton(MAKE_BUTTON(j + 2, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MULTITAP, j, i)); + S9xReportButton(MAKE_BUTTON(j + 2, i), s9x_input_state_cb(port, RETRO_DEVICE_JOYPAD_MULTITAP, j, i)); break; - case SNES_DEVICE_MOUSE: - _x = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_X); - _y = s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, SNES_DEVICE_ID_MOUSE_Y); + case RETRO_DEVICE_MOUSE: + _x = s9x_input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X); + _y = s9x_input_state_cb(port, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y); snes_mouse_state[port][0] += _x; snes_mouse_state[port][1] += _y; S9xReportPointer(BTN_POINTER + port, snes_mouse_state[port][0], snes_mouse_state[port][1]); for (int i = MOUSE_LEFT; i <= MOUSE_LAST; i++) - S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_MOUSE, 0, i)); + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_MOUSE, 0, i)); break; - case SNES_DEVICE_SUPER_SCOPE: - snes_scope_state[0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_X); - snes_scope_state[1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, SNES_DEVICE_ID_SUPER_SCOPE_Y); + case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE: + snes_scope_state[0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, RETRO_DEVICE_ID_LIGHTGUN_X); + snes_scope_state[1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, RETRO_DEVICE_ID_LIGHTGUN_Y); S9xReportPointer(BTN_POINTER, snes_scope_state[0], snes_scope_state[1]); for (int i = SCOPE_TRIGGER; i <= SCOPE_LAST; i++) - S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_SUPER_SCOPE, 0, i)); + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, i)); break; - case SNES_DEVICE_JUSTIFIER: - case SNES_DEVICE_JUSTIFIERS: - snes_justifier_state[0][0] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_X); - snes_justifier_state[0][1] += s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, SNES_DEVICE_ID_JUSTIFIER_Y); + case RETRO_DEVICE_LIGHTGUN_JUSTIFIER: + case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS: + snes_justifier_state[0][0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, RETRO_DEVICE_ID_LIGHTGUN_X); + snes_justifier_state[0][1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, RETRO_DEVICE_ID_LIGHTGUN_Y); S9xReportPointer(BTN_POINTER, snes_justifier_state[0][0], snes_justifier_state[0][1]); for (int i = JUSTIFIER_TRIGGER; i <= JUSTIFIER_LAST; i++) - S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port == SNES_PORT_2, SNES_DEVICE_JUSTIFIER, 0, i)); + S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, i)); break; default: - fprintf(stderr, "[libsnes]: Unknown device...\n"); + fprintf(stderr, "[libretro]: Unknown device...\n"); } } } -bool snes_load_cartridge_normal(const char *, const uint8_t *rom_data, unsigned rom_size) -{ - int loaded = Memory.LoadROMMem(rom_data,rom_size); - if (!loaded) - { - fprintf(stderr, "[libsnes]: Rom loading failed...\n"); - return false; - } - - set_environ_timing(); - - return true; -} - -void snes_run() +void retro_run() { s9x_poller_cb(); report_buttons(); S9xMainLoop(); } -void snes_term() +void retro_deinit() { S9xDeinitAPU(); Memory.Deinit(); @@ -495,30 +490,30 @@ void snes_term() } -bool snes_get_region() +unsigned retro_get_region() { - return Settings.PAL ? SNES_REGION_PAL : SNES_REGION_NTSC; + return Settings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; } -uint8_t* snes_get_memory_data(unsigned type) +void* retro_get_memory_data(unsigned type) { - uint8_t* data; + void* data; switch(type) { - case SNES_MEMORY_SUFAMI_TURBO_A_RAM: - case SNES_MEMORY_CARTRIDGE_RAM: + case RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM: + case RETRO_MEMORY_SAVE_RAM: data = Memory.SRAM; break; - case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + case RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM: data = Multi.sramB; break; - case SNES_MEMORY_CARTRIDGE_RTC: + case RETRO_MEMORY_RTC: data = RTCData.reg; break; - case SNES_MEMORY_WRAM: + case RETRO_MEMORY_SYSTEM_RAM: data = Memory.RAM; break; - case SNES_MEMORY_APURAM: + /*case SNES_MEMORY_APURAM: data = SNES::smp.apuram; break; case SNES_MEMORY_VRAM: @@ -529,7 +524,7 @@ uint8_t* snes_get_memory_data(unsigned type) break; case SNES_MEMORY_OAM: data = PPU.OAMData; - break; + break;*/ default: data = NULL; break; @@ -538,32 +533,32 @@ uint8_t* snes_get_memory_data(unsigned type) return data; } -void snes_unload_cartridge() +void retro_unload_cartridge() { } -unsigned snes_get_memory_size(unsigned type) +size_t retro_get_memory_size(unsigned type) { - unsigned size; + size_t size; switch(type) { - case SNES_MEMORY_SUFAMI_TURBO_A_RAM: - case SNES_MEMORY_CARTRIDGE_RAM: + case RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM: + case RETRO_MEMORY_SAVE_RAM: size = (unsigned) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0); if (size > 0x20000) size = 0x20000; break; - case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + case RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM: size = (unsigned) (Multi.cartType && Multi.sramSizeB ? (1 << (Multi.sramSizeB + 3)) * 128 : 0); break; - case SNES_MEMORY_CARTRIDGE_RTC: + case RETRO_MEMORY_RTC: size = (Settings.SRTC || Settings.SPC7110RTC)?20:0; break; - case SNES_MEMORY_WRAM: + case RETRO_MEMORY_SYSTEM_RAM: size = 128 * 1024; break; - case SNES_MEMORY_VRAM: + /*case SNES_MEMORY_VRAM: case SNES_MEMORY_APURAM: size = 64 * 1024; break; @@ -572,7 +567,7 @@ unsigned snes_get_memory_size(unsigned type) break; case SNES_MEMORY_OAM: size = 512 + 32; - break; + break;*/ default: size = 0; break; @@ -581,15 +576,12 @@ unsigned snes_get_memory_size(unsigned type) return size; } -void snes_set_cartridge_basename(const char*) -{} - -unsigned snes_serialize_size() +size_t retro_serialize_size() { return S9xFreezeSize(); } -bool snes_serialize(uint8_t *data, unsigned size) +bool retro_serialize(uint8_t *data, unsigned size) { if (S9xFreezeGameMem(data,size) == FALSE) return false; @@ -597,73 +589,28 @@ bool snes_serialize(uint8_t *data, unsigned size) return true; } -bool snes_unserialize(const uint8_t* data, unsigned size) +bool retro_unserialize(const uint8_t* data, unsigned size) { if (S9xUnfreezeGameMem(data,size) != SUCCESS) return false; return true; } -// Pitch 2048 -> 1024, only done once per res-change. -static void pack_frame(uint16_t *frame, int width, int height) -{ - for (int y = 1; y < height; y++) - { - uint16_t *src = frame + y * 1024; - uint16_t *dst = frame + y * 512; - - memcpy(dst, src, width * sizeof(uint16_t)); - } -} - -// Pitch 1024 -> 2048, only done once per res-change. -static void stretch_frame(uint16_t *frame, int width, int height) -{ - for (int y = height - 1; y >= 0; y--) - { - uint16_t *src = frame + y * 512; - uint16_t *dst = frame + y * 1024; - - memcpy(dst, src, width * sizeof(uint16_t)); - } -} - bool8 S9xDeinitUpdate(int width, int height) { - if (use_overscan) + if (!use_overscan) { - if (height == 224) + if (height >= SNES_HEIGHT << 1) { - memmove(GFX.Screen + (GFX.Pitch / 2) * 7, GFX.Screen, GFX.Pitch * height); - memset(GFX.Screen, 0x00, GFX.Pitch * 7); - memset(GFX.Screen + (GFX.Pitch / 2) * (7 + 224), 0, GFX.Pitch * 8); - height = 239; - } - else if (height == 448) - { - memmove(GFX.Screen + (GFX.Pitch / 2) * 15, GFX.Screen, GFX.Pitch * height); - memset(GFX.Screen, 0x00, GFX.Pitch * 15); - memset(GFX.Screen + (GFX.Pitch / 2) * (15 + 224), 0x00, GFX.Pitch * 17); - height = 478; - } - } - else // libsnes classic behavior - { - if (height == 448 || height == 478) - { - if (GFX.Pitch == 2048) - pack_frame(GFX.Screen, width, height); - GFX.Pitch = 1024; + height = SNES_HEIGHT << 1; } else { - if (GFX.Pitch == 1024) - stretch_frame(GFX.Screen, width, height); - GFX.Pitch = 2048; + height = SNES_HEIGHT; } } - s9x_video_cb(GFX.Screen, width, height); + s9x_video_cb(GFX.Screen, width, height, GFX.Pitch); return TRUE; } diff --git a/libretro/libretro.def b/libretro/libretro.def new file mode 100644 index 00000000..aa6381b4 --- /dev/null +++ b/libretro/libretro.def @@ -0,0 +1,41 @@ +LIBRARY libretro + +EXPORTS + +retro_api_version + +retro_get_system_info +retro_get_system_av_info + +retro_set_video_refresh +retro_set_audio_sample +retro_set_audio_sample_batch +retro_set_input_poll +retro_set_input_state + +retro_set_environment + +retro_set_controller_port_device + +retro_init +retro_deinit + +retro_reset +retro_run + +retro_serialize_size +retro_serialize +retro_unserialize + +retro_cheat_reset +retro_cheat_set + +retro_load_game +retro_unload_game +retro_load_game_special + +retro_unload_cartridge + +retro_get_region +retro_get_memory_data +retro_get_memory_size \ No newline at end of file diff --git a/libretro/libretro.h b/libretro/libretro.h new file mode 100644 index 00000000..3a1599e1 --- /dev/null +++ b/libretro/libretro.h @@ -0,0 +1,218 @@ +#ifndef LIBRETRO_H__ +#define LIBRETRO_H__ + +#include "snes9x.h" +#include + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +#define RETRO_API_VERSION 1 + +#define RETRO_DEVICE_MASK 0xff +#define RETRO_DEVICE_NONE 0 +#define RETRO_DEVICE_JOYPAD 1 +#define RETRO_DEVICE_MOUSE 2 +#define RETRO_DEVICE_KEYBOARD 3 +#define RETRO_DEVICE_LIGHTGUN 4 + +#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) +#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) + +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 + +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 + +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +#define RETRO_MEMORY_MASK 0xff +#define RETRO_MEMORY_SAVE_RAM 0 +#define RETRO_MEMORY_RTC 1 +#define RETRO_MEMORY_SYSTEM_RAM 2 + +#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC) + +#define RETRO_GAME_TYPE_BSX 0x101 +#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102 +#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103 +#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104 + + +// Environment commands. +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- + // Sets screen rotation of graphics. + // Is only implemented if rotation can be accelerated by hardware. + // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees + // counter-clockwise respectively. + // +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. + // +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- + // Boolean value whether or not SSNES supports frame duping, + // passing NULL to video frame callback. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- + // Interface to aquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // Mostly used for obscure, + // specific features that the user can tap into when neseccary. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 5 // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::value should contain a human readable description of the key. + // +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- + // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + +struct retro_message +{ + const char *msg; + unsigned frames; +}; + +struct retro_system_info +{ + const char *library_name; + const char *library_version; + const char *valid_extensions; + bool need_fullpath; + bool block_extract; +}; + +struct retro_game_geometry +{ + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. + + float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, + // an aspect ratio of base_width / base_height is assumed. + // A frontend could override this setting if desired. +}; + +struct retro_system_timing +{ + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info +{ + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable +{ + const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + // If NULL, obtains the complete environment string if more complex parsing is necessary. + // The environment string is formatted as key-value pairs delimited by semicolons as so: + // "key1=value1;key2=value2;..." + const char *value; // Value to be obtained. If key does not exist, it is set to NULL. +}; + +struct retro_game_info +{ + const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. + // May be NULL if rom was loaded from stdin or similar. + // SET_NEED_FULLPATH path guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. + // If the game is too big to load in one go. + // SET_NEED_FULLPATH should be used. + // In this case, data and size will be 0, + // and game can be loaded from path. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. +}; + +typedef bool (*retro_environment_t)(unsigned cmd, void *data); +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); +typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); + +typedef void (*retro_input_poll_t)(void); +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); + +void retro_init(void); +void retro_deinit(void); + +unsigned retro_api_version(void); + +void retro_get_system_info(struct retro_system_info *info); +void retro_get_system_av_info(struct retro_system_av_info *info); + +void retro_set_environment(retro_environment_t); +void retro_set_video_refresh(retro_video_refresh_t); +void retro_set_audio_sample(retro_audio_sample_t); +void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +void retro_set_input_poll(retro_input_poll_t); +void retro_set_input_state(retro_input_state_t); + +void retro_set_controller_port_device(unsigned port, unsigned device); + +void retro_reset(void); +void retro_run(void); + +size_t retro_serialize_size(void); +bool retro_serialize(void *data, size_t size); +bool retro_unserialize(const void *data, size_t size); + +void retro_cheat_reset(void); +void retro_cheat_set(unsigned index, bool enabled, const char *code); + +bool retro_load_game(const struct retro_game_info *game); + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info +); + +void retro_unload_game(void); + +unsigned retro_get_region(void); + +void *retro_get_memory_data(unsigned id); +size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libretro/link.T b/libretro/link.T new file mode 100644 index 00000000..9e82b5dd --- /dev/null +++ b/libretro/link.T @@ -0,0 +1,4 @@ +{ + global: retro_*; + local: *; +}; diff --git a/libsnes/libsnes.def b/libsnes/libsnes.def deleted file mode 100644 index c1017351..00000000 --- a/libsnes/libsnes.def +++ /dev/null @@ -1,47 +0,0 @@ -LIBRARY snes - -EXPORTS - -snes_library_id - -snes_library_revision_major -snes_library_revision_minor - -snes_set_video_refresh -snes_set_audio_sample -snes_set_input_poll -snes_set_input_state - -snes_set_environment - -snes_set_controller_port_device -snes_set_cartridge_basename - -snes_init -snes_term -snes_power -snes_reset -snes_run - -snes_serialize_size -snes_serialize -snes_unserialize - -snes_cheat_reset -snes_cheat_set - -snes_load_cartridge_normal - -snes_load_cartridge_bsx_slotted - -snes_load_cartridge_bsx - -snes_load_cartridge_sufami_turbo - -snes_load_cartridge_super_game_boy - -snes_unload_cartridge - -snes_get_region -snes_get_memory_data -snes_get_memory_size \ No newline at end of file diff --git a/libsnes/libsnes.hpp b/libsnes/libsnes.hpp deleted file mode 100644 index 78a49816..00000000 --- a/libsnes/libsnes.hpp +++ /dev/null @@ -1,1264 +0,0 @@ -#ifndef LIBSNES_HPP -#define LIBSNES_HPP - -#include "port.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/////////////////////////////////////////////////////////////////////////////// -// LIBSNES Super Nintendo emulation API -// -// Things you should know: -// - Linking against libsnes requires a C++ compiler. It can be compiled with -// a C99 compiler if you #include and if your C99 compiler's -// bool type is compatible with the bool type used by the C++ compiler used -// to compile libsnes. -// - libsnes supports exactly one emulated SNES; if you want to run two SNESes -// in a single process, you'll need to link against or dlopen() two -// different copies of the library. -// -// Typical usage of the libsnes API looks like this: -// -// 1. Call snes_init() to initialize the library. -// 2. Tell libsnes which callback should be called for each event (see the -// documentation on the individual callback types below. -// 3. Call one of the snes_load_cartridge_* functions to load cartridge data -// into the emulated SNES. -// 4. If the physical cart had any non-volatile storage, there may be data from -// a previous emulation run that needs to be loaded. Find the storage buffer -// by calling the snes_get_memory_* functions and load any saved data into -// it. -// 5. Call snes_set_controller_port_device() to connect appropriate controllers -// to the emulated SNES. -// 6. Call snes_get_region() to determine the intended screen refresh rate for -// this cartridge.. -// 7. Call snes_run() to emulate a single frame. Before snes_run() returns, the -// installed callbacks will be called - possibly multiple times. -// 8. When you're done, call snes_term() to free all memory allocated -// associated with the emulated SNES. -// -/////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -// Constants {{{ - -// These constants represent the two controller ports on the front of the SNES, -// for use with the snes_set_controller_port_device() function and the -// snes_input_state_t callback. -#define SNES_PORT_1 0 -#define SNES_PORT_2 1 - -// These constants represent the different kinds of controllers that can be -// connected to a controller port, for use with the -// snes_set_controller_port_device() function and the snes_input_state_t -// callback. -#define SNES_DEVICE_NONE 0 -#define SNES_DEVICE_JOYPAD 1 -#define SNES_DEVICE_MULTITAP 2 -#define SNES_DEVICE_MOUSE 3 -#define SNES_DEVICE_SUPER_SCOPE 4 -#define SNES_DEVICE_JUSTIFIER 5 -#define SNES_DEVICE_JUSTIFIERS 6 - -// These constants represent the button and axis inputs on various controllers, -// for use with the snes_input_state_t callback. -#define SNES_DEVICE_ID_JOYPAD_B 0 -#define SNES_DEVICE_ID_JOYPAD_Y 1 -#define SNES_DEVICE_ID_JOYPAD_SELECT 2 -#define SNES_DEVICE_ID_JOYPAD_START 3 -#define SNES_DEVICE_ID_JOYPAD_UP 4 -#define SNES_DEVICE_ID_JOYPAD_DOWN 5 -#define SNES_DEVICE_ID_JOYPAD_LEFT 6 -#define SNES_DEVICE_ID_JOYPAD_RIGHT 7 -#define SNES_DEVICE_ID_JOYPAD_A 8 -#define SNES_DEVICE_ID_JOYPAD_X 9 -#define SNES_DEVICE_ID_JOYPAD_L 10 -#define SNES_DEVICE_ID_JOYPAD_R 11 - -#define SNES_DEVICE_ID_MOUSE_X 0 -#define SNES_DEVICE_ID_MOUSE_Y 1 -#define SNES_DEVICE_ID_MOUSE_LEFT 2 -#define SNES_DEVICE_ID_MOUSE_RIGHT 3 - -#define SNES_DEVICE_ID_SUPER_SCOPE_X 0 -#define SNES_DEVICE_ID_SUPER_SCOPE_Y 1 -#define SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER 2 -#define SNES_DEVICE_ID_SUPER_SCOPE_CURSOR 3 -#define SNES_DEVICE_ID_SUPER_SCOPE_TURBO 4 -#define SNES_DEVICE_ID_SUPER_SCOPE_PAUSE 5 - -#define SNES_DEVICE_ID_JUSTIFIER_X 0 -#define SNES_DEVICE_ID_JUSTIFIER_Y 1 -#define SNES_DEVICE_ID_JUSTIFIER_TRIGGER 2 -#define SNES_DEVICE_ID_JUSTIFIER_START 3 - -// These constants will be returned by snes_get_region(), representing the -// region of the last loaded cartridge. -#define SNES_REGION_NTSC 0 -#define SNES_REGION_PAL 1 - -// These constants represent the kinds of non-volatile memory a SNES cartridge -// might have, for use with the snes_get_memory_* functions. -#define SNES_MEMORY_CARTRIDGE_RAM 0 -#define SNES_MEMORY_CARTRIDGE_RTC 1 -#define SNES_MEMORY_BSX_RAM 2 -#define SNES_MEMORY_BSX_PRAM 3 -#define SNES_MEMORY_SUFAMI_TURBO_A_RAM 4 -#define SNES_MEMORY_SUFAMI_TURBO_B_RAM 5 -#define SNES_MEMORY_GAME_BOY_RAM 6 -#define SNES_MEMORY_GAME_BOY_RTC 7 - -// These constants represent the various kinds of volatile storage the SNES -// offers, to allow libsnes clients to implement things like cheat-searching -// and certain kinds of debugging. They are for use with the snes_get_memory_* -// functions. -#define SNES_MEMORY_WRAM 100 -#define SNES_MEMORY_APURAM 101 -#define SNES_MEMORY_VRAM 102 -#define SNES_MEMORY_OAM 103 -#define SNES_MEMORY_CGRAM 104 - -// SSNES extension. Not required to be implemented for a working implementation. -#define SNES_ENVIRONMENT_GET_FULLPATH 0 // const char ** -- Full path of game loaded. -#define SNES_ENVIRONMENT_SET_GEOMETRY 1 // const struct snes_geometry * -- Window geometry information for the system/game. -#define SNES_ENVIRONMENT_SET_PITCH 2 // const unsigned * -- Pitch of game image. -#define SNES_ENVIRONMENT_GET_OVERSCAN 3 // bool * -- Boolean value whether or not the implementation should use overscan. -#define SNES_ENVIRONMENT_SET_TIMING 4 // const struct snes_system_timing * -- Set exact timings of the system. - // Used primarily for video recording. - -struct snes_geometry -{ - unsigned base_width; // Nominal video width of system. - unsigned base_height; // Nominal video height of system. - unsigned max_width; // Maximum possible width of system. - unsigned max_height; // Maximum possible height of system. -}; - -struct snes_system_timing -{ - double fps; - double sample_rate; -}; - -typedef bool (*snes_environment_t)(unsigned cmd, void *data); - -// Must be called before calling snes_init(). -void snes_set_environment(snes_environment_t); -//// - - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Callback types {{{ -// -// In order to deliver controller input to the emulated SNES, and retrieve -// video frames and audio samples, you will need to register callbacks. - -// snes_audio_sample_t: -// -// This callback delivers a stereo audio sample pair generated by the -// emulated SNES. -// -// This function is called once for every audio frame (one sample from left -// and right channels). The SNES generates audio samples at a rate of about -// 32040Hz (varies from unit to unit). -// -// Because the SNES generates video at exactly 59.94fps and most computer -// monitors only support a 60fps refresh rate, real-time emulation needs to -// run slightly fast so that each computer frame displays one emulated SNES -// frame. Because the emulation runs slightly fast, and because most -// consumer audio hardware does not play audio at precisely the requested -// sample rate, you'll likely need to let the end-user tweak the effective -// sample rate by 100Hz or so in either direction. -// -// Although the parameters are declared as unsigned for historical reasons, -// the data they contain is actually signed. To work with the audio (e.g. -// resample), you will need to reinterpret the sample value: -// -// int16_t real_left = *(int16_t*)(&left); -// -// Parameters: -// -// left: -// A signed 16-bit integer containing the next audio sample from the -// left audio channel. Yes, it's declared as unsigned for historical -// reasons. -// -// right: -// A signed 16-bit integer containing the next audio sample from the -// right audio channel. Yes, it's declared as unsigned for historical -// reasons. -// - -typedef void (*snes_audio_sample_t)(uint16_t left, uint16_t right); - - -// snes_video_refresh_t: -// -// This callback delivers a single SNES frame, generated by the emulated -// SNES. The same memory buffer may be re-used later, so take a copy of the -// data if you want to refer to it after your callback returns. -// -// The framebuffer is an array of unsigned 16-bit pixels, in a somewhat -// complicated format. A quick refresher on SNES video modes: -// - The basic SNES video-mode renders 256 pixels per scanline for a total -// of 224 scanlines. -// - When "overscan" mode is enabled, the SNES renders a few extra -// scanlines at the end of the frame, for a total of 239 scanlines. -// - When "hi-res" mode is enabled, the SNES speeds up its pixel rendering -// to fit 512 pixels per scanline. -// - Normally the SNES renders its pixels to one field of the interlaced -// NTSC signal, but if "interlaced" mode is enabled the SNES renders -// a second set of scanlines inbetween the regular set, for a total of -// 448 (normal) or 478 (overscan) scanlines. -// -// Thus, the framebuffer memory layout for a standard 256x240 frame looks -// something like this (note that 'height' has been reduced to 4 or 8 for -// these examples): -// -// 0 1024b -// ,---------------------------------------. -// |====== width ======|...................| -. -// |.......................................| | -// |===================|...................| | -// |.......................................| +- height = 4 -// |===================|...................| | -// |.......................................| | -// |===================|...................| | -// |.......................................| -' -// `---------------------------------------' -// -// A hi-res frame would look like this: -// -// 0 1024b -// ,---------------------------------------. -// |================ width ================| -. -// |.......................................| | -// |=======================================| | -// |.......................................| +- height = 4 -// |=======================================| | -// |.......................................| | -// |=======================================| | -// |.......................................| -' -// `---------------------------------------' -// -// An interlaced frame would look like this: -// -// 0 1024b -// ,---------------------------------------. -// |====== width ======|...................| -. -// |===================|...................| | -// |===================|...................| | -// |===================|...................| +- height = 8 -// |===================|...................| | -// |===================|...................| | -// |===================|...................| | -// |===================|...................| -' -// `---------------------------------------' -// -// And of course a hi-res, interlaced frame would look like this: -// -// 0 1024b -// ,---------------------------------------. -// |================ width ================| -. -// |=======================================| | -// |=======================================| | -// |=======================================| |+- height = 8 -// |=======================================| | -// |=======================================| | -// |=======================================| | -// |=======================================| -' -// `---------------------------------------' -// -// More succinctly: -// - the buffer begins at the top-left of the frame -// - the first "width" bytes contain the first scanline. -// - if the emulated SNES is in an interlaced video-mode (that is, if the -// "height" parameter" is 448 or 478) then the second scanline begins at -// an offset of 1024 bytes (512 pixels) after the first. -// - otherwise the second scanline begins at an offset of 2048 bytes (1024 -// pixels) after the first. -// - there are "height" scanlines in total. -// -// Each pixel contains a 15-bit RGB tuple: 0RRRRRGGGGGBBBBB (XRGB1555) -// -// Example code: -// -// void pack_frame (uint16_t * restrict out, const uint16_t * restrict in, -// unsigned width, unsigned height) -// { -// // Normally our pitch is 2048 bytes. -// int pitch_pixels = 1024; -// // If we have an interlaced mode, pitch is 1024 bytes. -// if ( height == 448 || height == 478 ) -// pitch_pixels = 512; -// -// for ( int y = 0; y < height; y++ ) -// { -// const uint16_t *src = in + y * pitch_pixels; -// uint16_t *dst = out + y * width; -// -// memcpy(dst, src, width * sizeof(uint16_t)); -// } -// } -// -// Parameters: -// -// data: -// a pointer to the beginning of the framebuffer described above. -// -// width: -// the width of the frame, in pixels. -// -// height: -// the number of scanlines in the frame. - -typedef void (*snes_video_refresh_t)(const uint16_t *data, unsigned width, - unsigned height); - -// snes_input_poll_t: -// -// This callback requests that you poll your input devices for events, if -// required. -// -// Generally called once per frame before the snes_input_state_t callback is -// called. -// - -typedef void (*snes_input_poll_t)(void); - -// snes_input_state_t: -// -// This callback asks for information about the state of a particular input. -// -// The callback may be called multiple times per frame with the same -// parameters. -// -// The callback might not be called at all, if the software running in the -// emulated SNES does not try to probe the controllers. -// -// The callback will not be called for a particular port if DEVICE_NONE is -// connected to it. -// -// If you wish to emulate any kind of turbo-fire, etc. then you will need to -// put that logic into this callback. -// -// Parameters: -// -// port: -// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which -// controller port you should report. -// -// device: -// One of the SNES_DEVICE_* constants describing which type of device -// is currently connected to the given port. -// -// index: -// A number describing which of the devices connected to the port is -// being reported. It's only useful for SNES_DEVICE_MULTITAP and -// SNES_DEVICE_JUSTIFIERS - for other device types, this parameter is -// always 0. -// -// id: -// One of the SNES_DEVICE_ID_* constants for the given device, -// describing which button or axis is being reported (for -// SNES_DEVICE_MULTITAP, use the SNES_DEVICE_ID_JOYPAD_* IDs; for -// SNES_DEVICE_JUSTIFIERS use the SNES_DEVICE_ID_JUSTIFIER_* IDs.). -// -// Returns: -// -// An integer representing the state of the described button or axis. -// -// - If it represents a digital input such as SNES_DEVICE_ID_JOYPAD_B or -// SNES_DEVICE_ID_MOUSE_LEFT), return 1 if the button is pressed, and -// 0 otherwise. -// - If "id" is SNES_DEVICE_ID_MOUSE_X or SNES_DEVICE_ID_MOUSE_Y then -// return the relative movement of the mouse during the current frame; -// values outside the range -127 to +127 will be clamped. -// - If "id" is one of the light-gun axes (such as -// SNES_DEVICE_ID_JUSTIFIER_Y or SNES_DEVICE_ID_SUPER_SCOPE_X), you -// should return the relative movement of the pointing device during the -// current frame. - -typedef int16_t (*snes_input_state_t)(bool port, unsigned device, - unsigned index, unsigned id); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// libsnes setup {{{ -// -// These functions are used to get information about and manipulate the libsnes -// library itself, not the emulated SNES it implements. - -// snes_library_id: -// -// Returns a human readable string describing this libsnes implementation. -// It is not supposed to be parsed or used in any other way than being -// printed to screen on request by user or otherwise. -// -// Returns: -// -// A human-readable string describing this implementation. - -const char* snes_library_id(void); - - -// snes_library_revision_major: -// -// Returns the major API version of this libsnes implementation. -// -// This number is increased every time there is a compatibility-breaking -// change to the libsnes API. At startup, your program should call this -// function and compare the return value to the major API version the -// program was designed to work with. If they are different, your program -// will (very likely) not work with this libsnes implementation. -// -// For example, if your program was designed to work with the libsnes API -// whose major.minor revision was 1.5, and this function returns a major -// version of 2, you have a problem. -// -// Returns: -// -// An integer, the major API version of this libsnes implementation. - -unsigned snes_library_revision_major(void); - -// snes_library_revision_minor: -// -// Returns the minor API version of this libsnes implementation. -// -// This number is increased every time there is a backwards-compatible -// change to the libsnes API. At startup, your program should call this -// function and compare the return value to the minor API version the -// program was designed to work with. If the return value is less than the -// expected minor version, your program will (very likely) not work with -// this libsnes implementation. -// -// For example, if your program was designed to work with the libsnes API -// whose major.minor revision was 1.5, and this libsnes implementation's -// major.minor version is 1.3, it's probably missing features you require. -// On the other hand, if this libsnes implementation's major.minor version -// is 1.9, it probably has extra fancy features you don't need to worry -// about. -// -// Returns: -// -// An integer, the minor API version of this libsnes implementation. - -unsigned snes_library_revision_minor(void); - -// snes_init: -// -// Initializes the libsnes implementation. -// -// This function must be called exactly once before any other library -// functions are called. - -void snes_init(void); - -// snes_term: -// -// Shuts down the libsnes implementation. -// -// This function must be called exactly once. Once called, you should not -// call any other libsnes functions besides (perhaps) snes_init(). - -void snes_term(void); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Callback registration {{{ -// -// Note that all callbacks should be set up before snes_run() is called for the -// first time. - -// snes_set_video_refresh: -// -// Sets the callback that will receive new video frames. -// -// See the documentation for snes_video_refresh_t for details. -// -// Parameters: -// -// A pointer to a function matching the snes_video_refresh_t call -// signature. - -void snes_set_video_refresh(snes_video_refresh_t); - -// snes_set_audio_sample -// -// Sets the callback that will receive new audio sample pairs. -// -// See the documentation for snes_audio_sample_t for details. -// -// Parameters: -// -// A pointer to a function matching the snes_audio_sample_t call -// signature. - -void snes_set_audio_sample(snes_audio_sample_t); - -// snes_set_input_poll: -// -// Sets the callback that will be notified to poll input devices. -// -// See the documentation for snes_input_poll_t for details. -// -// Parameters: -// -// A pointer to a function matching the snes_input_poll_t call signature. - -void snes_set_input_poll(snes_input_poll_t); - -// snes_set_input_state: -// -// Sets the callback that will be used to read input device state. -// -// See the documentation for snes_input_state_t for details. -// -// Parameters: -// -// A pointer to a function matching the snes_input_state_t call signature. - -void snes_set_input_state(snes_input_state_t); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// SNES operation {{{ -// -// Functions for manipulating the emulated SNES. - -// snes_set_controller_port_device: -// -// Sets the input device connected to a given controller port. -// -// Connecting a device to a port implicitly removes any device previously -// connected to that port. To remove a device without connecting a new one, -// pass DEVICE_NONE as the device parameter. From this point onward, the -// callback passed to set_input_state_cb() will be called with the -// appropriate device, index and id parameters. -// -// If this function is never called, the default is to have a DEVICE_JOYPAD -// connected to both ports. -// -// Calling this callback from inside the set_input_state_cb() has undefined -// results, so don't do that. -// -// Parameters: -// -// port: -// One of the constants SNES_PORT_1 or SNES_PORT_2, describing which -// controller port is being configured. -// -// device: -// One of the SNES_DEVICE_* constants describing which type of device -// should be connected to the given port. Note that some devices can -// only be connected to SNES_PORT_2. Attempting to connect -// a port-2-only device to SNES_PORT_1 has undefined results. -// -// These devices work in either port: -// - SNES_DEVICE_NONE: No device is connected to this port. -// - SNES_DEVICE_JOYPAD: A standard SNES gamepad. -// - SNES_DEVICE_MULTITAP: A multitap controller, which acts like -// 4 SNES_DEVICE_JOYPADs. Your input state callback will be -// passed "id" parameters between 0 and 3, inclusive. -// - SNES_DEVICE_MOUSE: A SNES mouse controller, as shipped with -// Mario Paint. -// -// These devices only work properly when connected to port 2: -// - SNES_DEVICE_SUPER_SCOPE: A Nintendo Super Scope light-gun -// device. -// - SNES_DEVICE_JUSTIFIER: A Konami Justifier light-gun device. -// - SNES_DEVICE_JUSTIFIERS: Two Konami Justifier light-gun -// devices, daisy-chained together. Your input state callback -// will be passed "id" parameters 0 and 1. - -void snes_set_controller_port_device(bool port, unsigned device); - -// snes_power: -// -// Turns the emulated console off and back on. -// -// This functionality is sometimes called "hard reset" and guarantees that -// all hardware state is reset to a reasonable default. -// -// Before bsnes v070r07, this resets the controller ports to both contain -// SNES_DEVICE_JOYPADs. -// -// This requires that a cartridge is loaded. - -void snes_power(void); - -// snes_reset: -// -// Presses the "reset" button on the emulated SNES. -// -// This functionality is sometimes called "soft reset". Most hardware state -// is reset to a reasonable befault, but not all. -// -// As of bsnes v073r01, this function (as a side-effect) resets the -// controller ports to both contain SNES_DEVICE_JOYPADs. -// -// This requires that a cartridge is loaded. - -void snes_reset(void); - -// snes_run(): -// -// Runs the emulated SNES until the end of the next video frame. -// -// Usually causes each registered callback to be called before returning. -// -// This function will run as fast as possible. It is up to the caller to -// make sure that the game runs at the intended speed. -// -// For optimal A/V sync, make sure that the audio callback never blocks for -// longer than a frame (approx 16ms for NTSC, 20ms for PAL) -// -// Optimally, it should never block for more than a few ms at a time. - -void snes_run(void); - -// snes_get_region(): -// -// Determines the intended frame-rate of the loaded cartridge. -// -// The two main SNES hardware variants are the US/Japan variant, designed -// for NTSC output, and the European variant, designed for PAL output. -// However, the world is not quite so tidy as that, and there are countries -// like Brazil that use PAL output at NTSC frame-rates. -// -// For historical reasons this function is named snes_get_region(), but -// effectively the only information you can reliably infer is the -// frame-rate. -// -// Returns: -// -// One of the SNES_REGION_* constants. SNES_REGION_PAL means 50fps, -// SNES_REGION_NTSC means 60fps. - -bool snes_get_region(void); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Save state support {{{ -// -// libsnes has the ability to save the current emulation state and restore it -// at a later time. -// -// Note 1: It is impossible to reliably restore the *exact* state, although the -// difference is only a few cycles. If you demand the ability to reliably -// restore state, call snes_serialize() after each frame to ensure the emulated -// SNES is in a state that can be reliably restored. -// -// Note 2: The save state information is specific to a particular cartridge -// loaded into a particular version of a particular libsnes implementation. -// Unfortunately, there is not yet a way to determine whether a given save -// state is compatible with a given libsnes implementation, other than by -// loading it. However, if snes_serialize_size() does not match the size of an -// old save state, that's a strong hint that something has incompatibly -// changed. - -// snes_serialize_size: -// -// Determines the minimum size of a save state. -// -// This value can change depending on the features used by the loaded -// cartridge, and the version of the libsnes implementation used. -// -// Returns: -// -// An integer representing the number of bytes required to store the -// current emulation state. - -unsigned snes_serialize_size(void); - -// snes_serialize: -// -// Serialize the current emulation state to a buffer. -// -// If the allocated buffer is smaller than the size returned by -// snes_serialize_size(), serialization will fail. If the allocated buffer -// is larger, only the first snes_serialize_size() bytes will be written to. -// -// The resulting buffer may be stored, and later passed to -// snes_unserialize() to restore the saved emulation state. -// -// Parameters: -// -// data: -// A pointer to an allocated buffer of memory. -// -// size: -// The size of the buffer pointed to by "data". Should be greater than -// or equal to the value returned by snes_serialize_size(). -// -// Returns: -// -// A boolean; True means the emulation state was serialized successfully, -// False means a problem was encountered. - -bool snes_serialize(uint8_t *data, unsigned size); - -// snes_unserialize: -// -// Unserialize the emulation state from a buffer. -// -// If the serialization data in the buffer does not appear to be compatible -// with the current libsnes implementation, the function returns False and -// the current emulation state is not modified. -// -// Parameters: -// -// data: -// A pointer to an allocated buffer of memory. -// -// size: -// The size of the buffer pointed to by "data". Should be greater than -// or equal to the value returned by snes_serialize_size(). -// -// Returns: -// -// A boolean; True means the emulation state was loaded successfully, -// False means a problem was encountered. - -bool snes_unserialize(const uint8_t *data, unsigned size); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Cheat support {{{ -// -// libsnes does not include any kind of cheat management API; the intention is -// that any change to the set of applied cheats will cause the containing -// application to call snes_cheat_reset() then apply the new set of cheats with -// snes_cheat_set(). -// -// Any currently-applied cheats are discarded when a new cartridge is loaded. - -// snes_cheat_reset: -// -// Discards all cheat codes applied to the emulated SNES. - -void snes_cheat_reset(void); - -// snes_cheat_set: -// -// Apply a sequence of cheat codes to the emulated SNES. -// -// Since a "cheat code" is basically an instruction to override the value of -// a particular byte in the SNES' memory, more complex cheats may require -// several individual codes applied at once. There's no effective difference -// between applying these codes in a group with one call to -// snes_cheat_set(), or applying them one at a time with individual calls. -// However, most cheat databases will have a collection of available cheats -// for each game, where each item in the collection has a description and -// a sequence of codes to be applied as a unit. This API makes it easy to -// present the list of descriptions to the user, and apply each cheat the -// user selects. -// -// Parameters: -// -// index: -// The given cheat code will be stored at this index in the array of -// applied cheats. If a cheat already exists at this location, it will -// be replaced by the new cheat. If the index is larger than any -// previously specififed index, the array will be resized to -// accommodate. -// -// enabled: -// True means that the cheat will actually be applied, False means -// that the cheat will have no effect. There is no way to enable or -// disable a cheat after it has been added, other than to call -// snes_cheat_set() a second time with the same values for "index" and -// "code". -// -// code: -// A string containing a sequence of cheat codes separated by '+' -// characters. Any spaces in the string will be removed before -// parsing. -// -// Each code in the sequence must be in either GameGenie format -// ("1234-ABCD") or ProActionReplay format ("1234AB:CD" or -// "1234ABCD"). - -void snes_cheat_set(unsigned index, bool enabled, const char *code); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Cartridge loading and unloading {{{ -// -// Before calling snes_run(), a cartridge must be loaded into the emulated SNES -// so that it has code to run. -// -// Loading a cartridge of any kind calls snes_cheat_reset() as a side-effect. - -// snes_load_cartridge_normal: -// -// Load a normal ROM image into the emulated SNES. -// -// Parameters: -// -// rom_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes where the ROM image is mapped into the SNES address -// space, what special chips it uses (and where they're mapped), etc. -// -// If NULL, libsnes will guess a memory map. The guessed memory map -// should be correct for all licenced games in all regions. -// -// rom_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image. -// -// rom_size: -// The length of the rom_data array, in bytes. -// -// Returns: -// -// A boolean; True means the cartridge was loaded correctly, False means -// an error occurred. - -bool snes_load_cartridge_normal( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size -); - -// snes_load_cartridge_bsx: -// -// Load a BS-X base cart image, optionally with a memory pack. -// -// The Satellaview system, abbreviated "BS-X" for unclear reasons, was an -// addon for the Super Famicom that connected it to the St. GIGA satellite -// network. The network would broadcast games at a particular time, and -// users could download them to replaceable memory packs. -// -// For more information, see http://en.wikipedia.org/wiki/Satellaview -// -// Parameters: -// -// rom_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes where the BS-X base cartridge ROM image is mapped -// into the SNES address space. -// -// If NULL, libsnes will guess a memory map. The guessed memory map -// should be correct for all known BS-X base cartridge images. -// -// rom_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image of the BS-X base cartridge. -// -// The BS-X base cartridge is named "BS-X - Sore wa Namae o Nusumareta -// Machi no Monogatari" in some SNES game databases. -// -// rom_size: -// The length of the rom_data array, in bytes. -// -// bsx_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes the BS-X memory pack. -// -// This parameter is currently ignored and should be passed as NULL. -// -// bsx_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless image of the BS-X memory-pack. -// -// If NULL, libsnes will behave as though no memory-pack were inserted -// into the base cartridge. -// -// bsx_size: -// The length of the bsx_data array, in bytes. -// -// Returns: -// -// A boolean; True means the cartridge was loaded correctly, False means -// an error occurred. - -bool snes_load_cartridge_bsx( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -); - -// snes_load_cartridge_bsx_slotted: -// -// Load a BS-X slotted cartridge, optionally with a memory pack. -// -// A BS-X slotted cartridge is an ordinary SNES cartridge, with a slot in -// the top that accepts the same memory packs used by the BS-X base -// cartridge. -// -// Parameters: -// -// rom_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes where the ROM image is mapped into the SNES address -// space, what special chips it uses (and where they're mapped), etc. -// -// If NULL, libsnes will guess a memory map. The guessed memory map -// should be correct for all licenced games in all regions. -// -// rom_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image. -// -// rom_size: -// The length of the rom_data array, in bytes. -// -// bsx_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes the BS-X memory pack. -// -// This parameter is currently ignored and should be passed as NULL. -// -// bsx_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless image of the BS-X memory-pack. -// -// If NULL, libsnes will behave as though no memory-pack were inserted -// into the base cartridge. -// -// bsx_size: -// The length of the bsx_data array, in bytes. -// -// Returns: -// -// A boolean; True means the cartridge was loaded correctly, False means -// an error occurred. - -bool snes_load_cartridge_bsx_slotted( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *bsx_xml, const uint8_t *bsx_data, unsigned bsx_size -); - -// snes_load_cartridge_sufami_turbo: -// -// Load a SuFami Turbo base cart image, optionally with game packs. -// -// The SuFami Turbo was a cartridge available for the Super Famicom, created -// by Bandai, with two slots in the top designed to accept special -// mini-cartridges. The cartridge in Slot A was the cartridge that actually -// ran, while the cartridge in Slot B was made available to the Slot -// A cartridge, enabling sharing of save-game data or using characters from -// one game in another. -// -// For more information, see: http://en.wikipedia.org/wiki/Sufami_Turbo -// -// Parameters: -// -// rom_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes where the SuFami Turbo base cartridge ROM image is -// mapped into the SNES address space. -// -// If NULL, libsnes will guess a memory map. The guessed memory map -// should be correct for all known SuFami Turbo base cartridge images. -// -// rom_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image of the SuFami Turbo base -// cartridge. -// -// The SuFami Turbo base cartridge is named "Sufami Turbo" in some -// SNES game databases. -// -// rom_size: -// The length of the rom_data array, in bytes. -// -// sta_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes the Sufami Turbo cartridge in Slot A. -// -// This parameter is currently ignored and should be passed as NULL. -// -// sta_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image of the SuFami Turbo cartridge -// in Slot A. -// -// This is the cartridge that will be executed by the SNES. -// -// If NULL, libsnes will behave as though no cartridge were inserted -// into the Slot A. -// -// sta_size: -// The length of the sta_data array, in bytes. -// -// stb_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes the Sufami Turbo cartridge in Slot B. -// -// This parameter is currently ignored and should be passed as NULL. -// -// stb_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image of the SuFami Turbo cartridge -// in Slot B. -// -// The data in this cartridge will be made available to the cartridge -// in Slot A. -// -// If NULL, libsnes will behave as though no cartridge were inserted -// into Slot B. -// -// stb_size: -// The length of the stb_data array, in bytes. -// -// Returns: -// -// A boolean; True means the cartridge was loaded correctly, False means -// an error occurred. - -bool snes_load_cartridge_sufami_turbo( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *sta_xml, const uint8_t *sta_data, unsigned sta_size, - const char *stb_xml, const uint8_t *stb_data, unsigned stb_size -); - -// snes_load_cartridge_super_game_boy: -// -// Load a Super Game Boy base cart, optionally with a Gameboy cartridge. -// -// The Super Game Boy was a cartridge available for the Super Famicom and -// Super Nintendo that accepted ordinary (original) Gameboy cartridges and -// allowed the user to play them with a Super Nintendo controller, on a TV. -// It extended the orginal Gameboy hardware in a few ways, including the -// ability to display games in various palettes (rather than strictly -// monochrome), to display a full-colour border image around the Gameboy -// video output, or even run native SNES code to enhance the game. -// -// For more information, see: http://en.wikipedia.org/wiki/Super_Game_Boy -// -// Up until bsnes v073, loading Super Game Boy cartridges only works if the -// libsupergameboy library from the bsnes release is installed. bsnes v074 -// includes a custom Gameboy emulation core, and external code is no longer -// required. -// -// Parameters: -// -// rom_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes where the Super Game Boy base cartridge ROM image is -// mapped into the SNES address space. -// -// If NULL, libsnes will guess a memory map. The guessed memory map -// should be correct for all known Super Game Boy base cartridge -// images. -// -// rom_data: -// A pointer to a byte array containing the uncompressed, -// de-interleaved, headerless ROM image of the Super Game Boy base -// cartridge. -// -// Appropriate base cartridge images are named "Super Game Boy" or -// "Super Game Boy 2" in some SNES game databases. -// -// rom_size: -// The length of the rom_data array, in bytes. -// -// dmg_xml: -// A pointer to a null-terminated string containing an XML memory map -// that describes the inserted Gameboy cartridge. -// -// If NULL, libsnes will guess a memory map. The guesed memory map -// should be correct for all licensed original Gameboy games in all -// regions. -// -// dmg_data: -// A pointer to a byte array containing the uncompressed, headerless -// ROM image of the inserted Gameboy cartridge. -// -// If NULL, libsnes will behave as though no cartridge were inserted. -// -// dmg_size: -// The length of the dmg_size array, in bytes. -// -// Returns: -// -// A boolean; True means the cartridge was loaded correctly, False means -// an error occurred. - -bool snes_load_cartridge_super_game_boy( - const char *rom_xml, const uint8_t *rom_data, unsigned rom_size, - const char *dmg_xml, const uint8_t *dmg_data, unsigned dmg_size -); - -// snes_set_cartridge_basename: -// -// Set the location and name of the loaded cartridge. -// -// libsnes uses this information to locate additional resources the -// cartridge might require. Currently, these resources include: -// -// - The MSU-1 data pack and associated audio tracks, if the cartridge makes -// use of bsnes' MSU-1 special-chip. -// - The serial-port data receiving library, if the cartridge makes uses of -// bsnes' serial-data-over-controller-port feature. -// -// Parameters: -// -// basename: -// The path and basename of the loaded cartridge. For example, if the -// full path to the loaded cartridge is "/path/to/filename.sfc", this -// parameter should be set to "/path/to/filename". - -void snes_set_cartridge_basename(const char *basename); - -// snes_unload_cartridge: -// -// Unloads the currently loaded cartridge from the emulated SNES. -// -// You will be unable to call snes_run() until another cartridge is loaded. - -void snes_unload_cartridge(void); - -////////////////////////////////////////////////////////////////////////////}}} - -/////////////////////////////////////////////////////////////////////////////// -// Volatile and non-volatile storage {{{ -// -// Certain SNES cartridges include non-volatile storage or other kinds of data -// that would persist after the SNES is turned off. libsnes exposes this -// information via the snes_get_memory_data() and snes_get_memory_size() -// functions. Since version 1.2 of the libsnes API, libsnes also exposes the -// contents of volatile storage such as WRAM and VRAM. -// -// After a cartridge is loaded, call snes_get_memory_size() and -// snes_get_memory_data() with the various SNES_MEMORY_* constants to determine -// which kinds of non-volatile storage the cartridge supports - unsupported -// storage types will have a size of 0 and the data pointer NULL. -// -// If you have non-volatile storage data from a previous run, you can memcpy() -// the data from your storage into the buffer described by the data and size -// values before calling snes_run(). Do not load non-volatile storage data if -// the size of the data you have is different from the size returned by -// snes_get_memory_size(). -// -// Before calling snes_unload_cartridge(), you should copy the contents of the -// relevant storage buffers into a file (or some non-volatile storage of your -// own) so that you can load it the next time you load the same cartridge into -// the emulated SNES. Do not call free() on the storage buffers; they will be -// handled by libsnes. Note: It is not necessary to store the contents of -// volatile storage; the emulated SNES expects information in volatile storage -// to be lost (hence the name 'volatile'). -// -// Because non-volatile storage is read and written by the software running on -// the emulated SNES, it should be compatible between different versions of -// different emulators running on different platforms, unlike save states. -// -// The various kinds of non-volatile storage and their uses are: -// -// SNES_MEMORY_CARTRIDGE_RAM: -// Standard battery-backed static RAM (SRAM). Traditionally, the SRAM for -// a ROM image named "foo.sfc" is stored in a file named "foo.srm" beside -// it. -// -// SNES_MEMORY_CARTRIDGE_RTC: -// Real-time clock data. Traditionally, the RTC data for a ROM image named -// "foo.sfc" is stored in a file named "foo.rtc" beside it. -// -// SNES_MEMORY_BSX_RAM: -// RAM data used with the BS-X base cartridge. -// -// SNES_MEMORY_BSX_PRAM: -// PRAM data used with the BS-X base cartridge. -// -// SNES_MEMORY_SUFAMI_TURBO_A_RAM: -// RAM data stored in the mini-cartridge inserted into Slot A of the -// SuFami Turbo base cartridge. -// -// SNES_MEMORY_SUFAMI_TURBO_B_RAM: -// RAM data stored in the mini-cartridge inserted into Slot B of the -// SuFami Turbo base cartridge. -// -// SNES_MEMORY_GAME_BOY_RAM: -// Standard battery-backed static RAM (SRAM) in the Gameboy cartridge -// inserted into the Super Game Boy base cartridge. Not all Gameboy games -// have SRAM. -// -// SNES_MEMORY_GAME_BOY_RTC: -// Real-time clock data in the Gameboy cartridge inserted into the Super -// Game Boy base cartridge. Not all Gameboy games have an RTC. -// -// The various kinds of volatile storage are: -// -// SNES_MEMORY_WRAM: -// Working RAM, accessible by the CPU. SNES software tends to keep runtime -// information in here; games' life-bars and inventory contents and so -// forth are in here somewhere. -// -// SNES_MEMORY_APURAM: -// RAM accessible by the Audio Processing Unit. Contains audio samples, -// music data and the code responsible for feeding the right notes to the -// DSP at the right times. -// -// SNES_MEMORY_VRAM: -// Video RAM. Stores almost everything related to video output, including -// the patterns used for each tile and sprite, tilemaps for each -// background. The exact format used depends on the current video mode of -// the emulated SNES. -// -// SNES_MEMORY_OAM: -// Object Attribute Memory. Stores the location, orientation and priority -// of all the sprites the SNES displays. -// -// SNES_MEMORY_CGRAM: -// Color Generator RAM. Contains the colour palettes used by tiles and -// sprites. Each palette entry is stored in a 16-bit int, in the standard -// XBGR1555 format. - -// snes_get_memory_data: -// -// Returns a pointer to the given non-volatile storage buffer. -// -// This requires that a cartridge is loaded. -// -// Parameters: -// -// id: -// One of the SNES_MEMORY_* constants. -// -// Returns: -// -// A pointer to the memory buffer used for storing the given type of data. -// The size of the buffer can be obtained from snes_get_memory_size(). -// -// If NULL, the loaded cartridge does not store the given type of data. - -uint8_t* snes_get_memory_data(unsigned id); - -// snes_get_memory_size: -// -// Returns the size of the given non-volatile storage buffer. -// -// This requires that a cartridge is loaded. -// -// Parameters: -// -// id: -// One of the SNES_MEMORY_* constants. -// -// Returns: -// -// The size of the memory buffer used for storing the given type of data. -// A pointer to the buffer can be obtained from snes_get_memory_data(). -// -// If 0, the loaded cartridge does not store the given type of data. - -unsigned snes_get_memory_size(unsigned id); - -////////////////////////////////////////////////////////////////////////////}}} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libsnes/link.T b/libsnes/link.T deleted file mode 100644 index 432292c1..00000000 --- a/libsnes/link.T +++ /dev/null @@ -1,4 +0,0 @@ -{ - global: snes_*; - local: *; -}; From 9551890d0ddc13d7bc08311884a731df9ee4bbc4 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 15 Apr 2012 21:44:25 +0200 Subject: [PATCH 114/130] libretro: always show overscan are if overscan is enabled --- libretro/libretro.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 50a6a875..f55d418e 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -609,6 +609,21 @@ bool8 S9xDeinitUpdate(int width, int height) height = SNES_HEIGHT; } } + else + { + if (height > SNES_HEIGHT_EXTENDED) + { + if (height < SNES_HEIGHT_EXTENDED << 1) + memset(GFX.Screen + (GFX.Pitch >> 1) * height,0,GFX.Pitch * ((SNES_HEIGHT_EXTENDED << 1) - height)); + height = SNES_HEIGHT_EXTENDED << 1; + } + else + { + if (height < SNES_HEIGHT_EXTENDED) + memset(GFX.Screen + (GFX.Pitch >> 1) * height,0,GFX.Pitch * (SNES_HEIGHT_EXTENDED - height)); + height = SNES_HEIGHT_EXTENDED; + } + } s9x_video_cb(GFX.Screen, width, height, GFX.Pitch); return TRUE; From 38f7459ee758f16488dc807431e0e12b1cbc869a Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 15 Apr 2012 21:46:09 +0200 Subject: [PATCH 115/130] libretro: fix uint8*/void* mismatch (Themaister) --- libretro/libretro.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index f55d418e..e5562acf 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -581,17 +581,17 @@ size_t retro_serialize_size() return S9xFreezeSize(); } -bool retro_serialize(uint8_t *data, unsigned size) +bool retro_serialize(void *data, size_t size) { - if (S9xFreezeGameMem(data,size) == FALSE) + if (S9xFreezeGameMem((uint8_t*)data,size) == FALSE) return false; return true; } -bool retro_unserialize(const uint8_t* data, unsigned size) +bool retro_unserialize(const void* data, size_t size) { - if (S9xUnfreezeGameMem(data,size) != SUCCESS) + if (S9xUnfreezeGameMem((const uint8_t*)data,size) != SUCCESS) return false; return true; } From 666b89f66fdc746a78fd4e25ea7eb70cb3dd849b Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 15 Apr 2012 21:58:04 +0200 Subject: [PATCH 116/130] libretro: supply 4/3 as nominal aspect ratio --- libretro/libretro.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index e5562acf..ec539be2 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -93,6 +93,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.base_height = SNES_HEIGHT; info->geometry.max_width = MAX_SNES_WIDTH; info->geometry.max_height = MAX_SNES_HEIGHT; + info->geometry.aspect_ratio = 4.0 / 3.0; info->timing.sample_rate = 32040.5; info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0; } From 9b5cefa6303c65a190d3026cda968123bfee0593 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 15 Apr 2012 22:02:37 +0200 Subject: [PATCH 117/130] libretro: remove unused libsnes remains --- libretro/libretro.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index ec539be2..12f04ad8 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -69,9 +69,6 @@ static void S9xAudioCallback(void*) size_t avail = S9xGetSampleCount(); S9xMixSamples((uint8*)audio_buf, avail); s9x_audio_batch_cb(audio_buf,avail >> 1); - - /*for (size_t i = 0; i < avail; i+=2) - s9x_audio_cb((uint16_t)audio_buf[i], (uint16_t)audio_buf[i + 1]);*/ } void retro_get_system_info(struct retro_system_info *info) @@ -514,18 +511,6 @@ void* retro_get_memory_data(unsigned type) case RETRO_MEMORY_SYSTEM_RAM: data = Memory.RAM; break; - /*case SNES_MEMORY_APURAM: - data = SNES::smp.apuram; - break; - case SNES_MEMORY_VRAM: - data = Memory.VRAM; - break; - case SNES_MEMORY_CGRAM: - data = (uint8_t*)PPU.CGDATA; - break; - case SNES_MEMORY_OAM: - data = PPU.OAMData; - break;*/ default: data = NULL; break; @@ -559,16 +544,6 @@ size_t retro_get_memory_size(unsigned type) case RETRO_MEMORY_SYSTEM_RAM: size = 128 * 1024; break; - /*case SNES_MEMORY_VRAM: - case SNES_MEMORY_APURAM: - size = 64 * 1024; - break; - case SNES_MEMORY_CGRAM: - size = 512; - break; - case SNES_MEMORY_OAM: - size = 512 + 32; - break;*/ default: size = 0; break; @@ -638,7 +613,6 @@ bool8 S9xContinueUpdate(int width, int height) // Dummy functions that should probably be implemented correctly later. void S9xParsePortConfig(ConfigFile&, int) {} void S9xSyncSpeed() {} -//void S9xPollPointer(int, short*, short*) {} const char* S9xStringInput(const char* in) { return in; } const char* S9xGetFilename(const char* in, s9x_getdirtype) { return in; } const char* S9xGetDirectory(s9x_getdirtype) { return ""; } From 08ff48a47981fb059f743aeeaf50efd5eac92e19 Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 16 Apr 2012 19:56:15 +0200 Subject: [PATCH 118/130] Remove old chown calls on linux --- memmap.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/memmap.cpp b/memmap.cpp index 54f83587..72196bb1 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -2167,9 +2167,6 @@ bool8 CMemory::SaveSRAM (const char *filename) size_t ignore; ignore = fwrite((char *) Multi.sramB, size, 1, file); fclose(file); - #ifdef __linux - ignore = chown(name, getuid(), getgid()); - #endif } strcpy(ROMFilename, temp); @@ -2187,9 +2184,6 @@ bool8 CMemory::SaveSRAM (const char *filename) size_t ignore; ignore = fwrite((char *) SRAM, size, 1, file); fclose(file); - #ifdef __linux - ignore = chown(sramName, getuid(), getgid()); - #endif if (Settings.SRTC || Settings.SPC7110RTC) SaveSRTC(); From dfdf197b27b093842878d8374385401034244a87 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Mon, 23 Apr 2012 01:40:35 -0500 Subject: [PATCH 119/130] Remove an improper use of chown. --- gtk/src/gtk_file.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp index 2182e39e..a0df75d8 100644 --- a/gtk/src/gtk_file.cpp +++ b/gtk/src/gtk_file.cpp @@ -311,13 +311,7 @@ S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file) { if ((*file = OPEN_STREAM (filename, "wb"))) { - if (chown (filename, getuid (), getgid ()) < 0) - { - fprintf (stderr, "Couldn't set ownership of file.\n"); - return (FALSE); - } - else - return (TRUE); + return (TRUE); } else { From b0233de08e8ee0e86e716be7eeaefa310b1d4c8e Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Thu, 26 Apr 2012 05:06:24 -0500 Subject: [PATCH 120/130] Work around internal compiler error on GCC 4.7.0. --- gtk/src/gtk_display.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp index 4729a765..c2897e1b 100644 --- a/gtk/src/gtk_display.cpp +++ b/gtk/src/gtk_display.cpp @@ -877,23 +877,24 @@ filter_scanlines (void *src_buffer, int height) { register int x, y; + register uint16 *src, *dst_a, *dst_b; uint8 shift = scanline_shifts[gui_config->scanline_filter_intensity]; + src = (uint16 *) src_buffer; + dst_a = (uint16 *) dst_buffer; + dst_b = ((uint16 *) dst_buffer) + (dst_pitch >> 1); + for (y = 0; y < height; y++) { - register uint16 *src = (uint16 *) ((uint8 *) src_buffer + y * src_pitch); - register uint16 *dst_a = (uint16 *) ((uint8 *) dst_buffer + (y * 2) * dst_pitch); - register uint16 *dst_b = (uint16 *) ((uint8 *) dst_buffer + ((y * 2) + 1) * dst_pitch); - for (x = 0; x < width; x++) { register uint8 rs, gs, bs, /* Source components */ rh, gh, bh; /* High (bright) components */ - rs = ((*(src + x) >> 10) & 0x1f); - gs = ((*(src + x) >> 5) & 0x1f); - bs = ((*(src + x)) & 0x1f); + rs = ((src[x] >> 10) & 0x1f); + gs = ((src[x] >> 5) & 0x1f); + bs = ((src[x]) & 0x1f); rh = rs + (rs >> shift); gh = gs + (gs >> shift); @@ -903,11 +904,15 @@ filter_scanlines (void *src_buffer, gh = (gh > 31) ? 31 : gh; bh = (bh > 31) ? 31 : bh; - *(dst_a + x) = (rh << 10) | (gh << 5) | (bh); - *(dst_b + x) = ((rs + rs - rh) << 10) | - ((gs + gs - gh) << 5) | - (bs + bs - bh); + dst_a[x] = (rh << 10) + (gh << 5) + (bh); + dst_b[x] = ((rs + rs - rh) << 10) + + ((gs + gs - gh) << 5) + + (bs + bs - bh); } + + src += src_pitch >> 1; + dst_a += dst_pitch; + dst_b += dst_pitch; } return; From 87c1717ac6cd3e8a821ce86e0b593863e3a949f7 Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 26 Apr 2012 13:16:58 +0200 Subject: [PATCH 121/130] libretro: update to latest libretro.h, add RETRO_MEMORY_VIDEO_RAM --- libretro/libretro.cpp | 16 +++++-- libretro/libretro.h | 105 +++++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 28 deletions(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 12f04ad8..f42db539 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -90,7 +90,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.base_height = SNES_HEIGHT; info->geometry.max_width = MAX_SNES_WIDTH; info->geometry.max_height = MAX_SNES_HEIGHT; - info->geometry.aspect_ratio = 4.0 / 3.0; + info->geometry.aspect_ratio = 4.0f / 3.0f; info->timing.sample_rate = 32040.5; info->timing.fps = retro_get_region() == RETRO_REGION_NTSC ? 21477272.0 / 357366.0 : 21281370.0 / 425568.0; } @@ -510,7 +510,10 @@ void* retro_get_memory_data(unsigned type) break; case RETRO_MEMORY_SYSTEM_RAM: data = Memory.RAM; - break; + break; + case RETRO_MEMORY_VIDEO_RAM: + data = Memory.VRAM; + break; default: data = NULL; break; @@ -541,9 +544,12 @@ size_t retro_get_memory_size(unsigned type) case RETRO_MEMORY_RTC: size = (Settings.SRTC || Settings.SPC7110RTC)?20:0; break; - case RETRO_MEMORY_SYSTEM_RAM: - size = 128 * 1024; - break; + case RETRO_MEMORY_SYSTEM_RAM: + size = 128 * 1024; + break; + case RETRO_MEMORY_VIDEO_RAM: + size = 64 * 1024; + break; default: size = 0; break; diff --git a/libretro/libretro.h b/libretro/libretro.h index 3a1599e1..fcd3bbc6 100644 --- a/libretro/libretro.h +++ b/libretro/libretro.h @@ -7,8 +7,14 @@ #ifdef __cplusplus extern "C" { #else +#if defined(_MSC_VER) && !defined(__cplusplus) +#define bool unsigned char +#define true 1 +#define false 0 +#else #include #endif +#endif #define RETRO_API_VERSION 1 @@ -48,7 +54,7 @@ extern "C" { #define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 #define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 #define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 -#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 @@ -57,6 +63,7 @@ extern "C" { #define RETRO_MEMORY_SAVE_RAM 0 #define RETRO_MEMORY_RTC 1 #define RETRO_MEMORY_SYSTEM_RAM 2 +#define RETRO_MEMORY_VIDEO_RAM 3 #define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) #define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) @@ -82,7 +89,7 @@ extern "C" { // Boolean value whether or not the implementation should use overscan, or crop away overscan. // #define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- - // Boolean value whether or not SSNES supports frame duping, + // Boolean value whether or not RetroArch supports frame duping, // passing NULL to video frame callback. // #define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- @@ -99,20 +106,31 @@ extern "C" { // #define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + // Should not be used for trivial messages, which should simply be logged to stderr. struct retro_message { - const char *msg; - unsigned frames; + const char *msg; // Message to be displayed. + unsigned frames; // Duration in frames of message. }; struct retro_system_info { - const char *library_name; - const char *library_version; - const char *valid_extensions; - bool need_fullpath; - bool block_extract; + const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc. + const char *library_version; // Descriptive version of core. + + const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe. + // I.e. "bin|rom|iso". + // Typically used for a GUI to filter out extensions. + + bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path. + // ::data and ::size are both invalid. + // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid. + // This is typically set to true for libretro implementations that must load from file. + // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc. + + bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real ROM. + // Necessary for certain libretro implementations that load games from zipped archives. }; struct retro_game_geometry @@ -152,32 +170,39 @@ struct retro_game_info { const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. // May be NULL if rom was loaded from stdin or similar. - // SET_NEED_FULLPATH path guaranteed that this path is valid. - const void *data; // Memory buffer of loaded game. - // If the game is too big to load in one go. - // SET_NEED_FULLPATH should be used. - // In this case, data and size will be 0, - // and game can be loaded from path. + // retro_system_info::need_fullpath guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set. size_t size; // Size of memory buffer. const char *meta; // String of implementation specific meta-data. }; +// Callbacks +// +// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. typedef bool (*retro_environment_t)(unsigned cmd, void *data); + +// Render a frame. Pixel format is 15-bit XRGB1555 native endian. +// Width and height specify dimensions of buffer. +// Pitch specifices length in bytes between two lines in buffer. typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); + +// Renders a single audio frame. Should only be used if implementation generates a single sample at a time. +// Format is signed 16-bit native endian. typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved. +// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. +// Only one of the audio callbacks must ever be used. typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); +// Polls input. typedef void (*retro_input_poll_t)(void); +// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK. +// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device() +// will still use the higher level RETRO_DEVICE_JOYPAD to request input. typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); -void retro_init(void); -void retro_deinit(void); - -unsigned retro_api_version(void); - -void retro_get_system_info(struct retro_system_info *info); -void retro_get_system_av_info(struct retro_system_av_info *info); - +// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init(). +// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made. void retro_set_environment(retro_environment_t); void retro_set_video_refresh(retro_video_refresh_t); void retro_set_audio_sample(retro_audio_sample_t); @@ -185,29 +210,63 @@ void retro_set_audio_sample_batch(retro_audio_sample_batch_t); void retro_set_input_poll(retro_input_poll_t); void retro_set_input_state(retro_input_state_t); +// Library global initialization/deinitialization. +void retro_init(void); +void retro_deinit(void); + +// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised. +unsigned retro_api_version(void); + +// Gets statically known system info. Pointers provided in *info must be statically allocated. +// Can be called at any time, even before retro_init(). +void retro_get_system_info(struct retro_system_info *info); + +// Gets information about system audio/video timings and geometry. +// Can be called only after retro_load_game() has successfully completed. +void retro_get_system_av_info(struct retro_system_av_info *info); + +// Sets device to be used for player 'port'. void retro_set_controller_port_device(unsigned port, unsigned device); +// Resets the current game. void retro_reset(void); + +// Runs the game for one video frame. +// During retro_run(), input_poll callback must be called at least once. +// +// If a frame is not rendered for reasons where a game "dropped" a frame, +// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true. +// In this case, the video callback can take a NULL argument for data. void retro_run(void); +// Returns the amount of data the implementation requires to serialize internal state (save states). +// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to +// ensure that the frontend can allocate a save state buffer once. size_t retro_serialize_size(void); + +// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise. bool retro_serialize(void *data, size_t size); bool retro_unserialize(const void *data, size_t size); void retro_cheat_reset(void); void retro_cheat_set(unsigned index, bool enabled, const char *code); +// Loads a game. bool retro_load_game(const struct retro_game_info *game); +// Loads a "special" kind of game. Should not be used except in extreme cases. bool retro_load_game_special( unsigned game_type, const struct retro_game_info *info, size_t num_info ); +// Unloads a currently loaded game. void retro_unload_game(void); +// Gets region of game. unsigned retro_get_region(void); +// Gets region of memory. void *retro_get_memory_data(unsigned id); size_t retro_get_memory_size(unsigned id); From 19b458bc4715958a342c5f8293db3ab6e74b68ba Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 8 May 2012 00:02:10 +0200 Subject: [PATCH 122/130] Do not depend on port-specific variable in core --- snapshot.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/snapshot.cpp b/snapshot.cpp index 282198f5..b816fd43 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1171,7 +1171,6 @@ void S9xResetSaveTimer (bool8 dontsave) uint32 S9xFreezeSize() { - if(Settings.StopEmulation) return 0; nulStream stream; S9xFreezeToStream(&stream); return stream.size(); From 518110646a73fe64f6061a5774a19f236b9f5163 Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 8 May 2012 00:03:20 +0200 Subject: [PATCH 123/130] libretro/win32: make sure S9xFreezeSize is only called after rom load --- libretro/libretro.cpp | 44 +++++++++++++++++++++---------------------- win32/wsnes9x.cpp | 2 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index f42db539..ced4bb58 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -21,7 +21,6 @@ #include #include - static retro_video_refresh_t s9x_video_cb = NULL; static retro_audio_sample_t s9x_audio_cb = NULL; static retro_audio_sample_batch_t s9x_audio_batch_cb = NULL; @@ -54,7 +53,8 @@ void retro_set_input_state(retro_input_state_t cb) } static retro_environment_t environ_cb; -static bool use_overscan; +static bool use_overscan = false; +static bool rom_loaded = false; void retro_set_environment(retro_environment_t cb) { environ_cb = cb; @@ -153,19 +153,18 @@ void retro_cheat_set(unsigned, bool, const char*) bool retro_load_game(const struct retro_game_info *game) { - int loaded = 0; if(game->data == NULL && game->size == NULL && game->path != NULL) - loaded = Memory.LoadROM(game->path); + rom_loaded = Memory.LoadROM(game->path); else - loaded = Memory.LoadROMMem((const uint8_t*)game->data ,game->size); + rom_loaded = Memory.LoadROMMem((const uint8_t*)game->data ,game->size); - if (!loaded) + if (!rom_loaded) { fprintf(stderr, "[libretro]: Rom loading failed...\n"); } - return loaded; + return rom_loaded; } void retro_unload_game(void) @@ -174,53 +173,55 @@ void retro_unload_game(void) bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) { - int loaded = 0; switch (game_type) { case RETRO_GAME_TYPE_BSX: if(num_info == 1) { - loaded = Memory.LoadROMMem((const uint8_t*)info[0].data,info[0].size); + rom_loaded = Memory.LoadROMMem((const uint8_t*)info[0].data,info[0].size); } else if(num_info == 2) { memcpy(Memory.BIOSROM,(const uint8_t*)info[0].data,info[0].size); - loaded = Memory.LoadROMMem((const uint8_t*)info[1].data,info[1].size); + rom_loaded = Memory.LoadROMMem((const uint8_t*)info[1].data,info[1].size); } - if (!loaded) + if (!rom_loaded) { fprintf(stderr, "[libretro]: BSX Rom loading failed...\n"); } - return loaded; + break; case RETRO_GAME_TYPE_BSX_SLOTTED: if(num_info == 2) - loaded = Memory.LoadMultiCartMem((const uint8_t*)info[0].data, info[0].size, + rom_loaded = Memory.LoadMultiCartMem((const uint8_t*)info[0].data, info[0].size, (const uint8_t*)info[1].data, info[1].size, NULL, NULL); - if (!loaded) + if (!rom_loaded) { fprintf(stderr, "[libretro]: Multirom loading failed...\n"); } - return loaded; + break; case RETRO_GAME_TYPE_SUFAMI_TURBO: if(num_info == 3) - loaded = Memory.LoadMultiCartMem((const uint8_t*)info[1].data, info[1].size, + rom_loaded = Memory.LoadMultiCartMem((const uint8_t*)info[1].data, info[1].size, (const uint8_t*)info[2].data, info[2].size, (const uint8_t*)info[0].data, info[0].size); - if (!loaded) + if (!rom_loaded) { fprintf(stderr, "[libretro]: Sufami Turbo Rom loading failed...\n"); } - return loaded; + break; default: - return false; + rom_loaded = false; + break; } + + return rom_loaded; } static void map_buttons(); @@ -251,13 +252,10 @@ void retro_init() Settings.InitialInfoStringTimeout = 120; Settings.HDMATimingHack = 100; Settings.BlockInvalidVRAMAccessMaster = TRUE; - Settings.StopEmulation = TRUE; Settings.WrongMovieStateProtection = TRUE; Settings.DumpStreamsMaxFrames = -1; Settings.StretchScreenshots = 0; Settings.SnapshotScreenshots = FALSE; - Settings.SkipFrames = AUTO_FRAMERATE; - Settings.TurboSkipFrames = 15; Settings.CartAName[0] = 0; Settings.CartBName[0] = 0; Settings.AutoSaveDelay = 1; @@ -560,7 +558,7 @@ size_t retro_get_memory_size(unsigned type) size_t retro_serialize_size() { - return S9xFreezeSize(); + return rom_loaded ? S9xFreezeSize() : 0; } bool retro_serialize(void *data, size_t size) diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index cb8c8883..510c5914 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -5041,7 +5041,7 @@ INT_PTR CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPar unsigned int newRewindBufSize = SendDlgItemMessage(hDlg, IDC_REWIND_BUFFER_SPIN, UDM_GETPOS, 0,0); if(GUI.rewindBufferSize != newRewindBufSize) { GUI.rewindBufferSize = newRewindBufSize; - stateMan.init(GUI.rewindBufferSize * 1024 * 1024); + if(!Settings.StopEmulation) stateMan.init(GUI.rewindBufferSize * 1024 * 1024); } WinSaveConfigFile(); From d23302de8ad416c6941af4a6490c7913d9d89765 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 2 Jun 2012 18:06:17 +0200 Subject: [PATCH 124/130] Win32: remove deprecated libpng defines (aphanic) --- win32/CGLCG.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/win32/CGLCG.cpp b/win32/CGLCG.cpp index 0d75a999..182314d2 100644 --- a/win32/CGLCG.cpp +++ b/win32/CGLCG.cpp @@ -776,7 +776,7 @@ bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } @@ -792,7 +792,7 @@ bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated * with the png_ptr and info_ptr */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); /* If we get here, we had a * problem reading the file */ @@ -826,11 +826,11 @@ bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool * PNG_TRANSFORM_EXPAND forces to * expand a palette into RGB */ - png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, png_voidp_NULL); + png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, (png_voidp)NULL); - outWidth = info_ptr->width; - outHeight = info_ptr->height; - switch (info_ptr->color_type) { + outWidth = png_get_image_width(png_ptr, info_ptr); + outHeight = png_get_image_height(png_ptr, info_ptr); + switch (png_get_color_type(png_ptr, info_ptr)) { case PNG_COLOR_TYPE_RGBA: outHasAlpha = true; break; @@ -853,7 +853,7 @@ bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool /* Clean up after the read, * and free any memory allocated */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* Close the file */ fclose(fp); From ea09fef2b94a0a667d2e7459f9022500f9b501df Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 2 Jun 2012 17:34:16 +0200 Subject: [PATCH 125/130] Log IRQ enable on debug trace --- ppu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ppu.cpp b/ppu.cpp index 0907021b..59d11f25 100644 --- a/ppu.cpp +++ b/ppu.cpp @@ -1498,6 +1498,11 @@ void S9xSetCPU (uint8 Byte, uint16 Address) Timings.NMITriggerPos = CPU.Cycles + 6 + 6; } + #ifdef DEBUGGER + S9xTraceFormattedMessage("--- IRQ Timer Enable HTimer:%d Pos:%04d VTimer:%d Pos:%03d", + PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition); + #endif + break; case 0x4201: // WRIO From 0c74e2c437cf330856783aa3e9ca2447626515d8 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sat, 2 Jun 2012 17:30:35 +0200 Subject: [PATCH 126/130] Fix IRQ edge cases --- cpuexec.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpuexec.h b/cpuexec.h index 7e65b313..1ffd5737 100644 --- a/cpuexec.h +++ b/cpuexec.h @@ -278,10 +278,11 @@ static inline void S9xCheckInterrupts (void) if (CPU.IRQLine && thisIRQ) CPU.IRQTransition = TRUE; - if (PPU.HTimerEnabled) + int32 htimepos = PPU.HTimerEnabled ? PPU.HTimerPosition : 10; + + if (thisIRQ) { - int32 htimepos = PPU.HTimerPosition; - if (CPU.Cycles >= Timings.H_Max) + if (CPU.Cycles >= Timings.H_Max && htimepos < CPU.PrevCycles) htimepos += Timings.H_Max; if (CPU.PrevCycles >= htimepos || CPU.Cycles < htimepos) @@ -291,7 +292,7 @@ static inline void S9xCheckInterrupts (void) if (PPU.VTimerEnabled) { int32 vcounter = CPU.V_Counter; - if (CPU.Cycles >= Timings.H_Max) + if (htimepos >= Timings.H_Max) vcounter++; if (vcounter != PPU.VTimerPosition) From 679db377c7cf296cc47552b1ccc11cdc27b2f950 Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 4 Jun 2012 19:03:07 +0200 Subject: [PATCH 127/130] libretro: disable oops snapshots --- libretro/libretro.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index ced4bb58..fb3950d4 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -259,6 +259,7 @@ void retro_init() Settings.CartAName[0] = 0; Settings.CartBName[0] = 0; Settings.AutoSaveDelay = 1; + Settings.DontSaveOopsSnapshot = TRUE; CPU.Flags = 0; From a08f4fb53137f4c51ebe72bc0515536caefaa26e Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 4 Jun 2012 21:31:27 +0200 Subject: [PATCH 128/130] Reroll IRQ edge case fix --- cpuexec.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpuexec.h b/cpuexec.h index 1ffd5737..8d201d01 100644 --- a/cpuexec.h +++ b/cpuexec.h @@ -278,10 +278,9 @@ static inline void S9xCheckInterrupts (void) if (CPU.IRQLine && thisIRQ) CPU.IRQTransition = TRUE; - int32 htimepos = PPU.HTimerEnabled ? PPU.HTimerPosition : 10; - - if (thisIRQ) + if (PPU.HTimerEnabled) { + int32 htimepos = PPU.HTimerPosition; if (CPU.Cycles >= Timings.H_Max && htimepos < CPU.PrevCycles) htimepos += Timings.H_Max; @@ -292,7 +291,7 @@ static inline void S9xCheckInterrupts (void) if (PPU.VTimerEnabled) { int32 vcounter = CPU.V_Counter; - if (htimepos >= Timings.H_Max) + if (CPU.Cycles >= Timings.H_Max && (!PPU.HTimerEnabled || PPU.HTimerPosition < CPU.PrevCycles)) vcounter++; if (vcounter != PPU.VTimerPosition) From 86b78aec558d5fb13d150cdc097758fcc4cc329a Mon Sep 17 00:00:00 2001 From: OV2 Date: Mon, 4 Jun 2012 23:13:21 +0200 Subject: [PATCH 129/130] libretro: report correct height if overscan is enabled --- libretro/libretro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index fb3950d4..90dc874d 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -87,7 +87,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) memset(info,0,sizeof(retro_system_av_info)); info->geometry.base_width = SNES_WIDTH; - info->geometry.base_height = SNES_HEIGHT; + info->geometry.base_height = use_overscan ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; info->geometry.max_width = MAX_SNES_WIDTH; info->geometry.max_height = MAX_SNES_HEIGHT; info->geometry.aspect_ratio = 4.0f / 3.0f; From 03caf3f4aed8c0a740cddb91073b4cd2ea0c1719 Mon Sep 17 00:00:00 2001 From: Brandon Wright Date: Tue, 3 Jul 2012 15:20:35 -0500 Subject: [PATCH 130/130] Fix appearance bugs with preferences dialog UI on GTK+ 3. --- gtk/src/snes9x.ui | 776 ++++++++++++++++++++++++---------------------- 1 file changed, 404 insertions(+), 372 deletions(-) diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index 2cd0e909..bff0a613 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -235,6 +235,203 @@ 0.01 0.10000000000000001 + + 512 + 350 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Snes9x Cheats + center-on-parent + dialog + True + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-close + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + False + False + 0 + + + + + False + True + end + 0 + + + + + True + False + 5 + + + True + False + 0 + in + + + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + + True + True + 0 + + + + + True + False + 5 + 5 + + + True + False + 0 + Code: + + + False + True + 0 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + False + True + True + + + False + True + 1 + + + + + True + False + 0 + Description: + + + False + True + 2 + + + + + True + True + 21 + True + False + False + True + True + + + False + True + 3 + + + + + gtk-add + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 4 + + + + + gtk-remove + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + True + + + + False + False + 5 + + + + + False + False + 1 + + + + + True + True + 1 + + + + + + button7 + + False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK @@ -600,6 +797,29 @@ + + + + + + + + + + + + + + Merge adjacent pairs + + + Output directly + + + Scale low-resolution screens + + + @@ -795,226 +1015,6 @@ - - 512 - 350 - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Snes9x Cheats - center-on-parent - dialog - True - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - gtk-close - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - False - False - 0 - - - - - False - True - end - 0 - - - - - True - False - 5 - - - True - False - 0 - in - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - - - True - True - 0 - - - - - True - False - 5 - 5 - - - True - False - 0 - Code: - - - False - True - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - False - False - True - True - - - False - True - 1 - - - - - True - False - 0 - Description: - - - False - True - 2 - - - - - True - True - 21 - True - False - False - True - True - - - False - True - 3 - - - - - gtk-add - True - True - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 4 - - - - - gtk-remove - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 5 - - - - - False - False - 1 - - - - - True - True - 1 - - - - - - button7 - - - - - - - - - - - - - - - - Merge adjacent pairs - - - Output directly - - - Scale low-resolution screens - - - False GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK @@ -2288,7 +2288,7 @@ True - True + False True 0 @@ -2360,7 +2360,7 @@ - True + False True 1 @@ -2379,7 +2379,7 @@ - True + False True 2 @@ -2684,10 +2684,6 @@ True True - left - 0 - 1 - 0 @@ -2838,7 +2834,7 @@ False - True + False 0 @@ -2919,7 +2915,7 @@ - True + False True 1 @@ -2978,7 +2974,7 @@ - True + False True 2 @@ -3020,7 +3016,7 @@ - True + False True 3 @@ -3084,7 +3080,7 @@ False - True + False 1 @@ -3200,7 +3196,7 @@ - True + False True 0 @@ -3226,6 +3222,7 @@ 6 7 GTK_FILL + GTK_FILL @@ -3240,6 +3237,7 @@ 4 5 GTK_FILL + GTK_FILL @@ -3254,6 +3252,7 @@ 3 4 GTK_FILL + GTK_FILL @@ -3268,6 +3267,7 @@ 2 3 GTK_FILL + GTK_FILL @@ -3282,6 +3282,7 @@ 1 2 GTK_FILL + GTK_FILL @@ -3294,6 +3295,7 @@ GTK_FILL + GTK_FILL @@ -3310,6 +3312,7 @@ 1 2 + GTK_FILL @@ -3328,6 +3331,7 @@ 2 1 2 + GTK_FILL @@ -3346,6 +3350,7 @@ 2 2 3 + GTK_FILL @@ -3364,6 +3369,7 @@ 2 3 4 + GTK_FILL @@ -3382,6 +3388,7 @@ 2 4 5 + GTK_FILL @@ -3400,6 +3407,7 @@ 2 6 7 + GTK_FILL @@ -3418,6 +3426,7 @@ 2 7 8 + GTK_FILL @@ -3436,6 +3445,7 @@ 2 8 9 + GTK_FILL @@ -3454,6 +3464,7 @@ 2 9 10 + GTK_FILL @@ -3472,6 +3483,7 @@ 2 10 11 + GTK_FILL @@ -3486,6 +3498,7 @@ 7 8 GTK_FILL + GTK_FILL @@ -3500,6 +3513,7 @@ 8 9 GTK_FILL + GTK_FILL @@ -3514,6 +3528,7 @@ 9 10 GTK_FILL + GTK_FILL @@ -3528,6 +3543,7 @@ 10 11 GTK_FILL + GTK_FILL @@ -3539,11 +3555,12 @@ 2 5 6 + GTK_FILL - True + False True 1 @@ -3558,7 +3575,7 @@ True - True + False True 2 @@ -3601,7 +3618,7 @@ - True + False True 3 @@ -3621,7 +3638,7 @@ False - True + False 2 @@ -3689,7 +3706,7 @@ False - True + False 3 @@ -3727,7 +3744,7 @@ - True + False True 0 @@ -3743,7 +3760,7 @@ True - True + False True 1 @@ -3782,7 +3799,7 @@ True - True + False True 1 @@ -3798,7 +3815,7 @@ True - True + False True 2 @@ -3815,7 +3832,7 @@ True - True + False True 3 @@ -3869,7 +3886,7 @@ - True + False True 4 @@ -3929,14 +3946,14 @@ - True + False True 5 - True + False True 2 @@ -3956,14 +3973,14 @@ True - True + False True 0 - True + False True 3 @@ -3983,7 +4000,7 @@ False - True + False 4 @@ -4004,7 +4021,7 @@ video-display - True + False True 0 @@ -4166,7 +4183,7 @@ GTK_FILL - + @@ -4239,6 +4256,7 @@ 1 2 GTK_FILL + GTK_FILL @@ -4256,6 +4274,7 @@ 2 1 2 + GTK_FILL @@ -4285,6 +4304,7 @@ 1 2 GTK_FILL + GTK_FILL @@ -4298,6 +4318,7 @@ 2 3 GTK_FILL + GTK_FILL @@ -4311,6 +4332,7 @@ 2 2 3 + GTK_FILL @@ -4352,7 +4374,7 @@ audio-x-generic - True + False True 0 @@ -4448,21 +4470,20 @@ False - True + False 0 Block invalid VRAM access - True True False False True - True + False True 1 @@ -4478,7 +4499,7 @@ True - True + False True 2 @@ -4498,7 +4519,7 @@ False - True + False 0 @@ -4530,7 +4551,7 @@ True - True + False True 0 @@ -4572,7 +4593,7 @@ - True + False True 1 @@ -4592,7 +4613,7 @@ False - True + False 1 @@ -4623,7 +4644,7 @@ True - True + False True 0 @@ -4643,7 +4664,7 @@ False - True + False 2 @@ -4654,6 +4675,7 @@ 2 + False @@ -4667,7 +4689,7 @@ utilities-terminal - True + False True 0 @@ -4738,6 +4760,7 @@ 1 2 + GTK_FILL @@ -4759,6 +4782,7 @@ 2 1 2 + GTK_FILL @@ -4780,6 +4804,7 @@ 2 2 3 + GTK_FILL @@ -4801,6 +4826,7 @@ 2 3 4 + GTK_FILL @@ -4822,6 +4848,7 @@ 2 4 5 + GTK_FILL @@ -4837,7 +4864,7 @@ 2 3 GTK_FILL - + @@ -4855,7 +4882,7 @@ 1 2 GTK_FILL - + @@ -4873,7 +4900,7 @@ 2 3 GTK_FILL - + @@ -4891,7 +4918,7 @@ 3 4 GTK_FILL - + @@ -4909,7 +4936,7 @@ 4 5 GTK_FILL - + @@ -4921,6 +4948,7 @@ GTK_FILL + GTK_FILL @@ -4934,6 +4962,7 @@ 1 2 GTK_FILL + GTK_FILL @@ -4947,6 +4976,7 @@ 2 3 GTK_FILL + GTK_FILL @@ -4960,6 +4990,7 @@ 3 4 GTK_FILL + GTK_FILL @@ -4973,6 +5004,7 @@ 4 5 GTK_FILL + GTK_FILL @@ -5096,7 +5128,7 @@ folder - True + False True 0 @@ -5300,7 +5332,7 @@ GTK_FILL - + @@ -5314,7 +5346,7 @@ 1 2 GTK_FILL - + @@ -5328,7 +5360,7 @@ 2 3 GTK_FILL - + @@ -5342,7 +5374,7 @@ 3 4 GTK_FILL - + @@ -5356,7 +5388,7 @@ 4 5 GTK_FILL - + @@ -5370,7 +5402,7 @@ 5 6 GTK_FILL - + @@ -5509,7 +5541,7 @@ GTK_FILL - + @@ -5523,7 +5555,7 @@ 1 2 GTK_FILL - + @@ -5537,7 +5569,7 @@ 2 3 GTK_FILL - + @@ -5551,7 +5583,7 @@ 3 4 GTK_FILL - + @@ -5565,7 +5597,7 @@ 4 5 GTK_FILL - + @@ -5579,7 +5611,7 @@ 5 6 GTK_FILL - + @@ -5739,7 +5771,7 @@ GTK_FILL - + @@ -5753,7 +5785,7 @@ 1 2 GTK_FILL - + @@ -5767,7 +5799,7 @@ 2 3 GTK_FILL - + @@ -5781,7 +5813,7 @@ 3 4 GTK_FILL - + @@ -5795,7 +5827,7 @@ 4 5 GTK_FILL - + @@ -5809,7 +5841,7 @@ 5 6 GTK_FILL - + @@ -5951,7 +5983,7 @@ GTK_FILL - + @@ -5965,7 +5997,7 @@ 1 2 GTK_FILL - + @@ -5979,7 +6011,7 @@ 2 3 GTK_FILL - + @@ -5993,7 +6025,7 @@ 3 4 GTK_FILL - + @@ -6007,7 +6039,7 @@ 4 5 GTK_FILL - + @@ -6021,7 +6053,7 @@ 5 6 GTK_FILL - + @@ -6155,8 +6187,8 @@ 1 2 - - + + @@ -6169,8 +6201,8 @@ center - - + + @@ -6421,7 +6453,7 @@ input-gaming - True + False True 0 @@ -6514,7 +6546,7 @@ 9 10 GTK_FILL - + @@ -6528,7 +6560,7 @@ 8 9 GTK_FILL - + @@ -6542,7 +6574,7 @@ 7 8 GTK_FILL - + @@ -6556,7 +6588,7 @@ 6 7 GTK_FILL - + @@ -6570,7 +6602,7 @@ 5 6 GTK_FILL - + @@ -6584,7 +6616,7 @@ 4 5 GTK_FILL - + @@ -6598,7 +6630,7 @@ 3 4 GTK_FILL - + @@ -6612,7 +6644,7 @@ 2 3 GTK_FILL - + @@ -6626,7 +6658,7 @@ 1 2 GTK_FILL - + @@ -6639,7 +6671,7 @@ GTK_FILL - + @@ -6898,7 +6930,7 @@ GTK_FILL - + @@ -6912,7 +6944,7 @@ 1 2 GTK_FILL - + @@ -6926,7 +6958,7 @@ 2 3 GTK_FILL - + @@ -6940,7 +6972,7 @@ 3 4 GTK_FILL - + @@ -6954,7 +6986,7 @@ 4 5 GTK_FILL - + @@ -6968,7 +7000,7 @@ 5 6 GTK_FILL - + @@ -6982,7 +7014,7 @@ 6 7 GTK_FILL - + @@ -6996,7 +7028,7 @@ 7 8 GTK_FILL - + @@ -7193,8 +7225,8 @@ 2 - - + + @@ -7208,8 +7240,8 @@ 2 4 - - + + @@ -7222,8 +7254,8 @@ 2 3 - - + + @@ -7236,8 +7268,8 @@ 1 2 - - + + @@ -7250,8 +7282,8 @@ 3 4 - - + + @@ -7264,8 +7296,8 @@ 4 5 - - + + @@ -7278,8 +7310,8 @@ 5 6 - - + + @@ -7292,8 +7324,8 @@ 6 7 - - + + @@ -7306,8 +7338,8 @@ 7 8 - - + + @@ -7320,8 +7352,8 @@ 8 9 - - + + @@ -7336,8 +7368,8 @@ 3 1 2 - - + + @@ -7352,8 +7384,8 @@ 3 2 3 - - + + @@ -7368,8 +7400,8 @@ 3 3 4 - - + + @@ -7384,8 +7416,8 @@ 3 4 5 - - + + @@ -7400,8 +7432,8 @@ 3 5 6 - - + + @@ -7416,8 +7448,8 @@ 3 6 7 - - + + @@ -7432,8 +7464,8 @@ 3 7 8 - - + + @@ -7448,8 +7480,8 @@ 3 8 9 - - + + @@ -7464,8 +7496,8 @@ 3 9 10 - - + + @@ -7478,8 +7510,8 @@ 9 10 - - + + @@ -7874,7 +7906,7 @@ GTK_FILL - + @@ -7888,7 +7920,7 @@ 1 2 GTK_FILL - + @@ -7902,7 +7934,7 @@ 2 3 GTK_FILL - + @@ -7916,7 +7948,7 @@ 3 4 GTK_FILL - + @@ -7930,7 +7962,7 @@ 4 5 GTK_FILL - + @@ -7944,7 +7976,7 @@ 5 6 GTK_FILL - + @@ -7958,7 +7990,7 @@ 6 7 GTK_FILL - + @@ -7972,7 +8004,7 @@ 7 8 GTK_FILL - + @@ -7986,7 +8018,7 @@ 8 9 GTK_FILL - + @@ -8191,7 +8223,7 @@ 4 5 GTK_FILL - + @@ -8206,7 +8238,7 @@ 3 4 GTK_FILL - + @@ -8221,7 +8253,7 @@ 2 3 GTK_FILL - + @@ -8236,7 +8268,7 @@ 1 2 GTK_FILL - + @@ -8249,7 +8281,7 @@ GTK_FILL - + @@ -8351,7 +8383,7 @@ 5 6 GTK_FILL - + @@ -8427,7 +8459,7 @@ input-keyboard - True + False True 0