From dd6d7f79813a8d4c0b8aa8df1f06b783095ff979 Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 21 Sep 2003 14:33:34 +0000 Subject: [PATCH] Cyberstella finally compiles! After a year of inactivity, I decided that someone had to look at the code and do something with it. As of now, joysticks and mouse aren't working. Settings aren't saved. And sound support is patchy. Definitely a work-in-progress. It looks like I'll be the maintainer for this as well, at least until we can find someone who is willing to take over full time. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@185 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/CyberstellaTodo.txt | 111 +- stella/src/emucore/CartMC.cxx | 12 +- stella/src/emucore/EventHandler.cxx | 12 +- stella/src/emucore/Settings.cxx | 19 +- stella/src/emucore/TIA.cxx | 7 +- stella/src/stellarc | 35 - stella/src/ui/cyberstella/AboutDlg.cpp | 10 +- stella/src/ui/cyberstella/Cyberstella.dsp | 109 +- stella/src/ui/cyberstella/Cyberstella.h | 2 +- stella/src/ui/cyberstella/Cyberstella.rc | 62 +- stella/src/ui/cyberstella/CyberstellaView.cpp | 276 +- stella/src/ui/cyberstella/CyberstellaView.h | 8 +- stella/src/ui/cyberstella/DirectInput.hxx | 30 +- .../src/ui/cyberstella/DirectXFullScreen.cxx | 216 +- .../src/ui/cyberstella/DirectXFullScreen.hxx | 18 +- stella/src/ui/cyberstella/M6502Hi.ins | 4432 +++++++++++++++++ stella/src/ui/cyberstella/M6502Low.ins | 4374 ++++++++++++++++ stella/src/ui/cyberstella/SettingsWin32.cxx | 63 + stella/src/ui/cyberstella/SettingsWin32.hxx | 38 + stella/src/ui/cyberstella/SoundWin32.cxx | 293 +- stella/src/ui/cyberstella/SoundWin32.hxx | 190 +- stella/src/ui/cyberstella/resource.h | 4 +- 22 files changed, 9528 insertions(+), 793 deletions(-) delete mode 100644 stella/src/stellarc create mode 100644 stella/src/ui/cyberstella/M6502Hi.ins create mode 100644 stella/src/ui/cyberstella/M6502Low.ins create mode 100644 stella/src/ui/cyberstella/SettingsWin32.cxx create mode 100644 stella/src/ui/cyberstella/SettingsWin32.hxx diff --git a/stella/CyberstellaTodo.txt b/stella/CyberstellaTodo.txt index 8650c4aa2..0bb257ccf 100644 --- a/stella/CyberstellaTodo.txt +++ b/stella/CyberstellaTodo.txt @@ -1,12 +1,7 @@ -Cyberstella V1.2 +What needs to be done ASAP (will be done eventually): -Urgent: -- Reasonably reduce the appearance of advertisment MessgageBoxes. -- Check if games are running without stella.pro (?!?) - -Later: -- More Columns / Advanced sorting -- Make whole screen resizable + - More Columns / Advanced sorting + - Make whole screen resizable like this: void CViewList::OnSize(UINT nType, int cx, int cy) @@ -15,80 +10,40 @@ Later: if ( m_listCtrl.m_hWnd ) m_listCtrl.MoveWindow (0, 0, cx, cy); } ??????? -- Check other versions command line params -- Check other versions keyboard mapping -- Add Screenshots - F12 -- Add Pause - F3 -- Add Fullscreen / Windowed mode -F4 -- Check Direct Draw implementation / upgrade to DX8 -- Integrate manuals for the built in games -- Think about french localisation + - Add Fullscreen / Windowed mode - Alt-Enter + - Check Direct Draw implementation / upgrade to DX8 + - Improve the DirectSound support + - Can you have two PC controllers connected? + - Make all dialog boxes resizable for any size text -ToDos from Brad Mott: -- Is the keyboard mapping correct (e.g., do both of the Joysticks - work via the keyboard) -- Can you have two PC controllers connected? -- Finish the windowed version of StellaX (e.g., so that it'll run in - a window as well as fullscreen) -- Improve the DirectSound support -- Provide custom keyboard / controller mapping (e.g., be able to - map joystick buttons to the 2600 Select/Reset as well as the - other 2600 functions...) +Integrated into the core, but not necessarily active in Cyberstella: -ToDos from Stephen Anthony: -1) In the information dialog box, could you change the -Stella homepage to -stella.sourceforge.net, and change the mailing list to -stella-main@lists.sourceforge.net? These are the new -addresses, and the -older ones you have used will be eventually phased out. + - Check other versions command line params + - Check other versions keyboard mapping + - Add Screenshots - F12 + - Add Pause - Pause + - Is the keyboard mapping correct (e.g., do both of the Joysticks + work via the keyboard) + - Provide custom keyboard / controller mapping (e.g., be able to + map joystick buttons to the 2600 Select/Reset as well as the + other 2600 functions...) -2) Sometimes, when resizing the window, the inner file- -list contents aren't -resized. Maybe you haven't associated the resize event -with the resize -listview event? +Future / never (depending on user enthusiasm and developer availability): -3) There seems to be some lines of text missing in the -various dialog boxes. -I'm not sure if that is a problem with the version of -Windows I using (Win98 -under VMWare) or not. - -ToDos from Thomas Jetzsch: --> Private Mail + (Update path earlier, etc...) ->> Maybe just adding some friendly game-info menu, that ->> doesn't pop-up on remote at all. - ->Auch 'ne gute Idee, könnte man auch schön mit den Anleitungen ->kombinieren. Und bei jedem Spiel vielleicht nur einmalig darauf ->verweisen. - -Own Ideas: -- Add a Sprite/Animation Editor -- Add a PF Editor -- Add a Sourcecode Editor -- Either Support DASM as frontend or integrate a 6507 -Assembler -- Either Support Distella as frontend or integrate a -6507 Disassembler -- AVI/MPEG export -- WAV/MP3 export -- Client/Server networked play for up to 4 Computers via -LAN/Internet -- Tracking Hiscores -- Record and Playback games - not as real movie, but by -logging Input/RAM/processor states in given intervals. -- Cheatcodes - -Suggestions from Brian Luttrull: -Are you planning or would you be interested in adding -more features to the front end of Stella? For -example, the ability to display screenshots, cart -pics, docs, details, etc. The Kstella frontend has -these features and the very friendly and helpful -author, Stephen Anthony, said you would be free to -take ideas and code from his frontend (under GPL). + - Add a Sprite/Animation Editor + - Add a PF Editor + - Add a Sourcecode Editor + - Either Support DASM as frontend or integrate a 6507 Assembler + - Either Support Distella as frontend or integrate a 6507 Disassembler + - AVI/MPEG export + - WAV/MP3 export + - Client/Server networked play for up to 4 Computers via LAN/Internet + - Tracking Hiscores + - Record and Playback games - not as real movie, but by logging + Input/RAM/processor states in given intervals. + - Cheatcodes + - Improve frontend by adding snapshots, labels, manuals, etc. + Like KStella for Linux. (Suggestion from Brian Luttrull) Suggestions from Glenn Saunders: A couple things I'd like to see in a 2600 emulator that Brad was working on diff --git a/stella/src/emucore/CartMC.cxx b/stella/src/emucore/CartMC.cxx index 151a4ec3b..745389130 100644 --- a/stella/src/emucore/CartMC.cxx +++ b/stella/src/emucore/CartMC.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CartMC.cxx,v 1.3 2002-12-01 15:59:47 stephena Exp $ +// $Id: CartMC.cxx,v 1.4 2003-09-21 14:33:33 stephena Exp $ //============================================================================ #include @@ -222,6 +222,7 @@ void CartridgeMC::poke(uInt16 address, uInt8 value) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMC::save(Serializer& out) { + uInt32 i; string cart = name(); try @@ -230,12 +231,12 @@ bool CartridgeMC::save(Serializer& out) // The currentBlock array out.putLong(4); - for(uInt32 i = 0; i < 4; ++i) + for(i = 0; i < 4; ++i) out.putLong(myCurrentBlock[i]); // The 32K of RAM out.putLong(32 * 1024); - for(uInt32 i = 0; i < 32 * 1024; ++i) + for(i = 0; i < 32 * 1024; ++i) out.putLong(myRAM[i]); } catch(char *msg) @@ -255,6 +256,7 @@ bool CartridgeMC::save(Serializer& out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMC::load(Deserializer& in) { + uInt32 i; string cart = name(); try @@ -266,12 +268,12 @@ bool CartridgeMC::load(Deserializer& in) // The currentBlock array limit = (uInt32) in.getLong(); - for(uInt32 i = 0; i < limit; ++i) + for(i = 0; i < limit; ++i) myCurrentBlock[i] = (uInt8) in.getLong(); // The 32K of RAM limit = (uInt32) in.getLong(); - for(uInt32 i = 0; i < limit; ++i) + for(i = 0; i < limit; ++i) myRAM[i] = (uInt8) in.getLong(); } catch(char *msg) diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index e7dcd5fe1..4af342fd0 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EventHandler.cxx,v 1.7 2003-09-19 15:45:01 stephena Exp $ +// $Id: EventHandler.cxx,v 1.8 2003-09-21 14:33:33 stephena Exp $ //============================================================================ #include @@ -37,20 +37,22 @@ EventHandler::EventHandler(Console* console) : myConsole(console), myCurrentState(0) { + Int32 i; + // Create the event object which will be used for this handler myEvent = new Event(); // Erase the KeyEvent array - for(Int32 i = 0; i < StellaEvent::LastKCODE; ++i) + for(i = 0; i < StellaEvent::LastKCODE; ++i) myKeyTable[i] = Event::LastType; // Erase the JoyEvent array - for(Int32 i = 0; i < StellaEvent::LastJSTICK; ++i) + for(i = 0; i < StellaEvent::LastJSTICK; ++i) for(Int32 j = 0; j < StellaEvent::LastJCODE; ++j) myJoyTable[i][j] = Event::LastType; // Erase the Message array - for(Int32 i = 0; i < Event::LastType; ++i) + for(i = 0; i < Event::LastType; ++i) ourMessageTable[i] = ""; // Set unchanging messages @@ -215,7 +217,6 @@ void EventHandler::setKeymap() if(isValidList(list, StellaEvent::LastKCODE)) { - Event::Type event; istringstream buf(list); string key; @@ -240,7 +241,6 @@ void EventHandler::setJoymap() if(isValidList(list, StellaEvent::LastJSTICK*StellaEvent::LastJCODE)) { - Event::Type event; istringstream buf(list); string key; diff --git a/stella/src/emucore/Settings.cxx b/stella/src/emucore/Settings.cxx index b3e582ca4..416b57c66 100644 --- a/stella/src/emucore/Settings.cxx +++ b/stella/src/emucore/Settings.cxx @@ -13,9 +13,10 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Settings.cxx,v 1.5 2003-09-19 15:45:01 stephena Exp $ +// $Id: Settings.cxx,v 1.6 2003-09-21 14:33:33 stephena Exp $ //============================================================================ +#include #include #include @@ -138,7 +139,21 @@ void Settings::saveConfig() return; } - out << "fps = " << theDesiredFrameRate << endl + out << "; Stella configuration file" << endl + << ";" << endl + << "; Lines starting with ';' are comments and are ignored." << endl + << "; Spaces and tabs are ignored." << endl + << ";" << endl + << "; Format MUST be as follows:" << endl + << "; command = value" << endl + << ";" << endl + << "; Commmands are the same as those specified on the commandline," << endl + << "; without the '-' character." << endl + << ";" << endl + << "; Values are the same as those allowed on the commandline." << endl + << "; Boolean values are specified as 1 (for true) and 0 (for false)" << endl + << ";" << endl + << "fps = " << theDesiredFrameRate << endl << "zoom = " << theZoomLevel << endl << "keymap = " << myConsole->eventHandler().getKeymap() << endl << "joymap = " << myConsole->eventHandler().getJoymap() << endl diff --git a/stella/src/emucore/TIA.cxx b/stella/src/emucore/TIA.cxx index dc1e21390..09b598207 100644 --- a/stella/src/emucore/TIA.cxx +++ b/stella/src/emucore/TIA.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TIA.cxx,v 1.19 2002-11-19 04:33:48 bwmott Exp $ +// $Id: TIA.cxx,v 1.20 2003-09-21 14:33:33 stephena Exp $ //============================================================================ #include @@ -656,9 +656,10 @@ void TIA::drawMessageText() } // Then, draw the text - for(uInt8 x = 0; x < length; ++x) +//FIXME - change back to x + for(uInt8 x1 = 0; x1 < length; ++x1) { - char letter = myMessageText[x]; + char letter = myMessageText[x1]; if((letter >= 'A') && (letter <= 'Z')) data = ourFontData[(int)letter - 65]; diff --git a/stella/src/stellarc b/stella/src/stellarc deleted file mode 100644 index 01d980237..000000000 --- a/stella/src/stellarc +++ /dev/null @@ -1,35 +0,0 @@ -; Stella configuration file -; -; Lines starting with ';' are comments and are ignored. -; Spaces and tabs are ignored. -; -; Format MUST be as follows: -; command = value -; -; Commmands are the same as those specified on the commandline, -; without the '-' character. -; -; Values are the same as those allowed on the commandline. -; Boolean values are specified as 1 (for true) and 0 (for false) -; -; LINUX VERSION -; This file can be put in "/etc/stellarc" for system-wide access -; or in "$HOME/.stella/stellarc" for individual users. - -;display = -;fps = -;owncmap = <0|1> -;zoom = -;grabmouse = <0|1> -;hidecursor = <0|1> -;center = <0|1> -;volume = -;paddle = <0|1|2|3|real> -;showinfo = <0|1> -;fullscreen = <0|1> -;ssdir = -;ssname = -;sssingle = <0|1> -;accurate = <0|1> -;sound = <0|oss|sdl> -;Dmerge = <0|1> diff --git a/stella/src/ui/cyberstella/AboutDlg.cpp b/stella/src/ui/cyberstella/AboutDlg.cpp index 3343a2c88..48dc23a71 100644 --- a/stella/src/ui/cyberstella/AboutDlg.cpp +++ b/stella/src/ui/cyberstella/AboutDlg.cpp @@ -51,17 +51,17 @@ BOOL AboutDlg::OnInitDialog() { CDialog::OnInitDialog(); - m_hlMail_JSM.SubclassDlgItem(IDC_EMAIL_JEFFMILL, this); - m_hlMail_JSM.SetURL( _T("mailto:miller@zipcon.net?Subject=StellaX") ); + m_hlMail_JSM.SubclassDlgItem(IDC_EMAIL_JEFFMILL, this); + m_hlMail_JSM.SetURL( _T("mailto:stephena@users.sourceforge.net?Subject=Cyberstella") ); m_hlWWW_JSM.SubclassDlgItem(IDC_WEB_JEFFMILL, this); - m_hlWWW_JSM.SetURL( _T("http://www.emuunlim.com/stellax/") ); + m_hlWWW_JSM.SetURL( _T("http://minbar.org") ); m_hlMail_Stella.SubclassDlgItem(IDC_EMAIL_STELLA, this); - m_hlMail_Stella.SetURL( _T("mailto:stella@csc.ncsu.edu") ); + m_hlMail_Stella.SetURL( _T("mailto:stella-main@lists.sourceforge.net") ); m_hlWWW_Stella.SubclassDlgItem(IDC_WEB_STELLA, this); - m_hlWWW_Stella.SetURL( _T("http://stella.atari.org/") ); + m_hlWWW_Stella.SetURL( _T("http://stella.sourceforge.net") ); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE diff --git a/stella/src/ui/cyberstella/Cyberstella.dsp b/stella/src/ui/cyberstella/Cyberstella.dsp index a682e659f..f49ded117 100644 --- a/stella/src/ui/cyberstella/Cyberstella.dsp +++ b/stella/src/ui/cyberstella/Cyberstella.dsp @@ -40,9 +40,10 @@ RSC=rc.exe # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\games" /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /FR /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\games" /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /D DIRECTINPUT_VERSION=0x0800 /FR /FD /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 @@ -53,7 +54,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 -# ADD LINK32 /nologo /subsystem:windows /machine:I386 +# ADD LINK32 dxguid.lib ddraw.lib dsound.lib /nologo /subsystem:windows /machine:I386 !ELSEIF "$(CFG)" == "Cyberstella - Win32 Debug" @@ -69,7 +70,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\games" /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /FR /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\games" /I "..\..\build" /I "..\..\emucore" /I "..\..\emucore\m6502\src" /I "..\..\emucore\m6502\src\bspf\src" /I "..\sound" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /D "BSPF_WIN32" /D DIRECTINPUT_VERSION=0x0800 /FR /FD /GZ /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 @@ -80,7 +81,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 dxguid.lib ddraw.lib dsound.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept !ENDIF @@ -97,10 +98,6 @@ SOURCE=.\AboutDlg.cpp # End Source File # Begin Source File -SOURCE=.\AudioStream.cxx -# End Source File -# Begin Source File - SOURCE=.\CRegBinding.cpp # End Source File # Begin Source File @@ -157,6 +154,10 @@ SOURCE=.\pch.cxx # End Source File # Begin Source File +SOURCE=.\SettingsWin32.cxx +# End Source File +# Begin Source File + SOURCE=.\SoundWin32.cxx # End Source File # Begin Source File @@ -177,10 +178,6 @@ SOURCE=.\AboutDlg.h # End Source File # Begin Source File -SOURCE=.\AudioStream.hxx -# End Source File -# Begin Source File - SOURCE=.\CRegBinding.h # End Source File # Begin Source File @@ -237,6 +234,10 @@ SOURCE=.\Resource.h # End Source File # Begin Source File +SOURCE=.\SettingsWin32.hxx +# End Source File +# Begin Source File + SOURCE=.\SoundWin32.hxx # End Source File # Begin Source File @@ -257,10 +258,6 @@ SOURCE=.\res\Cyberstella.rc2 # End Source File # Begin Source File -SOURCE=.\Dir.ico -# End Source File -# Begin Source File - SOURCE=.\res\Dir.ico # End Source File # Begin Source File @@ -269,10 +266,6 @@ SOURCE=.\res\Stella.ico # End Source File # Begin Source File -SOURCE=.\Stella.ico -# End Source File -# Begin Source File - SOURCE=.\res\Toolbar.bmp # End Source File # End Group @@ -361,6 +354,14 @@ SOURCE=..\..\emucore\CartE7.hxx # End Source File # Begin Source File +SOURCE=..\..\emucore\CartF4.cxx +# End Source File +# Begin Source File + +SOURCE=..\..\emucore\CartF4.hxx +# End Source File +# Begin Source File + SOURCE=..\..\emucore\CartF4SC.cxx # End Source File # Begin Source File @@ -473,6 +474,14 @@ SOURCE=..\..\emucore\Event.hxx # End Source File # Begin Source File +SOURCE=..\..\emucore\EventHandler.cxx +# End Source File +# Begin Source File + +SOURCE=..\..\emucore\EventHandler.hxx +# End Source File +# Begin Source File + SOURCE=..\..\emucore\Joystick.cxx # End Source File # Begin Source File @@ -553,6 +562,14 @@ SOURCE=..\..\emucore\Serializer.hxx # End Source File # Begin Source File +SOURCE=..\..\emucore\Settings.cxx +# End Source File +# Begin Source File + +SOURCE=..\..\emucore\Settings.hxx +# End Source File +# Begin Source File + SOURCE=..\..\emucore\Sound.cxx # End Source File # Begin Source File @@ -561,6 +578,10 @@ SOURCE=..\..\emucore\Sound.hxx # End Source File # Begin Source File +SOURCE=..\..\emucore\StellaEvent.hxx +# End Source File +# Begin Source File + SOURCE=..\..\emucore\Switches.cxx # End Source File # Begin Source File @@ -575,6 +596,14 @@ SOURCE=..\..\emucore\TIA.cxx SOURCE=..\..\emucore\TIA.hxx # End Source File +# Begin Source File + +SOURCE=..\..\emucore\TIASound.c +# End Source File +# Begin Source File + +SOURCE=..\..\emucore\TIASound.h +# End Source File # End Group # Begin Group "M6502" @@ -636,38 +665,6 @@ SOURCE=..\..\emucore\m6502\src\System.cxx SOURCE=..\..\emucore\m6502\src\System.hxx # End Source File # End Group -# Begin Group "Sound" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\sound\TIASound.c -# End Source File -# Begin Source File - -SOURCE=..\sound\TIASound.h -# End Source File -# End Group -# Begin Group "Games" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\games\Gunfight.h -# End Source File -# Begin Source File - -SOURCE=..\..\games\Jammed.h -# End Source File -# Begin Source File - -SOURCE=..\..\games\Qb.h -# End Source File -# Begin Source File - -SOURCE=..\..\games\Thrust.h -# End Source File -# End Group # Begin Source File SOURCE=..\..\emucore\m6502\src\bspf\src\bspf.hxx @@ -676,13 +673,5 @@ SOURCE=..\..\emucore\m6502\src\bspf\src\bspf.hxx SOURCE=..\..\..\CyberstellaTodo.txt # End Source File -# Begin Source File - -SOURCE=..\..\build\M6502Hi.ins -# End Source File -# Begin Source File - -SOURCE=..\..\build\M6502Low.ins -# End Source File # End Target # End Project diff --git a/stella/src/ui/cyberstella/Cyberstella.h b/stella/src/ui/cyberstella/Cyberstella.h index 585492bc0..aaec2e10d 100644 --- a/stella/src/ui/cyberstella/Cyberstella.h +++ b/stella/src/ui/cyberstella/Cyberstella.h @@ -27,7 +27,7 @@ public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCyberstellaApp) - public: + public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL diff --git a/stella/src/ui/cyberstella/Cyberstella.rc b/stella/src/ui/cyberstella/Cyberstella.rc index c22bfe4f3..8bcb967be 100644 --- a/stella/src/ui/cyberstella/Cyberstella.rc +++ b/stella/src/ui/cyberstella/Cyberstella.rc @@ -129,13 +129,6 @@ BEGIN BEGIN MENUITEM "&Cyberstella", IDC_CONFIG END - POPUP "&Games" - BEGIN - MENUITEM "&Gunfight", IDG_GUNFIGHT - MENUITEM "&Jammed", IDG_JAMMED - MENUITEM "&QB", IDG_QB - MENUITEM "&Thrust", IDG_THRUST - END POPUP "&Help" BEGIN MENUITEM "&About Cyberstella...", ID_APP_ABOUT @@ -173,7 +166,7 @@ END IDD_CYBERSTELLA_FORM DIALOGEX 0, 0, 409, 169 STYLE WS_CHILD -FONT 8, "MS Shell Dlg" +FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN CONTROL "&Files found in:",-1,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,7,7,44,8 @@ -185,29 +178,29 @@ BEGIN SS_NOPREFIX | WS_GROUP,57,7,254,8 END -IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 390, 133 +IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 285, 128 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Information" FONT 8, "MS Shell Dlg" BEGIN - LTEXT "You must own legal copies of all ROM images you are using. Neither Manuel Polik nor the rest of the Stella team can tell you where to find ROM images so DON'T ASK. All requests will either be deleted or sent to the appropriate authorities.", - -1,7,27,376,18,SS_NOPREFIX + LTEXT "You must own legal copies of all ROM images you are using. The Stella team cannot tell you where to find ROM images, so DON'T ASK. All requests will either be deleted or sent to the appropriate authorities.", + -1,7,21,266,26,SS_NOPREFIX LTEXT "If you have a question or a problem with Cyberstella, please try one of these contacts:", - -1,7,58,376,8,SS_NOPREFIX - LTEXT "Manuel Polik:",-1,7,76,62,8,SS_NOPREFIX - LTEXT "cybergoth@nexgo.de",IDC_EMAIL_JEFFMILL,73,76,103,8, + -1,7,58,271,8,SS_NOPREFIX + LTEXT "Stephen Anthony",-1,7,76,62,8,SS_NOPREFIX + LTEXT "stephena@users.sourceforge.net",IDC_EMAIL_MAINTAINER,73, + 76,103,8,SS_NOPREFIX | SS_NOTIFY + LTEXT "http://minbar.org",IDC_WEB_MAINTAINER,190,76,82,8, SS_NOPREFIX | SS_NOTIFY - LTEXT "http://www.emuunlim.com/stellax/",IDC_WEB_JEFFMILL,178, - 76,110,8,SS_NOPREFIX | SS_NOTIFY - LTEXT "Stella dev team:",-1,7,88,52,8,SS_NOPREFIX - LTEXT "stella@csc.ncsu.edu",IDC_EMAIL_STELLA,73,88,67,8, - SS_NOPREFIX | SS_NOTIFY - LTEXT "http://stella.atari.org",IDC_WEB_STELLA,178,88,65,8, - SS_NOPREFIX | SS_NOTIFY - LTEXT "Cyberstella is free software. It may not be sold or offered as part of a collection for sale without permission from Manuel Polik. When distributing Cyberstella, the original distribution (the .zip file) must not be altered.", - -1,7,7,376,19,SS_NOPREFIX - CONTROL "",-1,"Static",SS_ETCHEDHORZ,7,50,375,1 - PUSHBUTTON "&Continue",IDC_CONTINUE,136,111,118,14 + LTEXT "Stella dev team:",-1,7,89,52,8,SS_NOPREFIX + LTEXT "stella-main@lists.sourceforge.net",IDC_EMAIL_STELLA,73, + 89,105,8,SS_NOPREFIX | SS_NOTIFY + LTEXT "http://stella.sourceforge.net",IDC_WEB_STELLA,190,89,88, + 8,SS_NOPREFIX | SS_NOTIFY + LTEXT "Cyberstella v1.4 is GPL software.",-1,7,7,271,9, + SS_NOPREFIX + CONTROL "",-1,"Static",SS_ETCHEDHORZ,7,50,268,1 + PUSHBUTTON "&Continue",IDC_CONTINUE,112,107,60,14 END IDD_CONFIG_PAGE DIALOG DISCARDABLE 0, 0, 390, 112 @@ -239,8 +232,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 + FILEVERSION 1,0,0,0 + PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -253,17 +246,20 @@ VS_VERSION_INFO VERSIONINFO BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "040904B0" + BLOCK "040904b0" BEGIN + VALUE "Comments", "\0" VALUE "CompanyName", "\0" VALUE "FileDescription", "Cyberstella MFC Application\0" - VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "FileVersion", "1.4\0" VALUE "InternalName", "Cyberstella\0" - VALUE "LegalCopyright", "Copyright (C) 2002\0" + VALUE "LegalCopyright", "Copyright (C) 2003\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "Cyberstella.EXE\0" + VALUE "PrivateBuild", "\0" VALUE "ProductName", "Cyberstella Application\0" - VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "ProductVersion", "1.4\0" + VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" @@ -294,9 +290,9 @@ BEGIN IDD_ABOUTBOX, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 383 + RIGHTMARGIN, 278 TOPMARGIN, 7 - BOTTOMMARGIN, 126 + BOTTOMMARGIN, 121 END IDD_CONFIG_PAGE, DIALOG diff --git a/stella/src/ui/cyberstella/CyberstellaView.cpp b/stella/src/ui/cyberstella/CyberstellaView.cpp index d006ed70c..62cc9d63e 100644 --- a/stella/src/ui/cyberstella/CyberstellaView.cpp +++ b/stella/src/ui/cyberstella/CyberstellaView.cpp @@ -9,6 +9,7 @@ #include "StellaConfig.h" #include "Console.hxx" #include "SoundWin32.hxx" +#include "SettingsWin32.hxx" #ifdef _DEBUG #define new DEBUG_NEW @@ -41,10 +42,6 @@ BEGIN_MESSAGE_MAP(CCyberstellaView, CFormView) ON_BN_CLICKED(IDC_CONFIG, OnConfig) ON_BN_CLICKED(IDC_PLAY, OnPlay) ON_WM_DESTROY() - ON_COMMAND(IDG_GUNFIGHT, OnGunfight) - ON_COMMAND(IDG_JAMMED, OnJammed) - ON_COMMAND(IDG_QB, OnQb) - ON_COMMAND(IDG_THRUST, OnThrust) ON_MESSAGE(MSG_GAMELIST_UPDATE, updateListInfos) ON_MESSAGE(MSG_GAMELIST_DISPLAYNOTE, displayNote) ON_MESSAGE(MSG_VIEW_INITIALIZE, initialize) @@ -142,6 +139,10 @@ LRESULT CCyberstellaView::initialize(WPARAM wParam, LPARAM lParam) // Create a properties set for us to use m_pPropertiesSet = new PropertiesSet(); + // Create SettingsWin32 object + pSettings = new SettingsWin32(); + pSettings->loadConfig(); + // Set up the image list. HICON hFolder, hAtari; @@ -212,34 +213,6 @@ LRESULT CCyberstellaView::displayNote(WPARAM wParam, LPARAM lParam) return 0; } -void CCyberstellaView::OnGunfight() -{ - MessageBox("To avoid probable GPL violations by including non-GPL games into this project, this function is currently disabled. We're working on a GPL conform solution though, so check back soon.", "Sorry, currently not available!", MB_OK); - //playRom(IDG_GUNFIGHT); - //MessageBox("If you'd like to play Gunfight on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK); -} - -void CCyberstellaView::OnJammed() -{ - MessageBox("To avoid probable GPL violations by including non-GPL games into this project, this function is currently disabled. We're working on a GPL conform solution though, so check back soon.", "Sorry, currently not available!", MB_OK); - //playRom(IDG_JAMMED); - //MessageBox("If you'd like to play Jammed on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK); -} - -void CCyberstellaView::OnQb() -{ - MessageBox("To avoid probable GPL violations by including non-GPL games into this project, this function is currently disabled. We're working on a GPL conform solution though, so check back soon.", "Sorry, currently not available!", MB_OK); - //playRom(IDG_QB); - //MessageBox("If you'd like to play Qb on a real VCS, you can order a cartridge for only $16\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK); -} - -void CCyberstellaView::OnThrust() -{ - MessageBox("To avoid probable GPL violations by including non-GPL games into this project, this function is currently disabled. We're working on a GPL conform solution though, so check back soon.", "Sorry, currently not available!", MB_OK); - //playRom(IDG_THRUST); - //MessageBox("If you'd like to play Thrust on a real VCS, you can order a cartridge for only $25\nfrom http://webpages.charter.net/hozervideo!", "Commercial Break", MB_OK); -} - void CCyberstellaView::playRom(LONG gameID) { @@ -254,179 +227,116 @@ void CCyberstellaView::playRom(LONG gameID) CString fileName; BYTE* pImage = NULL; LPCTSTR pszFileName = NULL; - Console* pConsole = NULL; - Sound* pSound = NULL; DWORD dwImageSize; DWORD dwActualSize; - Event rEvent; + Console* pConsole = NULL; // Create Sound driver object // (Will be initialized once we have a window handle below) - if (m_pGlobalData->bNoSound) + if(m_pGlobalData->bNoSound) { TRACE("Creating Sound driver"); - pSound = new Sound; + pSound = new Sound(); } else { TRACE("Creating SoundWin32 driver"); - pSound = new SoundWin32; + pSound = new SoundWin32(); } if ( pSound == NULL ) { goto exit; } - // Special handling for special games - switch(gameID) + + fileName = m_List.getCurrentFile(); + + // Safety Bail Out + if(fileName.GetLength() <= 0) + return; + + // Load the rom file + HANDLE hFile; + hFile = ::CreateFile( fileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + if(hFile == INVALID_HANDLE_VALUE) { - case IDG_GUNFIGHT: - { - /*pszFileName = "Gunfight"; - dwActualSize = sizeof gunfight; - pImage = new BYTE[dwActualSize]; - for(int i=0; ibNoSound) + if(!m_pGlobalData->bNoSound) { - // - // 060499: Pass pwnd->GetHWND() in instead of hwnd as some systems - // will not play sound if this isn't set to the active window - // + SoundWin32* pSoundWin32 = static_cast( pSound ); - SoundWin32* pSoundWin32 = static_cast( pSound ); - - hr = pSoundWin32->Initialize( *pwnd ); - if ( FAILED(hr) ) - { - TRACE( "Sndwin32 Initialize failed, err = %X", hr ); - goto exit; - } + hr = pSoundWin32->Initialize(*pwnd); + if(FAILED(hr)) + { + TRACE( "Sndwin32 Initialize failed, err = %X", hr ); + } } ::ShowWindow( *this, SW_HIDE ); @@ -502,7 +400,9 @@ exit: delete pwnd; delete pConsole; delete pSound; - if (pImage) delete pImage; + + if(pImage) + delete pImage; EnableWindow(TRUE); diff --git a/stella/src/ui/cyberstella/CyberstellaView.h b/stella/src/ui/cyberstella/CyberstellaView.h index ce386a8f1..581dde440 100644 --- a/stella/src/ui/cyberstella/CyberstellaView.h +++ b/stella/src/ui/cyberstella/CyberstellaView.h @@ -11,6 +11,8 @@ #include "GlobalData.hxx" #include "PropsSet.hxx" +#include "Sound.hxx" +#include "SettingsWin32.hxx" #include "GameList.h" class CCyberstellaView : public CFormView @@ -60,10 +62,6 @@ protected: afx_msg void OnConfig(); afx_msg void OnPlay(); afx_msg void OnDestroy(); - afx_msg void OnGunfight(); - afx_msg void OnJammed(); - afx_msg void OnQb(); - afx_msg void OnThrust(); //}}AFX_MSG DECLARE_MESSAGE_MAP() @@ -78,6 +76,8 @@ private: // members PropertiesSet* m_pPropertiesSet; + Sound* pSound; + SettingsWin32* pSettings; bool m_bIsPause; }; diff --git a/stella/src/ui/cyberstella/DirectInput.hxx b/stella/src/ui/cyberstella/DirectInput.hxx index 188d6e018..7e106c2df 100644 --- a/stella/src/ui/cyberstella/DirectInput.hxx +++ b/stella/src/ui/cyberstella/DirectInput.hxx @@ -1,18 +1,32 @@ +//============================================================================ // -// StellaX -// Jeff Miller 05/01/2000 +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa // -#ifndef DIRECTIN_H -#define DIRECTIN_H +// Copyright (c) 1995-1999 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: DirectInput.hxx,v 1.2 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +#ifndef DIRECT_INPUT_HXX +#define DIRECT_INPUT_HXX class CDirectInput { -public: - + public: CDirectInput( HWND hwnd, DWORD dwDevType, int nButtonCount ); - virtual ~CDirectInput( ); + virtual ~CDirectInput( ); - virtual HRESULT Initialize( void ); + public: + virtual HRESULT Initialize( void ); virtual HRESULT Update( void ) = 0; diff --git a/stella/src/ui/cyberstella/DirectXFullScreen.cxx b/stella/src/ui/cyberstella/DirectXFullScreen.cxx index 56e19ea0b..ee1b2eb25 100644 --- a/stella/src/ui/cyberstella/DirectXFullScreen.cxx +++ b/stella/src/ui/cyberstella/DirectXFullScreen.cxx @@ -2,6 +2,8 @@ // StellaX // Jeff Miller 05/12/2000 // +#define STRICT + #include "pch.hxx" #include "DirectXFullScreen.hxx" #include "resource.h" @@ -10,7 +12,9 @@ #include "bspf.hxx" #include "Console.hxx" -#include "Event.hxx" +#include "EventHandler.hxx" +#include "StellaEvent.hxx" +#include "Sound.hxx" #include "MediaSrc.hxx" /* @@ -30,14 +34,14 @@ LPCTSTR CDirectXFullScreen::pszClassName = _T("StellaXClass"); CDirectXFullScreen::CDirectXFullScreen( const CGlobalData* rGlobalData, const Console* pConsole, - Event& rEvent + Sound* pSound ) : \ m_rGlobalData( rGlobalData ), - m_pConsole( pConsole ), - m_rEvent( rEvent ), + m_pConsole( pConsole ), + m_pSound( pSound ), m_fInitialized( FALSE ), - m_hwnd( NULL ), + m_hwnd( NULL ), m_piDD( NULL ), m_piDDSPrimary( NULL ), @@ -635,6 +639,9 @@ DWORD CDirectXFullScreen::Run( break; } +// FIXME - clean up this logic here, make it more like main in mainSDL + m_pSound->updateSound(rMediaSource); + // // Check for keyboard, mouse, joystick input // @@ -695,108 +702,101 @@ DWORD CDirectXFullScreen::Run( return msg.wParam; } +// FIXME - Event handling should be stripped out of this class +// This class should only be a Display class, similar to DisplaySDL +// or DisplayX11 + // --------------------------------------------------------------------------- // Event Handling // VK_* is defined in winuser.h - struct KeyEventStruct { int nVirtKey; int nAsyncVirtKey; - Event::Type eventCode; + StellaEvent::KeyCode keyCode; }; - static KeyEventStruct KeyEventMap[] = { - /* -------------------------------------------------------------------- */ - /* left keypad */ + { DIK_F1, VK_F1, StellaEvent::KCODE_F1 }, + { DIK_F2, VK_F2, StellaEvent::KCODE_F2 }, + { DIK_F3, VK_F3, StellaEvent::KCODE_F3 }, + { DIK_F4, VK_F4, StellaEvent::KCODE_F4 }, + { DIK_F5, VK_F5, StellaEvent::KCODE_F5 }, + { DIK_F6, VK_F6, StellaEvent::KCODE_F6 }, + { DIK_F7, VK_F7, StellaEvent::KCODE_F7 }, + { DIK_F8, VK_F8, StellaEvent::KCODE_F8 }, + { DIK_F9, VK_F9, StellaEvent::KCODE_F9 }, + { DIK_F10, VK_F10, StellaEvent::KCODE_F10 }, + { DIK_F11, VK_F11, StellaEvent::KCODE_F11 }, + { DIK_F12, VK_F12, StellaEvent::KCODE_F12 }, - { DIK_1, '1', Event::KeyboardZero1 }, - { DIK_2, '2', Event::KeyboardZero2 }, - { DIK_3, '3', Event::KeyboardZero3 }, - { DIK_Q, 'Q', Event::KeyboardZero4 }, - { DIK_W, 'W', Event::KeyboardZero5 }, - { DIK_E, 'E', Event::KeyboardZero6 }, - { DIK_A, 'A', Event::KeyboardZero7 }, - { DIK_S, 'S', Event::KeyboardZero8 }, - { DIK_D, 'D', Event::KeyboardZero9 }, - { DIK_Z, 'Z', Event::KeyboardZeroStar }, - { DIK_X, 'X', Event::KeyboardZero0 }, - { DIK_C, 'C', Event::KeyboardZeroPound }, + { DIK_UP, VK_UP, StellaEvent::KCODE_UP }, + { DIK_DOWN, VK_DOWN, StellaEvent::KCODE_DOWN }, + { DIK_LEFT, VK_LEFT, StellaEvent::KCODE_LEFT }, + { DIK_RIGHT, VK_RIGHT, StellaEvent::KCODE_RIGHT }, + { DIK_SPACE, VK_SPACE, StellaEvent::KCODE_SPACE }, + { DIK_LCONTROL, VK_CONTROL, StellaEvent::KCODE_CTRL }, + { DIK_RCONTROL, VK_CONTROL, StellaEvent::KCODE_CTRL }, +// FIXME +// { SDLK_LALT, StellaEvent::KCODE_ALT }, +// { SDLK_RALT, StellaEvent::KCODE_ALT }, - /* -------------------------------------------------------------------- */ - /* right keypad */ + { DIK_A, 'A', StellaEvent::KCODE_a }, + { DIK_B, 'B', StellaEvent::KCODE_b }, + { DIK_C, 'C', StellaEvent::KCODE_c }, + { DIK_D, 'D', StellaEvent::KCODE_d }, + { DIK_E, 'E', StellaEvent::KCODE_e }, + { DIK_F, 'F', StellaEvent::KCODE_f }, + { DIK_G, 'G', StellaEvent::KCODE_g }, + { DIK_H, 'H', StellaEvent::KCODE_h }, + { DIK_I, 'I', StellaEvent::KCODE_i }, + { DIK_J, 'J', StellaEvent::KCODE_j }, + { DIK_K, 'K', StellaEvent::KCODE_k }, + { DIK_L, 'L', StellaEvent::KCODE_l }, + { DIK_M, 'M', StellaEvent::KCODE_m }, + { DIK_N, 'N', StellaEvent::KCODE_n }, + { DIK_O, 'O', StellaEvent::KCODE_o }, + { DIK_P, 'P', StellaEvent::KCODE_p }, + { DIK_Q, 'Q', StellaEvent::KCODE_q }, + { DIK_R, 'R', StellaEvent::KCODE_r }, + { DIK_S, 'S', StellaEvent::KCODE_s }, + { DIK_T, 'T', StellaEvent::KCODE_t }, + { DIK_U, 'U', StellaEvent::KCODE_u }, + { DIK_V, 'V', StellaEvent::KCODE_v }, + { DIK_W, 'W', StellaEvent::KCODE_w }, + { DIK_X, 'X', StellaEvent::KCODE_x }, + { DIK_Y, 'Y', StellaEvent::KCODE_y }, + { DIK_Z, 'Z', StellaEvent::KCODE_z }, - { DIK_8, '8', Event::KeyboardOne1 }, - { DIK_9, '9', Event::KeyboardOne2 }, - { DIK_0, '0', Event::KeyboardOne3 }, - { DIK_I, 'I', Event::KeyboardOne4 }, - { DIK_O, 'O', Event::KeyboardOne5 }, - { DIK_P, 'P', Event::KeyboardOne6 }, - { DIK_K, 'K', Event::KeyboardOne7 }, - { DIK_L, 'L', Event::KeyboardOne8 }, - { DIK_SEMICOLON,';', Event::KeyboardOne9 }, - { DIK_COMMA, ',', Event::KeyboardOneStar }, - { DIK_PERIOD, '.', Event::KeyboardOne0 }, - { DIK_SLASH, '/', Event::KeyboardOnePound }, + { DIK_0, '0', StellaEvent::KCODE_0 }, + { DIK_1, '1', StellaEvent::KCODE_1 }, + { DIK_2, '2', StellaEvent::KCODE_2 }, + { DIK_3, '3', StellaEvent::KCODE_3 }, + { DIK_4, '4', StellaEvent::KCODE_4 }, + { DIK_5, '5', StellaEvent::KCODE_5 }, + { DIK_6, '6', StellaEvent::KCODE_6 }, + { DIK_7, '7', StellaEvent::KCODE_7 }, + { DIK_8, '8', StellaEvent::KCODE_8 }, + { DIK_9, '9', StellaEvent::KCODE_9 }, - /* -------------------------------------------------------------------- */ - /* left joystick */ +// FIXME - add keypad codes here ... - { DIK_DOWN, VK_DOWN, Event::JoystickZeroDown }, - { DIK_UP, VK_UP, Event::JoystickZeroUp }, - { DIK_LEFT, VK_LEFT, Event::JoystickZeroLeft }, - { DIK_RIGHT, VK_RIGHT, Event::JoystickZeroRight }, - { DIK_SPACE, VK_SPACE, Event::JoystickZeroFire }, - - /* left joystick (alt.) */ - - { DIK_W, 'W', Event::JoystickZeroUp }, - { DIK_S, 'S', Event::JoystickZeroDown }, - { DIK_A, 'A', Event::JoystickZeroLeft }, - { DIK_D, 'D', Event::JoystickZeroRight }, - { DIK_TAB, VK_TAB, Event::JoystickZeroFire }, - - /* I added this one (for my powerramp joystick) */ - - { DIK_LCONTROL, VK_CONTROL, Event::JoystickZeroFire }, - - /* left joystick booster-grip */ - - { DIK_Z, 'Z', Event::BoosterGripZeroTrigger }, - { DIK_X, 'X', Event::BoosterGripZeroBooster }, - - /* left joystick booster-grip (alt.) */ - - { DIK_1, '1', Event::BoosterGripZeroTrigger }, - { DIK_2, '2', Event::BoosterGripZeroBooster }, - - /* -------------------------------------------------------------------- */ - /* right joystick */ - - { DIK_L, 'L', Event::JoystickOneDown }, - { DIK_O, 'O', Event::JoystickOneUp }, - { DIK_K, 'K', Event::JoystickOneLeft }, - { DIK_SEMICOLON,';', Event::JoystickOneRight }, - { DIK_J, 'J', Event::JoystickOneFire }, - - /* right joystick booster-grip */ - - { DIK_N, 'N', Event::BoosterGripOneTrigger }, - { DIK_M, 'M', Event::BoosterGripOneBooster }, - - /* -------------------------------------------------------------------- */ - /* console controls */ - - { DIK_F1, VK_F1, Event::ConsoleSelect }, - { DIK_F2, VK_F2, Event::ConsoleReset }, - { DIK_F3, VK_F3, Event::ConsoleColor }, - { DIK_F4, VK_F4, Event::ConsoleBlackWhite }, - { DIK_F5, VK_F5, Event::ConsoleLeftDifficultyA }, - { DIK_F6, VK_F6, Event::ConsoleLeftDifficultyB }, - { DIK_F7, VK_F7, Event::ConsoleRightDifficultyA }, - { DIK_F8, VK_F8, Event::ConsoleRightDifficultyB } +// FIXME - get rest of codes ... +// { SDLK_BACKSPACE, StellaEvent::KCODE_BACKSPACE }, + { DIK_TAB, VK_TAB, StellaEvent::KCODE_TAB }, +// { SDLK_RETURN, StellaEvent::KCODE_RETURN }, +// { SDLK_PAUSE, StellaEvent::KCODE_PAUSE }, +// { SDLK_ESCAPE, StellaEvent::KCODE_ESCAPE }, + { DIK_COMMA, ',', StellaEvent::KCODE_COMMA }, + { DIK_PERIOD, '.', StellaEvent::KCODE_PERIOD }, + { DIK_SLASH, '/', StellaEvent::KCODE_SLASH }, +// { SDLK_BACKSLASH, StellaEvent::KCODE_BACKSLASH }, + { DIK_SEMICOLON,';', StellaEvent::KCODE_SEMICOLON } +// { SDLK_QUOTE, StellaEvent::KCODE_QUOTE }, +// { SDLK_BACKQUOTE, StellaEvent::KCODE_BACKQUOTE }, +// { SDLK_LEFTBRACKET, StellaEvent::KCODE_LEFTBRACKET}, +// { SDLK_RIGHTBRACKET,StellaEvent::KCODE_RIGHTBRACKET} }; void CDirectXFullScreen::UpdateEvents( @@ -808,9 +808,9 @@ void CDirectXFullScreen::UpdateEvents( // and I don't want to undo a set i may have done earlier in the loop // - const int nEventCount = Event::LastType; - long rgEventState[ nEventCount ]; - ZeroMemory( rgEventState, nEventCount * sizeof(long) ); + const int nSize = _countof(KeyEventMap); +// long rgKeyEventState[ nSize ]; +// ZeroMemory( rgKeyEventState, nSize * sizeof(StellaEvent::KeyCode) ); int i; @@ -820,25 +820,20 @@ void CDirectXFullScreen::UpdateEvents( if (m_pDirectKeyboard->Update() == S_OK) { - int nSize = _countof(KeyEventMap); - for (i = 0; i < nSize; ++i) { - rgEventState[KeyEventMap[i].eventCode] |= - m_pDirectKeyboard->IsButtonPressed(KeyEventMap[i].nVirtKey); + int state = (m_pDirectKeyboard->IsButtonPressed(KeyEventMap[i].nVirtKey)) ? 1 : 0; + m_pConsole->eventHandler().sendKeyEvent(KeyEventMap[i].keyCode, state); } } else { // Fallback -- if Keyboard update failed (most likely due to // DirectInput not being available), then use the old async - - int nSize = _countof(KeyEventMap); - for (i = 0; i < nSize; ++i) { - rgEventState[KeyEventMap[i].eventCode] |= - (::GetAsyncKeyState(KeyEventMap[i].nAsyncVirtKey) ? 1: 0); + int state = (::GetAsyncKeyState(KeyEventMap[i].nAsyncVirtKey)) ? 1 : 0; + m_pConsole->eventHandler().sendKeyEvent(KeyEventMap[i].keyCode, state); } } @@ -846,6 +841,7 @@ void CDirectXFullScreen::UpdateEvents( // Update joystick // +/* FIXME - add multiple joysticks if (m_pDirectJoystick->Update() == S_OK) { rgEventState[Event::JoystickZeroFire] |= @@ -871,7 +867,7 @@ void CDirectXFullScreen::UpdateEvents( { rgEventState[Event::JoystickZeroDown] = 1; } - } + } */ // // Update mouse @@ -886,19 +882,19 @@ void CDirectXFullScreen::UpdateEvents( // Mouse resistance is measured between 0...1000000 - rgEventState[ m_rGlobalData->PaddleResistanceEvent() ] = (999-x)*1000; +// rgEventState[ m_rGlobalData->PaddleResistanceEvent() ] = (999-x)*1000; - rgEventState[ m_rGlobalData->PaddleFireEvent() ] |= m_pDirectMouse->IsButtonPressed(0); +// rgEventState[ m_rGlobalData->PaddleFireEvent() ] |= m_pDirectMouse->IsButtonPressed(0); } // // Write new event state // - for (i = 0; i < nEventCount; ++i) - { - m_rEvent.set( (Event::Type)i, rgEventState[i] ); - } +// for (i = 0; i < nEventCount; ++i) +// { +// m_rEvent.set( (Event::Type)i, rgEventState[i] ); +// } } // --------------------------------------------------------------------------- diff --git a/stella/src/ui/cyberstella/DirectXFullScreen.hxx b/stella/src/ui/cyberstella/DirectXFullScreen.hxx index f81da633c..c3436df6b 100644 --- a/stella/src/ui/cyberstella/DirectXFullScreen.hxx +++ b/stella/src/ui/cyberstella/DirectXFullScreen.hxx @@ -8,6 +8,7 @@ class Console; class MediaSource; +class Sound; class CDirectInput; @@ -16,12 +17,10 @@ class CDirectInput; class CDirectXFullScreen { -public: - - CDirectXFullScreen( const CGlobalData* rGlobalData, - const Console* pConsole, - Event& rEvent ); - ~CDirectXFullScreen(); + public: + CDirectXFullScreen(const CGlobalData* rGlobalData, const Console* pConsole, + Sound* pSound); + ~CDirectXFullScreen(); HRESULT Initialize( int cx = 0, int cy = 0 ); @@ -55,10 +54,9 @@ private: // Stella objects - const Console* m_pConsole; - Event& m_rEvent; - - const CGlobalData* m_rGlobalData; + const Console* m_pConsole; + const CGlobalData* m_rGlobalData; + Sound* m_pSound; SIZE m_sizeGame; BYTE m_rgbPixelDataTable[256]; diff --git a/stella/src/ui/cyberstella/M6502Hi.ins b/stella/src/ui/cyberstella/M6502Hi.ins new file mode 100644 index 000000000..72a5ad828 --- /dev/null +++ b/stella/src/ui/cyberstella/M6502Hi.ins @@ -0,0 +1,4432 @@ +//============================================================================ +// +// MM MM 6666 555555 0000 2222 +// MMMM MMMM 66 66 55 00 00 22 22 +// MM MMM MM 66 55 00 00 22 +// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" +// MM MM 66 66 55 00 00 22 +// MM MM 66 66 55 55 00 00 22 +// MM MM 6666 5555 0000 222222 +// +// Copyright (c) 1995-1998 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: M6502Hi.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +/** + Code to handle addressing modes and branch instructions for + high compatibility emulation + + @author Bradford W. Mott + @version $Id: M6502Hi.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +*/ + +#ifndef NOTSAMEPAGE + #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00) +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//============================================================================ +// +// MM MM 6666 555555 0000 2222 +// MMMM MMMM 66 66 55 00 00 22 22 +// MM MMM MM 66 55 00 00 22 +// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" +// MM MM 66 66 55 00 00 22 +// MM MM 66 66 55 55 00 00 22 +// MM MM 6666 5555 0000 222222 +// +// Copyright (c) 1995-1998 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: M6502Hi.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +/** + Code and cases to emulate each of the 6502 instruction + + @author Bradford W. Mott + @version $Id: M6502Hi.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +*/ + +#ifndef NOTSAMEPAGE + #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00) +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +case 0x69: +{ + operand = peek(PC++); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x65: +{ + operand = peek(peek(PC++)); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x75: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x6d: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7d: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x79: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x61: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x71: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x4b: +{ + operand = peek(PC++); +} +{ + A &= operand; + + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = (A >> 1) & 0x7f; + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x0b: +case 0x2b: +{ + operand = peek(PC++); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; + C = N; +} +break; + + +case 0x29: +{ + operand = peek(PC++); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x25: +{ + operand = peek(peek(PC++)); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x35: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x2d: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3d: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x39: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x21: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x31: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x8b: +{ + operand = peek(PC++); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. This instruction is + // reported to be unstable! + A = (A | 0xee) & X & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x6b: +{ + operand = peek(PC++); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. There are mixed + // reports on its operation! + if(!D) + { + A &= operand; + A = ((A >> 1) & 0x7f) | (C ? 0x80 : 0x00); + + C = A & 0x40; + V = (A & 0x40) ^ ((A & 0x20) << 1); + + notZ = A; + N = A & 0x80; + } + else + { + uInt8 value = A & operand; + + A = ((value >> 1) & 0x7f) | (C ? 0x80 : 0x00); + N = C; + notZ = A; + V = (value ^ A) & 0x40; + + if(((value & 0x0f) + (value & 0x01)) > 0x05) + { + A = (A & 0xf0) | ((A + 0x06) & 0x0f); + } + + if(((value & 0xf0) + (value & 0x10)) > 0x50) + { + A = (A + 0x60) & 0xff; + C = 1; + } + else + { + C = 0; + } + } +} +break; + + +case 0x0a: +{ + peek(PC); +} +{ + // Set carry flag according to the left-most bit in A + C = A & 0x80; + + A <<= 1; + + notZ = A; + N = A & 0x80; +} +break; + +case 0x06: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x16: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x0e: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x1e: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x90: +{ + operand = peek(PC++); +} +{ + if(!C) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0xb0: +{ + operand = peek(PC++); +} +{ + if(C) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0xf0: +{ + operand = peek(PC++); +} +{ + if(!notZ) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0x24: +{ + operand = peek(peek(PC++)); +} +{ + notZ = (A & operand); + N = operand & 0x80; + V = operand & 0x40; +} +break; + +case 0x2C: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + notZ = (A & operand); + N = operand & 0x80; + V = operand & 0x40; +} +break; + + +case 0x30: +{ + operand = peek(PC++); +} +{ + if(N) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0xD0: +{ + operand = peek(PC++); +} +{ + if(notZ) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0x10: +{ + operand = peek(PC++); +} +{ + if(!N) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0x00: +{ + peek(PC++); + + B = true; + + poke(0x0100 + SP--, PC >> 8); + poke(0x0100 + SP--, PC & 0x00ff); + poke(0x0100 + SP--, PS()); + + I = true; + + PC = peek(0xfffe); + PC |= ((uInt16)peek(0xffff) << 8); +} +break; + + +case 0x50: +{ + operand = peek(PC++); +} +{ + if(!V) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0x70: +{ + operand = peek(PC++); +} +{ + if(V) + { + peek(PC); + uInt16 address = PC + (Int8)operand; + if(NOTSAMEPAGE(PC, address)) + peek((PC & 0xFF00) | (address & 0x00FF)); + PC = address; + } +} +break; + + +case 0x18: +{ + peek(PC); +} +{ + C = false; +} +break; + + +case 0xd8: +{ + peek(PC); +} +{ + D = false; +} +break; + + +case 0x58: +{ + peek(PC); +} +{ + I = false; +} +break; + + +case 0xb8: +{ + peek(PC); +} +{ + V = false; +} +break; + + +case 0xc9: +{ + operand = peek(PC++); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc5: +{ + operand = peek(peek(PC++)); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd5: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xcd: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xdd: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd9: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc1: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd1: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xe0: +{ + operand = peek(PC++); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xe4: +{ + operand = peek(peek(PC++)); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xec: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xc0: +{ + operand = peek(PC++); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc4: +{ + operand = peek(peek(PC++)); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xcc: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xcf: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xdf: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xdb: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xc7: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xd7: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xc3: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xd3: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + + +case 0xc6: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xd6: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xce: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xde: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + + +case 0xca: +{ + peek(PC); +} +{ + X--; + + notZ = X; + N = X & 0x80; +} +break; + + +case 0x88: +{ + peek(PC); +} +{ + Y--; + + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0x49: +{ + operand = peek(PC++); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x45: +{ + operand = peek(peek(PC++)); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x55: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x4d: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5d: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x59: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x41: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x51: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xe6: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xf6: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xee: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xfe: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + + +case 0xe8: +{ + peek(PC); +} +{ + X++; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xc8: +{ + peek(PC); +} +{ + Y++; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0xef: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xff: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xfb: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe7: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf7: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe3: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf3: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x4c: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); +} +{ + PC = operandAddress; +} +break; + +case 0x6c: +{ + uInt16 addr = peek(PC++); + addr |= ((uInt16)peek(PC++) << 8); + + // Simulate the error in the indirect addressing mode! + uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1); + + operandAddress = peek(addr); + operandAddress |= ((uInt16)peek(high) << 8); +} +{ + PC = operandAddress; +} +break; + + +case 0x20: +{ + uInt8 low = peek(PC++); + peek(0x0100 + SP); + + // It seems that the 650x does not push the address of the next instruction + // on the stack it actually pushes the address of the next instruction + // minus one. This is compensated for in the RTS instruction + poke(0x0100 + SP--, PC >> 8); + poke(0x0100 + SP--, PC & 0xff); + + PC = low | ((uInt16)peek(PC++) << 8); +} +break; + + +case 0xbb: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A = X = SP = SP & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xaf: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xbf: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa7: +{ + operand = peek(peek(PC++)); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb7: +{ + uInt8 address = peek(PC++); + peek(address); + address += Y; + operand = peek(address); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa3: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb3: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xa9: +{ + operand = peek(PC++); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa5: +{ + operand = peek(peek(PC++)); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb5: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xad: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xbd: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb9: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa1: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb1: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xa2: +{ + operand = peek(PC++); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xa6: +{ + operand = peek(peek(PC++)); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xb6: +{ + uInt8 address = peek(PC++); + peek(address); + address += Y; + operand = peek(address); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xae: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xbe: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xa0: +{ + operand = peek(PC++); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xa4: +{ + operand = peek(peek(PC++)); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xb4: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xac: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xbc: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0x4a: +{ + peek(PC); +} +{ + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = (A >> 1) & 0x7f; + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x46: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x56: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x4e: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x5e: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0xab: +{ + operand = peek(PC++); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. This instruction is + // reported to be very unstable! + A = X = (A | 0xee) & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x1a: +case 0x3a: +case 0x5a: +case 0x7a: +case 0xda: +case 0xea: +case 0xfa: +{ + peek(PC); +} +{ +} +break; + +case 0x80: +case 0x82: +case 0x89: +case 0xc2: +case 0xe2: +{ + operand = peek(PC++); +} +{ +} +break; + +case 0x04: +case 0x44: +case 0x64: +{ + operand = peek(peek(PC++)); +} +{ +} +break; + +case 0x14: +case 0x34: +case 0x54: +case 0x74: +case 0xd4: +case 0xf4: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ +} +break; + +case 0x0c: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ +} +break; + +case 0x1c: +case 0x3c: +case 0x5c: +case 0x7c: +case 0xdc: +case 0xfc: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ +} +break; + + +case 0x09: +{ + operand = peek(PC++); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x05: +{ + operand = peek(peek(PC++)); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x15: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x0d: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1d: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x19: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x01: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x11: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x48: +{ + peek(PC); +} +{ + poke(0x0100 + SP--, A); +} +break; + + +case 0x08: +{ + peek(PC); +} +{ + poke(0x0100 + SP--, PS()); +} +break; + + +case 0x68: +{ + peek(PC); +} +{ + peek(0x0100 + SP++); + A = peek(0x0100 + SP); + notZ = A; + N = A & 0x80; +} +break; + + +case 0x28: +{ + peek(PC); +} +{ + peek(0x0100 + SP++); + PS(peek(0x0100 + SP)); +} +break; + + +case 0x2f: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3f: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3b: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x27: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x37: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x23: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x33: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x2a: +{ + peek(PC); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit + C = A & 0x80; + + A = (A << 1) | (oldC ? 1 : 0); + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x26: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x36: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x2e: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x3e: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x6a: +{ + peek(PC); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = ((A >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + + notZ = A; + N = A & 0x80; +} +break; + +case 0x66: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x76: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x6e: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x7e: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x6f: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7f: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7b: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x67: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x77: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x63: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x73: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x40: +{ + peek(PC); +} +{ + peek(0x0100 + SP++); + PS(peek(0x0100 + SP++)); + PC = peek(0x0100 + SP++); + PC |= ((uInt16)peek(0x0100 + SP) << 8); +} +break; + + +case 0x60: +{ + peek(PC); +} +{ + peek(0x0100 + SP++); + PC = peek(0x0100 + SP++); + PC |= ((uInt16)peek(0x0100 + SP) << 8); + peek(PC++); +} +break; + + +case 0x8f: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x87: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x97: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + Y) & 0xFF; +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x83: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); +} +{ + poke(operandAddress, A & X); +} +break; + + +case 0xe9: +case 0xeb: +{ + operand = peek(PC++); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe5: +{ + operand = peek(peek(PC++)); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf5: +{ + uInt8 address = peek(PC++); + peek(address); + address += X; + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xed: +{ + uInt16 address = peek(PC++); + address |= ((uInt16)peek(PC++) << 8); + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xfd: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + X)); + if((low + X) > 0xFF) + operand = peek((high | low) + X); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf9: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe1: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + uInt16 address = peek(pointer++); + address |= ((uInt16)peek(pointer) << 8); + operand = peek(address); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf1: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + operand = peek(high | (uInt8)(low + Y)); + if((low + Y) > 0xFF) + operand = peek((high | low) + Y); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0xcb: +{ + operand = peek(PC++); +} +{ + uInt16 value = (uInt16)(X & A) - (uInt16)operand; + X = (value & 0xff); + + notZ = X; + N = X & 0x80; + C = !(value & 0x0100); +} +break; + + +case 0x38: +{ + peek(PC); +} +{ + C = true; +} +break; + + +case 0xf8: +{ + peek(PC); +} +{ + D = true; +} +break; + + +case 0x78: +{ + peek(PC); +} +{ + I = true; +} +break; + + +case 0x9f: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + +case 0x93: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9b: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + SP = A & X; + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9e: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9c: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, Y & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x0f: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1f: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1b: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x07: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x17: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x03: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x13: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x4f: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5f: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5b: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x47: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x57: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x43: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x53: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; + operand = peek(operandAddress); + poke(operandAddress, operand); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x85: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, A); +} +break; + +case 0x95: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; +} +{ + poke(operandAddress, A); +} +break; + +case 0x8d: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); +} +{ + poke(operandAddress, A); +} +break; + +case 0x9d: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + X)); + operandAddress = (high | low) + X; +} +{ + poke(operandAddress, A); +} +break; + +case 0x99: +{ + uInt16 low = peek(PC++); + uInt16 high = ((uInt16)peek(PC++) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + poke(operandAddress, A); +} +break; + +case 0x81: +{ + uInt8 pointer = peek(PC++); + peek(pointer); + pointer += X; + operandAddress = peek(pointer++); + operandAddress |= ((uInt16)peek(pointer) << 8); +} +{ + poke(operandAddress, A); +} +break; + +case 0x91: +{ + uInt8 pointer = peek(PC++); + uInt16 low = peek(pointer++); + uInt16 high = ((uInt16)peek(pointer) << 8); + peek(high | (uInt8)(low + Y)); + operandAddress = (high | low) + Y; +} +{ + poke(operandAddress, A); +} +break; + + +case 0x86: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, X); +} +break; + +case 0x96: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + Y) & 0xFF; +} +{ + poke(operandAddress, X); +} +break; + +case 0x8e: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); +} +{ + poke(operandAddress, X); +} +break; + + +case 0x84: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, Y); +} +break; + +case 0x94: +{ + operandAddress = peek(PC++); + peek(operandAddress); + operandAddress = (operandAddress + X) & 0xFF; +} +{ + poke(operandAddress, Y); +} +break; + +case 0x8c: +{ + operandAddress = peek(PC++); + operandAddress |= ((uInt16)peek(PC++) << 8); +} +{ + poke(operandAddress, Y); +} +break; + + +case 0xaa: +{ + peek(PC); +} +{ + X = A; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xa8: +{ + peek(PC); +} +{ + Y = A; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0xba: +{ + peek(PC); +} +{ + X = SP; + notZ = X; + N = X & 0x80; +} +break; + + +case 0x8a: +{ + peek(PC); +} +{ + A = X; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x9a: +{ + peek(PC); +} +{ + SP = X; +} +break; + + +case 0x98: +{ + peek(PC); +} +{ + A = Y; + notZ = A; + N = A & 0x80; +} +break; + + diff --git a/stella/src/ui/cyberstella/M6502Low.ins b/stella/src/ui/cyberstella/M6502Low.ins new file mode 100644 index 000000000..4fc6e07ea --- /dev/null +++ b/stella/src/ui/cyberstella/M6502Low.ins @@ -0,0 +1,4374 @@ +//============================================================================ +// +// MM MM 6666 555555 0000 2222 +// MMMM MMMM 66 66 55 00 00 22 22 +// MM MMM MM 66 55 00 00 22 +// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" +// MM MM 66 66 55 00 00 22 +// MM MM 66 66 55 55 00 00 22 +// MM MM 6666 5555 0000 222222 +// +// Copyright (c) 1995-1998 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: M6502Low.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +/** + Code to handle addressing modes and branch instructions for + low compatibility emulation + + @author Bradford W. Mott + @version $Id: M6502Low.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +*/ + +#ifndef NOTSAMEPAGE + #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00) +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//============================================================================ +// +// MM MM 6666 555555 0000 2222 +// MMMM MMMM 66 66 55 00 00 22 22 +// MM MMM MM 66 55 00 00 22 +// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" +// MM MM 66 66 55 00 00 22 +// MM MM 66 66 55 55 00 00 22 +// MM MM 6666 5555 0000 222222 +// +// Copyright (c) 1995-1998 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: M6502Low.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +/** + Code and cases to emulate each of the 6502 instruction + + @author Bradford W. Mott + @version $Id: M6502Low.ins,v 1.1 2003-09-21 14:33:34 stephena Exp $ +*/ + +#ifndef NOTSAMEPAGE + #define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00) +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +case 0x69: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x65: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x75: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x6d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x79: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x61: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x71: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x4b: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A &= operand; + + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = (A >> 1) & 0x7f; + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x0b: +case 0x2b: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; + C = N; +} +break; + + +case 0x29: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x25: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x35: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x2d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x39: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x21: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x31: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A &= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x8b: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. This instruction is + // reported to be unstable! + A = (A | 0xee) & X & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x6b: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. There are mixed + // reports on its operation! + if(!D) + { + A &= operand; + A = ((A >> 1) & 0x7f) | (C ? 0x80 : 0x00); + + C = A & 0x40; + V = (A & 0x40) ^ ((A & 0x20) << 1); + + notZ = A; + N = A & 0x80; + } + else + { + uInt8 value = A & operand; + + A = ((value >> 1) & 0x7f) | (C ? 0x80 : 0x00); + N = C; + notZ = A; + V = (value ^ A) & 0x40; + + if(((value & 0x0f) + (value & 0x01)) > 0x05) + { + A = (A & 0xf0) | ((A + 0x06) & 0x0f); + } + + if(((value & 0xf0) + (value & 0x10)) > 0x50) + { + A = (A + 0x60) & 0xff; + C = 1; + } + else + { + C = 0; + } + } +} +break; + + +case 0x0a: +{ +} +{ + // Set carry flag according to the left-most bit in A + C = A & 0x80; + + A <<= 1; + + notZ = A; + N = A & 0x80; +} +break; + +case 0x06: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x16: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x0e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x1e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x90: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(!C) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0xb0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(C) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0xf0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(!notZ) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0x24: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + notZ = (A & operand); + N = operand & 0x80; + V = operand & 0x40; +} +break; + +case 0x2C: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + notZ = (A & operand); + N = operand & 0x80; + V = operand & 0x40; +} +break; + + +case 0x30: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(N) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0xD0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(notZ) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0x10: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(!N) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0x00: +{ + peek(PC++); + + B = true; + + poke(0x0100 + SP--, PC >> 8); + poke(0x0100 + SP--, PC & 0x00ff); + poke(0x0100 + SP--, PS()); + + I = true; + + PC = peek(0xfffe); + PC |= ((uInt16)peek(0xffff) << 8); +} +break; + + +case 0x50: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(!V) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0x70: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + if(V) + { + uInt16 address = PC + (Int8)operand; + mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ? + mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle); + PC = address; + } +} +break; + + +case 0x18: +{ +} +{ + C = false; +} +break; + + +case 0xd8: +{ +} +{ + D = false; +} +break; + + +case 0x58: +{ +} +{ + I = false; +} +break; + + +case 0xb8: +{ +} +{ + V = false; +} +break; + + +case 0xc9: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc5: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd5: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xcd: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xdd: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd9: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc1: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xd1: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)A - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xe0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xe4: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xec: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)X - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xc0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xc4: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + +case 0xcc: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)Y - (uInt16)operand; + + notZ = value; + N = value & 0x0080; + C = !(value & 0x0100); +} +break; + + +case 0xcf: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xdf: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xdb: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xc7: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xd7: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xc3: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + +case 0xd3: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + uInt16 value2 = (uInt16)A - (uInt16)value; + notZ = value2; + N = value2 & 0x0080; + C = !(value2 & 0x0100); +} +break; + + +case 0xc6: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xd6: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xce: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xde: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 value = operand - 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + + +case 0xca: +{ +} +{ + X--; + + notZ = X; + N = X & 0x80; +} +break; + + +case 0x88: +{ +} +{ + Y--; + + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0x49: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x45: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x55: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x4d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x59: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x41: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x51: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xe6: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xf6: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xee: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + +case 0xfe: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 value = operand + 1; + poke(operandAddress, value); + + notZ = value; + N = value & 0x80; +} +break; + + +case 0xe8: +{ +} +{ + X++; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xc8: +{ +} +{ + Y++; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0xef: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xff: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xfb: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe7: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf7: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe3: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf3: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + operand = operand + 1; + poke(operandAddress, operand); + + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x4c: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; +} +{ + PC = operandAddress; +} +break; + +case 0x6c: +{ + uInt16 addr = peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // Simulate the error in the indirect addressing mode! + uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1); + + operandAddress = peek(addr) | ((uInt16)peek(high) << 8); +} +{ + PC = operandAddress; +} +break; + + +case 0x20: +{ + uInt8 low = peek(PC++); + peek(0x0100 + SP); + + // It seems that the 650x does not push the address of the next instruction + // on the stack it actually pushes the address of the next instruction + // minus one. This is compensated for in the RTS instruction + poke(0x0100 + SP--, PC >> 8); + poke(0x0100 + SP--, PC & 0xff); + + PC = low | ((uInt16)peek(PC++) << 8); +} +break; + + +case 0xbb: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A = X = SP = SP & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xaf: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xbf: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa7: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb7: +{ + operandAddress = (uInt8)(peek(PC++) + Y); + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa3: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb3: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A = operand; + X = operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xa9: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa5: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb5: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xad: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xbd: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb9: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xa1: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0xb1: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A = operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0xa2: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xa6: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xb6: +{ + operandAddress = (uInt8)(peek(PC++) + Y); + operand = peek(operandAddress); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xae: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + +case 0xbe: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + X = operand; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xa0: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xa4: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xb4: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xac: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + +case 0xbc: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + Y = operand; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0x4a: +{ +} +{ + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = (A >> 1) & 0x7f; + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x46: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x56: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x4e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x5e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0xab: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + // NOTE: The implementation of this instruction is based on + // information from the 64doc.txt file. This instruction is + // reported to be very unstable! + A = X = (A | 0xee) & operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x1a: +case 0x3a: +case 0x5a: +case 0x7a: +case 0xda: +case 0xea: +case 0xfa: +{ +} +{ +} +break; + +case 0x80: +case 0x82: +case 0x89: +case 0xc2: +case 0xe2: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ +} +break; + +case 0x04: +case 0x44: +case 0x64: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ +} +break; + +case 0x14: +case 0x34: +case 0x54: +case 0x74: +case 0xd4: +case 0xf4: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ +} +break; + +case 0x0c: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ +} +break; + +case 0x1c: +case 0x3c: +case 0x5c: +case 0x7c: +case 0xdc: +case 0xfc: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ +} +break; + + +case 0x09: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x05: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x15: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x0d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x19: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x01: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x11: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x48: +{ +} +{ + poke(0x0100 + SP--, A); +} +break; + + +case 0x08: +{ +} +{ + poke(0x0100 + SP--, PS()); +} +break; + + +case 0x68: +{ +} +{ + peek(0x0100 + SP++); + A = peek(0x0100 + SP); + notZ = A; + N = A & 0x80; +} +break; + + +case 0x28: +{ +} +{ + peek(0x0100 + SP++); + PS(peek(0x0100 + SP)); +} +break; + + +case 0x2f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x3b: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x27: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x37: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x23: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + +case 0x33: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 value = (operand << 1) | (C ? 1 : 0); + poke(operandAddress, value); + + A &= value; + C = operand & 0x80; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x2a: +{ +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit + C = A & 0x80; + + A = (A << 1) | (oldC ? 1 : 0); + + notZ = A; + N = A & 0x80; +} +break; + + +case 0x26: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x36: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x2e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x3e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the left-most bit in operand + C = operand & 0x80; + + operand = (operand << 1) | (oldC ? 1 : 0); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x6a: +{ +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = A & 0x01; + + A = ((A >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + + notZ = A; + N = A & 0x80; +} +break; + +case 0x66: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x76: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x6e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + +case 0x7e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + notZ = operand; + N = operand & 0x80; +} +break; + + +case 0x6f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x7b: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x67: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x77: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x63: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0x73: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + bool oldC = C; + + // Set carry flag according to the right-most bit + C = operand & 0x01; + + operand = ((operand >> 1) & 0x7f) | (oldC ? 0x80 : 0x00); + poke(operandAddress, operand); + + if(!D) + { + Int16 sum = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((sum > 127) || (sum < -128)); + + sum = (Int16)A + (Int16)operand + (C ? 1 : 0); + A = sum; + C = (sum > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 sum = ourBCDTable[0][A] + ourBCDTable[0][operand] + (C ? 1 : 0); + + C = (sum > 99); + A = ourBCDTable[1][sum & 0xff]; + notZ = A; + N = A & 0x80; + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0x40: +{ +} +{ + peek(0x0100 + SP++); + PS(peek(0x0100 + SP++)); + PC = peek(0x0100 + SP++); + PC |= ((uInt16)peek(0x0100 + SP) << 8); +} +break; + + +case 0x60: +{ +} +{ + peek(0x0100 + SP++); + PC = peek(0x0100 + SP++); + PC |= ((uInt16)peek(0x0100 + SP) << 8); + peek(PC++); +} +break; + + +case 0x8f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x87: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x97: +{ + operandAddress = (uInt8)(peek(PC++) + Y); +} +{ + poke(operandAddress, A & X); +} +break; + +case 0x83: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); +} +{ + poke(operandAddress, A & X); +} +break; + + +case 0xe9: +case 0xeb: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe5: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf5: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xed: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xfd: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + X)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += X; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf9: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + + // See if we need to add one cycle for indexing across a page boundary + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xe1: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + +case 0xf1: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + + if(NOTSAMEPAGE(operandAddress, operandAddress + Y)) + { + mySystem->incrementCycles(mySystemCyclesPerProcessorCycle); + } + + operandAddress += Y; + operand = peek(operandAddress); +} +{ + uInt8 oldA = A; + + if(!D) + { + operand = ~operand; + Int16 difference = (Int16)((Int8)A) + (Int16)((Int8)operand) + (C ? 1 : 0); + V = ((difference > 127) || (difference < -128)); + + difference = ((Int16)A) + ((Int16)operand) + (C ? 1 : 0); + A = difference; + C = (difference > 0xff); + notZ = A; + N = A & 0x80; + } + else + { + Int16 difference = ourBCDTable[0][A] - ourBCDTable[0][operand] + - (C ? 0 : 1); + + if(difference < 0) + difference += 100; + + A = ourBCDTable[1][difference]; + notZ = A; + N = A & 0x80; + + C = (oldA >= (operand + (C ? 0 : 1))); + V = ((oldA ^ A) & 0x80) && ((A ^ operand) & 0x80); + } +} +break; + + +case 0xcb: +{ + operandAddress = PC++; + operand = peek(operandAddress); +} +{ + uInt16 value = (uInt16)(X & A) - (uInt16)operand; + X = (value & 0xff); + + notZ = X; + N = X & 0x80; + C = !(value & 0x0100); +} +break; + + +case 0x38: +{ +} +{ + C = true; +} +break; + + +case 0xf8: +{ +} +{ + D = true; +} +break; + + +case 0x78: +{ +} +{ + I = true; +} +break; + + +case 0x9f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + +case 0x93: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9b: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + SP = A & X; + poke(operandAddress, A & X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, X & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x9c: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; +} +{ + // NOTE: There are mixed reports on the actual operation + // of this instruction! + poke(operandAddress, Y & (((operandAddress >> 8) & 0xff) + 1)); +} +break; + + +case 0x0f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x1b: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x07: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x17: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x03: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x13: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the left-most bit in value + C = operand & 0x80; + + operand <<= 1; + poke(operandAddress, operand); + + A |= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x4f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5f: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x5b: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x47: +{ + operandAddress = peek(PC++); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x57: +{ + operandAddress = (uInt8)(peek(PC++) + X); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x43: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + +case 0x53: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; + operand = peek(operandAddress); +} +{ + // Set carry flag according to the right-most bit in value + C = operand & 0x01; + + operand = (operand >> 1) & 0x7f; + poke(operandAddress, operand); + + A ^= operand; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x85: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, A); +} +break; + +case 0x95: +{ + operandAddress = (uInt8)(peek(PC++) + X); +} +{ + poke(operandAddress, A); +} +break; + +case 0x8d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; +} +{ + poke(operandAddress, A); +} +break; + +case 0x9d: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += X; +} +{ + poke(operandAddress, A); +} +break; + +case 0x99: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; + operandAddress += Y; +} +{ + poke(operandAddress, A); +} +break; + +case 0x81: +{ + uInt8 pointer = peek(PC++) + X; + operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8); +} +{ + poke(operandAddress, A); +} +break; + +case 0x91: +{ + uInt8 pointer = peek(PC++); + operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8); + operandAddress += Y; +} +{ + poke(operandAddress, A); +} +break; + + +case 0x86: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, X); +} +break; + +case 0x96: +{ + operandAddress = (uInt8)(peek(PC++) + Y); +} +{ + poke(operandAddress, X); +} +break; + +case 0x8e: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; +} +{ + poke(operandAddress, X); +} +break; + + +case 0x84: +{ + operandAddress = peek(PC++); +} +{ + poke(operandAddress, Y); +} +break; + +case 0x94: +{ + operandAddress = (uInt8)(peek(PC++) + X); +} +{ + poke(operandAddress, Y); +} +break; + +case 0x8c: +{ + operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8); + PC += 2; +} +{ + poke(operandAddress, Y); +} +break; + + +case 0xaa: +{ +} +{ + X = A; + notZ = X; + N = X & 0x80; +} +break; + + +case 0xa8: +{ +} +{ + Y = A; + notZ = Y; + N = Y & 0x80; +} +break; + + +case 0xba: +{ +} +{ + X = SP; + notZ = X; + N = X & 0x80; +} +break; + + +case 0x8a: +{ +} +{ + A = X; + notZ = A; + N = A & 0x80; +} +break; + + +case 0x9a: +{ +} +{ + SP = X; +} +break; + + +case 0x98: +{ +} +{ + A = Y; + notZ = A; + N = A & 0x80; +} +break; + + diff --git a/stella/src/ui/cyberstella/SettingsWin32.cxx b/stella/src/ui/cyberstella/SettingsWin32.cxx new file mode 100644 index 000000000..e58c7b3f3 --- /dev/null +++ b/stella/src/ui/cyberstella/SettingsWin32.cxx @@ -0,0 +1,63 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2002 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: SettingsWin32.cxx,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +#include "bspf.hxx" +#include "SettingsWin32.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SettingsWin32::SettingsWin32() +{ + mySettingsInputFilename = "stellarc"; + mySettingsOutputFilename = "stellarc"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SettingsWin32::~SettingsWin32() +{ + cerr << "SettingsWin32::~SettingsWin32()\n"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SettingsWin32::setArgument(string& key, string& value) +{ + cerr << "SettingsWin32::setArgument()\n"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string SettingsWin32::getArguments() +{ + cerr << "SettingsWin32::getArguments()\n"; + + return ""; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string SettingsWin32::stateFilename(uInt32 state) +{ + cerr << "SettingsWin32::stateFilename()\n"; + + return ""; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string SettingsWin32::snapshotFilename() +{ + cerr << "SettingsWin32::snapshotFilename()\n"; + + return ""; +} diff --git a/stella/src/ui/cyberstella/SettingsWin32.hxx b/stella/src/ui/cyberstella/SettingsWin32.hxx new file mode 100644 index 000000000..33faccdd4 --- /dev/null +++ b/stella/src/ui/cyberstella/SettingsWin32.hxx @@ -0,0 +1,38 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2002 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: SettingsWin32.hxx,v 1.1 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +#ifndef SETTINGS_WIN32_HXX +#define SETTINGS_WIN32_HXX + +#include "bspf.hxx" +#include "Settings.hxx" + +class SettingsWin32 : public Settings +{ + public: + SettingsWin32(); + virtual ~SettingsWin32(); + + public: + virtual void setArgument(string& key, string& value); + virtual string getArguments(); + virtual string stateFilename(uInt32 state); + virtual string snapshotFilename(); +}; + +#endif diff --git a/stella/src/ui/cyberstella/SoundWin32.cxx b/stella/src/ui/cyberstella/SoundWin32.cxx index d101c7f84..3da7a0b56 100644 --- a/stella/src/ui/cyberstella/SoundWin32.cxx +++ b/stella/src/ui/cyberstella/SoundWin32.cxx @@ -1,173 +1,162 @@ +//============================================================================ // -// StellaX -// Jeff Miller 04/26/2000 +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa // -#include "pch.hxx" +// Copyright (c) 1995-2002 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: SoundWin32.cxx,v 1.2 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +#include + +#include + +#include "bspf.hxx" +#include "MediaSrc.hxx" #include "SoundWin32.hxx" -#include "resource.h" -#include "AudioStream.hxx" - -SoundWin32::SoundWin32( - ) : - m_fInitialized( FALSE ), - m_pass( NULL ), - m_pasCurrent( NULL ) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SoundWin32::SoundWin32() + : myIsInitializedFlag(false), + myBufferSize(512), + mySampleRate(31400), + myDSBuffer(NULL) { - TRACE("SoundWin32::SoundWin32"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SoundWin32::~SoundWin32() +{ + closeDevice(); } -HRESULT SoundWin32::Initialize( - HWND hwnd - ) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +HRESULT SoundWin32::Initialize(HWND hWnd) { - TRACE( "SoundWin32::Initialize hwnd=%08X", hwnd ); - - if ( m_fInitialized ) - { - TRACE( "SoundWin32::Initialize - already initialized" ); - return S_OK; - } - - HRESULT hr = S_OK; - - m_pass = new AudioStreamServices; - if ( m_pass == NULL ) - { - hr = E_OUTOFMEMORY; - goto cleanup; - } - - if ( ! m_pass->Initialize( hwnd ) ) - { - TRACE( "ASS Initialize failed" ); - MessageBox( (HINSTANCE)::GetWindowLong( hwnd, GWL_HINSTANCE ), - hwnd, - IDS_ASS_FAILED ); - hr = E_FAIL; - goto cleanup; - } - - m_pasCurrent = new AudioStream; - if ( m_pasCurrent == NULL ) - { - hr = E_OUTOFMEMORY; - goto cleanup; - } - - if ( ! m_pasCurrent->Create( m_pass ) ) - { - TRACE( "PAS Create failed" ); - MessageBox( (HINSTANCE)::GetWindowLong( hwnd, GWL_HINSTANCE ), - hwnd, - IDS_PAS_FAILED ); - hr = E_FAIL; - goto cleanup; - } - - m_pasCurrent->Play(); - - m_fInitialized = TRUE; -cleanup: - - if ( FAILED(hr) ) - { - if ( m_pasCurrent ) - { - m_pasCurrent->Destroy(); - delete m_pasCurrent; - m_pasCurrent = NULL; - } - - if ( m_pass ) - { - delete m_pass; - m_pass = NULL; - } - } + HRESULT hr; + // Create IDirectSound using the primary sound device + if( FAILED( hr = DirectSoundCreate8( NULL, &myDSDevice, NULL ) ) ) + { + SoundError("DirectSoundCreate8"); return hr; + } + + // Set DirectSound coop level + if( FAILED(hr = myDSDevice->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)) ) + { + SoundError("SetCooperativeLevel"); + return hr; + } + + // Set up the static sound buffer + WAVEFORMATEX wfx; + DSBUFFERDESC dsbdesc; + + ZeroMemory(&wfx, sizeof(wfx)); + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 1; + wfx.nSamplesPerSec = mySampleRate; + wfx.wBitsPerSample = 8; + wfx.nBlockAlign = 1; //wfx.wBitsPerSample / 8 * wfx.nChannels; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + ZeroMemory(&dsbdesc, sizeof(dsbdesc)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME; + dsbdesc.dwBufferBytes = myBufferSize; + dsbdesc.lpwfxFormat = &wfx; + + hr = myDSDevice->CreateSoundBuffer(&dsbdesc, &myDSBuffer, NULL); + if(SUCCEEDED(hr)) + myIsInitializedFlag = true; + + return hr; } - -SoundWin32::~SoundWin32( - ) + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundWin32::closeDevice() { - TRACE("SoundWin32::~SoundWin32"); - - if ( m_pasCurrent ) - { - m_pasCurrent->Destroy(); - delete m_pasCurrent; - m_pasCurrent = NULL; - } - - delete m_pass; - m_pass = NULL; } - -void SoundWin32::set(Sound::Register reg, uInt8 value) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 SoundWin32::getSampleRate() const { - if ( ! m_fInitialized ) - { - TRACE( "SoundWin32::set -- not initialized" ); - return; - } - - // - // Process TIA data - // - - switch( reg ) - { - case AUDC0: - Update_tia_sound( 0x15, value ); - break; - - case AUDC1: - Update_tia_sound( 0x16, value ); - break; - - case AUDF0: - Update_tia_sound( 0x17, value ); - break; - - case AUDF1: - Update_tia_sound( 0x18, value ); - break; - - case AUDV0: - Update_tia_sound( 0x19, value ); - break; - - case AUDV1: - Update_tia_sound( 0x1A, value ); - break; - } - + return myIsInitializedFlag ? mySampleRate : 0; } -void SoundWin32::mute( - bool mute - ) +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool SoundWin32::isSuccessfullyInitialized() const { - if ( ! m_fInitialized ) - { - TRACE( "SoundWin32::mute -- not initialized" ); - return; - } - - if ( m_pasCurrent ) - { - if ( mute ) - { - m_pasCurrent->Stop(); - } - else - { - m_pasCurrent->Play(); - } - } + return myIsInitializedFlag; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundWin32::setSoundVolume(Int32 percent) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundWin32::updateSound(MediaSource& mediaSource) +{ + if(myIsInitializedFlag) + { + HRESULT hr; + uInt8 periodCount = 0; + uInt8* buffer = new uInt8[myBufferSize]; + + // Dequeue samples as long as full fragments are available + while(mediaSource.numberOfAudioSamples() >= myBufferSize) + { + mediaSource.dequeueAudioSamples(buffer, myBufferSize); + + LPVOID lpvWrite; + DWORD dwLength; + hr = myDSBuffer->Lock(0, 0, &lpvWrite, &dwLength, NULL, NULL, DSBLOCK_ENTIREBUFFER); + if(hr == DS_OK) + { + memcpy(lpvWrite, buffer, dwLength); + myDSBuffer->Unlock(lpvWrite, dwLength, NULL, 0); + myDSBuffer->SetCurrentPosition(0); + myDSBuffer->Play(0, 0, 0); + periodCount++; + } + } + delete[] buffer; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundWin32::SoundError(const char* message) +{ + cout << "ERROR in SOUND: " << message << endl; + myIsInitializedFlag = false; +} + +/* // Fill any unused fragments with silence so that we have a lower + // risk of having playback underruns + for(int i = 0; i < 1-periodCount; ++i) + { + frames = snd_pcm_avail_update(myPcmHandle); + if (frames > 0) + { + uInt8 buffer[frames]; + memset((void*)buffer, 0, frames); + snd_pcm_writei(myPcmHandle, buffer, frames); + } + else if(frames == -EPIPE) // this should never happen + { + cerr << "EPIPE after write\n"; + break; + } + }*/ diff --git a/stella/src/ui/cyberstella/SoundWin32.hxx b/stella/src/ui/cyberstella/SoundWin32.hxx index 916ac1c3b..7cb85f030 100644 --- a/stella/src/ui/cyberstella/SoundWin32.hxx +++ b/stella/src/ui/cyberstella/SoundWin32.hxx @@ -1,109 +1,117 @@ +//============================================================================ // -// StellaX -// Jeff Miller 05/01/2000 +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa // -#ifndef SNDWIN32_H -#define SNDWIN32_H +// Copyright (c) 1995-2002 by Bradford W. Mott +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: SoundWin32.hxx,v 1.2 2003-09-21 14:33:34 stephena Exp $ +//============================================================================ + +#ifndef SOUND_WIN32_HXX +#define SOUND_WIN32_HXX + +#include #include "bspf.hxx" +#include "MediaSrc.hxx" #include "Sound.hxx" -#include "TIASound.h" +/** + This class implements a sound class using the + Win32 DirectSound API. -class AudioStreamServices; -class AudioStream; - -#define SAMPLES_PER_SEC 22050 -#define NUM_CHANNELS 1 -#define BITS_PER_SAMPLE 8 - -class WaveFile -{ -public: - - WaveFile( void ) - { - ZeroMemory( &wfx, sizeof(wfx) ); - wfx.cbSize = sizeof( wfx ); - wfx.wFormatTag = WAVE_FORMAT_PCM; - wfx.nChannels = NUM_CHANNELS; - wfx.nSamplesPerSec = SAMPLES_PER_SEC; - wfx.wBitsPerSample = BITS_PER_SAMPLE; - wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; - wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; - - } - - ~WaveFile( void ) - { - } - - BOOL Open( void ) - { - Tia_sound_init( 31400, wfx.nSamplesPerSec ); - - return TRUE; - } - - BOOL Cue( void ) - { - return TRUE; - } - - void Read( BYTE* pbDest, UINT cbSize ) - { - Tia_process ( pbDest, cbSize ); - } - - UINT GetAvgDataRate (void) - { - return wfx.nAvgBytesPerSec; - } - - BYTE GetSilenceData (void) - { - return 0; - } - - WAVEFORMATEX* GetWaveFormatEx( void ) - { - return &wfx; - } - -private: - - WAVEFORMATEX wfx; - - WaveFile( const WaveFile& ); // no implementation - void operator=( const WaveFile& ); // no implementation -}; - + @author Stephen Anthony + @version $Id: SoundWin32.hxx,v 1.2 2003-09-21 14:33:34 stephena Exp $ +*/ class SoundWin32 : public Sound { -public: + public: + /** + Create a new sound object + */ + SoundWin32(); - SoundWin32(); - virtual ~SoundWin32(); + /** + Destructor + */ + virtual ~SoundWin32(); - HRESULT Initialize( HWND hwnd ); - - // - // base class virtuals - // + public: + /** + Closes the sound device + */ + void closeDevice(); - virtual void set(Sound::Register reg, uInt8 value); + /** + Return the playback sample rate for the sound device. - virtual void mute( bool state ); - -private: + @return The playback sample rate + */ + uInt32 getSampleRate() const; - BOOL m_fInitialized; + /** + Return true iff the sound device was successfully initlaized. - AudioStreamServices* m_pass; - AudioStream* m_pasCurrent; + @return true iff the sound device was successfully initlaized. + */ + bool isSuccessfullyInitialized() const; - SoundWin32( const SoundWin32& ); // no implementation - void operator=( const SoundWin32& ); // no implementation + /** + Sets the volume of the sound device to the specified level. The + volume is given as a percentage from 0 to 100. A -1 indicates + that the volume shouldn't be changed at all. + + @param percent The new volume percentage level for the sound device + */ + void setSoundVolume(Int32 percent); + + /** + Update the sound device using the audio sample from the specified + media source. + + @param mediaSource The media source to get audio samples from. + */ + void updateSound(MediaSource& mediaSource); + + /** + Initialize the DirectSound subsystem/ + + @return The result of initialization. + */ + HRESULT Initialize(HWND hwnd); + + private: + // Print error messages and clean up + void SoundError(const char* message); + + // Indicates if the sound device was successfully initialized + bool myIsInitializedFlag; + + // DirectSound device + LPDIRECTSOUND8 myDSDevice; + + // DirectSound secondary buffer + LPDIRECTSOUNDBUFFER myDSBuffer; + + // Mixer file descriptor + int myMixerFd; + + // Original mixer volume when the sound device was opened + int myOriginalVolume; + + // PCM buffer size + uInt32 myBufferSize; + + // DSP sample rate + uInt32 mySampleRate; }; #endif - diff --git a/stella/src/ui/cyberstella/resource.h b/stella/src/ui/cyberstella/resource.h index e1a947e6b..7c2d62a13 100644 --- a/stella/src/ui/cyberstella/resource.h +++ b/stella/src/ui/cyberstella/resource.h @@ -40,12 +40,12 @@ #define IDS_ROM_LOAD_FAILED 304 #define IDS_NO_ITEM_SELECTED 305 #define IDC_CONTINUE 1000 -#define IDC_EMAIL_JEFFMILL 1002 +#define IDC_EMAIL_MAINTAINER 1002 #define IDC_EMAIL_STELLA 1003 #define IDC_PLAY 1005 #define IDC_ROMCOUNT 1006 #define IDC_ROMLIST 1007 -#define IDC_WEB_JEFFMILL 1010 +#define IDC_WEB_MAINTAINER 1010 #define IDC_WEB_STELLA 1011 #define IDC_ROMPATH 1013 #define IDC_CONFIG 1015