Compare commits

...

7 Commits
master ... v46

Author SHA1 Message Date
David Voswinkel
764c0dd2c1 o compiles and still crashes 2009-05-14 20:22:39 +02:00
David Voswinkel
a1763efe21 o mac compiles and stil crashed 2009-05-14 20:21:18 +02:00
David Voswinkel
b3d930b143 o cleanup mocs 2009-05-12 23:18:16 +02:00
David Voswinkel
3063b354e7 o mac compiles 2009-05-12 23:17:44 +02:00
David Voswinkel
571737d59b o add missing files 2009-05-12 22:24:35 +02:00
David Voswinkel
09198f5099 o add missing files 2009-05-12 22:20:41 +02:00
David Voswinkel
8e877d38d4 o switch to v46 2009-05-12 22:17:42 +02:00
276 changed files with 25460 additions and 11282 deletions

View File

@ -53,7 +53,8 @@ void crc_check_memory(uint32_t top_addr)
} }
void crc_check_memory_range(uint32_t start_addr, uint32_t size) void crc_check_memory_
range(uint32_t start_addr, uint32_t size)
{ {
uint16_t crc = 0; uint16_t crc = 0;
uint32_t addr; uint32_t addr;

View File

@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>currentDocument</key> <key>currentDocument</key>
<string>poc/avr_usbload/main.c</string> <string>tools/bsnes/lib/nall/lzss.hpp</string>
<key>documents</key> <key>documents</key>
<array> <array>
<dict> <dict>
@ -254,14 +254,14 @@
<key>caret</key> <key>caret</key>
<dict> <dict>
<key>column</key> <key>column</key>
<integer>22</integer> <integer>0</integer>
<key>line</key> <key>line</key>
<integer>55</integer> <integer>56</integer>
</dict> </dict>
<key>firstVisibleColumn</key> <key>firstVisibleColumn</key>
<integer>0</integer> <integer>0</integer>
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>15</integer> <integer>4</integer>
</dict> </dict>
<key>poc/avr_usbload/requests.h</key> <key>poc/avr_usbload/requests.h</key>
<dict> <dict>
@ -587,21 +587,21 @@
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>0</integer> <integer>0</integer>
</dict> </dict>
<key>tools/bsnes/cart/cart.cpp</key> <key>tools/bsnes/Makefile</key>
<dict> <dict>
<key>caret</key> <key>caret</key>
<dict> <dict>
<key>column</key> <key>column</key>
<integer>0</integer> <integer>10</integer>
<key>line</key> <key>line</key>
<integer>95</integer> <integer>8</integer>
</dict> </dict>
<key>firstVisibleColumn</key> <key>firstVisibleColumn</key>
<integer>0</integer> <integer>0</integer>
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>44</integer> <integer>0</integer>
</dict> </dict>
<key>tools/bsnes/cart/cart.hpp</key> <key>tools/bsnes/lib/nall/algorithm.hpp</key>
<dict> <dict>
<key>caret</key> <key>caret</key>
<dict> <dict>
@ -613,7 +613,245 @@
<key>firstVisibleColumn</key> <key>firstVisibleColumn</key>
<integer>0</integer> <integer>0</integer>
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>24</integer> <integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/any.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/config.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/crc32.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/endian.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/lzss.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/new.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/static.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/nall/stdint.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/audio/ao.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/audio/ao.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/audio/openal.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>14</integer>
<key>line</key>
<integer>1</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/ruby.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>266</integer>
</dict>
<key>tools/bsnes/lib/ruby/ruby.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>55</integer>
</dict>
<key>tools/bsnes/lib/ruby/ruby_audio.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>68</integer>
</dict>
<key>tools/bsnes/lib/ruby/ruby_impl.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/video.hpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/lib/ruby/video/sdl.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>16</integer>
<key>line</key>
<integer>103</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>85</integer>
</dict> </dict>
<key>tools/bsnes/memory/smemory/mapper/chip.cpp</key> <key>tools/bsnes/memory/smemory/mapper/chip.cpp</key>
<dict> <dict>
@ -671,6 +909,64 @@
<key>firstVisibleLine</key> <key>firstVisibleLine</key>
<integer>0</integer> <integer>0</integer>
</dict> </dict>
<key>tools/bsnes/ui_qt/Makefile</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>tools/bsnes/ui_qt/main.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>11</integer>
<key>line</key>
<integer>136</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>110</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>4</integer>
<key>line</key>
<integer>136</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>11</integer>
<key>line</key>
<integer>136</integer>
</dict>
</dict>
<key>tools/bsnes/ui_qt/platform.cpp</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>48</integer>
</dict>
<key>tools/usbload/avr.mk</key> <key>tools/usbload/avr.mk</key>
<dict> <dict>
<key>caret</key> <key>caret</key>
@ -1125,12 +1421,6 @@
<string>snes/crc/event.c</string> <string>snes/crc/event.c</string>
<string>snes/crc/main.c</string> <string>snes/crc/main.c</string>
<string>poc/avr_sdcard/mmc.c</string> <string>poc/avr_sdcard/mmc.c</string>
<string>tools/bsnes/cart/cart.cpp</string>
<string>tools/bsnes/memory/smemory/mapper/chip.cpp</string>
<string>tools/bsnes/memory/smemory/mapper/generic.cpp</string>
<string>tools/bsnes/memory/smemory/mapper/system.cpp</string>
<string>tools/bsnes/memory/smemory/smemory.cpp</string>
<string>tools/bsnes/cart/cart.hpp</string>
<string>poc/avr_sdcard/main.c</string> <string>poc/avr_sdcard/main.c</string>
<string>poc/avr_usbload/crc.c</string> <string>poc/avr_usbload/crc.c</string>
<string>poc/avr_usbload/crc.h</string> <string>poc/avr_usbload/crc.h</string>
@ -1165,6 +1455,28 @@
<string>tools/vusb/examples/custom-class/commandline/set-led.c</string> <string>tools/vusb/examples/custom-class/commandline/set-led.c</string>
<string>tools/vusb/examples/custom-class/Readme.txt</string> <string>tools/vusb/examples/custom-class/Readme.txt</string>
<string>poc/avr_usbload/main.c</string> <string>poc/avr_usbload/main.c</string>
<string>tools/bsnes/Makefile</string>
<string>tools/bsnes/ui_qt/Makefile</string>
<string>tools/bsnes/lib/ruby/audio/openal.cpp</string>
<string>tools/bsnes/lib/ruby/video.hpp</string>
<string>tools/bsnes/lib/ruby/video/sdl.cpp</string>
<string>tools/bsnes/lib/ruby/ruby_impl.cpp</string>
<string>tools/bsnes/lib/ruby/ruby_audio.cpp</string>
<string>tools/bsnes/lib/ruby/ruby.hpp</string>
<string>tools/bsnes/lib/ruby/ruby.cpp</string>
<string>tools/bsnes/lib/nall/algorithm.hpp</string>
<string>tools/bsnes/lib/nall/any.hpp</string>
<string>tools/bsnes/lib/nall/config.hpp</string>
<string>tools/bsnes/lib/nall/crc32.hpp</string>
<string>tools/bsnes/lib/nall/endian.hpp</string>
<string>tools/bsnes/lib/nall/static.hpp</string>
<string>tools/bsnes/lib/nall/stdint.hpp</string>
<string>tools/bsnes/lib/nall/new.hpp</string>
<string>tools/bsnes/lib/nall/lzss.hpp</string>
<string>tools/bsnes/ui_qt/main.cpp</string>
<string>tools/bsnes/ui_qt/platform.cpp</string>
<string>tools/bsnes/lib/ruby/audio/ao.cpp</string>
<string>tools/bsnes/lib/ruby/audio/ao.hpp</string>
<string>poc/avr_usbload/uart.h</string> <string>poc/avr_usbload/uart.h</string>
<string>poc/avr_usbload/commandline/Makefile</string> <string>poc/avr_usbload/commandline/Makefile</string>
<string>poc/avr_usbload/commandline/snesuploader.c</string> <string>poc/avr_usbload/commandline/snesuploader.c</string>
@ -1191,29 +1503,6 @@
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>poc</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>avr_usbload</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>commandline</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
</dict>
</dict>
</dict>
</dict>
<key>scripts</key> <key>scripts</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
@ -1221,45 +1510,38 @@
<key>subItems</key> <key>subItems</key>
<dict/> <dict/>
</dict> </dict>
<key>snes</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>tools</key> <key>tools</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>vusb</key> <key>bsnes</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>examples</key> <key>lib</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict> <dict>
<key>custom-class</key> <key>nall</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>commandline</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
<key>subItems</key> <key>subItems</key>
<dict/> <dict/>
</dict> </dict>
<key>firmware</key> <key>ruby</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>video</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
@ -1268,13 +1550,9 @@
</dict> </dict>
</dict> </dict>
</dict> </dict>
<key>hid-custom-rq</key> </dict>
<dict> </dict>
<key>isExpanded</key> <key>ui_qt</key>
<true/>
<key>subItems</key>
<dict>
<key>firmware</key>
<dict> <dict>
<key>isExpanded</key> <key>isExpanded</key>
<true/> <true/>
@ -1283,52 +1561,12 @@
</dict> </dict>
</dict> </dict>
</dict> </dict>
<key>hid-data</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict>
<key>commandline</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>firmware</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
</dict>
</dict>
<key>hid-mouse</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
<key>usbtool</key>
<dict>
<key>isExpanded</key>
<true/>
<key>subItems</key>
<dict/>
</dict>
</dict>
</dict>
</dict>
</dict>
</dict> </dict>
</dict> </dict>
</dict> </dict>
</dict> </dict>
</dict> </dict>
<key>windowFrame</key> <key>windowFrame</key>
<string>{{4, 56}, {733, 822}}</string> <string>{{0, 60}, {720, 818}}</string>
</dict> </dict>
</plist> </plist>

142
tools/bsnes/.cproject Normal file
View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<?fileVersion 4.0.0?>
<cproject>
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876" moduleId="org.eclipse.cdt.core.settings" name="MacOSX GCC">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.MachO" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="bsnes" buildProperties="" id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876" name="MacOSX GCC" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.macosx.base.1958627876.81319156" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.base.1621265583" name="cdt.managedbuild.toolchain.gnu.macosx.base" superClass="cdt.managedbuild.toolchain.gnu.macosx.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.MachO" id="cdt.managedbuild.target.gnu.platform.macosx.base.980966539" name="Debug Platform" osList="macosx" superClass="cdt.managedbuild.target.gnu.platform.macosx.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.macosx.base.1148816406" managedBuildOn="false" name="Gnu Make Builder.MacOSX GCC" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.base.18412343" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.base"/>
<tool id="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base.951081191" name="MacOS X C++ Linker" superClass="cdt.managedbuild.tool.macosx.cpp.linker.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.assembler.macosx.base.672073602" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.macosx.base.1929224322" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.base.430483384" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.macosx.base"/>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.macosx.base.773198848" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.macosx.base"/>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-f ${project_name}_scd.mk" command="make" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="avr-gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="de.innot.avreclipse.core.AVRGCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="avr-g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="bsnes2.null.2078314739" name="bsnes2"/>
</storageModule>
</cproject>

78
tools/bsnes/.project Normal file
View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>bsnes</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
</natures>
</projectDescription>

View File

@ -1,141 +1,109 @@
include lib/nall/Makefile.string include lib/nall/Makefile
prefix = /usr/local
ui = ui_qt ui = ui_qt
################
### compiler ###
################
platform=mac platform=mac
compiler=gcc compiler=gcc
enable_gzip=false enable_gzip=false
ifneq ($(findstring gcc,$(compiler)),) # GCC family ################
flags = -O2 -fomit-frame-pointer -Ilib ### compiler ###
libcoflags := $(flags) -static ################
c = $(compiler)
cpp = $(subst cc,++,$(compiler))
obj = o
rule = -c $< -o $@
link =
mkbin = -o$1
mkdef = -D$1
mkincpath = -I$1
mklib = -l$1
mklibpath = -L$1
# profile-guided optimization:
#flags += -fprofile-generate
#link += -lgcov
#flags += -fprofile-use
flags += -g -ggdb -export-symbols
else ifeq ($(compiler),cl) # Visual C++
flags = /nologo /wd4355 /wd4805 /wd4996 /Ox /GL /EHsc /Ilib
libcoflags = $(flags)
c = cl
cpp = cl
obj = obj
rule = /c $< /Fo$@
link = /link
mkbin = /Fe$1
mkdef = /D$1
mkincpath = /I$1
mklib = $1.lib
mklibpath = /L$1
else
unknown_compiler: help;
endif
########## c := $(compiler)
### os ### cpp := $(subst cc,++,$(compiler))
########## flags := -ggdb3 -O3 -fomit-frame-pointer -Ilib
link :=
ifeq ($(platform),mac) #Mac ################
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x ### platform ###
mkbin = -o $1 ################
delete = rm -f $1
link += -L/opt/local/lib \ ifeq ($(platform),mac)
-lSDL -framework,Cocoa \ flags +=-I/Developer/SDKs/Qt/include \
-lX11 \ -I/Developer/SDKs/Qt/include/QtCore \
-I/Developer/SDKs/Qt/include/QtGui \
-I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers \
-I/System/Library/Frameworks/AGL.framework/Headers \
-I/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers \
-I/usr/X11R6/include \
-I/opt/local/include
link += -lz \
-lm \ -lm \
-framework Foundation\ -lao \
-framework Cocoa \
-framework AGL \
-framework OpenAL\
-framework ApplicationServices \ -framework ApplicationServices \
-framework Foundation\
-framework OpenGL \ -framework OpenGL \
-framework GLUT \ -framework OpenAL \
-lz \ -framework AGL \
-L/opt/local/lib \
-lSDL -Wl,-framework,Cocoa \
-lXext \
-lgl \ -lgl \
-lao -lX11
#ruby := video.glx video.sdl
#ruby += audio.openal audio.ao
#ruby += input.sdl
#-DVIDEO_GLX -DVIDEO_XV -DVIDEO_SDL -DAUDIO_ALS
#-DAUDIO_OPENAL -DAUDIO_OSS -DAUDIO_PULSEAUDIO
#-DAUDIO_AO -DINPUT_SDL -DINPUT_X
flags += -DVIDEO_SDL -DINPUT_SDL -DVIDEO_GLX -DAUDIO_AO -DAUDIO_OPENAL
flags +=-I/opt/local/include \
-I/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers/\
-DVIDEO_SDL \
-DINPUT_SDL \
-DVIDEO_GLX \
-DAUDIO_AO \
-DAUDIO_OPENAL
endif endif
ifeq ($(platform),x) # X11 ifeq ($(platform),x)
ruby = video.glx video.xv video.sdl audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao input.sdl input.x ruby := video.glx video.xv video.sdl
delete = rm -f $1 ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
ruby += input.sdl input.x
else ifeq ($(platform),win)
ruby := video.direct3d video.wgl video.directdraw video.gdi
ruby += audio.directsound
ruby += input.rawinput input.directinput
else ifeq ($(platform),win) # Windows link += -mwindows
mingw_link_flags = -mwindows link += -luuid -lkernel32 -luser32 -lgdi32 -lshell32
# mingw_links_flags = -mconsole # statically link Qt for Windows build
# enable static linking to Qt for Windows build link += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
mingw_link_flags += -enable-stdcall-fixup -Wl,-s -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
ruby = video.direct3d video.wgl video.directdraw video.gdi audio.directsound input.rawinput input.directinput
delete = $(if $(findstring i586-mingw-gcc,$(compiler)),rm -f $1,del $(subst /,\,$1))
link += $(if $(findstring mingw,$(compiler)),$(mingw_link_flags))
link += $(call mklib,uuid)
link += $(call mklib,kernel32)
link += $(call mklib,user32)
link += $(call mklib,gdi32)
link += $(call mklib,shell32)
endif endif
############ ############
### ruby ### ### ruby ###
############ ############
rubyflags = $(if $(findstring .sdl,$(ruby)),`sdl-config --cflags`) rubyflags = $(call ifhas,.sdl,$(ruby),`sdl-config --cflags`)
#link += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
#link += $(if $(findstring video.direct3d,$(ruby)),$(call mklib,d3d9)) link += $(call ifhas,.sdl,$(ruby),`sdl-config --libs`)
#link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw)) link += $(call ifhas,video.direct3d,$(ruby),-ld3d9)
#link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL)) link += $(call ifhas,video.directdraw,$(ruby),-lddraw)
#link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32)) link += $(call ifhas,video.glx,$(ruby),-lGL)
#link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv)) link += $(call ifhas,video.wgl,$(ruby),-lopengl32)
#link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound)) link += $(call ifhas,video.xv,$(ruby),-lXv)
#link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao)) link += $(call ifhas,audio.alsa,$(ruby),-lasound)
#link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound)) link += $(call ifhas,audio.ao,$(ruby),-lao)
#link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32))) link += $(call ifhas,audio.directsound,$(ruby),-ldsound)
#link += $(if $(findstring audio.pulseaudio,$(ruby)),$(call mklib,pulse-simple)) link += $(call ifhas,audio.openal,$(ruby),$(if $(call streq,$(platform),x),-lopenal,-lopenal32))
#link += $(if $(findstring input.directinput,$(ruby)),$(call mklib,dinput8) $(call mklib,dxguid)) link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
#link += $(if $(findstring input.rawinput,$(ruby)),$(call mklib,xinput) $(call mklib,dinput8) $(call mklib,dxguid)) link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
link += $(call ifhas,input.rawinput,$(ruby),-lxinput -ldinput8 -ldxguid)
#################### ####################
### core objects ### ### core objects ###
#################### ####################
objects = libco ruby libfilter string \ objects = libco ruby libreader libfilter string \
reader cart cheat \ system cartridge cheat \
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \ memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu \
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 sgb sa1 bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
ifeq ($(enable_gzip),true) ifeq ($(enable_gzip),true)
#objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
#flags += $(call mkdef,GZIP_SUPPORT) flags += -DGZIP_SUPPORT
endif endif
ifeq ($(enable_jma),true) ifeq ($(enable_jma),true)
#objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
#flags += $(call mkdef,JMA_SUPPORT) flags += -DJMA_SUPPORT
endif endif
###################### ######################
@ -145,135 +113,137 @@ endif
compile = \ compile = \
$(strip \ $(strip \
$(if $(filter %.c,$<), \ $(if $(filter %.c,$<), \
$(c) $(flags) $1 $(rule), \ $(c) $(flags) $1 -c $< -o $@, \
$(if $(filter %.cpp,$<), \ $(if $(filter %.cpp,$<), \
$(cpp) $(flags) $1 $(rule) \ $(cpp) $(flags) $1 -c $< -o $@ \
) \ ) \
) \ ) \
) )
%.$(obj): $<; $(call compile) %.o: $<; $(call compile)
all: build; all: build;
include $(ui)/Makefile include $(ui)/Makefile
objects := $(patsubst %,obj/%.o,$(objects))
objects := $(patsubst %,obj/%.$(obj),$(objects)) rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
#rubydef := $(foreach c,$(subst .,_,$(call strupper,$(ruby))),$(call mkdef,$c))
################# #################
### libraries ### ### libraries ###
################# #################
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/* obj/ruby.o: lib/ruby/ruby.cpp $(call rwildcard,lib/ruby/*)
$(call compile,$(rubydef) $(rubyflags)) $(call compile,$(rubydef) $(rubyflags))
obj/libco.$(obj): lib/libco/libco.c lib/libco/* obj/libco.o: lib/libco/libco.c lib/libco/*
$(c) $(libcoflags) $(rule) $(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
obj/libfilter.$(obj): lib/libfilter/libfilter.cpp lib/libfilter/* obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
obj/string.$(obj): lib/nall/string.cpp lib/nall/* obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
obj/string.o: lib/nall/string.cpp lib/nall/*
################# #################
### utilities ### ### utilities ###
################# #################
obj/reader.$(obj): reader/reader.cpp reader/* obj/cartridge.o: cartridge/cartridge.cpp cartridge/*
obj/cart.$(obj) : cart/cart.cpp cart/* obj/cheat.o : cheat/cheat.cpp cheat/*
obj/cheat.$(obj) : cheat/cheat.cpp cheat/*
############## ##############
### memory ### ### memory ###
############## ##############
obj/memory.$(obj) : memory/memory.cpp memory/* obj/memory.o : memory/memory.cpp memory/*
obj/smemory.$(obj): memory/smemory/smemory.cpp memory/smemory/* memory/smemory/mapper/* obj/smemory.o: memory/smemory/smemory.cpp $(call rwildcard,memory/smemory/)
########### ###########
### cpu ### ### cpu ###
########### ###########
obj/cpu.$(obj) : cpu/cpu.cpp cpu/* obj/cpu.o : cpu/cpu.cpp cpu/*
obj/scpu.$(obj): cpu/scpu/scpu.cpp cpu/scpu/* cpu/scpu/core/* cpu/scpu/dma/* cpu/scpu/memory/* cpu/scpu/mmio/* cpu/scpu/timing/* obj/cpucore.o: cpu/core/core.cpp $(call rwildcard,cpu/core/)
obj/scpu.o : cpu/scpu/scpu.cpp $(call rwildcard,cpu/scpu/)
########### ###########
### smp ### ### smp ###
########### ###########
obj/smp.$(obj) : smp/smp.cpp smp/* obj/smp.o : smp/smp.cpp smp/*
obj/ssmp.$(obj): smp/ssmp/ssmp.cpp smp/ssmp/* smp/ssmp/core/* smp/ssmp/memory/* smp/ssmp/timing/* obj/smpcore.o: smp/core/core.cpp $(call rwildcard,smp/core/)
obj/ssmp.o : smp/ssmp/ssmp.cpp $(call rwildcard,smp/ssmp/)
########### ###########
### dsp ### ### dsp ###
########### ###########
obj/adsp.$(obj): dsp/adsp/adsp.cpp dsp/adsp/* obj/adsp.o: dsp/adsp/adsp.cpp dsp/adsp/*
obj/sdsp.$(obj): dsp/sdsp/sdsp.cpp dsp/sdsp/* obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
########### ###########
### ppu ### ### ppu ###
########### ###########
obj/ppu.$(obj) : ppu/ppu.cpp ppu/* obj/ppu.o : ppu/ppu.cpp ppu/*
obj/bppu.$(obj): ppu/bppu/bppu.cpp ppu/bppu/* obj/bppu.o: ppu/bppu/bppu.cpp ppu/bppu/*
############ ##############
### snes ### ### system ###
############ ##############
obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/* snes/input/* obj/system.o: system/system.cpp $(call rwildcard,system/)
##################### #####################
### special chips ### ### special chips ###
##################### #####################
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/* obj/sgb.o : chip/sgb/sgb.cpp $(call rwildcard,chip/sgb/)
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/* obj/sa1.o : chip/sa1/sa1.cpp $(call rwildcard,chip/sa1/)
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/* obj/bsx.o : chip/bsx/bsx.cpp chip/bsx/*
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/* obj/srtc.o : chip/srtc/srtc.cpp chip/srtc/*
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/* obj/sdd1.o : chip/sdd1/sdd1.cpp chip/sdd1/*
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/* obj/spc7110.o: chip/spc7110/spc7110.cpp chip/spc7110/*
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/* obj/cx4.o : chip/cx4/cx4.cpp chip/cx4/*
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/* obj/dsp1.o : chip/dsp1/dsp1.cpp chip/dsp1/*
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/* obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/* obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/* obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
obj/st010.o : chip/st010/st010.cpp chip/st010/*
############ ############
### zlib ### ### zlib ###
############ ############
obj/adler32.$(obj) : reader/zlib/adler32.c reader/zlib/* obj/adler32.o : lib/zlib/adler32.c lib/zlib/*
obj/compress.$(obj): reader/zlib/compress.c reader/zlib/* obj/compress.o: lib/zlib/compress.c lib/zlib/*
obj/crc32.$(obj) : reader/zlib/crc32.c reader/zlib/* obj/crc32.o : lib/zlib/crc32.c lib/zlib/*
obj/deflate.$(obj) : reader/zlib/deflate.c reader/zlib/* obj/deflate.o : lib/zlib/deflate.c lib/zlib/*
obj/gzio.$(obj) : reader/zlib/gzio.c reader/zlib/* obj/gzio.o : lib/zlib/gzio.c lib/zlib/*
obj/inffast.$(obj) : reader/zlib/inffast.c reader/zlib/* obj/inffast.o : lib/zlib/inffast.c lib/zlib/*
obj/inflate.$(obj) : reader/zlib/inflate.c reader/zlib/* obj/inflate.o : lib/zlib/inflate.c lib/zlib/*
obj/inftrees.$(obj): reader/zlib/inftrees.c reader/zlib/* obj/inftrees.o: lib/zlib/inftrees.c lib/zlib/*
obj/ioapi.$(obj) : reader/zlib/ioapi.c reader/zlib/* obj/ioapi.o : lib/zlib/ioapi.c lib/zlib/*
obj/trees.$(obj) : reader/zlib/trees.c reader/zlib/* obj/trees.o : lib/zlib/trees.c lib/zlib/*
obj/unzip.$(obj) : reader/zlib/unzip.c reader/zlib/* obj/unzip.o : lib/zlib/unzip.c lib/zlib/*
obj/zip.$(obj) : reader/zlib/zip.c reader/zlib/* obj/zip.o : lib/zlib/zip.c lib/zlib/*
obj/zutil.$(obj) : reader/zlib/zutil.c reader/zlib/* obj/zutil.o : lib/zlib/zutil.c lib/zlib/*
########### ##############
### jma ### ### libjma ###
########### ##############
obj/jma.$(obj) : reader/jma/jma.cpp reader/jma/* obj/jma.o : lib/libjma/jma.cpp lib/libjma/*
obj/jcrc32.$(obj) : reader/jma/jcrc32.cpp reader/jma/* obj/jcrc32.o : lib/libjma/jcrc32.cpp lib/libjma/*
obj/lzmadec.$(obj): reader/jma/lzmadec.cpp reader/jma/* obj/lzmadec.o: lib/libjma/lzmadec.cpp lib/libjma/*
obj/7zlzma.$(obj) : reader/jma/7zlzma.cpp reader/jma/* obj/7zlzma.o : lib/libjma/7zlzma.cpp lib/libjma/*
obj/iiostrm.$(obj): reader/jma/iiostrm.cpp reader/jma/* obj/iiostrm.o: lib/libjma/iiostrm.cpp lib/libjma/*
obj/inbyte.$(obj) : reader/jma/inbyte.cpp reader/jma/* obj/inbyte.o : lib/libjma/inbyte.cpp lib/libjma/*
obj/lzma.$(obj) : reader/jma/lzma.cpp reader/jma/* obj/lzma.o : lib/libjma/lzma.cpp lib/libjma/*
obj/winout.$(obj) : reader/jma/winout.cpp reader/jma/* obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
############### ###############
### targets ### ### targets ###
############### ###############
build: ui_build $(objects) build: ui_build $(objects)
g++ $(call mkbin,bsnes) $(objects) $(link) $(strip g++ -o bsnes $(objects) $(link))
install: install:
install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes install -D -m 755 ../bsnes $(DESTDIR)$(prefix)/bin/bsnes
@ -281,13 +251,7 @@ install:
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
clean: ui_clean clean: ui_clean
-@$(call delete,obj/*.$(obj)) rm obj/*.o
-@$(call delete,*.res)
-@$(call delete,*.pgd)
-@$(call delete,*.pgc)
-@$(call delete,*.ilk)
-@$(call delete,*.pdb)
-@$(call delete,*.manifest)
help: help:
@echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]" @echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]"
@ -300,7 +264,6 @@ help:
@echo " gcc - GCC compiler" @echo " gcc - GCC compiler"
@echo " mingw32-gcc - MinGW compiler" @echo " mingw32-gcc - MinGW compiler"
@echo " i586-mingw32-gcc - MinGW cross compiler" @echo " i586-mingw32-gcc - MinGW cross compiler"
@echo " cl - Visual C++"
@echo "" @echo ""
@echo "Available options:" @echo "Available options:"
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)" @echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
@ -308,3 +271,4 @@ help:
@echo "" @echo ""
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true" @echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
@echo "" @echo ""

View File

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.042" #define BSNES_VERSION "0.046"
#define BSNES_TITLE "bsnes v" BSNES_VERSION #define BSNES_TITLE "bsnes v" BSNES_VERSION
#define BUSCORE sBus #define BUSCORE sBus
@ -9,12 +9,7 @@
//S-DSP can be encapsulated into a state machine using #define magic //S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup) //this avoids ~2.048m co_switch() calls per second (~5% speedup)
#define USE_STATE_MACHINE #define DSP_STATE_MACHINE
//FAST_FRAMESKIP disables calculation of RTO during frameskip
//frameskip offers near-zero speedup if RTO is calculated
//accuracy is not affected by this define when frameskipping is off
#define FAST_FRAMESKIP
//game genie + pro action replay code support (~2% speed hit) //game genie + pro action replay code support (~2% speed hit)
#define CHEAT_SYSTEM #define CHEAT_SYSTEM
@ -25,8 +20,9 @@
#include <nall/array.hpp> #include <nall/array.hpp>
#include <nall/bit.hpp> #include <nall/bit.hpp>
#include <nall/detect.hpp> #include <nall/detect.hpp>
#include <nall/dl.hpp>
#include <nall/endian.hpp> #include <nall/endian.hpp>
#include <nall/file.hpp> #include <nall/function.hpp>
#include <nall/moduloarray.hpp> #include <nall/moduloarray.hpp>
#include <nall/new.hpp> #include <nall/new.hpp>
#include <nall/platform.hpp> #include <nall/platform.hpp>
@ -40,10 +36,9 @@ using namespace nall;
typedef int8_t int8; typedef int8_t int8;
typedef int16_t int16; typedef int16_t int16;
typedef int32_t int32; typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8; typedef uint8_t uint8;
typedef uint16_t uint16; typedef uint16_t uint16;
typedef uint32_t uint32; typedef uint32_t uint32;
typedef uint64_t uint64;
#include "interface.hpp" #include "interface.hpp"

View File

@ -1,234 +0,0 @@
#include <../base.hpp>
#include <../chip/chip.hpp>
#include <../reader/reader.hpp>
#define CART_CPP
#include <nall/crc32.hpp>
#include <nall/ups.hpp>
#include "cart.hpp"
#include "cart_file.cpp"
#include "cart_header.cpp"
#include "cart_loader.cpp"
namespace memory {
MappedRAM cartrom, cartram, cartrtc;
MappedRAM bscram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
};
Cartridge cartridge;
void Cartridge::load_begin(Mode cartridge_mode) {
cart.rom = cart.ram = cart.rtc = 0;
bs.ram = 0;
stA.rom = stA.ram = 0;
stB.rom = stB.ram = 0;
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
bs.ram_size = 0;
stA.rom_size = stA.ram_size = 0;
stB.rom_size = stB.ram_size = 0;
set(loaded, false);
set(bsx_flash_loaded, false);
set(patched, false);
set(mode, cartridge_mode);
}
void Cartridge::load_end() {
memory::cartrom.map(cart.rom, cart.rom_size);
memory::cartram.map(cart.ram, cart.ram_size);
memory::cartrtc.map(cart.rtc, cart.rtc_size);
memory::bscram.map(bs.ram, bs.ram_size);
memory::stArom.map(stA.rom, stA.rom_size);
memory::stAram.map(stA.ram, stA.ram_size);
memory::stBrom.map(stB.rom, stB.rom_size);
memory::stBram.map(stB.ram, stB.ram_size);
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::bscram.write_protect(true);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(file::exists(cheat_file)) {
cheat.clear();
cheat.load(cheat_file);
}
bus.load_cart();
set(loaded, true);
}
void Cartridge::unload() {
if(loaded() == false) return;
bus.unload_cart();
switch(mode()) {
case ModeNormal: unload_normal(); break;
case ModeBsxSlotted: unload_bsx_slotted(); break;
case ModeBsx: unload_bsx(); break;
case ModeSufamiTurbo: unload_sufami_turbo(); break;
}
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
string cheat_file = get_filename(cart.filename, "cht", snes.config.path.cheat);
if(cheat.count() > 0 || file::exists(cheat_file)) {
cheat.save(cheat_file);
cheat.clear();
}
set(loaded, false);
}
Cartridge::Cartridge() {
set(loaded, false);
}
Cartridge::~Cartridge() {
if(loaded() == true) unload();
}
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
set(region, source.region);
set(mapper, source.mapper);
set(dsp1_mapper, source.dsp1_mapper);
set(has_bsx_slot, source.bsx_slot);
set(has_superfx, source.superfx);
set(has_sa1, source.sa1);
set(has_srtc, source.srtc);
set(has_sdd1, source.sdd1);
set(has_spc7110, source.spc7110);
set(has_spc7110rtc, source.spc7110rtc);
set(has_cx4, source.cx4);
set(has_dsp1, source.dsp1);
set(has_dsp2, source.dsp2);
set(has_dsp3, source.dsp3);
set(has_dsp4, source.dsp4);
set(has_obc1, source.obc1);
set(has_st010, source.st010);
set(has_st011, source.st011);
set(has_st018, source.st018);
}
//==========
//cartinfo_t
//==========
void Cartridge::cartinfo_t::reset() {
type = TypeUnknown;
mapper = LoROM;
dsp1_mapper = DSP1Unmapped;
region = NTSC;
rom_size = 0;
ram_size = 0;
bsx_slot = false;
superfx = false;
sa1 = false;
srtc = false;
sdd1 = false;
spc7110 = false;
spc7110rtc = false;
cx4 = false;
dsp1 = false;
dsp2 = false;
dsp3 = false;
dsp4 = false;
obc1 = false;
st010 = false;
st011 = false;
st018 = false;
}
Cartridge::cartinfo_t::cartinfo_t() {
reset();
}
//=======
//utility
//=======
//ensure file path is absolute (eg resolve relative paths)
string Cartridge::filepath(const char *filename, const char *pathname) {
//if no pathname, return filename as-is
string file(filename);
file.replace("\\", "/");
string path = (!pathname || !*pathname) ? (const char*)snes.config.path.current : pathname;
//ensure path ends with trailing '/'
path.replace("\\", "/");
if(!strend(path, "/")) path.append("/");
//replace relative path with absolute path
if(strbegin(path, "./")) {
ltrim(path, "./");
path = string() << snes.config.path.base << path;
}
//remove folder part of filename
lstring part;
part.split("/", file);
return path << part[part.size() - 1];
}
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
string Cartridge::basename(const char *filename) {
string name(filename);
//remove extension
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '.') {
name[i] = 0;
break;
}
}
//remove directory information
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
i++;
char *output = name();
while(true) {
*output++ = name[i];
if(!name[i]) break;
i++;
}
break;
}
}
return name;
}
//remove filename and return path only ("/foo/bar.ext" -> "/foo/bar/")
string Cartridge::basepath(const char *filename) {
string path(filename);
path.replace("\\", "/");
//remove filename
for(signed i = strlen(path) - 1; i >= 0; i--) {
if(path[i] == '/') {
path[i] = 0;
break;
}
}
if(!strend(path, "/")) path.append("/");
return path;
}

View File

@ -1,178 +0,0 @@
class Cartridge : public property {
public:
enum Mode {
ModeNormal,
ModeBsxSlotted,
ModeBsx,
ModeSufamiTurbo,
};
enum Type {
TypeNormal,
TypeBsxSlotted,
TypeBsxBios,
TypeBsx,
TypeSufamiTurboBios,
TypeSufamiTurbo,
TypeUnknown,
};
enum Region {
NTSC,
PAL,
};
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
SPC7110ROM,
BSCLoROM,
BSCHiROM,
BSXROM,
STROM,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
//warning: if loaded() == false, no other property is considered valid!
property_t<bool> loaded; //is a base cartridge inserted?
property_t<bool> bsx_flash_loaded; //is a BS-X flash cart connected?
property_t<bool> patched; //has a UPS patch been applied?
property_t<string> name; //display name (filename sans path and extension)
property_t<Mode> mode;
property_t<Region> region;
property_t<MemoryMapper> mapper;
property_t<DSP1MemoryMapper> dsp1_mapper;
property_t<bool> has_bsx_slot;
property_t<bool> has_superfx;
property_t<bool> has_sa1;
property_t<bool> has_srtc;
property_t<bool> has_sdd1;
property_t<bool> has_spc7110, has_spc7110rtc;
property_t<bool> has_cx4;
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
property_t<bool> has_obc1;
property_t<bool> has_st010, has_st011, has_st018;
//main interface
bool load_normal (const char *base);
bool load_bsx_slotted (const char *base, const char *slot = "");
bool load_bsx (const char *base, const char *slot = "");
bool load_sufami_turbo(const char *base, const char *slotA = "", const char *slotB = "");
void unload();
//utility functions
static string filepath(const char *filename, const char *pathname); //"./bar.ext" -> "/foo/bar.ext"
static string basename(const char *filename); //"/foo/bar.ext" -> "bar"
static string basepath(const char *filename); //"/foo/bar.ext" -> "/foo/bar/"
//this function will load 'filename', decompress it if needed, and determine what type of
//image file 'filename' refers to (eg normal cart, BS-X flash cart, Sufami Turbo cart, etc.)
//warning: this operation is very expensive, use sparingly!
Type detect_image_type(const char *filename) const;
Cartridge();
~Cartridge();
private:
void load_begin(Mode);
void load_end();
void unload_normal();
void unload_bsx_slotted();
void unload_bsx();
void unload_sufami_turbo();
struct cartinfo_t {
Type type;
Region region;
MemoryMapper mapper;
DSP1MemoryMapper dsp1_mapper;
unsigned rom_size, ram_size;
bool bsx_slot;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool spc7110, spc7110rtc;
bool cx4;
bool dsp1, dsp2, dsp3, dsp4;
bool obc1;
bool st010, st011, st018;
void reset();
cartinfo_t();
};
enum HeaderField {
CartName = 0x00,
Mapper = 0x15,
RomType = 0x16,
RomSize = 0x17,
RamSize = 0x18,
CartRegion = 0x19,
Company = 0x1a,
Version = 0x1b,
Complement = 0x1c, //inverse checksum
Checksum = 0x1e,
ResetVector = 0x3c,
};
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
unsigned find_header(const uint8_t *data, unsigned size) const;
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
void set_cartinfo(const cartinfo_t&);
bool load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const;
bool load_ram (const char *filename, uint8_t *&data, unsigned size, uint8_t init_value) const;
enum CompressionMode {
CompressionNone, //always load without compression
CompressionInspect, //use file header inspection
CompressionAuto, //use file extension or file header inspection (configured by user)
};
bool load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression = CompressionNone) const;
bool save_file(const char *fn, uint8 *data, unsigned size) const;
bool apply_patch(const uint8_t *pdata, unsigned psize, uint8_t *&data, unsigned &size) const;
string modify_extension(const char *filename, const char *extension) const;
string get_filename(const char *source, const char *extension, const char *path) const;
struct {
string filename;
uint8_t *rom, *ram, *rtc;
unsigned rom_size, ram_size, rtc_size;
} cart;
struct {
string filename;
uint8_t *ram;
unsigned ram_size;
} bs;
struct {
string filename;
uint8_t *rom, *ram;
unsigned rom_size, ram_size;
} stA, stB;
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bscram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
};
extern Cartridge cartridge;

View File

@ -1,109 +0,0 @@
#ifdef CART_CPP
#include "../reader/filereader.hpp"
#if defined(GZIP_SUPPORT)
#include "../reader/gzreader.hpp"
#include "../reader/zipreader.hpp"
#endif
#if defined(JMA_SUPPORT)
#include "../reader/jmareader.hpp"
#endif
string Cartridge::modify_extension(const char *filename_, const char *extension) const {
string filename = filename_;
int i;
for(i = strlen(filename); i >= 0; i--) {
if(filename[i] == '.') break;
if(filename[i] == '/') break;
if(filename[i] == '\\') break;
}
if(i > 0 && filename[i] == '.') filename[i] = 0;
return filename << "." << extension;
}
string Cartridge::get_filename(const char *source, const char *extension, const char *path) const {
return filepath(modify_extension(source, extension), path);
}
bool Cartridge::load_file(const char *fn, uint8 *&data, unsigned &size, CompressionMode compression) const {
if(file::exists(fn) == false) return false;
Reader::Type filetype = Reader::Normal;
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
if(compression == CompressionAuto) filetype = Reader::detect(fn, snes.config.file.autodetect_type);
switch(filetype) { default:
case Reader::Normal: {
FileReader ff(fn);
if(!ff.ready()) return false;
size = ff.size();
data = ff.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::GZIP: {
GZReader gf(fn);
if(!gf.ready()) return false;
size = gf.size();
data = gf.read();
} break;
case Reader::ZIP: {
ZipReader zf(fn);
if(!zf.ready()) return false;
size = zf.size();
data = zf.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::JMA: {
try {
JMAReader jf(fn);
size = jf.size();
data = jf.read();
} catch(JMA::jma_errors jma_error) {
return false;
}
} break;
#endif
}
return true;
}
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) const {
uint8_t *outdata = 0;
unsigned outsize;
ups patcher;
ups::result result = patcher.apply(pdata, psize, data, size, outdata, outsize);
bool apply = false;
if(result == ups::ok) apply = true;
if(snes.config.file.bypass_patch_crc32 == true) {
if(result == ups::input_crc32_invalid) apply = true;
if(result == ups::output_crc32_invalid) apply = true;
}
//if patch application was successful, replace old data, size with new data, size
if(apply == true) {
delete[] data;
data = new uint8_t[size = outsize];
memcpy(data, outdata, outsize);
}
if(outdata) delete[] outdata;
return apply;
}
bool Cartridge::save_file(const char *fn, uint8 *data, unsigned size) const {
file fp;
if(!fp.open(fn, file::mode_write)) return false;
fp.write(data, size);
fp.close();
return true;
}
#endif

View File

@ -1,244 +0,0 @@
#ifdef CART_CPP
//================
//Normal cartridge
//================
bool Cartridge::load_normal(const char *base) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
load_begin(ModeNormal);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
if(cartinfo.srtc || cartinfo.spc7110rtc) {
load_ram(get_filename(base, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size = 20, 0x00);
}
load_end();
set(name, basename(base));
return true;
}
void Cartridge::unload_normal() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
if(cart.rtc) save_file(get_filename(cart.filename, "rtc", snes.config.path.save), cart.rtc, cart.rtc_size);
}
//======================
//BS-X slotted cartridge
//======================
bool Cartridge::load_bsx_slotted(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsxSlotted);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
if(cartinfo.ram_size > 0) {
load_ram(get_filename(base, "srm", snes.config.path.save), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
}
load_end();
string filename = basename(base);
if(*slot) filename << " + " << basename(slot);
set(name, filename);
return true;
}
void Cartridge::unload_bsx_slotted() {
if(cart.ram) save_file(get_filename(cart.filename, "srm", snes.config.path.save), cart.ram, cart.ram_size);
}
//====================
//BS-X flash cartridge
//====================
bool Cartridge::load_bsx(const char *base, const char *slot) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
bs.filename = slot;
load_begin(ModeBsx);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
cart.ram = 0;
cart.ram_size = 0;
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
if(load_file(get_filename(base, "srm", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
delete[] data;
}
if(load_file(get_filename(base, "psr", snes.config.path.save), data, size, CompressionNone) == true) {
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
delete[] data;
}
if(load_image(slot, data, size, patch_applied) == true) {
set(bsx_flash_loaded, true);
if(patch_applied) set(patched, true);
bs.ram = data;
bs.ram_size = size;
}
load_end();
set(name, !*slot ? basename(base) : basename(slot));
return true;
}
void Cartridge::unload_bsx() {
save_file(get_filename(cart.filename, "srm", snes.config.path.save), bsxcart.sram.handle (), bsxcart.sram.size ());
save_file(get_filename(cart.filename, "psr", snes.config.path.save), bsxcart.psram.handle(), bsxcart.psram.size());
}
//============================
//Sufami Turbo flash cartridge
//============================
bool Cartridge::load_sufami_turbo(const char *base, const char *slotA, const char *slotB) {
uint8_t *data;
unsigned size;
bool patch_applied;
cart.filename = base;
stA.filename = slotA;
stB.filename = slotB;
load_begin(ModeSufamiTurbo);
if(load_image(base, data, size, patch_applied) == false) return false;
snes.config.path.current = basepath(cart.filename);
if(patch_applied) set(patched, true);
cartinfo_t cartinfo;
read_header(cartinfo, cart.rom = data, cart.rom_size = size);
set_cartinfo(cartinfo);
if(load_image(slotA, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
memcpy(stA.rom, data, min(size, stA.rom_size));
delete[] data;
load_ram(get_filename(slotA, "srm", snes.config.path.save), stA.ram, stA.ram_size = 0x020000, 0xff);
}
if(load_image(slotB, data, size, patch_applied) == true) {
if(patch_applied) set(patched, true);
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
memcpy(stB.rom, data, min(size, stB.rom_size));
delete[] data;
load_ram(get_filename(slotB, "srm", snes.config.path.save), stB.ram, stB.ram_size = 0x020000, 0xff);
}
load_end();
string filename;
if(!*slotA && !*slotB) filename << basename(base);
else if( *slotA && !*slotB) filename << basename(slotA);
else if(!*slotA && *slotB) filename << basename(slotB);
else filename << basename(slotA) << " + " << basename(slotB);
set(name, filename);
return true;
}
void Cartridge::unload_sufami_turbo() {
if(stA.ram) save_file(get_filename(stA.filename, "srm", snes.config.path.save), stA.ram, stA.ram_size);
if(stB.ram) save_file(get_filename(stB.filename, "srm", snes.config.path.save), stB.ram, stB.ram_size);
}
//=================
//utility functions
//=================
Cartridge::Type Cartridge::detect_image_type(const char *filename) const {
uint8_t *data;
unsigned size;
bool patch_applied;
if(!load_image(filename, data, size, patch_applied)) return TypeUnknown;
cartinfo_t info;
read_header(info, data, size);
delete[] data;
return info.type;
}
bool Cartridge::load_image(const char *filename, uint8_t *&data, unsigned &size, bool &patched) const {
if(!filename || !*filename) return false;
if(!load_file(filename, data, size, CompressionAuto)) return false;
if((size & 0x7fff) == 512) {
//remove 512-byte header
memmove(data, data + 512, size -= 512);
}
uint8_t *pdata;
unsigned psize;
if(load_file(get_filename(filename, "ups", snes.config.path.patch), pdata, psize, CompressionInspect) == true) {
apply_patch(pdata, psize, data, size);
delete[] pdata;
patched = true;
} else {
patched = false;
}
return true;
}
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) const {
data = new uint8_t[size];
memset(data, init, size);
uint8_t *savedata;
unsigned savesize;
if(load_file(filename, savedata, savesize, CompressionNone) == false) return false;
memcpy(data, savedata, min(size, savesize));
delete[] savedata;
return true;
}
#endif

View File

@ -0,0 +1,157 @@
#include <../base.hpp>
#define CARTRIDGE_CPP
namespace SNES {
#include "header.cpp"
namespace memory {
MappedRAM cartrom, cartram, cartrtc;
MappedRAM bsxflash, bsxram, bsxpram;
MappedRAM stArom, stAram;
MappedRAM stBrom, stBram;
MappedRAM gbrom, gbram;
};
Cartridge cartridge;
void Cartridge::load(Mode cartridge_mode) {
cartinfo_t cartinfo;
read_header(cartinfo, memory::cartrom.data(), memory::cartrom.size());
set_cartinfo(cartinfo);
set(mode, cartridge_mode);
if(cartinfo.ram_size > 0) {
memory::cartram.map(new(zeromemory) uint8_t[cartinfo.ram_size], cartinfo.ram_size);
}
if(cartinfo.srtc || cartinfo.spc7110rtc) {
memory::cartrtc.map(new(zeromemory) uint8_t[20], 20);
}
if(mode() == ModeBsx) {
memory::bsxram.map (new(zeromemory) uint8_t[ 32 * 1024], 32 * 1024);
memory::bsxpram.map(new(zeromemory) uint8_t[512 * 1024], 512 * 1024);
}
if(mode() == ModeSufamiTurbo) {
if(memory::stArom.data()) memory::stAram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
if(memory::stBrom.data()) memory::stBram.map(new(zeromemory) uint8_t[128 * 1024], 128 * 1024);
}
if(mode() == ModeSuperGameBoy) {
if(memory::gbrom.data()) memory::gbram.map(new(zeromemory) uint8_t[64 * 1024], 64 * 1024);
}
memory::cartrom.write_protect(true);
memory::cartram.write_protect(false);
memory::cartrtc.write_protect(false);
memory::bsxflash.write_protect(true);
memory::bsxram.write_protect(false);
memory::bsxpram.write_protect(false);
memory::stArom.write_protect(true);
memory::stAram.write_protect(false);
memory::stBrom.write_protect(true);
memory::stBram.write_protect(false);
memory::gbrom.write_protect(true);
memory::gbram.write_protect(false);
bus.load_cart();
set(loaded, true);
}
void Cartridge::unload() {
memory::cartrom.reset();
memory::cartram.reset();
memory::cartrtc.reset();
memory::bsxflash.reset();
memory::bsxram.reset();
memory::bsxpram.reset();
memory::stArom.reset();
memory::stAram.reset();
memory::stBrom.reset();
memory::stBram.reset();
memory::gbrom.reset();
memory::gbram.reset();
if(loaded() == false) return;
bus.unload_cart();
set(loaded, false);
}
Cartridge::Type Cartridge::detect_image_type(uint8_t *data, unsigned size) const {
cartinfo_t info;
read_header(info, data, size);
return info.type;
}
Cartridge::Cartridge() {
set(loaded, false);
unload();
}
Cartridge::~Cartridge() {
unload();
}
void Cartridge::set_cartinfo(const Cartridge::cartinfo_t &source) {
set(region, source.region);
set(mapper, source.mapper);
set(dsp1_mapper, source.dsp1_mapper);
set(has_bsx_slot, source.bsx_slot);
set(has_superfx, source.superfx);
set(has_sa1, source.sa1);
set(has_srtc, source.srtc);
set(has_sdd1, source.sdd1);
set(has_spc7110, source.spc7110);
set(has_spc7110rtc, source.spc7110rtc);
set(has_cx4, source.cx4);
set(has_dsp1, source.dsp1);
set(has_dsp2, source.dsp2);
set(has_dsp3, source.dsp3);
set(has_dsp4, source.dsp4);
set(has_obc1, source.obc1);
set(has_st010, source.st010);
set(has_st011, source.st011);
set(has_st018, source.st018);
}
//==========
//cartinfo_t
//==========
void Cartridge::cartinfo_t::reset() {
type = TypeUnknown;
mapper = LoROM;
dsp1_mapper = DSP1Unmapped;
region = NTSC;
rom_size = 0;
ram_size = 0;
bsx_slot = false;
superfx = false;
sa1 = false;
srtc = false;
sdd1 = false;
spc7110 = false;
spc7110rtc = false;
cx4 = false;
dsp1 = false;
dsp2 = false;
dsp3 = false;
dsp4 = false;
obc1 = false;
st010 = false;
st011 = false;
st018 = false;
}
Cartridge::cartinfo_t::cartinfo_t() {
reset();
}
};

View File

@ -0,0 +1,130 @@
class Cartridge : public property {
public:
enum Mode {
ModeNormal,
ModeBsxSlotted,
ModeBsx,
ModeSufamiTurbo,
ModeSuperGameBoy,
};
enum Type {
TypeNormal,
TypeBsxSlotted,
TypeBsxBios,
TypeBsx,
TypeSufamiTurboBios,
TypeSufamiTurbo,
TypeSuperGameBoyBios,
TypeGameBoy,
TypeUnknown,
};
enum Region {
NTSC,
PAL,
};
enum MemoryMapper {
LoROM,
HiROM,
ExLoROM,
ExHiROM,
SA1ROM,
SPC7110ROM,
BSCLoROM,
BSCHiROM,
BSXROM,
STROM,
};
enum DSP1MemoryMapper {
DSP1Unmapped,
DSP1LoROM1MB,
DSP1LoROM2MB,
DSP1HiROM,
};
//properties can be read via operator(), eg "if(cartridge.loaded() == true)";
//warning: if loaded() == false, no other property is considered valid!
property_t<bool> loaded; //is a base cartridge inserted?
property_t<Mode> mode;
property_t<Region> region;
property_t<MemoryMapper> mapper;
property_t<DSP1MemoryMapper> dsp1_mapper;
property_t<bool> has_bsx_slot;
property_t<bool> has_superfx;
property_t<bool> has_sa1;
property_t<bool> has_srtc;
property_t<bool> has_sdd1;
property_t<bool> has_spc7110, has_spc7110rtc;
property_t<bool> has_cx4;
property_t<bool> has_dsp1, has_dsp2, has_dsp3, has_dsp4;
property_t<bool> has_obc1;
property_t<bool> has_st010, has_st011, has_st018;
//main interface
void load(Mode);
//void read();
//void load();
void unload();
Type detect_image_type(uint8_t *data, unsigned size) const;
Cartridge();
~Cartridge();
private:
struct cartinfo_t {
Type type;
Region region;
MemoryMapper mapper;
DSP1MemoryMapper dsp1_mapper;
unsigned rom_size, ram_size;
bool bsx_slot;
bool superfx;
bool sa1;
bool srtc;
bool sdd1;
bool spc7110, spc7110rtc;
bool cx4;
bool dsp1, dsp2, dsp3, dsp4;
bool obc1;
bool st010, st011, st018;
void reset();
cartinfo_t();
};
enum HeaderField {
CartName = 0x00,
Mapper = 0x15,
RomType = 0x16,
RomSize = 0x17,
RamSize = 0x18,
CartRegion = 0x19,
Company = 0x1a,
Version = 0x1b,
Complement = 0x1c, //inverse checksum
Checksum = 0x1e,
ResetVector = 0x3c,
};
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const;
unsigned find_header(const uint8_t *data, unsigned size) const;
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const;
void set_cartinfo(const cartinfo_t&);
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bsxflash, bsxram, bsxpram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
extern MappedRAM gbrom, gbram;
};
extern Cartridge cartridge;

View File

@ -1,8 +1,35 @@
#ifdef CART_CPP #ifdef CARTRIDGE_CPP
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const { void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) const {
info.reset(); info.reset();
unsigned index = find_header(data, size);
//=====================
//detect Game Boy carts
//=====================
if(size >= 0x0140) {
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
info.type = TypeGameBoy;
return;
}
}
const unsigned index = find_header(data, size);
const uint8 mapper = data[index + Mapper];
const uint8 rom_type = data[index + RomType];
const uint8 rom_size = data[index + RomSize];
const uint8 company = data[index + Company];
const uint8 region = data[index + CartRegion] & 0x7f;
if(data[index + RamSize] & 7) {
info.ram_size = 1024 << (data[index + RamSize] & 7);
} else {
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
//======================= //=======================
//detect BS-X flash carts //detect BS-X flash carts
@ -37,16 +64,19 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
return; //RAM size handled internally by load_cart_st(); return; //RAM size handled internally by load_cart_st();
} }
//==========================
//detect Super Game Boy BIOS
//==========================
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
info.type = TypeSuperGameBoyBios;
return;
}
//===================== //=====================
//detect standard carts //detect standard carts
//===================== //=====================
const uint8 mapper = data[index + Mapper];
const uint8 rom_type = data[index + RomType];
const uint8 rom_size = data[index + RomSize];
const uint8 company = data[index + Company];
const uint8 region = data[index + CartRegion] & 0x7f;
//detect presence of BS-X flash cartridge connector (reads extended header information) //detect presence of BS-X flash cartridge connector (reads extended header information)
if(data[index - 14] == 'Z') { if(data[index - 14] == 'Z') {
if(data[index - 11] == 'J') { if(data[index - 11] == 'J') {
@ -91,8 +121,9 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
info.superfx = true; info.superfx = true;
} }
if(mapper == 0x23 && (rom_type == 0x34 || rom_type == 0x35)) { if(mapper == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
info.sa1 = true; info.sa1 = true;
info.mapper = SA1ROM;
} }
if(mapper == 0x35 && rom_type == 0x55) { if(mapper == 0x35 && rom_type == 0x55) {
@ -162,15 +193,6 @@ void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size
if(mapper == 0x30 && rom_type == 0xf5) { if(mapper == 0x30 && rom_type == 0xf5) {
info.st018 = true; info.st018 = true;
} }
if(data[index + RamSize] & 7) {
info.ram_size = 1024 << (data[index + RamSize] & 7);
} else {
info.ram_size = 0;
}
//0, 1, 13 = NTSC; 2 - 12 = PAL
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
} }
unsigned Cartridge::find_header(const uint8_t *data, unsigned size) const { unsigned Cartridge::find_header(const uint8_t *data, unsigned size) const {

View File

@ -1,3 +0,0 @@
::@mingw32-make platform=win compiler=mingw32-gcc
@mingw32-make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
@pause

View File

@ -1,2 +0,0 @@
make platform=x compiler=gcc
#make platform=x compiler=gcc enable_gzip=true enable_jma=true

View File

@ -1,5 +1,8 @@
#include <../base.hpp> #include <../base.hpp>
#define CHEAT_CPP
namespace SNES {
Cheat cheat; Cheat cheat;
Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) { Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) {
@ -178,9 +181,7 @@ void Cheat::disable(unsigned i) {
//... //...
//=============================== //===============================
bool Cheat::load(const char *fn) { void Cheat::load(string data) {
string data;
if(!data.readfile(fn)) return false;
data.replace("\r\n", "\n"); data.replace("\r\n", "\n");
data.qreplace(" ", ""); data.qreplace(" ", "");
@ -193,21 +194,16 @@ bool Cheat::load(const char *fn) {
trim(part[0], "\""); trim(part[0], "\"");
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]); add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
} }
return true;
} }
bool Cheat::save(const char *fn) const { string Cheat::save() const {
file fp; string data;
if(!fp.open(fn, file::mode_write)) return false;
for(unsigned i = 0; i < code.size(); i++) { for(unsigned i = 0; i < code.size(); i++) {
fp.print(string() data << "\"" << code[i].desc << "\", "
<< "\"" << code[i].desc << "\", "
<< (code[i].enabled ? "enabled, " : "disabled, ") << (code[i].enabled ? "enabled, " : "disabled, ")
<< code[i].code << "\r\n"); << code[i].code << "\r\n";
} }
fp.close(); return data;
return true;
} }
void Cheat::clear() { void Cheat::clear() {
@ -390,3 +386,6 @@ string& Cheat::decode_description(string &desc) const {
desc.replace("\\n", "\n"); desc.replace("\\n", "\n");
return desc; return desc;
} }
};

View File

@ -38,8 +38,8 @@ public:
void enable(unsigned i); void enable(unsigned i);
void disable(unsigned i); void disable(unsigned i);
bool load(const char *fn); void load(string data);
bool save(const char *fn) const; string save() const;
void clear(); void clear();
Cheat(); Cheat();

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define BSX_CPP
#include "bsx.hpp" #define BSX_CPP
namespace SNES {
#include "bsx_base.cpp" #include "bsx_base.cpp"
#include "bsx_cart.cpp" #include "bsx_cart.cpp"
#include "bsx_flash.cpp" #include "bsx_flash.cpp"
};

View File

@ -32,16 +32,10 @@ public:
uint8 mmio_read(unsigned addr); uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data); void mmio_write(unsigned addr, uint8 data);
MappedRAM sram;
MappedRAM psram;
BSXCart(); BSXCart();
~BSXCart(); ~BSXCart();
private: private:
uint8 *sram_data; //256kbit SRAM
uint8 *psram_data; // 4mbit PSRAM
struct { struct {
uint8 r[16]; uint8 r[16];
} regs; } regs;

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXBase bsxbase;
void BSXBase::init() { void BSXBase::init() {
} }
@ -135,3 +137,4 @@ void BSXBase::mmio_write(unsigned addr, uint8 data) {
} }
#endif #endif

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXCart bsxcart;
void BSXCart::init() { void BSXCart::init() {
} }
@ -20,7 +22,7 @@ void BSXCart::reset() {
} }
void BSXCart::update_memory_map() { void BSXCart::update_memory_map() {
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram; Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)memory::bsxpram;
if((regs.r[0x02] & 0x80) == 0x00) { if((regs.r[0x02] & 0x80) == 0x00) {
//LoROM mapping //LoROM mapping
@ -35,16 +37,16 @@ void BSXCart::update_memory_map() {
} }
if(regs.r[0x03] & 0x80) { if(regs.r[0x03] & 0x80) {
bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
//bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram); //bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
} }
if((regs.r[0x05] & 0x80) == 0x00) { if((regs.r[0x05] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
} }
if((regs.r[0x06] & 0x80) == 0x00) { if((regs.r[0x06] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
} }
if(regs.r[0x07] & 0x80) { if(regs.r[0x07] & 0x80) {
@ -55,8 +57,8 @@ void BSXCart::update_memory_map() {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom); bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
} }
bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, psram); bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, psram); bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
} }
uint8 BSXCart::mmio_read(unsigned addr) { uint8 BSXCart::mmio_read(unsigned addr) {
@ -66,7 +68,7 @@ uint8 BSXCart::mmio_read(unsigned addr) {
} }
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff)); return memory::bsxram.read(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff));
} }
return 0x00; return 0x00;
@ -81,21 +83,15 @@ void BSXCart::mmio_write(unsigned addr, uint8 data) {
} }
if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM if((addr & 0xf8f000) == 0x105000) { //$[10-17]:[5000-5fff] SRAM
return sram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data); return memory::bsxram.write(((addr >> 16) & 7) * 0x1000 + (addr & 0xfff), data);
} }
} }
BSXCart::BSXCart() { BSXCart::BSXCart() {
sram_data = new uint8_t[ 32 * 1024];
psram_data = new uint8_t[512 * 1024];
sram.map (sram_data, 32 * 1024);
psram.map(psram_data, 512 * 1024);
} }
BSXCart::~BSXCart() { BSXCart::~BSXCart() {
delete[] sram_data;
delete[] psram_data;
} }
#endif #endif

View File

@ -1,5 +1,7 @@
#ifdef BSX_CPP #ifdef BSX_CPP
BSXFlash bsxflash;
void BSXFlash::init() {} void BSXFlash::init() {}
void BSXFlash::enable() {} void BSXFlash::enable() {}
@ -15,10 +17,11 @@ void BSXFlash::reset() {
regs.flash_enable = false; regs.flash_enable = false;
regs.read_enable = false; regs.read_enable = false;
regs.write_enable = false; regs.write_enable = false;
memory::bsxflash.write_protect(!regs.write_enable);
} }
unsigned BSXFlash::size() const { unsigned BSXFlash::size() const {
return memory::bscram.size(); return memory::bsxflash.size();
} }
uint8 BSXFlash::read(unsigned addr) { uint8 BSXFlash::read(unsigned addr) {
@ -45,7 +48,7 @@ uint8 BSXFlash::read(unsigned addr) {
} }
} }
return memory::bscram.read(addr); return memory::bsxflash.read(addr);
} }
void BSXFlash::write(unsigned addr, uint8 data) { void BSXFlash::write(unsigned addr, uint8 data) {
@ -64,11 +67,11 @@ void BSXFlash::write(unsigned addr, uint8 data) {
regs.write_new = data; regs.write_new = data;
if(regs.write_enable && regs.write_old == regs.write_new) { if(regs.write_enable && regs.write_old == regs.write_new) {
return memory::bscram.write(addr, data); return memory::bsxflash.write(addr, data);
} }
} else { } else {
if(regs.write_enable) { if(regs.write_enable) {
return memory::bscram.write(addr, data); return memory::bsxflash.write(addr, data);
} }
} }
@ -107,7 +110,10 @@ void BSXFlash::write(unsigned addr, uint8 data) {
regs.read_enable = false; regs.read_enable = false;
regs.write_enable = false; regs.write_enable = false;
} }
memory::bsxflash.write_protect(!regs.write_enable);
} }
} }
#endif #endif

View File

@ -1,3 +1,5 @@
#include "sgb/sgb.hpp"
#include "sa1/sa1.hpp"
#include "bsx/bsx.hpp" #include "bsx/bsx.hpp"
#include "srtc/srtc.hpp" #include "srtc/srtc.hpp"
#include "sdd1/sdd1.hpp" #include "sdd1/sdd1.hpp"

View File

@ -6,9 +6,12 @@
*/ */
#include <../base.hpp> #include <../base.hpp>
#define CX4_CPP
#include "cx4.hpp" #define CX4_CPP
namespace SNES {
Cx4 cx4;
#include "cx4data.cpp" #include "cx4data.cpp"
#include "cx4fn.cpp" #include "cx4fn.cpp"
#include "cx4oam.cpp" #include "cx4oam.cpp"
@ -30,8 +33,8 @@ uint16 addr = 0x0080 + (r * 3);
} }
void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) { void Cx4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff; int64_t rx = x & 0xffffff;
int64 ry = y & 0xffffff; int64_t ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff; if(rx & 0x800000)rx |= ~0x7fffff;
if(ry & 0x800000)ry |= ~0x7fffff; if(ry & 0x800000)ry |= ~0x7fffff;
@ -195,3 +198,5 @@ void Cx4::reset() {
memset(ram, 0, 0x0c00); memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100); memset(reg, 0, 0x0100);
} }
};

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define DSP1_CPP
#include "dsp1.hpp" #define DSP1_CPP
namespace SNES {
DSP1 dsp1;
#include "dsp1emu.cpp" #include "dsp1emu.cpp"
void DSP1::init() {} void DSP1::init() {}
@ -57,3 +59,5 @@ void DSP1::write(unsigned addr, uint8 data) {
dsp1.setDr(data); dsp1.setDr(data);
} }
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP2_CPP
#include "dsp2.hpp" #define DSP2_CPP
namespace SNES {
DSP2 dsp2;
#include "dsp2_op.cpp" #include "dsp2_op.cpp"
void DSP2::init() {} void DSP2::init() {}
@ -134,3 +137,5 @@ void DSP2::write(unsigned addr, uint8 data) {
DSP2::DSP2() {} DSP2::DSP2() {}
DSP2::~DSP2() {} DSP2::~DSP2() {}
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP3_CPP
#include "dsp3.hpp" #define DSP3_CPP
namespace SNES {
DSP3 dsp3;
namespace DSP3i { namespace DSP3i {
#define bool8 uint8 #define bool8 uint8
#include "dsp3emu.c" #include "dsp3emu.c"
@ -33,3 +36,5 @@ void DSP3::write(unsigned addr, uint8 data) {
DSP3i::dsp3_byte = data; DSP3i::dsp3_byte = data;
DSP3i::DSP3SetByte(); DSP3i::DSP3SetByte();
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define DSP4_CPP
#include "dsp4.hpp" #define DSP4_CPP
namespace SNES {
DSP4 dsp4;
namespace DSP4i { namespace DSP4i {
inline uint16 READ_WORD(uint8 *addr) { inline uint16 READ_WORD(uint8 *addr) {
return (addr[0]) + (addr[1] << 8); return (addr[0]) + (addr[1] << 8);
@ -53,3 +56,5 @@ void DSP4::write(unsigned addr, uint8 data) {
DSP4i::DSP4SetByte(); DSP4i::DSP4SetByte();
} }
} }
};

View File

@ -1,6 +1,9 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#include "obc1.hpp" #define OBC1_CPP
namespace SNES {
OBC1 obc1;
void OBC1::init() {} void OBC1::init() {}
void OBC1::enable() {} void OBC1::enable() {}
@ -70,3 +73,6 @@ void OBC1::ram_write(unsigned addr, uint8 data) {
OBC1::OBC1() {} OBC1::OBC1() {}
OBC1::~OBC1() {} OBC1::~OBC1() {}
};

164
tools/bsnes/chip/sa1/bus/bus.cpp Executable file
View File

@ -0,0 +1,164 @@
#ifdef SA1_CPP
SA1Bus sa1bus;
namespace memory {
VectorSelectionPage vectorsp;
StaticRAM iram(2048);
MappedRAM &bwram = memory::cartram;
CC1BWRAM cc1bwram;
BitmapRAM bitmapram;
}
void SA1Bus::init() {
for(uint32_t i = 0x0000; i <= 0xffff; i++) {
map(i << 8, memory::memory_unmapped, 0);
}
for(uint16_t i = 0x2200; i <= 0x23ff; i++) {
memory::mmio.map(i, sa1);
}
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram);
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bwram);
map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
map(MapDirect, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram);
bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cc1bwram);
bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram);
bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
memory::vectorsp.sync();
}
//===================
//VectorSelectionPage
//===================
//this class maps $00:[ff00-ffff] for the purpose of supporting:
//$2209.d6 IVSW (S-CPU IRQ vector selection) (0 = cart, 1 = SA-1)
//$2209.d4 NVSW (S-CPU NMI vector selection) (0 = cart, 1 = SA-1)
//when set, vector addresses are over-ridden with SA-1 register settings:
//SIV = S-CPU IRQ vector address override
//SNV = S-CPU NMI vector address override
//
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
//all other addresses return original mapped data.
uint8_t VectorSelectionPage::read(unsigned addr) {
switch(0xff00 | (addr & 0xff)) {
case 0xffea: case 0xffeb: {
if(sa1.mmio.cpu_nvsw == true) return (sa1.mmio.snv >> ((addr & 1) << 3));
} break;
case 0xffee: case 0xffef: {
if(sa1.mmio.cpu_ivsw == true) return (sa1.mmio.siv >> ((addr & 1) << 3));
} break;
}
return access->read(addr);
}
void VectorSelectionPage::write(unsigned addr, uint8_t data) {
return access->write(addr, data);
}
//call this whenever bus is remapped.
//note: S-CPU and SA-1 bus always share $00:[ff00-ffff] as cartridge ROM data;
//the SA-1 MMC does not allow mapping these independently between processors.
//this allows this class to be shared for both, caching only ones' access class.
void VectorSelectionPage::sync() {
if(bus.page[0x00ff00 >> 8].access != this) {
//bus was re-mapped, hook access routine
access = bus.page[0x00ff00 >> 8].access;
bus.page[0x00ff00 >> 8].access = this;
sa1bus.page[0x00ff00 >> 8].access = this;
}
}
//========
//CC1BWRAM
//========
unsigned CC1BWRAM::size() const {
return memory::cartram.size();
}
uint8_t CC1BWRAM::read(unsigned addr) {
if(dma) return sa1.dma_cc1_read(addr);
return memory::cartram.read(addr);
}
void CC1BWRAM::write(unsigned addr, uint8_t data) {
memory::cartram.write(addr, data);
}
//=========
//BitmapRAM
//=========
unsigned BitmapRAM::size() const {
return 0x100000;
}
uint8_t BitmapRAM::read(unsigned addr) {
if(sa1.mmio.bbf == 0) {
//4bpp
unsigned shift = addr & 1;
addr = (addr >> 1) & (memory::cartram.size() - 1);
switch(shift) {
case 0: return (memory::cartram.read(addr) >> 0) & 15;
case 1: return (memory::cartram.read(addr) >> 4) & 15;
}
} else {
//2bpp
unsigned shift = addr & 3;
addr = (addr >> 2) & (memory::cartram.size() - 1);
switch(shift) {
case 0: return (memory::cartram.read(addr) >> 0) & 3;
case 1: return (memory::cartram.read(addr) >> 2) & 3;
case 2: return (memory::cartram.read(addr) >> 4) & 3;
case 3: return (memory::cartram.read(addr) >> 6) & 3;
}
}
}
void BitmapRAM::write(unsigned addr, uint8_t data) {
if(sa1.mmio.bbf == 0) {
//4bpp
uint8_t shift = addr & 1;
addr = (addr >> 1) & (memory::cartram.size() - 1);
switch(shift) {
case 0: data = (memory::cartram.read(addr) & 0xf0) | ((data & 15) << 0); break;
case 1: data = (memory::cartram.read(addr) & 0x0f) | ((data & 15) << 4); break;
}
} else {
//2bpp
uint8_t shift = addr & 3;
addr = (addr >> 2) & (memory::cartram.size() - 1);
switch(shift) {
case 0: data = (memory::cartram.read(addr) & 0xfc) | ((data & 3) << 0); break;
case 1: data = (memory::cartram.read(addr) & 0xf3) | ((data & 3) << 2); break;
case 2: data = (memory::cartram.read(addr) & 0xcf) | ((data & 3) << 4); break;
case 3: data = (memory::cartram.read(addr) & 0x3f) | ((data & 3) << 6); break;
}
}
memory::cartram.write(addr, data);
}
#endif

View File

@ -0,0 +1,31 @@
struct SA1Bus : Bus {
void init();
};
struct VectorSelectionPage : Memory {
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
void sync();
Memory *access;
};
struct CC1BWRAM : Memory {
unsigned size() const;
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
bool dma;
};
struct BitmapRAM : Memory {
unsigned size() const;
alwaysinline uint8_t read(unsigned);
alwaysinline void write(unsigned, uint8_t);
};
namespace memory {
extern VectorSelectionPage vectorsp;
extern StaticRAM iram;
extern MappedRAM &bwram;
extern CC1BWRAM cc1bwram;
extern BitmapRAM bitmapram;
}

139
tools/bsnes/chip/sa1/dma/dma.cpp Executable file
View File

@ -0,0 +1,139 @@
#ifdef SA1_CPP
//====================
//direct data transfer
//====================
void SA1::dma_normal() {
while(mmio.dtc--) {
uint8_t data = regs.mdr;
uint32_t dsa = mmio.dsa++;
uint32_t dda = mmio.dda++;
//source and destination cannot be the same
if(mmio.sd == DMA::SourceBWRAM && mmio.dd == DMA::DestBWRAM) continue;
if(mmio.sd == DMA::SourceIRAM && mmio.dd == DMA::DestIRAM ) continue;
switch(mmio.sd) {
case DMA::SourceROM: {
if((dsa & 0x408000) == 0x008000 || (dsa & 0xc00000) == 0xc00000) {
data = sa1bus.read(dsa);
}
} break;
case DMA::SourceBWRAM: {
if((dsa & 0x40e000) == 0x006000 || (dsa & 0xf00000) == 0x400000) {
data = sa1bus.read(dsa);
}
} break;
case DMA::SourceIRAM: {
data = memory::iram.read(dsa & 0x07ff);
} break;
}
switch(mmio.dd) {
case DMA::DestBWRAM: {
if((dda & 0x40e000) == 0x006000 || (dda & 0xf00000) == 0x400000) {
sa1bus.write(dda, data);
}
} break;
case DMA::DestIRAM: {
memory::iram.write(dda & 0x07ff, data);
} break;
}
}
mmio.dma_irqfl = true;
if(mmio.dma_irqen) mmio.dma_irqcl = 0;
}
//((byte & 6) << 3) + (byte & 1) explanation:
//transforms a byte index (0-7) into a planar index:
//result[] = { 0, 1, 16, 17, 32, 33, 48, 49 };
//works for 2bpp, 4bpp and 8bpp modes
//===========================
//type-1 character conversion
//===========================
void SA1::dma_cc1() {
memory::cc1bwram.dma = true;
mmio.chdma_irqfl = true;
if(mmio.chdma_irqen) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
}
}
uint8_t SA1::dma_cc1_read(unsigned addr) {
//16 bytes/char (2bpp); 32 bytes/char (4bpp); 64 bytes/char (8bpp)
unsigned charmask = (1 << (6 - mmio.dmacb)) - 1;
if((addr & charmask) == 0) {
//buffer next character to I-RAM
unsigned bpp = 2 << (2 - mmio.dmacb);
unsigned bpl = (8 << mmio.dmasize) >> mmio.dmacb;
unsigned bwmask = memory::bwram.size() - 1;
unsigned tile = ((addr - mmio.dsa) & bwmask) >> (6 - mmio.dmacb);
unsigned ty = (tile >> mmio.dmasize);
unsigned tx = tile & ((1 << mmio.dmasize) - 1);
unsigned bwaddr = mmio.dsa + ty * 8 * bpl + tx * bpp;
for(unsigned y = 0; y < 8; y++) {
uint64_t data = 0;
for(unsigned byte = 0; byte < bpp; byte++) {
data |= (uint64_t)memory::bwram.read((bwaddr + byte) & bwmask) << (byte << 3);
}
bwaddr += bpl;
uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
for(unsigned x = 0; x < 8; x++) {
out[0] |= (data & 1) << (7 - x); data >>= 1;
out[1] |= (data & 1) << (7 - x); data >>= 1;
if(mmio.dmacb == 2) continue;
out[2] |= (data & 1) << (7 - x); data >>= 1;
out[3] |= (data & 1) << (7 - x); data >>= 1;
if(mmio.dmacb == 1) continue;
out[4] |= (data & 1) << (7 - x); data >>= 1;
out[5] |= (data & 1) << (7 - x); data >>= 1;
out[6] |= (data & 1) << (7 - x); data >>= 1;
out[7] |= (data & 1) << (7 - x); data >>= 1;
}
for(unsigned byte = 0; byte < bpp; byte++) {
unsigned p = mmio.dda + (y << 1) + ((byte & 6) << 3) + (byte & 1);
memory::iram.write(p & 0x07ff, out[byte]);
}
}
}
return memory::iram.read((mmio.dda + (addr & charmask)) & 0x07ff);
}
//===========================
//type-2 character conversion
//===========================
void SA1::dma_cc2() {
//select register file index (0-7 or 8-15)
const uint8_t *brf = &mmio.brf[(dma.line & 1) << 3];
unsigned bpp = 2 << (2 - mmio.dmacb);
unsigned addr = mmio.dda & 0x07ff;
addr &= ~((1 << (7 - mmio.dmacb)) - 1);
addr += (dma.line & 8) * bpp;
addr += (dma.line & 7) * 2;
for(unsigned byte = 0; byte < bpp; byte++) {
uint8_t output = 0;
for(unsigned bit = 0; bit < 8; bit++) {
output |= ((brf[bit] >> byte) & 1) << (7 - bit);
}
memory::iram.write(addr + ((byte & 6) << 3) + (byte & 1), output);
}
dma.line = (dma.line + 1) & 15;
}
#endif

View File

@ -0,0 +1,11 @@
struct DMA {
enum CDEN { DmaNormal = 0, DmaCharConversion = 1 };
enum SD { SourceROM = 0, SourceBWRAM = 1, SourceIRAM = 2 };
enum DD { DestIRAM = 0, DestBWRAM = 1 };
unsigned line;
} dma;
void dma_normal();
void dma_cc1();
uint8_t dma_cc1_read(unsigned addr);
void dma_cc2();

View File

@ -0,0 +1,39 @@
#ifdef SA1_CPP
//==========================
//SA-1 opcode core functions
//==========================
void SA1::op_io() {
tick();
if(regs.wai) scheduler.sync_copcpu();
}
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
//BW-RAM is accessed at ~5.37MHz (4 clock ticks)
//tick() == 2 clock ticks
//note: bus conflict delays are not emulated at this time
#define is_bwram(addr) (\
((addr & 0x40e000) == 0x006000) \
|| ((addr & 0xf00000) == 0x400000) \
|| ((addr & 0xf00000) == 0x600000) \
)
uint8_t SA1::op_read(unsigned addr) {
tick();
if(is_bwram(addr)) tick();
scheduler.sync_copcpu();
return sa1bus.read(addr);
}
void SA1::op_write(unsigned addr, uint8_t data) {
tick();
if(is_bwram(addr)) tick();
scheduler.sync_copcpu();
sa1bus.write(addr, data);
}
#undef is_bwram
#endif

View File

@ -0,0 +1,4 @@
alwaysinline void op_io();
alwaysinline uint8_t op_read(unsigned addr);
alwaysinline void op_write(unsigned addr, uint8_t data);
alwaysinline unsigned bus_speed(unsigned addr);

View File

@ -0,0 +1,631 @@
#ifdef SA1_CPP
//BS-X flash carts, when present, are mapped to 0x400000+
Memory& SA1::mmio_access(unsigned &addr) {
if(!memory::bsxflash.data()) return memory::cartrom;
if(addr < 0x400000) return memory::cartrom;
addr &= 0x3fffff;
return bsxflash;
}
//(CCNT) SA-1 control
void SA1::mmio_w2200(uint8_t data) {
if(mmio.sa1_resb && !(data & 0x80)) {
//reset SA-1 CPU
regs.pc.w = mmio.crv;
regs.pc.b = 0x00;
}
mmio.sa1_irq = (data & 0x80);
mmio.sa1_rdyb = (data & 0x40);
mmio.sa1_resb = (data & 0x20);
mmio.sa1_nmi = (data & 0x10);
mmio.smeg = (data & 0x0f);
if(mmio.sa1_irq) {
mmio.sa1_irqfl = true;
if(mmio.sa1_irqen) mmio.sa1_irqcl = 0;
}
if(mmio.sa1_nmi) {
mmio.sa1_nmifl = true;
if(mmio.sa1_nmien) mmio.sa1_nmicl = 0;
}
}
//(SIE) S-CPU interrupt enable
void SA1::mmio_w2201(uint8_t data) {
if(!mmio.cpu_irqen && (data & 0x80)) {
if(mmio.cpu_irqfl) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
}
}
if(!mmio.chdma_irqen && (data & 0x20)) {
if(mmio.chdma_irqfl) {
mmio.chdma_irqcl = 0;
cpu.regs.irq = 1;
}
}
mmio.cpu_irqen = (data & 0x80);
mmio.chdma_irqen = (data & 0x20);
}
//(SIC) S-CPU interrupt clear
void SA1::mmio_w2202(uint8_t data) {
mmio.cpu_irqcl = (data & 0x80);
mmio.chdma_irqcl = (data & 0x20);
if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false;
if(mmio.chdma_irqcl) mmio.chdma_irqfl = false;
if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0;
}
//(CRV) SA-1 reset vector
void SA1::mmio_w2203(uint8_t data) { mmio.crv = (mmio.crv & 0xff00) | data; }
void SA1::mmio_w2204(uint8_t data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }
//(CNV) SA-1 NMI vector
void SA1::mmio_w2205(uint8_t data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }
void SA1::mmio_w2206(uint8_t data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }
//(CIV) SA-1 IRQ vector
void SA1::mmio_w2207(uint8_t data) { mmio.civ = (mmio.civ & 0xff00) | data; }
void SA1::mmio_w2208(uint8_t data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }
//(SCNT) S-CPU control
void SA1::mmio_w2209(uint8_t data) {
mmio.cpu_irq = (data & 0x80);
mmio.cpu_ivsw = (data & 0x40);
mmio.cpu_nvsw = (data & 0x10);
mmio.cmeg = (data & 0x0f);
if(mmio.cpu_irq) {
mmio.cpu_irqfl = true;
if(mmio.cpu_irqen) {
mmio.cpu_irqcl = 0;
cpu.regs.irq = 1;
}
}
}
//(CIE) SA-1 interrupt enable
void SA1::mmio_w220a(uint8_t data) {
if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;
if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;
if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;
if(!mmio.sa1_nmien && (data & 0x10) && mmio.sa1_nmifl ) mmio.sa1_nmicl = 0;
mmio.sa1_irqen = (data & 0x80);
mmio.timer_irqen = (data & 0x40);
mmio.dma_irqen = (data & 0x20);
mmio.sa1_nmien = (data & 0x10);
}
//(CIC) SA-1 interrupt clear
void SA1::mmio_w220b(uint8_t data) {
mmio.sa1_irqcl = (data & 0x80);
mmio.timer_irqcl = (data & 0x40);
mmio.dma_irqcl = (data & 0x20);
mmio.sa1_nmicl = (data & 0x10);
if(mmio.sa1_irqcl) mmio.sa1_irqfl = false;
if(mmio.timer_irqcl) mmio.timer_irqfl = false;
if(mmio.dma_irqcl) mmio.dma_irqfl = false;
if(mmio.sa1_nmicl) mmio.sa1_nmifl = false;
}
//(SNV) S-CPU NMI vector
void SA1::mmio_w220c(uint8_t data) { mmio.snv = (mmio.snv & 0xff00) | data; }
void SA1::mmio_w220d(uint8_t data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }
//(SIV) S-CPU IRQ vector
void SA1::mmio_w220e(uint8_t data) { mmio.siv = (mmio.siv & 0xff00) | data; }
void SA1::mmio_w220f(uint8_t data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }
//(TMC) H/V timer control
void SA1::mmio_w2210(uint8_t data) {
mmio.hvselb = (data & 0x80);
mmio.ven = (data & 0x02);
mmio.hen = (data & 0x01);
}
//(CTR) SA-1 timer restart
void SA1::mmio_w2211(uint8_t data) {
status.vcounter = 0;
status.hcounter = 0;
}
//(HCNT) H-count
void SA1::mmio_w2212(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }
void SA1::mmio_w2213(uint8_t data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }
//(VCNT) V-count
void SA1::mmio_w2214(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }
void SA1::mmio_w2215(uint8_t data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }
//(CXB) Super MMC bank C
void SA1::mmio_w2220(uint8_t data) {
mmio.cbmode = (data & 0x80);
mmio.cb = (data & 0x07);
unsigned addr = mmio.cb << 20;
Memory &access = mmio_access(addr);
if(mmio.cbmode == 0) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
} else {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
memory::vectorsp.sync();
}
//(DXB) Super MMC bank D
void SA1::mmio_w2221(uint8_t data) {
mmio.dbmode = (data & 0x80);
mmio.db = (data & 0x07);
unsigned addr = mmio.db << 20;
Memory &access = mmio_access(addr);
if(mmio.dbmode == 0) {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
} else {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
}
//(EXB) Super MMC bank E
void SA1::mmio_w2222(uint8_t data) {
mmio.ebmode = (data & 0x80);
mmio.eb = (data & 0x07);
unsigned addr = mmio.eb << 20;
Memory &access = mmio_access(addr);
if(mmio.ebmode == 0) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
} else {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
}
//(FXB) Super MMC bank F
void SA1::mmio_w2223(uint8_t data) {
mmio.fbmode = (data & 0x80);
mmio.fb = (data & 0x07);
unsigned addr = mmio.fb << 20;
Memory &access = mmio_access(addr);
if(mmio.fbmode == 0) {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
} else {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
}
//(BMAPS) S-CPU BW-RAM address mapping
void SA1::mmio_w2224(uint8_t data) {
mmio.sbm = (data & 0x1f);
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
}
//(BMAP) SA-1 BW-RAM address mapping
void SA1::mmio_w2225(uint8_t data) {
mmio.sw46 = (data & 0x80);
mmio.cbm = (data & 0x7f);
if(mmio.sw46 == 0) {
//$[40-43]:[0000-ffff] x 32 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
} else {
//$[60-6f]:[0000-ffff] x 128 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
}
}
//(SWBE) S-CPU BW-RAM write enable
void SA1::mmio_w2226(uint8_t data) {
mmio.swen = (data & 0x80);
}
//(CWBE) SA-1 BW-RAM write enable
void SA1::mmio_w2227(uint8_t data) {
mmio.cwen = (data & 0x80);
}
//(BWPA) BW-RAM write-protected area
void SA1::mmio_w2228(uint8_t data) {
mmio.bwp = (data & 0x0f);
}
//(SIWP) S-CPU I-RAM write protection
void SA1::mmio_w2229(uint8_t data) {
mmio.siwp = data;
}
//(CIWP) SA-1 I-RAM write protection
void SA1::mmio_w222a(uint8_t data) {
mmio.ciwp = data;
}
//(DCNT) DMA control
void SA1::mmio_w2230(uint8_t data) {
mmio.dmaen = (data & 0x80);
mmio.dprio = (data & 0x40);
mmio.cden = (data & 0x20);
mmio.cdsel = (data & 0x10);
mmio.dd = (data & 0x04);
mmio.sd = (data & 0x03);
if(mmio.dmaen == 0) dma.line = 0;
}
//(CDMA) character conversion DMA parameters
void SA1::mmio_w2231(uint8_t data) {
mmio.chdend = (data & 0x80);
mmio.dmasize = (data >> 2) & 7;
mmio.dmacb = (data & 0x03);
if(mmio.chdend) memory::cc1bwram.dma = false;
if(mmio.dmasize > 5) mmio.dmasize = 5;
if(mmio.dmacb > 2) mmio.dmacb = 2;
}
//(SDA) DMA source device start address
void SA1::mmio_w2232(uint8_t data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }
void SA1::mmio_w2233(uint8_t data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }
void SA1::mmio_w2234(uint8_t data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }
//(DDA) DMA destination start address
void SA1::mmio_w2235(uint8_t data) {
mmio.dda = (mmio.dda & 0xffff00) | (data << 0);
}
void SA1::mmio_w2236(uint8_t data) {
mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);
if(mmio.dmaen == true) {
if(mmio.cden == 0 && mmio.dd == DMA::DestIRAM) {
dma_normal();
} else if(mmio.cden == 1 && mmio.cdsel == 1) {
dma_cc1();
}
}
}
void SA1::mmio_w2237(uint8_t data) {
mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);
if(mmio.dmaen == true) {
if(mmio.cden == 0 && mmio.dd == DMA::DestBWRAM) {
dma_normal();
}
}
}
//(DTC) DMA terminal counter
void SA1::mmio_w2238(uint8_t data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }
void SA1::mmio_w2239(uint8_t data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }
//(BBF) BW-RAM bitmap format
void SA1::mmio_w223f(uint8_t data) {
mmio.bbf = (data & 0x80);
}
//(BRF) bitmap register files
void SA1::mmio_w2240(uint8_t data) { mmio.brf[ 0] = data; }
void SA1::mmio_w2241(uint8_t data) { mmio.brf[ 1] = data; }
void SA1::mmio_w2242(uint8_t data) { mmio.brf[ 2] = data; }
void SA1::mmio_w2243(uint8_t data) { mmio.brf[ 3] = data; }
void SA1::mmio_w2244(uint8_t data) { mmio.brf[ 4] = data; }
void SA1::mmio_w2245(uint8_t data) { mmio.brf[ 5] = data; }
void SA1::mmio_w2246(uint8_t data) { mmio.brf[ 6] = data; }
void SA1::mmio_w2247(uint8_t data) { mmio.brf[ 7] = data;
if(mmio.dmaen == true) {
if(mmio.cden == 1 && mmio.cdsel == 0) {
dma_cc2();
}
}
}
void SA1::mmio_w2248(uint8_t data) { mmio.brf[ 8] = data; }
void SA1::mmio_w2249(uint8_t data) { mmio.brf[ 9] = data; }
void SA1::mmio_w224a(uint8_t data) { mmio.brf[10] = data; }
void SA1::mmio_w224b(uint8_t data) { mmio.brf[11] = data; }
void SA1::mmio_w224c(uint8_t data) { mmio.brf[12] = data; }
void SA1::mmio_w224d(uint8_t data) { mmio.brf[13] = data; }
void SA1::mmio_w224e(uint8_t data) { mmio.brf[14] = data; }
void SA1::mmio_w224f(uint8_t data) { mmio.brf[15] = data;
if(mmio.dmaen == true) {
if(mmio.cden == 1 && mmio.cdsel == 0) {
dma_cc2();
}
}
}
//(MCNT) arithmetic control
void SA1::mmio_w2250(uint8_t data) {
mmio.acm = (data & 0x02);
mmio.md = (data & 0x01);
if(mmio.acm) mmio.mr = 0;
}
//(MAL) multiplicand / dividend low
void SA1::mmio_w2251(uint8_t data) {
mmio.ma = (mmio.ma & 0xff00) | data;
}
//(MAH) multiplicand / dividend high
void SA1::mmio_w2252(uint8_t data) {
mmio.ma = (data << 8) | (mmio.ma & 0x00ff);
}
//(MBL) multiplier / divisor low
void SA1::mmio_w2253(uint8_t data) {
mmio.mb = (mmio.mb & 0xff00) | data;
}
//(MBH) multiplier / divisor high
//multiplication / cumulative sum only resets MB
//division resets both MA and MB
void SA1::mmio_w2254(uint8_t data) {
mmio.mb = (data << 8) | (mmio.mb & 0x00ff);
if(mmio.acm == 0) {
if(mmio.md == 0) {
//signed multiplication
mmio.mr = (int16_t)mmio.ma * (int16_t)mmio.mb;
mmio.mb = 0;
} else {
//unsigned division
if(mmio.mb == 0) {
mmio.mr = 0;
} else {
int16_t quotient = (int16_t)mmio.ma / (uint16_t)mmio.mb;
uint16_t remainder = (int16_t)mmio.ma % (uint16_t)mmio.mb;
mmio.mr = (remainder << 16) | quotient;
}
mmio.ma = 0;
mmio.mb = 0;
}
} else {
//sigma (accumulative multiplication)
mmio.mr += (int16_t)mmio.ma * (int16_t)mmio.mb;
mmio.overflow = (mmio.mr >= (1ULL << 40));
mmio.mr &= (1ULL << 40) - 1;
mmio.mb = 0;
}
}
//(VBD) variable-length bit processing
void SA1::mmio_w2258(uint8_t data) {
mmio.hl = (data & 0x80);
mmio.vb = (data & 0x0f);
if(mmio.vb == 0) mmio.vb = 16;
if(mmio.hl == 0) {
//fixed mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
}
}
//(VDA) variable-length bit game pak ROM start address
void SA1::mmio_w2259(uint8_t data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }
void SA1::mmio_w225a(uint8_t data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }
void SA1::mmio_w225b(uint8_t data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }
//(SFR) S-CPU flag read
uint8_t SA1::mmio_r2300() {
uint8_t data;
data = mmio.cpu_irqfl << 7;
data |= mmio.cpu_ivsw << 6;
data |= mmio.chdma_irqfl << 5;
data |= mmio.cpu_nvsw << 4;
data |= mmio.cmeg;
return data;
}
//(CFR) SA-1 flag read
uint8_t SA1::mmio_r2301() {
uint8_t data;
data = mmio.sa1_irqfl << 7;
data |= mmio.timer_irqfl << 6;
data |= mmio.dma_irqfl << 5;
data |= mmio.sa1_nmifl << 4;
data |= mmio.smeg;
return data;
}
//(HCR) hcounter read
uint8_t SA1::mmio_r2302() {
//latch counters
mmio.hcr = status.hcounter >> 2;
mmio.vcr = status.vcounter;
return mmio.hcr >> 0; }
uint8_t SA1::mmio_r2303() { return mmio.hcr >> 8; }
//(VCR) vcounter read
uint8_t SA1::mmio_r2304() { return mmio.vcr >> 0; }
uint8_t SA1::mmio_r2305() { return mmio.vcr >> 8; }
//(MR) arithmetic result
uint8_t SA1::mmio_r2306() { return mmio.mr >> 0; }
uint8_t SA1::mmio_r2307() { return mmio.mr >> 8; }
uint8_t SA1::mmio_r2308() { return mmio.mr >> 16; }
uint8_t SA1::mmio_r2309() { return mmio.mr >> 24; }
uint8_t SA1::mmio_r230a() { return mmio.mr >> 32; }
//(OF) arithmetic overflow flag
uint8_t SA1::mmio_r230b() { return mmio.overflow << 7; }
//(VDPL) variable-length data read port low
uint8_t SA1::mmio_r230c() {
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
| (sa1bus.read(mmio.va + 1) << 8)
| (sa1bus.read(mmio.va + 2) << 16);
data >>= mmio.vbit;
return data >> 0;
}
//(VDPH) variable-length data read port high
uint8_t SA1::mmio_r230d() {
uint32_t data = (sa1bus.read(mmio.va + 0) << 0)
| (sa1bus.read(mmio.va + 1) << 8)
| (sa1bus.read(mmio.va + 2) << 16);
data >>= mmio.vbit;
if(mmio.hl == 1) {
//auto-increment mode
mmio.vbit += mmio.vb;
mmio.va += (mmio.vbit >> 3);
mmio.vbit &= 7;
}
return data >> 8;
}
//(VC) version code register
uint8_t SA1::mmio_r230e() {
return 0x01; //true value unknown
}
uint8_t SA1::mmio_read(unsigned addr) {
addr &= 0xffff;
switch(addr) {
case 0x2300: return mmio_r2300();
case 0x2301: return mmio_r2301();
case 0x2302: return mmio_r2302();
case 0x2303: return mmio_r2303();
case 0x2304: return mmio_r2304();
case 0x2305: return mmio_r2305();
case 0x2306: return mmio_r2306();
case 0x2307: return mmio_r2307();
case 0x2308: return mmio_r2308();
case 0x2309: return mmio_r2309();
case 0x230a: return mmio_r230a();
case 0x230b: return mmio_r230b();
case 0x230c: return mmio_r230c();
case 0x230d: return mmio_r230d();
case 0x230e: return mmio_r230e();
}
return 0x00;
}
void SA1::mmio_write(unsigned addr, uint8_t data) {
addr &= 0xffff;
switch(addr) {
case 0x2200: return mmio_w2200(data);
case 0x2201: return mmio_w2201(data);
case 0x2202: return mmio_w2202(data);
case 0x2203: return mmio_w2203(data);
case 0x2204: return mmio_w2204(data);
case 0x2205: return mmio_w2205(data);
case 0x2206: return mmio_w2206(data);
case 0x2207: return mmio_w2207(data);
case 0x2208: return mmio_w2208(data);
case 0x2209: return mmio_w2209(data);
case 0x220a: return mmio_w220a(data);
case 0x220b: return mmio_w220b(data);
case 0x220c: return mmio_w220c(data);
case 0x220d: return mmio_w220d(data);
case 0x220e: return mmio_w220e(data);
case 0x220f: return mmio_w220f(data);
case 0x2210: return mmio_w2210(data);
case 0x2211: return mmio_w2211(data);
case 0x2212: return mmio_w2212(data);
case 0x2213: return mmio_w2213(data);
case 0x2214: return mmio_w2214(data);
case 0x2215: return mmio_w2215(data);
case 0x2220: return mmio_w2220(data);
case 0x2221: return mmio_w2221(data);
case 0x2222: return mmio_w2222(data);
case 0x2223: return mmio_w2223(data);
case 0x2224: return mmio_w2224(data);
case 0x2225: return mmio_w2225(data);
case 0x2226: return mmio_w2226(data);
case 0x2227: return mmio_w2227(data);
case 0x2228: return mmio_w2228(data);
case 0x2229: return mmio_w2229(data);
case 0x222a: return mmio_w222a(data);
case 0x2230: return mmio_w2230(data);
case 0x2231: return mmio_w2231(data);
case 0x2232: return mmio_w2232(data);
case 0x2233: return mmio_w2233(data);
case 0x2234: return mmio_w2234(data);
case 0x2235: return mmio_w2235(data);
case 0x2236: return mmio_w2236(data);
case 0x2237: return mmio_w2237(data);
case 0x2238: return mmio_w2238(data);
case 0x2239: return mmio_w2239(data);
case 0x223f: return mmio_w223f(data);
case 0x2240: return mmio_w2240(data);
case 0x2241: return mmio_w2241(data);
case 0x2242: return mmio_w2242(data);
case 0x2243: return mmio_w2243(data);
case 0x2244: return mmio_w2244(data);
case 0x2245: return mmio_w2245(data);
case 0x2246: return mmio_w2246(data);
case 0x2247: return mmio_w2247(data);
case 0x2248: return mmio_w2248(data);
case 0x2249: return mmio_w2249(data);
case 0x224a: return mmio_w224a(data);
case 0x224b: return mmio_w224b(data);
case 0x224c: return mmio_w224c(data);
case 0x224d: return mmio_w224d(data);
case 0x224e: return mmio_w224e(data);
case 0x224f: return mmio_w224f(data);
case 0x2250: return mmio_w2250(data);
case 0x2251: return mmio_w2251(data);
case 0x2252: return mmio_w2252(data);
case 0x2253: return mmio_w2253(data);
case 0x2254: return mmio_w2254(data);
case 0x2258: return mmio_w2258(data);
case 0x2259: return mmio_w2259(data);
case 0x225a: return mmio_w225a(data);
case 0x225b: return mmio_w225b(data);
}
}
#endif

View File

@ -0,0 +1,256 @@
uint8_t mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8_t data);
Memory& mmio_access(unsigned &addr);
struct MMIO {
//$2200 CCNT
bool sa1_irq;
bool sa1_rdyb;
bool sa1_resb;
bool sa1_nmi;
uint8_t smeg;
//$2201 SIE
bool cpu_irqen;
bool chdma_irqen;
//$2202 SIC
bool cpu_irqcl;
bool chdma_irqcl;
//$2203,$2204 CRV
uint16_t crv;
//$2205,$2206 CNV
uint16_t cnv;
//$2207,$2208 CIV
uint16_t civ;
//$2209 SCNT
bool cpu_irq;
bool cpu_ivsw;
bool cpu_nvsw;
uint8_t cmeg;
//$220a CIE
bool sa1_irqen;
bool timer_irqen;
bool dma_irqen;
bool sa1_nmien;
//$220b CIC
bool sa1_irqcl;
bool timer_irqcl;
bool dma_irqcl;
bool sa1_nmicl;
//$220c,$220d SNV
uint16_t snv;
//$220e,$220f SIV
uint16_t siv;
//$2210 TMC
bool hvselb;
bool ven;
bool hen;
//$2212,$2213
uint16_t hcnt;
//$2214,$2215
uint16_t vcnt;
//$2220 CXB
bool cbmode;
uint8_t cb;
//$2221 DXB
bool dbmode;
uint8_t db;
//$2222 EXB
bool ebmode;
uint8_t eb;
//$2223 FXB
bool fbmode;
uint8_t fb;
//$2224 BMAPS
uint8_t sbm;
//$2225 BMAP
bool sw46;
uint8_t cbm;
//$2226 SBWE
bool swen;
//$2227 CBWE
bool cwen;
//$2228 BWPA
uint8_t bwp;
//$2229 SIWP
uint8_t siwp;
//$222a CIWP
uint8_t ciwp;
//$2230 DCNT
bool dmaen;
bool dprio;
bool cden;
bool cdsel;
bool dd;
uint8_t sd;
//$2231 CDMA
bool chdend;
uint8_t dmasize;
uint8_t dmacb;
//$2232-$2234 SDA
uint32_t dsa;
//$2235-$2237 DDA
uint32_t dda;
//$2238,$2239 DTC
uint16_t dtc;
//$223f BBF
bool bbf;
//$2240-224f BRF
uint8_t brf[16];
//$2250 MCNT
bool acm;
bool md;
//$2251,$2252 MA
uint16_t ma;
//$2253,$2254 MB
uint16_t mb;
//$2258 VBD
bool hl;
uint8_t vb;
//$2259-$225b VDA
uint32_t va;
uint8_t vbit;
//$2300 SFR
bool cpu_irqfl;
bool chdma_irqfl;
//$2301 CFR
bool sa1_irqfl;
bool timer_irqfl;
bool dma_irqfl;
bool sa1_nmifl;
//$2302,$2303 HCR
uint16_t hcr;
//$2304,$2305 VCR
uint16_t vcr;
//$2306-230a MR
uint64_t mr;
//$230b OF
bool overflow;
} mmio;
void mmio_w2200(uint8_t); //CCNT
void mmio_w2201(uint8_t); //SIE
void mmio_w2202(uint8_t); //SIC
void mmio_w2203(uint8_t); //CRVL
void mmio_w2204(uint8_t); //CRVH
void mmio_w2205(uint8_t); //CNVL
void mmio_w2206(uint8_t); //CNVH
void mmio_w2207(uint8_t); //CIVL
void mmio_w2208(uint8_t); //CIVH
void mmio_w2209(uint8_t); //SCNT
void mmio_w220a(uint8_t); //CIE
void mmio_w220b(uint8_t); //CIC
void mmio_w220c(uint8_t); //SNVL
void mmio_w220d(uint8_t); //SNVH
void mmio_w220e(uint8_t); //SIVL
void mmio_w220f(uint8_t); //SIVH
void mmio_w2210(uint8_t); //TMC
void mmio_w2211(uint8_t); //CTR
void mmio_w2212(uint8_t); //HCNTL
void mmio_w2213(uint8_t); //HCNTH
void mmio_w2214(uint8_t); //VCNTL
void mmio_w2215(uint8_t); //VCNTH
void mmio_w2220(uint8_t); //CXB
void mmio_w2221(uint8_t); //DXB
void mmio_w2222(uint8_t); //EXB
void mmio_w2223(uint8_t); //FXB
void mmio_w2224(uint8_t); //BMAPS
void mmio_w2225(uint8_t); //BMAP
void mmio_w2226(uint8_t); //SBWE
void mmio_w2227(uint8_t); //CBWE
void mmio_w2228(uint8_t); //BWPA
void mmio_w2229(uint8_t); //SIWP
void mmio_w222a(uint8_t); //CIWP
void mmio_w2230(uint8_t); //DCNT
void mmio_w2231(uint8_t); //CDMA
void mmio_w2232(uint8_t); //SDAL
void mmio_w2233(uint8_t); //SDAH
void mmio_w2234(uint8_t); //SDAB
void mmio_w2235(uint8_t); //DDAL
void mmio_w2236(uint8_t); //DDAH
void mmio_w2237(uint8_t); //DDAB
void mmio_w2238(uint8_t); //DTCL
void mmio_w2239(uint8_t); //DTCH
void mmio_w223f(uint8_t); //BBF
void mmio_w2240(uint8_t); //BRF0
void mmio_w2241(uint8_t); //BRF1
void mmio_w2242(uint8_t); //BRF2
void mmio_w2243(uint8_t); //BRF3
void mmio_w2244(uint8_t); //BRF4
void mmio_w2245(uint8_t); //BRF5
void mmio_w2246(uint8_t); //BRF6
void mmio_w2247(uint8_t); //BRF7
void mmio_w2248(uint8_t); //BRF8
void mmio_w2249(uint8_t); //BRF9
void mmio_w224a(uint8_t); //BRFA
void mmio_w224b(uint8_t); //BRFB
void mmio_w224c(uint8_t); //BRFC
void mmio_w224d(uint8_t); //BRFD
void mmio_w224e(uint8_t); //BRFE
void mmio_w224f(uint8_t); //BRFF
void mmio_w2250(uint8_t); //MCNT
void mmio_w2251(uint8_t); //MAL
void mmio_w2252(uint8_t); //MAH
void mmio_w2253(uint8_t); //MBL
void mmio_w2254(uint8_t); //MBH
void mmio_w2258(uint8_t); //VBD
void mmio_w2259(uint8_t); //VDAL
void mmio_w225a(uint8_t); //VDAH
void mmio_w225b(uint8_t); //VDAB
uint8_t mmio_r2300(); //SFR
uint8_t mmio_r2301(); //CFR
uint8_t mmio_r2302(); //HCRL
uint8_t mmio_r2303(); //HCRH
uint8_t mmio_r2304(); //VCRL
uint8_t mmio_r2305(); //VCRH
uint8_t mmio_r2306(); //MR [00-07]
uint8_t mmio_r2307(); //MR [08-15]
uint8_t mmio_r2308(); //MR [16-23]
uint8_t mmio_r2309(); //MR [24-31]
uint8_t mmio_r230a(); //MR [32-40]
uint8_t mmio_r230b(); //OF
uint8_t mmio_r230c(); //VDPL
uint8_t mmio_r230d(); //VDPH
uint8_t mmio_r230e(); //VC

318
tools/bsnes/chip/sa1/sa1.cpp Executable file
View File

@ -0,0 +1,318 @@
#include <../base.hpp>
#define SA1_CPP
namespace SNES {
SA1 sa1;
#include "bus/bus.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
void SA1::enter() {
while(true) {
while(mmio.sa1_rdyb || mmio.sa1_resb) {
//SA-1 co-processor is asleep
tick();
scheduler.sync_copcpu();
}
if(status.interrupt_pending) {
status.interrupt_pending = false;
interrupt(status.interrupt_vector);
}
(this->*opcode_table[op_readpc()])();
}
}
void SA1::last_cycle() {
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.cnv;
mmio.sa1_nmifl = true;
mmio.sa1_nmicl = 1;
regs.wai = false;
} else if(!regs.p.i) {
if(mmio.timer_irqen && !mmio.timer_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.timer_irqfl = true;
regs.wai = false;
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.dma_irqfl = true;
regs.wai = false;
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
status.interrupt_pending = true;
status.interrupt_vector = mmio.civ;
mmio.sa1_irqfl = true;
regs.wai = false;
}
}
}
void SA1::interrupt(uint16_t vector) {
op_read(regs.pc.d);
op_io();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
regs.pc.w = vector;
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
}
bool SA1::interrupt_pending() {
return status.interrupt_pending;
}
void SA1::tick() {
scheduler.addclocks_cop(2);
//adjust counters:
//note that internally, status counters are in clocks;
//whereas MMIO register counters are in dots (4 clocks = 1 dot)
if(mmio.hvselb == 0) {
//HV timer
status.hcounter += 2;
if(status.hcounter >= 1364) {
status.hcounter = 0;
if(++status.vcounter >= status.scanlines) status.vcounter = 0;
}
} else {
//linear timer
status.hcounter += 2;
status.vcounter += (status.hcounter >> 11);
status.hcounter &= 0x07ff;
status.vcounter &= 0x01ff;
}
//test counters for timer IRQ
switch((mmio.ven << 1) + (mmio.hen << 0)) {
case 0: break;
case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
case 3: if(status.vcounter == mmio.hcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
}
}
void SA1::trigger_irq() {
mmio.timer_irqfl = true;
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
}
void SA1::init() {
}
void SA1::enable() {
}
void SA1::power() {
regs.a = regs.x = regs.y = 0x0000;
regs.s = 0x01ff;
reset();
}
void SA1::reset() {
memory::vectorsp.access = 0;
memory::cc1bwram.dma = false;
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
memory::iram.write(addr, 0x00);
}
sa1bus.init();
regs.pc.d = 0x000000;
regs.x.h = 0x00;
regs.y.h = 0x00;
regs.s.h = 0x01;
regs.d = 0x0000;
regs.db = 0x00;
regs.p = 0x34;
regs.e = 1;
regs.mdr = 0x00;
regs.wai = false;
update_table();
status.interrupt_pending = false;
status.interrupt_vector = 0x0000;
status.scanlines = (system.region() == System::NTSC ? 262 : 312);
status.vcounter = 0;
status.hcounter = 0;
dma.line = 0;
//$2200 CCNT
mmio.sa1_irq = false;
mmio.sa1_rdyb = false;
mmio.sa1_resb = true;
mmio.sa1_nmi = false;
mmio.smeg = 0;
//$2201 SIE
mmio.cpu_irqen = false;
mmio.chdma_irqen = false;
//$2202 SIC
mmio.cpu_irqcl = false;
mmio.chdma_irqcl = false;
//$2203,$2204 CRV
mmio.crv = 0x0000;
//$2205,$2206 CNV
mmio.cnv = 0x0000;
//$2207,$2208 CIV
mmio.civ = 0x0000;
//$2209 SCNT
mmio.cpu_irq = false;
mmio.cpu_ivsw = false;
mmio.cpu_nvsw = false;
mmio.cmeg = 0;
//$220a CIE
mmio.sa1_irqen = false;
mmio.timer_irqen = false;
mmio.dma_irqen = false;
mmio.sa1_nmien = false;
//$220b CIC
mmio.sa1_irqcl = false;
mmio.timer_irqcl = false;
mmio.dma_irqcl = false;
mmio.sa1_nmicl = false;
//$220c,$220d SNV
mmio.snv = 0x0000;
//$220e,$220f SIV
mmio.siv = 0x0000;
//$2210
mmio.hvselb = false;
mmio.ven = false;
mmio.hen = false;
//$2212,$2213 HCNT
mmio.hcnt = 0x0000;
//$2214,$2215 VCNT
mmio.vcnt = 0x0000;
//$2220-2223 CXB, DXB, EXB, FXB
mmio.cbmode = 0;
mmio.dbmode = 0;
mmio.ebmode = 0;
mmio.fbmode = 0;
mmio.cb = 0x00;
mmio.db = 0x01;
mmio.eb = 0x02;
mmio.fb = 0x03;
//$2224 BMAPS
mmio.sbm = 0x00;
//$2225 BMAP
mmio.sw46 = false;
mmio.cbm = 0x00;
//$2226 SWBE
mmio.swen = false;
//$2227 CWBE
mmio.cwen = false;
//$2228 BWPA
mmio.bwp = 0x0f;
//$2229 SIWP
mmio.siwp = 0x00;
//$222a CIWP
mmio.ciwp = 0x00;
//$2230 DCNT
mmio.dmaen = false;
mmio.dprio = false;
mmio.cden = false;
mmio.cdsel = false;
mmio.dd = 0;
mmio.sd = 0;
//$2231 CDMA
mmio.chdend = false;
mmio.dmasize = 0;
mmio.dmacb = 0;
//$2232-$2234 SDA
mmio.dsa = 0x000000;
//$2235-$2237 DDA
mmio.dda = 0x000000;
//$2238,$2239 DTC
mmio.dtc = 0x0000;
//$223f BBF
mmio.bbf = 0;
//$2240-$224f BRF
for(unsigned i = 0; i < 16; i++) {
mmio.brf[i] = 0x00;
}
//$2250 MCNT
mmio.acm = 0;
mmio.md = 0;
//$2251,$2252 MA
mmio.ma = 0x0000;
//$2253,$2254 MB
mmio.mb = 0x0000;
//$2258 VBD
mmio.hl = false;
mmio.vb = 16;
//$2259-$225b
mmio.va = 0x000000;
mmio.vbit = 0;
//$2300 SFR
mmio.cpu_irqfl = false;
mmio.chdma_irqfl = false;
//$2301 CFR
mmio.sa1_irqfl = false;
mmio.timer_irqfl = false;
mmio.dma_irqfl = false;
mmio.sa1_nmifl = false;
//$2302,$2303 HCR
mmio.hcr = 0x0000;
//$2304,$2305 VCR
mmio.vcr = 0x0000;
//$2306-$230a MR
mmio.mr = 0;
//$230b
mmio.overflow = false;
}
SA1::SA1() {
}
};

35
tools/bsnes/chip/sa1/sa1.hpp Executable file
View File

@ -0,0 +1,35 @@
#include "bus/bus.hpp"
class SA1 : public CPUcore, public MMIO {
public:
#include "dma/dma.hpp"
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
struct Status {
bool interrupt_pending;
uint16_t interrupt_vector;
uint16_t scanlines;
uint16_t vcounter;
uint16_t hcounter;
} status;
void enter();
void interrupt(uint16_t vector);
void tick();
alwaysinline void trigger_irq();
alwaysinline void last_cycle();
alwaysinline bool interrupt_pending();
void init();
void enable();
void power();
void reset();
SA1();
};
extern SA1 sa1;
extern SA1Bus sa1bus;

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define SDD1_CPP
#include "sdd1.hpp" #define SDD1_CPP
namespace SNES {
SDD1 sdd1;
#include "sdd1emu.cpp" #include "sdd1emu.cpp"
void SDD1::init() {} void SDD1::init() {}
@ -11,7 +13,7 @@ void SDD1::enable() {
//hook S-CPU DMA MMIO registers to gather information for struct dma[]; //hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::read() //buffer address and transfer size information for use in SDD1::read()
for(unsigned i = 0x4300; i <= 0x437f; i++) { for(unsigned i = 0x4300; i <= 0x437f; i++) {
cpu_mmio[i & 0x7f] = memory::mmio.get(i); cpu_mmio[i & 0x7f] = memory::mmio.mmio[i - 0x2000];
memory::mmio.map(i, *this); memory::mmio.map(i, *this);
} }
@ -156,3 +158,5 @@ SDD1::SDD1() {
SDD1::~SDD1() { SDD1::~SDD1() {
delete[] buffer.data; delete[] buffer.data;
} }
};

66
tools/bsnes/chip/sgb/sgb.cpp Executable file
View File

@ -0,0 +1,66 @@
#include <../base.hpp>
#define SGB_CPP
namespace SNES {
SuperGameBoy sgb;
void SuperGameBoy::enter() {
while(true) {
if(sgb_run) {
unsigned samples = sgb_run(samplebuffer, 16);
scheduler.addclocks_cop(samples * 10);
scheduler.sync_copcpu();
} else {
scheduler.addclocks_cop(64 * 1024 * 1024);
scheduler.sync_copcpu();
}
}
}
uint8_t SuperGameBoy::read(unsigned addr) {
addr &= 0xffff;
if(sgb_read) return sgb_read(addr);
return 0x00;
}
void SuperGameBoy::write(unsigned addr, uint8_t data) {
addr &= 0xffff;
if(sgb_write) return sgb_write(addr, data);
}
void SuperGameBoy::init() {
if(libsgb.open("SuperGameBoy")) {
sgb_init = libsgb.sym("sgb_init");
sgb_term = libsgb.sym("sgb_term");
sgb_power = libsgb.sym("sgb_power");
sgb_reset = libsgb.sym("sgb_reset");
sgb_read = libsgb.sym("sgb_read");
sgb_write = libsgb.sym("sgb_write");
sgb_run = libsgb.sym("sgb_run");
}
}
void SuperGameBoy::enable() {
}
void SuperGameBoy::power() {
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
if(sgb_init) {
sgb_init(SGB2,
memory::gbrom.data(), memory::gbrom.size(),
memory::gbram.data(), memory::gbram.size()
);
}
if(sgb_power) sgb_power();
}
void SuperGameBoy::reset() {
if(sgb_reset) sgb_reset();
}
};

28
tools/bsnes/chip/sgb/sgb.hpp Executable file
View File

@ -0,0 +1,28 @@
class SuperGameBoy : public Memory {
public:
void enter();
uint8_t read(unsigned addr);
void write(unsigned addr, uint8_t data);
void init();
void enable();
void power();
void reset();
private:
library libsgb;
uint32_t samplebuffer[4096];
enum { SGB1 = 0, SGB2 = 1 };
function<bool (bool, uint8_t*, unsigned, uint8_t*, unsigned)> sgb_init;
function<void ()> sgb_term;
function<void ()> sgb_power;
function<void ()> sgb_reset;
function<uint8_t (unsigned)> sgb_read;
function<void (unsigned, uint8_t)> sgb_write;
function<unsigned (uint32_t*, unsigned)> sgb_run;
};
extern SuperGameBoy sgb;

View File

@ -1,8 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#define SPC7110_CPP
#include "spc7110.hpp" #define SPC7110_CPP
namespace SNES {
SPC7110 spc7110;
#include "decomp.cpp" #include "decomp.cpp"
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@ -670,3 +672,6 @@ void SPC7110::write(unsigned addr, uint8 data) {
SPC7110::SPC7110() { SPC7110::SPC7110() {
} }
};

View File

@ -1,6 +1,9 @@
#include <../base.hpp> #include <../base.hpp>
#include <../cart/cart.hpp>
#include "srtc.hpp" #define SRTC_CPP
namespace SNES {
SRTC srtc;
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@ -224,3 +227,6 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
SRTC::SRTC() { SRTC::SRTC() {
} }
};

View File

@ -1,7 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define ST010_CPP
#include "st010.hpp" #define ST010_CPP
namespace SNES {
ST010 st010;
#include "st010_data.hpp" #include "st010_data.hpp"
#include "st010_op.cpp" #include "st010_op.cpp"
@ -85,3 +88,5 @@ void ST010::write(unsigned addr, uint8 data) {
ram[0x0021] &= ~0x80; ram[0x0021] &= ~0x80;
} }
} }
};

View File

@ -1 +0,0 @@
@mingw32-make platform=win compiler=mingw32-gcc clean

View File

@ -1 +0,0 @@
make platform=x compiler=gcc clean

3
tools/bsnes/cpu/core/bpp.sh Executable file
View File

@ -0,0 +1,3 @@
clear
bpp opcode_functions.cpp opcode_functions.bpp
bpp opcode_headers.hpp opcode_headers.bpp

51
tools/bsnes/cpu/core/core.cpp Executable file
View File

@ -0,0 +1,51 @@
#include <../base.hpp>
#define CPUCORE_CPP
namespace SNES {
#include "opcode_algorithms.cpp"
#include "opcode_functions.cpp"
#include "opcode_tables.cpp"
#include "disasm/disasm.cpp"
//immediate, 2-cycle opcodes with I/O cycle will become bus read
//when an IRQ is to be triggered immediately after opcode completion.
//this affects the following opcodes:
// clc, cld, cli, clv, sec, sed, sei,
// tax, tay, txa, txy, tya, tyx,
// tcd, tcs, tdc, tsc, tsx, txs,
// inc, inx, iny, dec, dex, dey,
// asl, lsr, rol, ror, nop, xce.
alwaysinline void CPUcore::op_io_irq() {
if(interrupt_pending()) {
//modify I/O cycle to bus read cycle, do not increment PC
op_read(regs.pc.d);
} else {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
alwaysinline void CPUcore::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}
CPUcore::CPUcore() {
initialize_opcode_table();
}
};

View File

@ -1,11 +1,25 @@
class CPUcore {
public:
#include "registers.hpp"
#include "memory.hpp"
#include "opcode_headers.hpp"
#include "disasm/disasm.hpp"
regs_t regs;
reg24_t aa, rd; reg24_t aa, rd;
uint8_t dp, sp; uint8_t sp, dp;
void op_irq(); virtual void op_io() = 0;
virtual uint8_t op_read(uint32_t addr) = 0;
virtual void op_write(uint32_t addr, uint8_t data) = 0;
virtual void last_cycle() = 0;
virtual bool interrupt_pending() = 0;
inline bool in_opcode() { return status.in_opcode; } void op_io_irq();
void op_io_cond2();
void op_io_cond4(uint16 x, uint16 y);
void op_io_cond6(uint16 addr);
//op_read
void op_adc_b(); void op_adc_b();
void op_adc_w(); void op_adc_w();
void op_and_b(); void op_and_b();
@ -30,7 +44,7 @@
void op_ora_w(); void op_ora_w();
void op_sbc_b(); void op_sbc_b();
void op_sbc_w(); void op_sbc_w();
//op_rmw
void op_inc_b(); void op_inc_b();
void op_inc_w(); void op_inc_w();
void op_dec_b(); void op_dec_b();
@ -48,7 +62,18 @@
void op_tsb_b(); void op_tsb_b();
void op_tsb_w(); void op_tsb_w();
void op_io_irq(); void (CPUcore::**opcode_table)();
void op_io_cond2(); void (CPUcore::*op_table[256 * 5])();
void op_io_cond4(uint16 x, uint16 y); void initialize_opcode_table();
void op_io_cond6(uint16 addr); void update_table();
enum {
table_EM = 0, // 8-bit accumulator, 8-bit index (emulation mode)
table_MX = 256, // 8-bit accumulator, 8-bit index
table_Mx = 512, // 8-bit accumulator, 16-bit index
table_mX = 768, //16-bit accumulator, 8-bit index
table_mx = 1024, //16-bit accumulator, 16-bit index
};
CPUcore();
};

View File

@ -1,6 +1,4 @@
#ifdef CPU_CPP uint8 CPUcore::dreadb(uint32 addr) {
uint8 CPU::dreadb(uint32 addr) {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) { if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff] //$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger //do not read MMIO registers within debugger
@ -9,14 +7,14 @@ uint8 CPU::dreadb(uint32 addr) {
return bus.read(addr); return bus.read(addr);
} }
uint16 CPU::dreadw(uint32 addr) { uint16 CPUcore::dreadw(uint32 addr) {
uint16 r; uint16 r;
r = dreadb((addr + 0) & 0xffffff) << 0; r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8; r |= dreadb((addr + 1) & 0xffffff) << 8;
return r; return r;
} }
uint32 CPU::dreadl(uint32 addr) { uint32 CPUcore::dreadl(uint32 addr) {
uint32 r; uint32 r;
r = dreadb((addr + 0) & 0xffffff) << 0; r = dreadb((addr + 0) & 0xffffff) << 0;
r |= dreadb((addr + 1) & 0xffffff) << 8; r |= dreadb((addr + 1) & 0xffffff) << 8;
@ -24,7 +22,7 @@ uint32 CPU::dreadl(uint32 addr) {
return r; return r;
} }
uint32 CPU::decode(uint8 offset_type, uint32 addr) { uint32 CPUcore::decode(uint8 offset_type, uint32 addr) {
uint32 r = 0; uint32 r = 0;
switch(offset_type) { switch(offset_type) {
@ -104,12 +102,12 @@ uint32 CPU::decode(uint8 offset_type, uint32 addr) {
return(r & 0xffffff); return(r & 0xffffff);
} }
void CPU::disassemble_opcode(char *output) { void CPUcore::disassemble_opcode(char *output) {
static reg24_t pc; static reg24_t pc;
char t[256]; char t[256];
char *s = output; char *s = output;
if(in_opcode() == true) { if(false /* in_opcode() == true */) {
strcpy(s, "?????? <CPU within opcode>"); strcpy(s, "?????? <CPU within opcode>");
return; return;
} }
@ -443,7 +441,7 @@ void CPU::disassemble_opcode(char *output) {
//emulation mode, as regs.p.m/regs.p.x should *always* be //emulation mode, as regs.p.m/regs.p.x should *always* be
//set in emulation mode. //set in emulation mode.
uint8 CPU::opcode_length() { uint8 CPUcore::opcode_length() {
uint8 op, len; uint8 op, len;
static uint8 op_len_tbl[256] = { static uint8 op_len_tbl[256] = {
//0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f //0,1,2,3, 4,5,6,7, 8,9,a,b, c,d,e,f
@ -469,7 +467,7 @@ uint8 CPU::opcode_length() {
2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn 2,2,2,2, 3,2,2,2, 1,3,1,1, 3,3,3,4 //0xfn
}; };
if(in_opcode() == true) { if(false /* in_opcode() == true */) {
return 0; return 0;
} }
@ -479,5 +477,3 @@ uint8 CPU::opcode_length() {
if(len == 6) return (regs.e || regs.p.x) ? 2 : 3; if(len == 6) return (regs.e || regs.p.x) ? 2 : 3;
return len; return len;
} }
#endif //ifdef CPU_CPP

View File

@ -0,0 +1,30 @@
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
void disassemble_opcode(char *output);
uint8 dreadb(uint32 addr);
uint16 dreadw(uint32 addr);
uint32 dreadl(uint32 addr);
uint32 decode(uint8 offset_type, uint32 addr);
uint8 opcode_length();

77
tools/bsnes/cpu/core/memory.hpp Executable file
View File

@ -0,0 +1,77 @@
alwaysinline uint8_t op_readpc() {
return op_read((regs.pc.b << 16) + regs.pc.w++);
}
alwaysinline uint8_t op_readstack() {
regs.e ? regs.s.l++ : regs.s.w++;
return op_read(regs.s.w);
}
alwaysinline uint8_t op_readstackn() {
return op_read(++regs.s.w);
}
alwaysinline uint8_t op_readaddr(uint32_t addr) {
return op_read(addr & 0xffff);
}
alwaysinline uint8_t op_readlong(uint32_t addr) {
return op_read(addr & 0xffffff);
}
alwaysinline uint8_t op_readdbr(uint32_t addr) {
return op_read(((regs.db << 16) + addr) & 0xffffff);
}
alwaysinline uint8_t op_readpbr(uint32_t addr) {
return op_read((regs.pc.b << 16) + (addr & 0xffff));
}
alwaysinline uint8_t op_readdp(uint32_t addr) {
if(regs.e && regs.d.l == 0x00) {
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
} else {
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
}
}
alwaysinline uint8_t op_readsp(uint32_t addr) {
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
}
alwaysinline void op_writestack(uint8_t data) {
op_write(regs.s.w, data);
regs.e ? regs.s.l-- : regs.s.w--;
}
alwaysinline void op_writestackn(uint8_t data) {
op_write(regs.s.w--, data);
}
alwaysinline void op_writeaddr(uint32_t addr, uint8_t data) {
op_write(addr & 0xffff, data);
}
alwaysinline void op_writelong(uint32_t addr, uint8_t data) {
op_write(addr & 0xffffff, data);
}
alwaysinline void op_writedbr(uint32_t addr, uint8_t data) {
op_write(((regs.db << 16) + addr) & 0xffffff, data);
}
alwaysinline void op_writepbr(uint32_t addr, uint8_t data) {
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
}
alwaysinline void op_writedp(uint32_t addr, uint8_t data) {
if(regs.e && regs.d.l == 0x00) {
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
} else {
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
}
}
alwaysinline void op_writesp(uint32_t addr, uint8_t data) {
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
}

View File

@ -1,7 +1,6 @@
#ifdef SCPU_CPP #ifdef CPUCORE_CPP
//op_read inline void CPUcore::op_adc_b() {
inline void sCPU::op_adc_b() {
int r; int r;
if(regs.p.d) { if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15; uint8 n0 = (regs.a.l ) & 15;
@ -29,7 +28,7 @@ inline void sCPU::op_adc_b() {
regs.a.l = r; regs.a.l = r;
} }
inline void sCPU::op_adc_w() { inline void CPUcore::op_adc_w() {
int r; int r;
if(regs.p.d) { if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15; uint8 n0 = (regs.a.w ) & 15;
@ -69,133 +68,133 @@ inline void sCPU::op_adc_w() {
regs.a.w = r; regs.a.w = r;
} }
inline void sCPU::op_and_b() { inline void CPUcore::op_and_b() {
regs.a.l &= rd.l; regs.a.l &= rd.l;
regs.p.n = regs.a.l & 0x80; regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0; regs.p.z = regs.a.l == 0;
} }
inline void sCPU::op_and_w() { inline void CPUcore::op_and_w() {
regs.a.w &= rd.w; regs.a.w &= rd.w;
regs.p.n = regs.a.w & 0x8000; regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0; regs.p.z = regs.a.w == 0;
} }
inline void sCPU::op_bit_b() { inline void CPUcore::op_bit_b() {
regs.p.n = rd.l & 0x80; regs.p.n = rd.l & 0x80;
regs.p.v = rd.l & 0x40; regs.p.v = rd.l & 0x40;
regs.p.z = (rd.l & regs.a.l) == 0; regs.p.z = (rd.l & regs.a.l) == 0;
} }
inline void sCPU::op_bit_w() { inline void CPUcore::op_bit_w() {
regs.p.n = rd.w & 0x8000; regs.p.n = rd.w & 0x8000;
regs.p.v = rd.w & 0x4000; regs.p.v = rd.w & 0x4000;
regs.p.z = (rd.w & regs.a.w) == 0; regs.p.z = (rd.w & regs.a.w) == 0;
} }
inline void sCPU::op_cmp_b() { inline void CPUcore::op_cmp_b() {
int r = regs.a.l - rd.l; int r = regs.a.l - rd.l;
regs.p.n = r & 0x80; regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0; regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_cmp_w() { inline void CPUcore::op_cmp_w() {
int r = regs.a.w - rd.w; int r = regs.a.w - rd.w;
regs.p.n = r & 0x8000; regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0; regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_cpx_b() { inline void CPUcore::op_cpx_b() {
int r = regs.x.l - rd.l; int r = regs.x.l - rd.l;
regs.p.n = r & 0x80; regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0; regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_cpx_w() { inline void CPUcore::op_cpx_w() {
int r = regs.x.w - rd.w; int r = regs.x.w - rd.w;
regs.p.n = r & 0x8000; regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0; regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_cpy_b() { inline void CPUcore::op_cpy_b() {
int r = regs.y.l - rd.l; int r = regs.y.l - rd.l;
regs.p.n = r & 0x80; regs.p.n = r & 0x80;
regs.p.z = (uint8)r == 0; regs.p.z = (uint8)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_cpy_w() { inline void CPUcore::op_cpy_w() {
int r = regs.y.w - rd.w; int r = regs.y.w - rd.w;
regs.p.n = r & 0x8000; regs.p.n = r & 0x8000;
regs.p.z = (uint16)r == 0; regs.p.z = (uint16)r == 0;
regs.p.c = r >= 0; regs.p.c = r >= 0;
} }
inline void sCPU::op_eor_b() { inline void CPUcore::op_eor_b() {
regs.a.l ^= rd.l; regs.a.l ^= rd.l;
regs.p.n = regs.a.l & 0x80; regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0; regs.p.z = regs.a.l == 0;
} }
inline void sCPU::op_eor_w() { inline void CPUcore::op_eor_w() {
regs.a.w ^= rd.w; regs.a.w ^= rd.w;
regs.p.n = regs.a.w & 0x8000; regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0; regs.p.z = regs.a.w == 0;
} }
inline void sCPU::op_lda_b() { inline void CPUcore::op_lda_b() {
regs.a.l = rd.l; regs.a.l = rd.l;
regs.p.n = regs.a.l & 0x80; regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0; regs.p.z = regs.a.l == 0;
} }
inline void sCPU::op_lda_w() { inline void CPUcore::op_lda_w() {
regs.a.w = rd.w; regs.a.w = rd.w;
regs.p.n = regs.a.w & 0x8000; regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0; regs.p.z = regs.a.w == 0;
} }
inline void sCPU::op_ldx_b() { inline void CPUcore::op_ldx_b() {
regs.x.l = rd.l; regs.x.l = rd.l;
regs.p.n = regs.x.l & 0x80; regs.p.n = regs.x.l & 0x80;
regs.p.z = regs.x.l == 0; regs.p.z = regs.x.l == 0;
} }
inline void sCPU::op_ldx_w() { inline void CPUcore::op_ldx_w() {
regs.x.w = rd.w; regs.x.w = rd.w;
regs.p.n = regs.x.w & 0x8000; regs.p.n = regs.x.w & 0x8000;
regs.p.z = regs.x.w == 0; regs.p.z = regs.x.w == 0;
} }
inline void sCPU::op_ldy_b() { inline void CPUcore::op_ldy_b() {
regs.y.l = rd.l; regs.y.l = rd.l;
regs.p.n = regs.y.l & 0x80; regs.p.n = regs.y.l & 0x80;
regs.p.z = regs.y.l == 0; regs.p.z = regs.y.l == 0;
} }
inline void sCPU::op_ldy_w() { inline void CPUcore::op_ldy_w() {
regs.y.w = rd.w; regs.y.w = rd.w;
regs.p.n = regs.y.w & 0x8000; regs.p.n = regs.y.w & 0x8000;
regs.p.z = regs.y.w == 0; regs.p.z = regs.y.w == 0;
} }
inline void sCPU::op_ora_b() { inline void CPUcore::op_ora_b() {
regs.a.l |= rd.l; regs.a.l |= rd.l;
regs.p.n = regs.a.l & 0x80; regs.p.n = regs.a.l & 0x80;
regs.p.z = regs.a.l == 0; regs.p.z = regs.a.l == 0;
} }
inline void sCPU::op_ora_w() { inline void CPUcore::op_ora_w() {
regs.a.w |= rd.w; regs.a.w |= rd.w;
regs.p.n = regs.a.w & 0x8000; regs.p.n = regs.a.w & 0x8000;
regs.p.z = regs.a.w == 0; regs.p.z = regs.a.w == 0;
} }
inline void sCPU::op_sbc_b() { inline void CPUcore::op_sbc_b() {
int r; int r;
if(regs.p.d) { if(regs.p.d) {
uint8 n0 = (regs.a.l ) & 15; uint8 n0 = (regs.a.l ) & 15;
@ -223,7 +222,7 @@ inline void sCPU::op_sbc_b() {
regs.a.l = r; regs.a.l = r;
} }
inline void sCPU::op_sbc_w() { inline void CPUcore::op_sbc_w() {
int r; int r;
if(regs.p.d) { if(regs.p.d) {
uint8 n0 = (regs.a.w ) & 15; uint8 n0 = (regs.a.w ) & 15;
@ -263,60 +262,59 @@ inline void sCPU::op_sbc_w() {
regs.a.w = r; regs.a.w = r;
} }
//op_rmw inline void CPUcore::op_inc_b() {
inline void sCPU::op_inc_b() {
rd.l++; rd.l++;
regs.p.n = rd.l & 0x80; regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_inc_w() { inline void CPUcore::op_inc_w() {
rd.w++; rd.w++;
regs.p.n = rd.w & 0x8000; regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_dec_b() { inline void CPUcore::op_dec_b() {
rd.l--; rd.l--;
regs.p.n = rd.l & 0x80; regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_dec_w() { inline void CPUcore::op_dec_w() {
rd.w--; rd.w--;
regs.p.n = rd.w & 0x8000; regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_asl_b() { inline void CPUcore::op_asl_b() {
regs.p.c = rd.l & 0x80; regs.p.c = rd.l & 0x80;
rd.l <<= 1; rd.l <<= 1;
regs.p.n = rd.l & 0x80; regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_asl_w() { inline void CPUcore::op_asl_w() {
regs.p.c = rd.w & 0x8000; regs.p.c = rd.w & 0x8000;
rd.w <<= 1; rd.w <<= 1;
regs.p.n = rd.w & 0x8000; regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_lsr_b() { inline void CPUcore::op_lsr_b() {
regs.p.c = rd.l & 1; regs.p.c = rd.l & 1;
rd.l >>= 1; rd.l >>= 1;
regs.p.n = rd.l & 0x80; regs.p.n = rd.l & 0x80;
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_lsr_w() { inline void CPUcore::op_lsr_w() {
regs.p.c = rd.w & 1; regs.p.c = rd.w & 1;
rd.w >>= 1; rd.w >>= 1;
regs.p.n = rd.w & 0x8000; regs.p.n = rd.w & 0x8000;
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_rol_b() { inline void CPUcore::op_rol_b() {
unsigned carry = (unsigned)regs.p.c; unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.l & 0x80; regs.p.c = rd.l & 0x80;
rd.l = (rd.l << 1) | carry; rd.l = (rd.l << 1) | carry;
@ -324,7 +322,7 @@ inline void sCPU::op_rol_b() {
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_rol_w() { inline void CPUcore::op_rol_w() {
unsigned carry = (unsigned)regs.p.c; unsigned carry = (unsigned)regs.p.c;
regs.p.c = rd.w & 0x8000; regs.p.c = rd.w & 0x8000;
rd.w = (rd.w << 1) | carry; rd.w = (rd.w << 1) | carry;
@ -332,7 +330,7 @@ inline void sCPU::op_rol_w() {
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_ror_b() { inline void CPUcore::op_ror_b() {
unsigned carry = (unsigned)regs.p.c << 7; unsigned carry = (unsigned)regs.p.c << 7;
regs.p.c = rd.l & 1; regs.p.c = rd.l & 1;
rd.l = carry | (rd.l >> 1); rd.l = carry | (rd.l >> 1);
@ -340,7 +338,7 @@ inline void sCPU::op_ror_b() {
regs.p.z = rd.l == 0; regs.p.z = rd.l == 0;
} }
inline void sCPU::op_ror_w() { inline void CPUcore::op_ror_w() {
unsigned carry = (unsigned)regs.p.c << 15; unsigned carry = (unsigned)regs.p.c << 15;
regs.p.c = rd.w & 1; regs.p.c = rd.w & 1;
rd.w = carry | (rd.w >> 1); rd.w = carry | (rd.w >> 1);
@ -348,24 +346,24 @@ inline void sCPU::op_ror_w() {
regs.p.z = rd.w == 0; regs.p.z = rd.w == 0;
} }
inline void sCPU::op_trb_b() { inline void CPUcore::op_trb_b() {
regs.p.z = (rd.l & regs.a.l) == 0; regs.p.z = (rd.l & regs.a.l) == 0;
rd.l &= ~regs.a.l; rd.l &= ~regs.a.l;
} }
inline void sCPU::op_trb_w() { inline void CPUcore::op_trb_w() {
regs.p.z = (rd.w & regs.a.w) == 0; regs.p.z = (rd.w & regs.a.w) == 0;
rd.w &= ~regs.a.w; rd.w &= ~regs.a.w;
} }
inline void sCPU::op_tsb_b() { inline void CPUcore::op_tsb_b() {
regs.p.z = (rd.l & regs.a.l) == 0; regs.p.z = (rd.l & regs.a.l) == 0;
rd.l |= regs.a.l; rd.l |= regs.a.l;
} }
inline void sCPU::op_tsb_w() { inline void CPUcore::op_tsb_w() {
regs.p.z = (rd.w & regs.a.w) == 0; regs.p.z = (rd.w & regs.a.w) == 0;
rd.w |= regs.a.w; rd.w |= regs.a.w;
} }
#endif
#endif //ifdef SCPU_CPP

View File

@ -0,0 +1,13 @@
//opcode_functions.cpp was generated via bpp -> opcode_functions.bpp
@global class CPUcore
@global lc last_cycle();
@global wai regs.wai
@include "opcode_read.bpp"
@include "opcode_write.bpp"
@include "opcode_rmw.bpp"
@include "opcode_pc.bpp"
@include "opcode_misc.bpp"
@include "opcode_list.bpp"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,386 @@
//===============
//opcode_read.bpp
//===============
@macro op_read_const(name)
void op_{name}_const_b();
void op_{name}_const_w();
@endmacro
@macro op_read_bit_const()
void op_bit_const_b();
void op_bit_const_w();
@endmacro
@macro op_read_addr(name)
void op_{name}_addr_b();
void op_{name}_addr_w();
@endmacro
@macro op_read_addrx(name)
void op_{name}_addrx_b();
void op_{name}_addrx_w();
@endmacro
@macro op_read_addry(name)
void op_{name}_addry_b();
void op_{name}_addry_w();
@endmacro
@macro op_read_long(name)
void op_{name}_long_b();
void op_{name}_long_w();
@endmacro
@macro op_read_longx(name)
void op_{name}_longx_b();
void op_{name}_longx_w();
@endmacro
@macro op_read_dp(name)
void op_{name}_dp_b();
void op_{name}_dp_w();
@endmacro
@macro op_read_dpr(name, r)
void op_{name}_dpr_b();
void op_{name}_dpr_w();
@endmacro
@macro op_read_idp(name)
void op_{name}_idp_b();
void op_{name}_idp_w();
@endmacro
@macro op_read_idpx(name)
void op_{name}_idpx_b();
void op_{name}_idpx_w();
@endmacro
@macro op_read_idpy(name)
void op_{name}_idpy_b();
void op_{name}_idpy_w();
@endmacro
@macro op_read_ildp(name)
void op_{name}_ildp_b();
void op_{name}_ildp_w();
@endmacro
@macro op_read_ildpy(name)
void op_{name}_ildpy_b();
void op_{name}_ildpy_w();
@endmacro
@macro op_read_sr(name)
void op_{name}_sr_b();
void op_{name}_sr_w();
@endmacro
@macro op_read_isry(name)
void op_{name}_isry_b();
void op_{name}_isry_w();
@endmacro
//================
//opcode_write.bpp
//================
@macro op_store_addr(name, r)
void op_{name}_addr_b();
void op_{name}_addr_w();
@endmacro
@macro op_store_addrr(name, suffix, r, index)
void op_{name}_addr{suffix}_b();
void op_{name}_addr{suffix}_w();
@endmacro
@macro op_store_longr(name, suffix, index)
void op_{name}_long{suffix}_b();
void op_{name}_long{suffix}_w();
@endmacro
@macro op_store_dp(name, r)
void op_{name}_dp_b();
void op_{name}_dp_w();
@endmacro
@macro op_store_dpr(name, r, index)
void op_{name}_dpr_b();
void op_{name}_dpr_w();
@endmacro
@macro op_sta_idp()
void op_sta_idp_b();
void op_sta_idp_w();
@endmacro
@macro op_sta_ildp()
void op_sta_ildp_b();
void op_sta_ildp_w();
@endmacro
@macro op_sta_idpx()
void op_sta_idpx_b();
void op_sta_idpx_w();
@endmacro
@macro op_sta_idpy()
void op_sta_idpy_b();
void op_sta_idpy_w();
@endmacro
@macro op_sta_ildpy()
void op_sta_ildpy_b();
void op_sta_ildpy_w();
@endmacro
@macro op_sta_sr()
void op_sta_sr_b();
void op_sta_sr_w();
@endmacro
@macro op_sta_isry()
void op_sta_isry_b();
void op_sta_isry_w();
@endmacro
//==============
//opcode_rmw.bpp
//==============
@macro op_adjust(name, r, op)
void op_{name}_imm_b();
void op_{name}_imm_w();
@endmacro
@macro op_asl()
void op_asl_imm_b();
void op_asl_imm_w();
@endmacro
@macro op_lsr()
void op_lsr_imm_b();
void op_lsr_imm_w();
@endmacro
@macro op_rol()
void op_rol_imm_b();
void op_rol_imm_w();
@endmacro
@macro op_ror()
void op_ror_imm_b();
void op_ror_imm_w();
@endmacro
@macro op_adjust_addr(name)
void op_{name}_addr_b();
void op_{name}_addr_w();
@endmacro
@macro op_adjust_addrx(name)
void op_{name}_addrx_b();
void op_{name}_addrx_w();
@endmacro
@macro op_adjust_dp(name)
void op_{name}_dp_b();
void op_{name}_dp_w();
@endmacro
@macro op_adjust_dpx(name)
void op_{name}_dpx_b();
void op_{name}_dpx_w();
@endmacro
//=============
//opcode_pc.bpp
//=============
@macro op_branch(name, condition)
void op_{name}();
@endmacro
@macro op_bra()
void op_bra();
@endmacro
@macro op_brl()
void op_brl();
@endmacro
@macro op_jmp_addr()
void op_jmp_addr();
@endmacro
@macro op_jmp_long()
void op_jmp_long();
@endmacro
@macro op_jmp_iaddr()
void op_jmp_iaddr();
@endmacro
@macro op_jmp_iaddrx()
void op_jmp_iaddrx();
@endmacro
@macro op_jmp_iladdr()
void op_jmp_iladdr();
@endmacro
@macro op_jsr_addr()
void op_jsr_addr();
@endmacro
@macro op_jsr_long()
void op_jsr_long_e();
void op_jsr_long_n();
@endmacro
@macro op_jsr_iaddrx()
void op_jsr_iaddrx_e();
void op_jsr_iaddrx_n();
@endmacro
@macro op_rti()
void op_rti_e();
void op_rti_n();
@endmacro
@macro op_rts()
void op_rts();
@endmacro
@macro op_rtl()
void op_rtl_e();
void op_rtl_n();
@endmacro
//===============
//opcode_misc.bpp
//===============
@macro op_nop()
void op_nop();
@endmacro
@macro op_wdm()
void op_wdm();
@endmacro
@macro op_xba()
void op_xba();
@endmacro
@macro op_move(name, op)
void op_{name}_b();
void op_{name}_w();
@endmacro
@macro op_interrupt(name, vectorE, vectorN)
void op_{name}_e();
void op_{name}_n();
@endmacro
@macro op_stp()
void op_stp();
@endmacro
@macro op_wai()
void op_wai();
@endmacro
@macro op_xce()
void op_xce();
@endmacro
@macro op_flag(name, rule)
void op_{name}();
@endmacro
@macro op_pflag(name, op)
void op_{name}_e();
void op_{name}_n();
@endmacro
@macro op_transfer(name, from, to)
void op_{name}_b();
void op_{name}_w();
@endmacro
@macro op_transfer_word(name, from, to)
void op_{name}();
@endmacro
@macro op_tcs()
void op_tcs_e();
void op_tcs_n();
@endmacro
@macro op_tsc()
void op_tsc_e();
void op_tsc_n();
@endmacro
@macro op_tsx()
void op_tsx_b();
void op_tsx_w();
@endmacro
@macro op_txs()
void op_txs_e();
void op_txs_n();
@endmacro
@macro op_push(name, r)
void op_{name}_b();
void op_{name}_w();
@endmacro
@macro op_phd()
void op_phd_e();
void op_phd_n();
@endmacro
@macro op_push_byte(name, r)
void op_{name}();
@endmacro
@macro op_pull(name, r)
void op_{name}_b();
void op_{name}_w();
@endmacro
@macro op_pld()
void op_pld_e();
void op_pld_n();
@endmacro
@macro op_plb()
void op_plb();
@endmacro
@macro op_plp()
void op_plp_e();
void op_plp_n();
@endmacro
@macro op_pea()
void op_pea_e();
void op_pea_n();
@endmacro
@macro op_pei()
void op_pei_e();
void op_pei_n();
@endmacro
@macro op_per()
void op_per_e();
void op_per_n();
@endmacro
@include "opcode_list.bpp"

View File

@ -0,0 +1,892 @@
//===============
//opcode_read.bpp
//===============
//================
//opcode_write.bpp
//================
//==============
//opcode_rmw.bpp
//==============
//=============
//opcode_pc.bpp
//=============
//===============
//opcode_misc.bpp
//===============
//===============
//opcode_read.bpp
//===============
void op_adc_const_b();
void op_adc_const_w();
void op_and_const_b();
void op_and_const_w();
void op_cmp_const_b();
void op_cmp_const_w();
void op_cpx_const_b();
void op_cpx_const_w();
void op_cpy_const_b();
void op_cpy_const_w();
void op_eor_const_b();
void op_eor_const_w();
void op_lda_const_b();
void op_lda_const_w();
void op_ldx_const_b();
void op_ldx_const_w();
void op_ldy_const_b();
void op_ldy_const_w();
void op_ora_const_b();
void op_ora_const_w();
void op_sbc_const_b();
void op_sbc_const_w();
void op_bit_const_b();
void op_bit_const_w();
void op_adc_addr_b();
void op_adc_addr_w();
void op_and_addr_b();
void op_and_addr_w();
void op_bit_addr_b();
void op_bit_addr_w();
void op_cmp_addr_b();
void op_cmp_addr_w();
void op_cpx_addr_b();
void op_cpx_addr_w();
void op_cpy_addr_b();
void op_cpy_addr_w();
void op_eor_addr_b();
void op_eor_addr_w();
void op_lda_addr_b();
void op_lda_addr_w();
void op_ldx_addr_b();
void op_ldx_addr_w();
void op_ldy_addr_b();
void op_ldy_addr_w();
void op_ora_addr_b();
void op_ora_addr_w();
void op_sbc_addr_b();
void op_sbc_addr_w();
void op_adc_addrx_b();
void op_adc_addrx_w();
void op_and_addrx_b();
void op_and_addrx_w();
void op_bit_addrx_b();
void op_bit_addrx_w();
void op_cmp_addrx_b();
void op_cmp_addrx_w();
void op_eor_addrx_b();
void op_eor_addrx_w();
void op_lda_addrx_b();
void op_lda_addrx_w();
void op_ldy_addrx_b();
void op_ldy_addrx_w();
void op_ora_addrx_b();
void op_ora_addrx_w();
void op_sbc_addrx_b();
void op_sbc_addrx_w();
void op_adc_addry_b();
void op_adc_addry_w();
void op_and_addry_b();
void op_and_addry_w();
void op_cmp_addry_b();
void op_cmp_addry_w();
void op_eor_addry_b();
void op_eor_addry_w();
void op_lda_addry_b();
void op_lda_addry_w();
void op_ldx_addry_b();
void op_ldx_addry_w();
void op_ora_addry_b();
void op_ora_addry_w();
void op_sbc_addry_b();
void op_sbc_addry_w();
void op_adc_long_b();
void op_adc_long_w();
void op_and_long_b();
void op_and_long_w();
void op_cmp_long_b();
void op_cmp_long_w();
void op_eor_long_b();
void op_eor_long_w();
void op_lda_long_b();
void op_lda_long_w();
void op_ora_long_b();
void op_ora_long_w();
void op_sbc_long_b();
void op_sbc_long_w();
void op_adc_longx_b();
void op_adc_longx_w();
void op_and_longx_b();
void op_and_longx_w();
void op_cmp_longx_b();
void op_cmp_longx_w();
void op_eor_longx_b();
void op_eor_longx_w();
void op_lda_longx_b();
void op_lda_longx_w();
void op_ora_longx_b();
void op_ora_longx_w();
void op_sbc_longx_b();
void op_sbc_longx_w();
void op_adc_dp_b();
void op_adc_dp_w();
void op_and_dp_b();
void op_and_dp_w();
void op_bit_dp_b();
void op_bit_dp_w();
void op_cmp_dp_b();
void op_cmp_dp_w();
void op_cpx_dp_b();
void op_cpx_dp_w();
void op_cpy_dp_b();
void op_cpy_dp_w();
void op_eor_dp_b();
void op_eor_dp_w();
void op_lda_dp_b();
void op_lda_dp_w();
void op_ldx_dp_b();
void op_ldx_dp_w();
void op_ldy_dp_b();
void op_ldy_dp_w();
void op_ora_dp_b();
void op_ora_dp_w();
void op_sbc_dp_b();
void op_sbc_dp_w();
void op_adc_dpr_b();
void op_adc_dpr_w();
void op_and_dpr_b();
void op_and_dpr_w();
void op_bit_dpr_b();
void op_bit_dpr_w();
void op_cmp_dpr_b();
void op_cmp_dpr_w();
void op_eor_dpr_b();
void op_eor_dpr_w();
void op_lda_dpr_b();
void op_lda_dpr_w();
void op_ldx_dpr_b();
void op_ldx_dpr_w();
void op_ldy_dpr_b();
void op_ldy_dpr_w();
void op_ora_dpr_b();
void op_ora_dpr_w();
void op_sbc_dpr_b();
void op_sbc_dpr_w();
void op_adc_idp_b();
void op_adc_idp_w();
void op_and_idp_b();
void op_and_idp_w();
void op_cmp_idp_b();
void op_cmp_idp_w();
void op_eor_idp_b();
void op_eor_idp_w();
void op_lda_idp_b();
void op_lda_idp_w();
void op_ora_idp_b();
void op_ora_idp_w();
void op_sbc_idp_b();
void op_sbc_idp_w();
void op_adc_idpx_b();
void op_adc_idpx_w();
void op_and_idpx_b();
void op_and_idpx_w();
void op_cmp_idpx_b();
void op_cmp_idpx_w();
void op_eor_idpx_b();
void op_eor_idpx_w();
void op_lda_idpx_b();
void op_lda_idpx_w();
void op_ora_idpx_b();
void op_ora_idpx_w();
void op_sbc_idpx_b();
void op_sbc_idpx_w();
void op_adc_idpy_b();
void op_adc_idpy_w();
void op_and_idpy_b();
void op_and_idpy_w();
void op_cmp_idpy_b();
void op_cmp_idpy_w();
void op_eor_idpy_b();
void op_eor_idpy_w();
void op_lda_idpy_b();
void op_lda_idpy_w();
void op_ora_idpy_b();
void op_ora_idpy_w();
void op_sbc_idpy_b();
void op_sbc_idpy_w();
void op_adc_ildp_b();
void op_adc_ildp_w();
void op_and_ildp_b();
void op_and_ildp_w();
void op_cmp_ildp_b();
void op_cmp_ildp_w();
void op_eor_ildp_b();
void op_eor_ildp_w();
void op_lda_ildp_b();
void op_lda_ildp_w();
void op_ora_ildp_b();
void op_ora_ildp_w();
void op_sbc_ildp_b();
void op_sbc_ildp_w();
void op_adc_ildpy_b();
void op_adc_ildpy_w();
void op_and_ildpy_b();
void op_and_ildpy_w();
void op_cmp_ildpy_b();
void op_cmp_ildpy_w();
void op_eor_ildpy_b();
void op_eor_ildpy_w();
void op_lda_ildpy_b();
void op_lda_ildpy_w();
void op_ora_ildpy_b();
void op_ora_ildpy_w();
void op_sbc_ildpy_b();
void op_sbc_ildpy_w();
void op_adc_sr_b();
void op_adc_sr_w();
void op_and_sr_b();
void op_and_sr_w();
void op_cmp_sr_b();
void op_cmp_sr_w();
void op_eor_sr_b();
void op_eor_sr_w();
void op_lda_sr_b();
void op_lda_sr_w();
void op_ora_sr_b();
void op_ora_sr_w();
void op_sbc_sr_b();
void op_sbc_sr_w();
void op_adc_isry_b();
void op_adc_isry_w();
void op_and_isry_b();
void op_and_isry_w();
void op_cmp_isry_b();
void op_cmp_isry_w();
void op_eor_isry_b();
void op_eor_isry_w();
void op_lda_isry_b();
void op_lda_isry_w();
void op_ora_isry_b();
void op_ora_isry_w();
void op_sbc_isry_b();
void op_sbc_isry_w();
//================
//opcode_write.bpp
//================
void op_sta_addr_b();
void op_sta_addr_w();
void op_stx_addr_b();
void op_stx_addr_w();
void op_sty_addr_b();
void op_sty_addr_w();
void op_stz_addr_b();
void op_stz_addr_w();
void op_sta_addrx_b();
void op_sta_addrx_w();
void op_sta_addry_b();
void op_sta_addry_w();
void op_stz_addrx_b();
void op_stz_addrx_w();
void op_sta_long_b();
void op_sta_long_w();
void op_sta_longx_b();
void op_sta_longx_w();
void op_sta_dp_b();
void op_sta_dp_w();
void op_stx_dp_b();
void op_stx_dp_w();
void op_sty_dp_b();
void op_sty_dp_w();
void op_stz_dp_b();
void op_stz_dp_w();
void op_sta_dpr_b();
void op_sta_dpr_w();
void op_stx_dpr_b();
void op_stx_dpr_w();
void op_sty_dpr_b();
void op_sty_dpr_w();
void op_stz_dpr_b();
void op_stz_dpr_w();
void op_sta_idp_b();
void op_sta_idp_w();
void op_sta_ildp_b();
void op_sta_ildp_w();
void op_sta_idpx_b();
void op_sta_idpx_w();
void op_sta_idpy_b();
void op_sta_idpy_w();
void op_sta_ildpy_b();
void op_sta_ildpy_w();
void op_sta_sr_b();
void op_sta_sr_w();
void op_sta_isry_b();
void op_sta_isry_w();
//==============
//opcode_rmw.bpp
//==============
void op_inc_imm_b();
void op_inc_imm_w();
void op_inx_imm_b();
void op_inx_imm_w();
void op_iny_imm_b();
void op_iny_imm_w();
void op_dec_imm_b();
void op_dec_imm_w();
void op_dex_imm_b();
void op_dex_imm_w();
void op_dey_imm_b();
void op_dey_imm_w();
void op_asl_imm_b();
void op_asl_imm_w();
void op_lsr_imm_b();
void op_lsr_imm_w();
void op_rol_imm_b();
void op_rol_imm_w();
void op_ror_imm_b();
void op_ror_imm_w();
void op_inc_addr_b();
void op_inc_addr_w();
void op_dec_addr_b();
void op_dec_addr_w();
void op_asl_addr_b();
void op_asl_addr_w();
void op_lsr_addr_b();
void op_lsr_addr_w();
void op_rol_addr_b();
void op_rol_addr_w();
void op_ror_addr_b();
void op_ror_addr_w();
void op_trb_addr_b();
void op_trb_addr_w();
void op_tsb_addr_b();
void op_tsb_addr_w();
void op_inc_addrx_b();
void op_inc_addrx_w();
void op_dec_addrx_b();
void op_dec_addrx_w();
void op_asl_addrx_b();
void op_asl_addrx_w();
void op_lsr_addrx_b();
void op_lsr_addrx_w();
void op_rol_addrx_b();
void op_rol_addrx_w();
void op_ror_addrx_b();
void op_ror_addrx_w();
void op_inc_dp_b();
void op_inc_dp_w();
void op_dec_dp_b();
void op_dec_dp_w();
void op_asl_dp_b();
void op_asl_dp_w();
void op_lsr_dp_b();
void op_lsr_dp_w();
void op_rol_dp_b();
void op_rol_dp_w();
void op_ror_dp_b();
void op_ror_dp_w();
void op_trb_dp_b();
void op_trb_dp_w();
void op_tsb_dp_b();
void op_tsb_dp_w();
void op_inc_dpx_b();
void op_inc_dpx_w();
void op_dec_dpx_b();
void op_dec_dpx_w();
void op_asl_dpx_b();
void op_asl_dpx_w();
void op_lsr_dpx_b();
void op_lsr_dpx_w();
void op_rol_dpx_b();
void op_rol_dpx_w();
void op_ror_dpx_b();
void op_ror_dpx_w();
//=============
//opcode_pc.bpp
//=============
void op_bcc();
void op_bcs();
void op_bne();
void op_beq();
void op_bpl();
void op_bmi();
void op_bvc();
void op_bvs();
void op_bra();
void op_brl();
void op_jmp_addr();
void op_jmp_long();
void op_jmp_iaddr();
void op_jmp_iaddrx();
void op_jmp_iladdr();
void op_jsr_addr();
void op_jsr_long_e();
void op_jsr_long_n();
void op_jsr_iaddrx_e();
void op_jsr_iaddrx_n();
void op_rti_e();
void op_rti_n();
void op_rts();
void op_rtl_e();
void op_rtl_n();
//===============
//opcode_misc.bpp
//===============
void op_nop();
void op_wdm();
void op_xba();
void op_mvn_b();
void op_mvn_w();
void op_mvp_b();
void op_mvp_w();
void op_brk_e();
void op_brk_n();
void op_cop_e();
void op_cop_n();
void op_stp();
void op_wai();
void op_xce();
void op_clc();
void op_cld();
void op_cli();
void op_clv();
void op_sec();
void op_sed();
void op_sei();
void op_rep_e();
void op_rep_n();
void op_sep_e();
void op_sep_n();
void op_tax_b();
void op_tax_w();
void op_tay_b();
void op_tay_w();
void op_txa_b();
void op_txa_w();
void op_txy_b();
void op_txy_w();
void op_tya_b();
void op_tya_w();
void op_tyx_b();
void op_tyx_w();
void op_tcd();
void op_tdc();
void op_tcs_e();
void op_tcs_n();
void op_tsc_e();
void op_tsc_n();
void op_tsx_b();
void op_tsx_w();
void op_txs_e();
void op_txs_n();
void op_pha_b();
void op_pha_w();
void op_phx_b();
void op_phx_w();
void op_phy_b();
void op_phy_w();
void op_phd_e();
void op_phd_n();
void op_phb();
void op_phk();
void op_php();
void op_pla_b();
void op_pla_w();
void op_plx_b();
void op_plx_w();
void op_ply_b();
void op_ply_w();
void op_pld_e();
void op_pld_n();
void op_plb();
void op_plp_e();
void op_plp_n();
void op_pea_e();
void op_pea_n();
void op_pei_e();
void op_pei_n();
void op_per_e();
void op_per_n();

View File

@ -0,0 +1,317 @@
//===============
//opcode_read.bpp
//===============
@op_read_const(adc)
@op_read_const(and)
@op_read_const(cmp)
@op_read_const(cpx)
@op_read_const(cpy)
@op_read_const(eor)
@op_read_const(lda)
@op_read_const(ldx)
@op_read_const(ldy)
@op_read_const(ora)
@op_read_const(sbc)
@op_read_bit_const()
@op_read_addr(adc)
@op_read_addr(and)
@op_read_addr(bit)
@op_read_addr(cmp)
@op_read_addr(cpx)
@op_read_addr(cpy)
@op_read_addr(eor)
@op_read_addr(lda)
@op_read_addr(ldx)
@op_read_addr(ldy)
@op_read_addr(ora)
@op_read_addr(sbc)
@op_read_addrx(adc)
@op_read_addrx(and)
@op_read_addrx(bit)
@op_read_addrx(cmp)
@op_read_addrx(eor)
@op_read_addrx(lda)
@op_read_addrx(ldy)
@op_read_addrx(ora)
@op_read_addrx(sbc)
@op_read_addry(adc)
@op_read_addry(and)
@op_read_addry(cmp)
@op_read_addry(eor)
@op_read_addry(lda)
@op_read_addry(ldx)
@op_read_addry(ora)
@op_read_addry(sbc)
@op_read_long(adc)
@op_read_long(and)
@op_read_long(cmp)
@op_read_long(eor)
@op_read_long(lda)
@op_read_long(ora)
@op_read_long(sbc)
@op_read_longx(adc)
@op_read_longx(and)
@op_read_longx(cmp)
@op_read_longx(eor)
@op_read_longx(lda)
@op_read_longx(ora)
@op_read_longx(sbc)
@op_read_dp(adc)
@op_read_dp(and)
@op_read_dp(bit)
@op_read_dp(cmp)
@op_read_dp(cpx)
@op_read_dp(cpy)
@op_read_dp(eor)
@op_read_dp(lda)
@op_read_dp(ldx)
@op_read_dp(ldy)
@op_read_dp(ora)
@op_read_dp(sbc)
@op_read_dpr(adc, x)
@op_read_dpr(and, x)
@op_read_dpr(bit, x)
@op_read_dpr(cmp, x)
@op_read_dpr(eor, x)
@op_read_dpr(lda, x)
@op_read_dpr(ldx, y)
@op_read_dpr(ldy, x)
@op_read_dpr(ora, x)
@op_read_dpr(sbc, x)
@op_read_idp(adc)
@op_read_idp(and)
@op_read_idp(cmp)
@op_read_idp(eor)
@op_read_idp(lda)
@op_read_idp(ora)
@op_read_idp(sbc)
@op_read_idpx(adc)
@op_read_idpx(and)
@op_read_idpx(cmp)
@op_read_idpx(eor)
@op_read_idpx(lda)
@op_read_idpx(ora)
@op_read_idpx(sbc)
@op_read_idpy(adc)
@op_read_idpy(and)
@op_read_idpy(cmp)
@op_read_idpy(eor)
@op_read_idpy(lda)
@op_read_idpy(ora)
@op_read_idpy(sbc)
@op_read_ildp(adc)
@op_read_ildp(and)
@op_read_ildp(cmp)
@op_read_ildp(eor)
@op_read_ildp(lda)
@op_read_ildp(ora)
@op_read_ildp(sbc)
@op_read_ildpy(adc)
@op_read_ildpy(and)
@op_read_ildpy(cmp)
@op_read_ildpy(eor)
@op_read_ildpy(lda)
@op_read_ildpy(ora)
@op_read_ildpy(sbc)
@op_read_sr(adc)
@op_read_sr(and)
@op_read_sr(cmp)
@op_read_sr(eor)
@op_read_sr(lda)
@op_read_sr(ora)
@op_read_sr(sbc)
@op_read_isry(adc)
@op_read_isry(and)
@op_read_isry(cmp)
@op_read_isry(eor)
@op_read_isry(lda)
@op_read_isry(ora)
@op_read_isry(sbc)
//================
//opcode_write.bpp
//================
@op_store_addr(sta, regs.a.w)
@op_store_addr(stx, regs.x.w)
@op_store_addr(sty, regs.y.w)
@op_store_addr(stz, 0x0000)
@op_store_addrr(sta, x, regs.a.w, regs.x.w)
@op_store_addrr(sta, y, regs.a.w, regs.y.w)
@op_store_addrr(stz, x, 0x0000, regs.x.w)
@op_store_longr(sta, , 0x0000)
@op_store_longr(sta, x, regs.x.w)
@op_store_dp(sta, regs.a.w)
@op_store_dp(stx, regs.x.w)
@op_store_dp(sty, regs.y.w)
@op_store_dp(stz, 0x0000)
@op_store_dpr(sta, regs.a.w, x)
@op_store_dpr(stx, regs.x.w, y)
@op_store_dpr(sty, regs.y.w, x)
@op_store_dpr(stz, 0x0000, x)
@op_sta_idp()
@op_sta_ildp()
@op_sta_idpx()
@op_sta_idpy()
@op_sta_ildpy()
@op_sta_sr()
@op_sta_isry()
//==============
//opcode_rmw.bpp
//==============
@op_adjust(inc, a, ++)
@op_adjust(inx, x, ++)
@op_adjust(iny, y, ++)
@op_adjust(dec, a, --)
@op_adjust(dex, x, --)
@op_adjust(dey, y, --)
@op_asl()
@op_lsr()
@op_rol()
@op_ror()
@op_adjust_addr(inc)
@op_adjust_addr(dec)
@op_adjust_addr(asl)
@op_adjust_addr(lsr)
@op_adjust_addr(rol)
@op_adjust_addr(ror)
@op_adjust_addr(trb)
@op_adjust_addr(tsb)
@op_adjust_addrx(inc)
@op_adjust_addrx(dec)
@op_adjust_addrx(asl)
@op_adjust_addrx(lsr)
@op_adjust_addrx(rol)
@op_adjust_addrx(ror)
@op_adjust_dp(inc)
@op_adjust_dp(dec)
@op_adjust_dp(asl)
@op_adjust_dp(lsr)
@op_adjust_dp(rol)
@op_adjust_dp(ror)
@op_adjust_dp(trb)
@op_adjust_dp(tsb)
@op_adjust_dpx(inc)
@op_adjust_dpx(dec)
@op_adjust_dpx(asl)
@op_adjust_dpx(lsr)
@op_adjust_dpx(rol)
@op_adjust_dpx(ror)
//=============
//opcode_pc.bpp
//=============
@op_branch(bcc, !regs.p.c)
@op_branch(bcs, regs.p.c)
@op_branch(bne, !regs.p.z)
@op_branch(beq, regs.p.z)
@op_branch(bpl, !regs.p.n)
@op_branch(bmi, regs.p.n)
@op_branch(bvc, !regs.p.v)
@op_branch(bvs, regs.p.v)
@op_bra()
@op_brl()
@op_jmp_addr()
@op_jmp_long()
@op_jmp_iaddr()
@op_jmp_iaddrx()
@op_jmp_iladdr()
@op_jsr_addr()
@op_jsr_long()
@op_jsr_iaddrx()
@op_rti()
@op_rts()
@op_rtl()
//===============
//opcode_misc.bpp
//===============
@op_nop()
@op_wdm()
@op_xba()
@op_move(mvn, ++)
@op_move(mvp, --)
@op_interrupt(brk, 0xfffe, 0xffe6)
@op_interrupt(cop, 0xfff4, 0xffe4)
@op_stp()
@op_wai()
@op_xce()
@op_flag(clc, regs.p.c = 0)
@op_flag(cld, regs.p.d = 0)
@op_flag(cli, regs.p.i = 0)
@op_flag(clv, regs.p.v = 0)
@op_flag(sec, regs.p.c = 1)
@op_flag(sed, regs.p.d = 1)
@op_flag(sei, regs.p.i = 1)
@op_pflag(rep, &=~)
@op_pflag(sep, |=)
@op_transfer(tax, a, x)
@op_transfer(tay, a, y)
@op_transfer(txa, x, a)
@op_transfer(txy, x, y)
@op_transfer(tya, y, a)
@op_transfer(tyx, y, x)
@op_transfer_word(tcd, a, d)
@op_transfer_word(tdc, d, a)
@op_tcs()
@op_tsc()
@op_tsx()
@op_txs()
@op_push(pha, a)
@op_push(phx, x)
@op_push(phy, y)
@op_phd()
@op_push_byte(phb, regs.db)
@op_push_byte(phk, regs.pc.b)
@op_push_byte(php, regs.p)
@op_pull(pla, a)
@op_pull(plx, x)
@op_pull(ply, y)
@op_pld()
@op_plb()
@op_plp()
@op_pea()
@op_pei()
@op_per()

View File

@ -0,0 +1,397 @@
@macro op_nop()
void {class}::op_nop() {
{lc}op_io_irq();
}
@endmacro
@macro op_wdm()
void {class}::op_wdm() {
{lc}op_readpc();
}
@endmacro
@macro op_xba()
void {class}::op_xba() {
op_io();
{lc}op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
@endmacro
@macro op_move(name, op)
void {class}::op_{name}_b() {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
regs.x.l {op};
regs.y.l {op};
{lc}op_io();
if(regs.a.w--) regs.pc.w -= 3;
}
void {class}::op_{name}_w() {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
regs.x.w {op};
regs.y.w {op};
{lc}op_io();
if(regs.a.w--) regs.pc.w -= 3;
}
@endmacro
@macro op_interrupt(name, vectorE, vectorN)
void {class}::op_{name}_e() {
op_readpc();
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong({vectorE} + 0);
regs.pc.b = 0;
regs.p.i = 1;
regs.p.d = 0;
{lc}rd.h = op_readlong({vectorE} + 1);
regs.pc.w = rd.w;
}
void {class}::op_{name}_n() {
op_readpc();
op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong({vectorN} + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
{lc}rd.h = op_readlong({vectorN} + 1);
regs.pc.w = rd.w;
}
@endmacro
@macro op_stp()
void {class}::op_stp() {
while({wai} = true) {
{lc} op_io();
}
}
@endmacro
@macro op_wai()
void {class}::op_wai() {
{wai} = true;
while({wai}) {
{lc} op_io();
}
op_io();
}
@endmacro
@macro op_xce()
void {class}::op_xce() {
{lc}op_io_irq();
bool carry = regs.p.c;
regs.p.c = regs.e;
regs.e = carry;
if(regs.e) {
regs.p |= 0x30;
regs.s.h = 0x01;
}
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
@endmacro
@macro op_flag(name, rule)
void {class}::op_{name}() {
{lc}op_io_irq();
{rule};
}
@endmacro
@macro op_pflag(name, op)
void {class}::op_{name}_e() {
rd.l = op_readpc();
{lc}op_io();
regs.p {op} rd.l;
regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
void {class}::op_{name}_n() {
rd.l = op_readpc();
{lc}op_io();
regs.p {op} rd.l;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
@endmacro
@macro op_transfer(name, from, to)
void {class}::op_{name}_b() {
{lc}op_io_irq();
regs.{to}.l = regs.{from}.l;
regs.p.n = (regs.{to}.l & 0x80);
regs.p.z = (regs.{to}.l == 0);
}
void {class}::op_{name}_w() {
{lc}op_io_irq();
regs.{to}.w = regs.{from}.w;
regs.p.n = (regs.{to}.w & 0x8000);
regs.p.z = (regs.{to}.w == 0);
}
@endmacro
@macro op_transfer_word(name, from, to)
void {class}::op_{name}() {
{lc}op_io_irq();
regs.{to}.w = regs.{from}.w;
regs.p.n = (regs.{to}.w & 0x8000);
regs.p.z = (regs.{to}.w == 0);
}
@endmacro
@macro op_tcs()
void {class}::op_tcs_e() {
{lc}op_io_irq();
regs.s.l = regs.a.l;
}
void {class}::op_tcs_n() {
{lc}op_io_irq();
regs.s.w = regs.a.w;
}
@endmacro
@macro op_tsc()
void {class}::op_tsc_e() {
{lc}op_io_irq();
regs.a.w = regs.s.w;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void {class}::op_tsc_n() {
{lc}op_io_irq();
regs.a.w = regs.s.w;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
@endmacro
@macro op_tsx()
void {class}::op_tsx_b() {
{lc}op_io_irq();
regs.x.l = regs.s.l;
regs.p.n = (regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
}
void {class}::op_tsx_w() {
{lc}op_io_irq();
regs.x.w = regs.s.w;
regs.p.n = (regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
@endmacro
@macro op_txs()
void {class}::op_txs_e() {
{lc}op_io_irq();
regs.s.l = regs.x.l;
}
void {class}::op_txs_n() {
{lc}op_io_irq();
regs.s.w = regs.x.w;
}
@endmacro
@macro op_push(name, r)
void {class}::op_{name}_b() {
op_io();
{lc}op_writestack(regs.{r}.l);
}
void {class}::op_{name}_w() {
op_io();
op_writestack(regs.{r}.h);
{lc}op_writestack(regs.{r}.l);
}
@endmacro
@macro op_phd()
void {class}::op_phd_e() {
op_io();
op_writestackn(regs.d.h);
{lc}op_writestackn(regs.d.l);
regs.s.h = 0x01;
}
void {class}::op_phd_n() {
op_io();
op_writestackn(regs.d.h);
{lc}op_writestackn(regs.d.l);
}
@endmacro
@macro op_push_byte(name, r)
void {class}::op_{name}() {
op_io();
{lc}op_writestack({r});
}
@endmacro
@macro op_pull(name, r)
void {class}::op_{name}_b() {
op_io();
op_io();
{lc}regs.{r}.l = op_readstack();
regs.p.n = (regs.{r}.l & 0x80);
regs.p.z = (regs.{r}.l == 0);
}
void {class}::op_{name}_w() {
op_io();
op_io();
regs.{r}.l = op_readstack();
{lc}regs.{r}.h = op_readstack();
regs.p.n = (regs.{r}.w & 0x8000);
regs.p.z = (regs.{r}.w == 0);
}
@endmacro
@macro op_pld()
void {class}::op_pld_e() {
op_io();
op_io();
regs.d.l = op_readstackn();
{lc}regs.d.h = op_readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
regs.s.h = 0x01;
}
void {class}::op_pld_n() {
op_io();
op_io();
regs.d.l = op_readstackn();
{lc}regs.d.h = op_readstackn();
regs.p.n = (regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
@endmacro
@macro op_plb()
void {class}::op_plb() {
op_io();
op_io();
{lc}regs.db = op_readstack();
regs.p.n = (regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
@endmacro
@macro op_plp()
void {class}::op_plp_e() {
op_io();
op_io();
{lc}regs.p = op_readstack() | 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
void {class}::op_plp_n() {
op_io();
op_io();
{lc}regs.p = op_readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
update_table();
}
@endmacro
@macro op_pea()
void {class}::op_pea_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(aa.h);
{lc}op_writestackn(aa.l);
regs.s.h = 0x01;
}
void {class}::op_pea_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(aa.h);
{lc}op_writestackn(aa.l);
}
@endmacro
@macro op_pei()
void {class}::op_pei_e() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writestackn(aa.h);
{lc}op_writestackn(aa.l);
regs.s.h = 0x01;
}
void {class}::op_pei_n() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writestackn(aa.h);
{lc}op_writestackn(aa.l);
}
@endmacro
@macro op_per()
void {class}::op_per_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16_t)aa.w;
op_writestackn(rd.h);
{lc}op_writestackn(rd.l);
regs.s.h = 0x01;
}
void {class}::op_per_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16_t)aa.w;
op_writestackn(rd.h);
{lc}op_writestackn(rd.l);
}
@endmacro

View File

@ -0,0 +1,205 @@
@macro op_branch(name, condition)
void {class}::op_{name}() {
if({condition} == false) {
{lc} rd.l = op_readpc();
} else {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8_t)rd.l;
op_io_cond6(aa.w);
{lc} op_io();
regs.pc.w = aa.w;
}
}
@endmacro
@macro op_bra()
void {class}::op_bra() {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8_t)rd.l;
op_io_cond6(aa.w);
{lc}op_io();
regs.pc.w = aa.w;
}
@endmacro
@macro op_brl()
void {class}::op_brl() {
rd.l = op_readpc();
rd.h = op_readpc();
{lc}op_io();
regs.pc.w = regs.pc.d + (int16_t)rd.w;
}
@endmacro
@macro op_jmp_addr()
void {class}::op_jmp_addr() {
rd.l = op_readpc();
{lc}rd.h = op_readpc();
regs.pc.w = rd.w;
}
@endmacro
@macro op_jmp_long()
void {class}::op_jmp_long() {
rd.l = op_readpc();
rd.h = op_readpc();
{lc}rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
@endmacro
@macro op_jmp_iaddr()
void {class}::op_jmp_iaddr() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w + 0);
{lc}rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
@endmacro
@macro op_jmp_iaddrx()
void {class}::op_jmp_iaddrx() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
@endmacro
@macro op_jmp_iladdr()
void {class}::op_jmp_iladdr() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w + 0);
rd.h = op_readaddr(aa.w + 1);
{lc}rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
@endmacro
@macro op_jsr_addr()
void {class}::op_jsr_addr() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
regs.pc.w--;
op_writestack(regs.pc.h);
{lc}op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
@endmacro
@macro op_jsr_long()
void {class}::op_jsr_long_e() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestackn(regs.pc.h);
{lc}op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
regs.s.h = 0x01;
}
void {class}::op_jsr_long_n() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestackn(regs.pc.h);
{lc}op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
}
@endmacro
@macro op_jsr_iaddrx()
void {class}::op_jsr_iaddrx_e() {
aa.l = op_readpc();
op_writestackn(regs.pc.h);
op_writestackn(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
regs.s.h = 0x01;
}
void {class}::op_jsr_iaddrx_n() {
aa.l = op_readpc();
op_writestackn(regs.pc.h);
op_writestackn(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w + 0);
{lc}rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
@endmacro
@macro op_rti()
void {class}::op_rti_e() {
op_io();
op_io();
regs.p = op_readstack() | 0x30;
rd.l = op_readstack();
{lc}rd.h = op_readstack();
regs.pc.w = rd.w;
}
void {class}::op_rti_n() {
op_io();
op_io();
regs.p = op_readstack();
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
rd.l = op_readstack();
rd.h = op_readstack();
{lc}rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
update_table();
}
@endmacro
@macro op_rts()
void {class}::op_rts() {
op_io();
op_io();
rd.l = op_readstack();
rd.h = op_readstack();
{lc}op_io();
regs.pc.w = ++rd.w;
}
@endmacro
@macro op_rtl()
void {class}::op_rtl_e() {
op_io();
op_io();
rd.l = op_readstackn();
rd.h = op_readstackn();
{lc}rd.b = op_readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
regs.s.h = 0x01;
}
void {class}::op_rtl_n() {
op_io();
op_io();
rd.l = op_readstackn();
rd.h = op_readstackn();
{lc}rd.b = op_readstackn();
regs.pc.b = rd.b;
regs.pc.w = ++rd.w;
}
@endmacro

View File

@ -0,0 +1,307 @@
@macro op_read_const(name)
void {class}::op_{name}_const_b() {
{lc}rd.l = op_readpc();
op_{name}_b();
}
void {class}::op_{name}_const_w() {
rd.l = op_readpc();
{lc}rd.h = op_readpc();
op_{name}_w();
}
@endmacro
@macro op_read_bit_const()
void {class}::op_bit_const_b() {
{lc}rd.l = op_readpc();
regs.p.z = ((rd.l & regs.a.l) == 0);
}
void {class}::op_bit_const_w() {
rd.l = op_readpc();
{lc}rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}
@endmacro
@macro op_read_addr(name)
void {class}::op_{name}_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
{lc}rd.l = op_readdbr(aa.w);
op_{name}_b();
}
void {class}::op_{name}_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w + 0);
{lc}rd.h = op_readdbr(aa.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_addrx(name)
void {class}::op_{name}_addrx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
{lc}rd.l = op_readdbr(aa.w + regs.x.w);
op_{name}_b();
}
void {class}::op_{name}_addrx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.x.w);
rd.l = op_readdbr(aa.w + regs.x.w + 0);
{lc}rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_addry(name)
void {class}::op_{name}_addry_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
op_{name}_b();
}
void {class}::op_{name}_addry_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io_cond4(aa.w, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w + 0);
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_long(name)
void {class}::op_{name}_long_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
{lc}rd.l = op_readlong(aa.d);
op_{name}_b();
}
void {class}::op_{name}_long_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
rd.l = op_readlong(aa.d + 0);
{lc}rd.h = op_readlong(aa.d + 1);
op_{name}_w();
}
@endmacro
@macro op_read_longx(name)
void {class}::op_{name}_longx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
{lc}rd.l = op_readlong(aa.d + regs.x.w);
op_{name}_b();
}
void {class}::op_{name}_longx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
rd.l = op_readlong(aa.d + regs.x.w + 0);
{lc}rd.h = op_readlong(aa.d + regs.x.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_dp(name)
void {class}::op_{name}_dp_b() {
dp = op_readpc();
op_io_cond2();
{lc}rd.l = op_readdp(dp);
op_{name}_b();
}
void {class}::op_{name}_dp_w() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp + 0);
{lc}rd.h = op_readdp(dp + 1);
op_{name}_w();
}
@endmacro
@macro op_read_dpr(name, r)
void {class}::op_{name}_dpr_b() {
dp = op_readpc();
op_io_cond2();
op_io();
{lc}rd.l = op_readdp(dp + regs.{r}.w);
op_{name}_b();
}
void {class}::op_{name}_dpr_w() {
dp = op_readpc();
op_io_cond2();
op_io();
{lc}rd.l = op_readdp(dp + regs.{r}.w + 0);
rd.h = op_readdp(dp + regs.{r}.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_idp(name)
void {class}::op_{name}_idp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
{lc}rd.l = op_readdbr(aa.w);
op_{name}_b();
}
void {class}::op_{name}_idp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
rd.l = op_readdbr(aa.w + 0);
{lc}rd.h = op_readdbr(aa.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_idpx(name)
void {class}::op_{name}_idpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
{lc}rd.l = op_readdbr(aa.w);
op_{name}_b();
}
void {class}::op_{name}_idpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
rd.l = op_readdbr(aa.w + 0);
{lc}rd.h = op_readdbr(aa.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_idpy(name)
void {class}::op_{name}_idpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
op_{name}_b();
}
void {class}::op_{name}_idpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io_cond4(aa.w, aa.w + regs.y.w);
rd.l = op_readdbr(aa.w + regs.y.w + 0);
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_ildp(name)
void {class}::op_{name}_ildp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
{lc}rd.l = op_readlong(aa.d);
op_{name}_b();
}
void {class}::op_{name}_ildp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
rd.l = op_readlong(aa.d + 0);
{lc}rd.h = op_readlong(aa.d + 1);
op_{name}_w();
}
@endmacro
@macro op_read_ildpy(name)
void {class}::op_{name}_ildpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
{lc}rd.l = op_readlong(aa.d + regs.y.w);
op_{name}_b();
}
void {class}::op_{name}_ildpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
rd.l = op_readlong(aa.d + regs.y.w + 0);
{lc}rd.h = op_readlong(aa.d + regs.y.w + 1);
op_{name}_w();
}
@endmacro
@macro op_read_sr(name)
void {class}::op_{name}_sr_b() {
sp = op_readpc();
op_io();
{lc}rd.l = op_readsp(sp);
op_{name}_b();
}
void {class}::op_{name}_sr_w() {
sp = op_readpc();
op_io();
rd.l = op_readsp(sp + 0);
{lc}rd.h = op_readsp(sp + 1);
op_{name}_w();
}
@endmacro
@macro op_read_isry(name)
void {class}::op_{name}_isry_b() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
{lc}rd.l = op_readdbr(aa.w + regs.y.w);
op_{name}_b();
}
void {class}::op_{name}_isry_w() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
rd.l = op_readdbr(aa.w + regs.y.w + 0);
{lc}rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_{name}_w();
}
@endmacro

View File

@ -0,0 +1,183 @@
@macro op_adjust(name, r, op)
void {class}::op_{name}_imm_b() {
{lc}op_io_irq();
regs.{r}.l {op};
regs.p.n = (regs.{r}.l & 0x80);
regs.p.z = (regs.{r}.l == 0);
}
void {class}::op_{name}_imm_w() {
{lc}op_io_irq();
regs.{r}.w {op};
regs.p.n = (regs.{r}.w & 0x8000);
regs.p.z = (regs.{r}.w == 0);
}
@endmacro
@macro op_asl()
void {class}::op_asl_imm_b() {
{lc}op_io_irq();
regs.p.c = (regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void {class}::op_asl_imm_w() {
{lc}op_io_irq();
regs.p.c = (regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
@endmacro
@macro op_lsr()
void {class}::op_lsr_imm_b() {
{lc}op_io_irq();
regs.p.c = (regs.a.l & 0x01);
regs.a.l >>= 1;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void {class}::op_lsr_imm_w() {
{lc}op_io_irq();
regs.p.c = (regs.a.w & 0x0001);
regs.a.w >>= 1;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
@endmacro
@macro op_rol()
void {class}::op_rol_imm_b() {
{lc}op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x80);
regs.a.l = (regs.a.l << 1) | carry;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void {class}::op_rol_imm_w() {
{lc}op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x8000);
regs.a.w = (regs.a.w << 1) | carry;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
@endmacro
@macro op_ror()
void {class}::op_ror_imm_b() {
{lc}op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.l & 0x01);
regs.a.l = (carry << 7) | (regs.a.l >> 1);
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void {class}::op_ror_imm_w() {
{lc}op_io_irq();
bool carry = regs.p.c;
regs.p.c = (regs.a.w & 0x0001);
regs.a.w = (carry << 15) | (regs.a.w >> 1);
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
@endmacro
@macro op_adjust_addr(name)
void {class}::op_{name}_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
op_io();
op_{name}_b();
{lc}op_writedbr(aa.w, rd.l);
}
void {class}::op_{name}_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w + 0);
rd.h = op_readdbr(aa.w + 1);
op_io();
op_{name}_w();
op_writedbr(aa.w + 1, rd.h);
{lc}op_writedbr(aa.w + 0, rd.l);
}
@endmacro
@macro op_adjust_addrx(name)
void {class}::op_{name}_addrx_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
op_io();
op_{name}_b();
{lc}op_writedbr(aa.w + regs.x.w, rd.l);
}
void {class}::op_{name}_addrx_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w + 0);
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
op_{name}_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h);
{lc}op_writedbr(aa.w + regs.x.w + 0, rd.l);
}
@endmacro
@macro op_adjust_dp(name)
void {class}::op_{name}_dp_b() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
op_io();
op_{name}_b();
{lc}op_writedp(dp, rd.l);
}
void {class}::op_{name}_dp_w() {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp + 0);
rd.h = op_readdp(dp + 1);
op_io();
op_{name}_w();
op_writedp(dp + 1, rd.h);
{lc}op_writedp(dp + 0, rd.l);
}
@endmacro
@macro op_adjust_dpx(name)
void {class}::op_{name}_dpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
op_io();
op_{name}_b();
{lc}op_writedp(dp + regs.x.w, rd.l);
}
void {class}::op_{name}_dpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w + 0);
rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
op_{name}_w();
op_writedp(dp + regs.x.w + 1, rd.h);
{lc}op_writedp(dp + regs.x.w + 0, rd.l);
}
@endmacro

View File

@ -0,0 +1,141 @@
#ifdef CPUCORE_CPP
void CPUcore::initialize_opcode_table() {
//same implementation for all processor states
#define opA(id, name) \
op_table[table_EM + id] = &CPUcore::op_ ## name; \
op_table[table_MX + id] = &CPUcore::op_ ## name; \
op_table[table_Mx + id] = &CPUcore::op_ ## name; \
op_table[table_mX + id] = &CPUcore::op_ ## name; \
op_table[table_mx + id] = &CPUcore::op_ ## name;
//implementation changes based on E processor state
#define opE(id, name) \
op_table[table_EM + id] = &CPUcore::op_ ## name ## _e; \
op_table[table_MX + id] = &CPUcore::op_ ## name ## _n; \
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _n; \
op_table[table_mX + id] = &CPUcore::op_ ## name ## _n; \
op_table[table_mx + id] = &CPUcore::op_ ## name ## _n; \
//implementation changes based on M processor state
#define opM(id, name) \
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_mX + id] = &CPUcore::op_ ## name ## _w; \
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
//implementation changes based on X processor state
#define opX(id, name) \
op_table[table_EM + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_MX + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_Mx + id] = &CPUcore::op_ ## name ## _w; \
op_table[table_mX + id] = &CPUcore::op_ ## name ## _b; \
op_table[table_mx + id] = &CPUcore::op_ ## name ## _w;
opE(0x00, brk) opM(0x01, ora_idpx) opE(0x02, cop) opM(0x03, ora_sr)
opM(0x04, tsb_dp) opM(0x05, ora_dp) opM(0x06, asl_dp) opM(0x07, ora_ildp)
opA(0x08, php) opM(0x09, ora_const) opM(0x0a, asl_imm) opE(0x0b, phd)
opM(0x0c, tsb_addr) opM(0x0d, ora_addr) opM(0x0e, asl_addr) opM(0x0f, ora_long)
opA(0x10, bpl) opM(0x11, ora_idpy) opM(0x12, ora_idp) opM(0x13, ora_isry)
opM(0x14, trb_dp) opM(0x15, ora_dpr) opM(0x16, asl_dpx) opM(0x17, ora_ildpy)
opA(0x18, clc) opM(0x19, ora_addry) opM(0x1a, inc_imm) opE(0x1b, tcs)
opM(0x1c, trb_addr) opM(0x1d, ora_addrx) opM(0x1e, asl_addrx) opM(0x1f, ora_longx)
opA(0x20, jsr_addr) opM(0x21, and_idpx) opE(0x22, jsr_long) opM(0x23, and_sr)
opM(0x24, bit_dp) opM(0x25, and_dp) opM(0x26, rol_dp) opM(0x27, and_ildp)
opE(0x28, plp) opM(0x29, and_const) opM(0x2a, rol_imm) opE(0x2b, pld)
opM(0x2c, bit_addr) opM(0x2d, and_addr) opM(0x2e, rol_addr) opM(0x2f, and_long)
opA(0x30, bmi) opM(0x31, and_idpy) opM(0x32, and_idp) opM(0x33, and_isry)
opM(0x34, bit_dpr) opM(0x35, and_dpr) opM(0x36, rol_dpx) opM(0x37, and_ildpy)
opA(0x38, sec) opM(0x39, and_addry) opM(0x3a, dec_imm) opE(0x3b, tsc)
opM(0x3c, bit_addrx) opM(0x3d, and_addrx) opM(0x3e, rol_addrx) opM(0x3f, and_longx)
opE(0x40, rti) opM(0x41, eor_idpx) opA(0x42, wdm) opM(0x43, eor_sr)
opX(0x44, mvp) opM(0x45, eor_dp) opM(0x46, lsr_dp) opM(0x47, eor_ildp)
opM(0x48, pha) opM(0x49, eor_const) opM(0x4a, lsr_imm) opA(0x4b, phk)
opA(0x4c, jmp_addr) opM(0x4d, eor_addr) opM(0x4e, lsr_addr) opM(0x4f, eor_long)
opA(0x50, bvc) opM(0x51, eor_idpy) opM(0x52, eor_idp) opM(0x53, eor_isry)
opX(0x54, mvn) opM(0x55, eor_dpr) opM(0x56, lsr_dpx) opM(0x57, eor_ildpy)
opA(0x58, cli) opM(0x59, eor_addry) opX(0x5a, phy) opA(0x5b, tcd)
opA(0x5c, jmp_long) opM(0x5d, eor_addrx) opM(0x5e, lsr_addrx) opM(0x5f, eor_longx)
opA(0x60, rts) opM(0x61, adc_idpx) opE(0x62, per) opM(0x63, adc_sr)
opM(0x64, stz_dp) opM(0x65, adc_dp) opM(0x66, ror_dp) opM(0x67, adc_ildp)
opM(0x68, pla) opM(0x69, adc_const) opM(0x6a, ror_imm) opE(0x6b, rtl)
opA(0x6c, jmp_iaddr) opM(0x6d, adc_addr) opM(0x6e, ror_addr) opM(0x6f, adc_long)
opA(0x70, bvs) opM(0x71, adc_idpy) opM(0x72, adc_idp) opM(0x73, adc_isry)
opM(0x74, stz_dpr) opM(0x75, adc_dpr) opM(0x76, ror_dpx) opM(0x77, adc_ildpy)
opA(0x78, sei) opM(0x79, adc_addry) opX(0x7a, ply) opA(0x7b, tdc)
opA(0x7c, jmp_iaddrx) opM(0x7d, adc_addrx) opM(0x7e, ror_addrx) opM(0x7f, adc_longx)
opA(0x80, bra) opM(0x81, sta_idpx) opA(0x82, brl) opM(0x83, sta_sr)
opX(0x84, sty_dp) opM(0x85, sta_dp) opX(0x86, stx_dp) opM(0x87, sta_ildp)
opX(0x88, dey_imm) opM(0x89, bit_const) opM(0x8a, txa) opA(0x8b, phb)
opX(0x8c, sty_addr) opM(0x8d, sta_addr) opX(0x8e, stx_addr) opM(0x8f, sta_long)
opA(0x90, bcc) opM(0x91, sta_idpy) opM(0x92, sta_idp) opM(0x93, sta_isry)
opX(0x94, sty_dpr) opM(0x95, sta_dpr) opX(0x96, stx_dpr) opM(0x97, sta_ildpy)
opM(0x98, tya) opM(0x99, sta_addry) opE(0x9a, txs) opX(0x9b, txy)
opM(0x9c, stz_addr) opM(0x9d, sta_addrx) opM(0x9e, stz_addrx) opM(0x9f, sta_longx)
opX(0xa0, ldy_const) opM(0xa1, lda_idpx) opX(0xa2, ldx_const) opM(0xa3, lda_sr)
opX(0xa4, ldy_dp) opM(0xa5, lda_dp) opX(0xa6, ldx_dp) opM(0xa7, lda_ildp)
opX(0xa8, tay) opM(0xa9, lda_const) opX(0xaa, tax) opA(0xab, plb)
opX(0xac, ldy_addr) opM(0xad, lda_addr) opX(0xae, ldx_addr) opM(0xaf, lda_long)
opA(0xb0, bcs) opM(0xb1, lda_idpy) opM(0xb2, lda_idp) opM(0xb3, lda_isry)
opX(0xb4, ldy_dpr) opM(0xb5, lda_dpr) opX(0xb6, ldx_dpr) opM(0xb7, lda_ildpy)
opA(0xb8, clv) opM(0xb9, lda_addry) opX(0xba, tsx) opX(0xbb, tyx)
opX(0xbc, ldy_addrx) opM(0xbd, lda_addrx) opX(0xbe, ldx_addry) opM(0xbf, lda_longx)
opX(0xc0, cpy_const) opM(0xc1, cmp_idpx) opE(0xc2, rep) opM(0xc3, cmp_sr)
opX(0xc4, cpy_dp) opM(0xc5, cmp_dp) opM(0xc6, dec_dp) opM(0xc7, cmp_ildp)
opX(0xc8, iny_imm) opM(0xc9, cmp_const) opX(0xca, dex_imm) opA(0xcb, wai)
opX(0xcc, cpy_addr) opM(0xcd, cmp_addr) opM(0xce, dec_addr) opM(0xcf, cmp_long)
opA(0xd0, bne) opM(0xd1, cmp_idpy) opM(0xd2, cmp_idp) opM(0xd3, cmp_isry)
opE(0xd4, pei) opM(0xd5, cmp_dpr) opM(0xd6, dec_dpx) opM(0xd7, cmp_ildpy)
opA(0xd8, cld) opM(0xd9, cmp_addry) opX(0xda, phx) opA(0xdb, stp)
opA(0xdc, jmp_iladdr) opM(0xdd, cmp_addrx) opM(0xde, dec_addrx) opM(0xdf, cmp_longx)
opX(0xe0, cpx_const) opM(0xe1, sbc_idpx) opE(0xe2, sep) opM(0xe3, sbc_sr)
opX(0xe4, cpx_dp) opM(0xe5, sbc_dp) opM(0xe6, inc_dp) opM(0xe7, sbc_ildp)
opX(0xe8, inx_imm) opM(0xe9, sbc_const) opA(0xea, nop) opA(0xeb, xba)
opX(0xec, cpx_addr) opM(0xed, sbc_addr) opM(0xee, inc_addr) opM(0xef, sbc_long)
opA(0xf0, beq) opM(0xf1, sbc_idpy) opM(0xf2, sbc_idp) opM(0xf3, sbc_isry)
opE(0xf4, pea) opM(0xf5, sbc_dpr) opM(0xf6, inc_dpx) opM(0xf7, sbc_ildpy)
opA(0xf8, sed) opM(0xf9, sbc_addry) opX(0xfa, plx) opA(0xfb, xce)
opE(0xfc, jsr_iaddrx) opM(0xfd, sbc_addrx) opM(0xfe, inc_addrx) opM(0xff, sbc_longx)
#undef opA
#undef opE
#undef opM
#undef opX
}
void CPUcore::update_table() {
if(regs.e) {
opcode_table = &op_table[table_EM];
} else if(regs.p.m) {
if(regs.p.x) {
opcode_table = &op_table[table_MX];
} else {
opcode_table = &op_table[table_Mx];
}
} else {
if(regs.p.x) {
opcode_table = &op_table[table_mX];
} else {
opcode_table = &op_table[table_mx];
}
}
}
#endif

View File

@ -0,0 +1,219 @@
@macro op_store_addr(name, r)
void {class}::op_{name}_addr_b() {
aa.l = op_readpc();
aa.h = op_readpc();
{lc}op_writedbr(aa.w, {r});
}
void {class}::op_{name}_addr_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_writedbr(aa.w + 0, {r} >> 0);
{lc}op_writedbr(aa.w + 1, {r} >> 8);
}
@endmacro
@macro op_store_addrr(name, suffix, r, index)
void {class}::op_{name}_addr{suffix}_b() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
{lc}op_writedbr(aa.w + {index}, {r});
}
void {class}::op_{name}_addr{suffix}_w() {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
op_writedbr(aa.w + {index} + 0, {r} >> 0);
{lc}op_writedbr(aa.w + {index} + 1, {r} >> 8);
}
@endmacro
@macro op_store_longr(name, suffix, index)
void {class}::op_{name}_long{suffix}_b() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
{lc}op_writelong(aa.d + {index}, regs.a.l);
}
void {class}::op_{name}_long{suffix}_w() {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
op_writelong(aa.d + {index} + 0, regs.a.l);
{lc}op_writelong(aa.d + {index} + 1, regs.a.h);
}
@endmacro
@macro op_store_dp(name, r)
void {class}::op_{name}_dp_b() {
dp = op_readpc();
op_io_cond2();
{lc}op_writedp(dp, {r});
}
void {class}::op_{name}_dp_w() {
dp = op_readpc();
op_io_cond2();
op_writedp(dp + 0, {r} >> 0);
{lc}op_writedp(dp + 1, {r} >> 8);
}
@endmacro
@macro op_store_dpr(name, r, index)
void {class}::op_{name}_dpr_b() {
dp = op_readpc();
op_io_cond2();
op_io();
{lc}op_writedp(dp + regs.{index}.w, {r});
}
void {class}::op_{name}_dpr_w() {
dp = op_readpc();
op_io_cond2();
op_io();
op_writedp(dp + regs.{index}.w + 0, {r} >> 0);
{lc}op_writedp(dp + regs.{index}.w + 1, {r} >> 8);
}
@endmacro
@macro op_sta_idp()
void {class}::op_sta_idp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
{lc}op_writedbr(aa.w, regs.a.l);
}
void {class}::op_sta_idp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_writedbr(aa.w + 0, regs.a.l);
{lc}op_writedbr(aa.w + 1, regs.a.h);
}
@endmacro
@macro op_sta_ildp()
void {class}::op_sta_ildp_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
{lc}op_writelong(aa.d, regs.a.l);
}
void {class}::op_sta_ildp_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
op_writelong(aa.d + 0, regs.a.l);
{lc}op_writelong(aa.d + 1, regs.a.h);
}
@endmacro
@macro op_sta_idpx()
void {class}::op_sta_idpx_b() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
{lc}op_writedbr(aa.w, regs.a.l);
}
void {class}::op_sta_idpx_w() {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w + 0);
aa.h = op_readdp(dp + regs.x.w + 1);
op_writedbr(aa.w + 0, regs.a.l);
{lc}op_writedbr(aa.w + 1, regs.a.h);
}
@endmacro
@macro op_sta_idpy()
void {class}::op_sta_idpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io();
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
}
void {class}::op_sta_idpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
op_io();
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
@endmacro
@macro op_sta_ildpy()
void {class}::op_sta_ildpy_b() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
{lc}op_writelong(aa.d + regs.y.w, regs.a.l);
}
void {class}::op_sta_ildpy_w() {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp + 0);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
op_writelong(aa.d + regs.y.w + 0, regs.a.l);
{lc}op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
@endmacro
@macro op_sta_sr()
void {class}::op_sta_sr_b() {
sp = op_readpc();
op_io();
{lc}op_writesp(sp, regs.a.l);
}
void {class}::op_sta_sr_w() {
sp = op_readpc();
op_io();
op_writesp(sp + 0, regs.a.l);
{lc}op_writesp(sp + 1, regs.a.h);
}
@endmacro
@macro op_sta_isry()
void {class}::op_sta_isry_b() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
{lc}op_writedbr(aa.w + regs.y.w, regs.a.l);
}
void {class}::op_sta_isry_w() {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp + 0);
aa.h = op_readsp(sp + 1);
op_io();
op_writedbr(aa.w + regs.y.w + 0, regs.a.l);
{lc}op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
@endmacro

View File

@ -68,7 +68,12 @@ struct regs_t {
reg24_t pc; reg24_t pc;
reg16_t a, x, y, s, d; reg16_t a, x, y, s, d;
flag_t p; flag_t p;
uint8_t db, mdr; uint8_t db;
bool e; bool e;
regs_t() : db(0), mdr(0), e(false) {}
bool irq; //IRQ pin (0 = low, 1 = trigger)
bool wai; //raised during wai, cleared after interrupt triggered
uint8_t mdr; //memory data register
regs_t() : db(0), e(false), irq(false), wai(false), mdr(0) {}
}; };

View File

@ -1,10 +1,10 @@
#include <../base.hpp> #include <../base.hpp>
#define CPU_CPP
#include "dcpu.cpp" #define CPU_CPP
namespace SNES {
void CPU::power() { void CPU::power() {
cpu_version = snes.config.cpu.version; cpu_version = config.cpu.version;
} }
void CPU::reset() { void CPU::reset() {
@ -15,3 +15,5 @@ CPU::CPU() {
CPU::~CPU() { CPU::~CPU() {
} }
};

View File

@ -13,62 +13,10 @@ public:
virtual uint8 port_read(uint8 port) = 0; virtual uint8 port_read(uint8 port) = 0;
virtual void port_write(uint8 port, uint8 value) = 0; virtual void port_write(uint8 port, uint8 value) = 0;
#include "cpuregs.hpp"
regs_t regs;
virtual void scanline() = 0; virtual void scanline() = 0;
virtual void power(); virtual void power();
virtual void reset(); virtual void reset();
/*****
* in opcode-based CPU emulators, the main emulation routine
* will only be able to call the disassemble_opcode() function
* on clean opcode edges. but with cycle-based CPU emulators,
* the CPU may be in the middle of executing an opcode when the
* emulator (e.g. debugger) wants to disassemble an opcode. this
* would mean that important registers may not reflect what they
* did at the start of the opcode (especially regs.pc), so in
* cycle-based emulators, this function should be overridden to
* reflect whether or not an opcode has only been partially
* executed. if not, the debugger should abort attempts to skip,
* disable, or disassemble the current opcode.
*****/
virtual bool in_opcode() { return false; }
/*****
* opcode disassembler
*****/
enum {
OPTYPE_DP = 0, //dp
OPTYPE_DPX, //dp,x
OPTYPE_DPY, //dp,y
OPTYPE_IDP, //(dp)
OPTYPE_IDPX, //(dp,x)
OPTYPE_IDPY, //(dp),y
OPTYPE_ILDP, //[dp]
OPTYPE_ILDPY, //[dp],y
OPTYPE_ADDR, //addr
OPTYPE_ADDRX, //addr,x
OPTYPE_ADDRY, //addr,y
OPTYPE_IADDRX, //(addr,x)
OPTYPE_ILADDR, //[addr]
OPTYPE_LONG, //long
OPTYPE_LONGX, //long, x
OPTYPE_SR, //sr,s
OPTYPE_ISRY, //(sr,s),y
OPTYPE_ADDR_PC, //pbr:addr
OPTYPE_IADDR_PC, //pbr:(addr)
OPTYPE_RELB, //relb
OPTYPE_RELW, //relw
};
void disassemble_opcode(char *output);
uint8 dreadb(uint32 addr);
uint16 dreadw(uint32 addr);
uint32 dreadl(uint32 addr);
uint32 decode(uint8 offset_type, uint32 addr);
uint8 opcode_length();
CPU(); CPU();
virtual ~CPU(); virtual ~CPU();
}; };

View File

@ -1,4 +0,0 @@
g++ -c scpugen.cpp -I../../../lib
g++ -c ../../../lib/nall/string.cpp -I../../../lib
g++ -o scpugen scpugen.o string.o
rm *.o

View File

@ -1 +0,0 @@
rm scpugen

View File

@ -1,90 +0,0 @@
#ifdef SCPU_CPP
#include "opfn.cpp"
void sCPU::enter() {
initialize:
//initial latch values for $213c/$213d
//[x]0035 : [y]0000 (53.0 -> 212) [lda $2137]
//[x]0038 : [y]0000 (56.5 -> 226) [nop : lda $2137]
add_clocks(186);
loop:
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.nmi_pending) {
status.nmi_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
} else if(status.irq_pending) {
status.irq_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
}
op_irq();
}
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
status.in_opcode = true;
switch(op_readpc()) {
#include "op_read.cpp"
#include "op_write.cpp"
#include "op_rmw.cpp"
#include "op_pc.cpp"
#include "op_misc.cpp"
}
status.in_opcode = false;
goto loop;
}
void sCPU::op_irq() {
op_read(regs.pc.d);
op_io();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_read(status.interrupt_vector + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_read(status.interrupt_vector + 1);
regs.pc.w = rd.w;
}
//immediate, 2-cycle opcodes with I/O cycle will become bus read
//when an IRQ is to be triggered immediately after opcode completion
//this affects the following opcodes:
// clc, cld, cli, clv, sec, sed, sei,
// tax, tay, txa, txy, tya, tyx,
// tcd, tcs, tdc, tsc, tsx, txs,
// inc, inx, iny, dec, dex, dey,
// asl, lsr, rol, ror, nop, xce.
alwaysinline void sCPU::op_io_irq() {
if(status.interrupt_pending) {
//IRQ pending, modify I/O cycle to bus read cycle, do not increment PC
op_read(regs.pc.d);
} else {
op_io();
}
}
alwaysinline void sCPU::op_io_cond2() {
if(regs.d.l != 0x00) {
op_io();
}
}
alwaysinline void sCPU::op_io_cond4(uint16 x, uint16 y) {
if(!regs.p.x || (x & 0xff00) != (y & 0xff00)) {
op_io();
}
}
alwaysinline void sCPU::op_io_cond6(uint16 addr) {
if(regs.e && (regs.pc.w & 0xff00) != (addr & 0xff00)) {
op_io();
}
}
#endif

View File

@ -1,298 +0,0 @@
nop(0xea) {
1:last_cycle();
op_io_irq();
}
wdm(0x42) {
1:last_cycle();
op_readpc();
}
xba(0xeb) {
1:op_io();
2:last_cycle();
op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
mvn(0x54, ++),
mvp(0x44, --) {
1:dp = op_readpc();
2:sp = op_readpc();
3:regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
4:op_writelong((dp << 16) | regs.y.w, rd.l);
5:op_io();
if(regs.p.x) {
regs.x.l $1;
regs.y.l $1;
} else {
regs.x.w $1;
regs.y.w $1;
}
6:last_cycle();
op_io();
if(regs.a.w--) regs.pc.w -= 3;
}
brk(0x00, 0xfffe, 0xffff, 0xffe6, 0xffe7),
cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
1:op_readpc();
2:if(!regs.e) op_writestack(regs.pc.b);
3:op_writestack(regs.pc.h);
4:op_writestack(regs.pc.l);
5:op_writestack(regs.p);
6:rd.l = op_readlong(regs.e ? $1 : $3);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
7:last_cycle();
rd.h = op_readlong(regs.e ? $2 : $4);
regs.pc.w = rd.w;
}
stp(0xdb) {
1:op_io();
2:last_cycle();
while(true) op_io();
}
wai(0xcb) {
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
1:status.wai_lock = true;
while(status.wai_lock) {
last_cycle();
op_io();
}
2:op_io();
}
xce(0xfb) {
1:last_cycle();
op_io_irq();
bool carry = regs.p.c;
regs.p.c = regs.e;
regs.e = carry;
if(regs.e) {
regs.p |= 0x30;
regs.s.h = 0x01;
}
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
clc(0x18, regs.p.c = 0),
cld(0xd8, regs.p.d = 0),
cli(0x58, regs.p.i = 0),
clv(0xb8, regs.p.v = 0),
sec(0x38, regs.p.c = 1),
sed(0xf8, regs.p.d = 1),
sei(0x78, regs.p.i = 1) {
1:last_cycle();
op_io_irq();
$1;
}
rep(0xc2, &=~),
sep(0xe2, |=) {
1:rd.l = op_readpc();
2:last_cycle();
op_io();
regs.p $1 rd.l;
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
tax(0xaa, regs.p.x, x, a),
tay(0xa8, regs.p.x, y, a),
txa(0x8a, regs.p.m, a, x),
txy(0x9b, regs.p.x, y, x),
tya(0x98, regs.p.m, a, y),
tyx(0xbb, regs.p.x, x, y) {
1:last_cycle();
op_io_irq();
if($1) {
regs.$2.l = regs.$3.l;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w = regs.$3.w;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
tcd(0x5b) {
1:last_cycle();
op_io_irq();
regs.d.w = regs.a.w;
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
}
tcs(0x1b) {
1:last_cycle();
op_io_irq();
regs.s.w = regs.a.w;
if(regs.e) regs.s.h = 0x01;
}
tdc(0x7b) {
1:last_cycle();
op_io_irq();
regs.a.w = regs.d.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
tsc(0x3b) {
1:last_cycle();
op_io_irq();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
tsx(0xba) {
1:last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l = regs.s.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
}
txs(0x9a) {
1:last_cycle();
op_io_irq();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
}
pha(0x48, regs.p.m, a),
phx(0xda, regs.p.x, x),
phy(0x5a, regs.p.x, y) {
1:op_io();
2:if(!$1)op_writestack(regs.$2.h);
3:last_cycle();
op_writestack(regs.$2.l);
}
phd(0x0b) {
1:op_io();
2:op_writestackn(regs.d.h);
3:last_cycle();
op_writestackn(regs.d.l);
if(regs.e) regs.s.h = 0x01;
}
phb(0x8b, regs.db),
phk(0x4b, regs.pc.b),
php(0x08, regs.p) {
1:op_io();
2:last_cycle();
op_writestack($1);
}
pla(0x68, regs.p.m, a),
plx(0xfa, regs.p.x, x),
ply(0x7a, regs.p.x, y) {
1:op_io();
2:op_io();
3:if($1)last_cycle();
regs.$2.l = op_readstack();
if($1) {
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
end;
}
4:last_cycle();
regs.$2.h = op_readstack();
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
pld(0x2b) {
1:op_io();
2:op_io();
3:regs.d.l = op_readstackn();
4:last_cycle();
regs.d.h = op_readstackn();
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
if(regs.e) regs.s.h = 0x01;
}
plb(0xab) {
1:op_io();
2:op_io();
3:last_cycle();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
}
plp(0x28) {
1:op_io();
2:op_io();
3:last_cycle();
regs.p = op_readstack();
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
}
pea(0xf4) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestackn(aa.h);
4:last_cycle();
op_writestackn(aa.l);
if(regs.e) regs.s.h = 0x01;
}
pei(0xd4) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_writestackn(aa.h);
6:last_cycle();
op_writestackn(aa.l);
if(regs.e) regs.s.h = 0x01;
}
per(0x62) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
rd.w = regs.pc.d + (int16)aa.w;
4:op_writestackn(rd.h);
5:last_cycle();
op_writestackn(rd.l);
if(regs.e) regs.s.h = 0x01;
}

View File

@ -1,539 +0,0 @@
#ifdef SCPU_CPP
//nop
case 0xea: {
last_cycle();
op_io_irq();
} break;
//wdm
case 0x42: {
last_cycle();
op_readpc();
} break;
//xba
case 0xeb: {
op_io();
last_cycle();
op_io();
regs.a.l ^= regs.a.h;
regs.a.h ^= regs.a.l;
regs.a.l ^= regs.a.h;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} break;
//mvn
case 0x54: {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
if(regs.p.x) {
regs.x.l ++;
regs.y.l ++;
} else {
regs.x.w ++;
regs.y.w ++;
}
last_cycle();
op_io();
if(regs.a.w--) regs.pc.w -= 3;
} break;
//mvp
case 0x44: {
dp = op_readpc();
sp = op_readpc();
regs.db = dp;
rd.l = op_readlong((sp << 16) | regs.x.w);
op_writelong((dp << 16) | regs.y.w, rd.l);
op_io();
if(regs.p.x) {
regs.x.l --;
regs.y.l --;
} else {
regs.x.w --;
regs.y.w --;
}
last_cycle();
op_io();
if(regs.a.w--) regs.pc.w -= 3;
} break;
//brk
case 0x00: {
op_readpc();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong(regs.e ? 0xfffe : 0xffe6);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
last_cycle();
rd.h = op_readlong(regs.e ? 0xffff : 0xffe7);
regs.pc.w = rd.w;
} break;
//cop
case 0x02: {
op_readpc();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.p);
rd.l = op_readlong(regs.e ? 0xfff4 : 0xffe4);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
last_cycle();
rd.h = op_readlong(regs.e ? 0xfff5 : 0xffe5);
regs.pc.w = rd.w;
} break;
//stp
case 0xdb: {
op_io();
last_cycle();
while(true) op_io();
} break;
//wai
case 0xcb: {
//last_cycle() will clear status.wai_lock once an NMI / IRQ edge is reached
status.wai_lock = true;
while(status.wai_lock) {
last_cycle();
op_io();
}
op_io();
} break;
//xce
case 0xfb: {
last_cycle();
op_io_irq();
bool carry = regs.p.c;
regs.p.c = regs.e;
regs.e = carry;
if(regs.e) {
regs.p |= 0x30;
regs.s.h = 0x01;
}
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//clc
case 0x18: {
last_cycle();
op_io_irq();
regs.p.c = 0;
} break;
//cld
case 0xd8: {
last_cycle();
op_io_irq();
regs.p.d = 0;
} break;
//cli
case 0x58: {
last_cycle();
op_io_irq();
regs.p.i = 0;
} break;
//clv
case 0xb8: {
last_cycle();
op_io_irq();
regs.p.v = 0;
} break;
//sec
case 0x38: {
last_cycle();
op_io_irq();
regs.p.c = 1;
} break;
//sed
case 0xf8: {
last_cycle();
op_io_irq();
regs.p.d = 1;
} break;
//sei
case 0x78: {
last_cycle();
op_io_irq();
regs.p.i = 1;
} break;
//rep
case 0xc2: {
rd.l = op_readpc();
last_cycle();
op_io();
regs.p &=~ rd.l;
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//sep
case 0xe2: {
rd.l = op_readpc();
last_cycle();
op_io();
regs.p |= rd.l;
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//tax
case 0xaa: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l = regs.a.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.a.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//tay
case 0xa8: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.y.l = regs.a.l;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.a.w;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//txa
case 0x8a: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.a.l = regs.x.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.x.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//txy
case 0x9b: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.y.l = regs.x.l;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w = regs.x.w;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//tya
case 0x98: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.a.l = regs.y.l;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w = regs.y.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//tyx
case 0xbb: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l = regs.y.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.y.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//tcd
case 0x5b: {
last_cycle();
op_io_irq();
regs.d.w = regs.a.w;
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
} break;
//tcs
case 0x1b: {
last_cycle();
op_io_irq();
regs.s.w = regs.a.w;
if(regs.e) regs.s.h = 0x01;
} break;
//tdc
case 0x7b: {
last_cycle();
op_io_irq();
regs.a.w = regs.d.w;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
} break;
//tsc
case 0x3b: {
last_cycle();
op_io_irq();
regs.a.w = regs.s.w;
if(regs.e) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//tsx
case 0xba: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l = regs.s.l;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w = regs.s.w;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//txs
case 0x9a: {
last_cycle();
op_io_irq();
if(regs.e) {
regs.s.l = regs.x.l;
} else {
regs.s.w = regs.x.w;
}
} break;
//pha
case 0x48: {
op_io();
if(!regs.p.m)op_writestack(regs.a.h);
last_cycle();
op_writestack(regs.a.l);
} break;
//phx
case 0xda: {
op_io();
if(!regs.p.x)op_writestack(regs.x.h);
last_cycle();
op_writestack(regs.x.l);
} break;
//phy
case 0x5a: {
op_io();
if(!regs.p.x)op_writestack(regs.y.h);
last_cycle();
op_writestack(regs.y.l);
} break;
//phd
case 0x0b: {
op_io();
op_writestackn(regs.d.h);
last_cycle();
op_writestackn(regs.d.l);
if(regs.e) regs.s.h = 0x01;
} break;
//phb
case 0x8b: {
op_io();
last_cycle();
op_writestack(regs.db);
} break;
//phk
case 0x4b: {
op_io();
last_cycle();
op_writestack(regs.pc.b);
} break;
//php
case 0x08: {
op_io();
last_cycle();
op_writestack(regs.p);
} break;
//pla
case 0x68: {
op_io();
op_io();
if(regs.p.m)last_cycle();
regs.a.l = op_readstack();
if(regs.p.m) {
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
break;
}
last_cycle();
regs.a.h = op_readstack();
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
} break;
//plx
case 0xfa: {
op_io();
op_io();
if(regs.p.x)last_cycle();
regs.x.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
break;
}
last_cycle();
regs.x.h = op_readstack();
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
} break;
//ply
case 0x7a: {
op_io();
op_io();
if(regs.p.x)last_cycle();
regs.y.l = op_readstack();
if(regs.p.x) {
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
break;
}
last_cycle();
regs.y.h = op_readstack();
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
} break;
//pld
case 0x2b: {
op_io();
op_io();
regs.d.l = op_readstackn();
last_cycle();
regs.d.h = op_readstackn();
regs.p.n = !!(regs.d.w & 0x8000);
regs.p.z = (regs.d.w == 0);
if(regs.e) regs.s.h = 0x01;
} break;
//plb
case 0xab: {
op_io();
op_io();
last_cycle();
regs.db = op_readstack();
regs.p.n = !!(regs.db & 0x80);
regs.p.z = (regs.db == 0);
} break;
//plp
case 0x28: {
op_io();
op_io();
last_cycle();
regs.p = op_readstack();
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
} break;
//pea
case 0xf4: {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(aa.h);
last_cycle();
op_writestackn(aa.l);
if(regs.e) regs.s.h = 0x01;
} break;
//pei
case 0xd4: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_writestackn(aa.h);
last_cycle();
op_writestackn(aa.l);
if(regs.e) regs.s.h = 0x01;
} break;
//per
case 0x62: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.w = regs.pc.d + (int16)aa.w;
op_writestackn(rd.h);
last_cycle();
op_writestackn(rd.l);
if(regs.e) regs.s.h = 0x01;
} break;
#endif

View File

@ -1,163 +0,0 @@
bcc(0x90, !regs.p.c),
bcs(0xb0, regs.p.c),
bne(0xd0, !regs.p.z),
beq(0xf0, regs.p.z),
bpl(0x10, !regs.p.n),
bmi(0x30, regs.p.n),
bvc(0x50, !regs.p.v),
bvs(0x70, regs.p.v) {
1:if(!$1) last_cycle();
rd.l = op_readpc();
if($1) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
end;
}
2:op_io_cond6(aa.w);
3:last_cycle();
op_io();
}
bra(0x80) {
1:rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
2:op_io_cond6(aa.w);
3:last_cycle();
op_io();
}
brl(0x82) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
op_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
}
jmp_addr(0x4c) {
1:rd.l = op_readpc();
2:last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
}
jmp_long(0x5c) {
1:rd.l = op_readpc();
2:rd.h = op_readpc();
3:last_cycle();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
}
jmp_iaddr(0x6c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
}
jmp_iaddrx(0x7c) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:rd.l = op_readpbr(aa.w + regs.x.w);
5:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
}
jmp_iladdr(0xdc) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readaddr(aa.w);
4:rd.h = op_readaddr(aa.w + 1);
5:last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
}
jsr_addr(0x20) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:regs.pc.w--;
op_writestack(regs.pc.h);
5:last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
}
jsr_long(0x22) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_writestackn(regs.pc.b);
4:op_io();
5:aa.b = op_readpc();
6:regs.pc.w--;
op_writestackn(regs.pc.h);
7:last_cycle();
op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
if(regs.e) regs.s.h = 0x01;
}
jsr_iaddrx(0xfc) {
1:aa.l = op_readpc();
2:op_writestackn(regs.pc.h);
3:op_writestackn(regs.pc.l);
4:aa.h = op_readpc();
5:op_io();
6:rd.l = op_readpbr(aa.w + regs.x.w);
7:last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
if(regs.e) regs.s.h = 0x01;
}
rti(0x40) {
1:op_io();
2:op_io();
3:regs.p = op_readstack();
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
4:rd.l = op_readstack();
5:if(regs.e) last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
end;
}
6:last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
}
rts(0x60) {
1:op_io();
2:op_io();
3:rd.l = op_readstack();
4:rd.h = op_readstack();
5:last_cycle();
op_io();
regs.pc.w = rd.w;
regs.pc.w++;
}
rtl(0x6b) {
1:op_io();
2:op_io();
3:rd.l = op_readstackn();
4:rd.h = op_readstackn();
5:last_cycle();
rd.b = op_readstackn();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
if(regs.e) regs.s.h = 0x01;
}

View File

@ -1,279 +0,0 @@
#ifdef SCPU_CPP
//bcc
case 0x90: {
if(!!regs.p.c) last_cycle();
rd.l = op_readpc();
if(!regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bcs
case 0xb0: {
if(!regs.p.c) last_cycle();
rd.l = op_readpc();
if(regs.p.c) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bne
case 0xd0: {
if(!!regs.p.z) last_cycle();
rd.l = op_readpc();
if(!regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//beq
case 0xf0: {
if(!regs.p.z) last_cycle();
rd.l = op_readpc();
if(regs.p.z) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bpl
case 0x10: {
if(!!regs.p.n) last_cycle();
rd.l = op_readpc();
if(!regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bmi
case 0x30: {
if(!regs.p.n) last_cycle();
rd.l = op_readpc();
if(regs.p.n) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bvc
case 0x50: {
if(!!regs.p.v) last_cycle();
rd.l = op_readpc();
if(!regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bvs
case 0x70: {
if(!regs.p.v) last_cycle();
rd.l = op_readpc();
if(regs.p.v) {
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
} else {
break;
}
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//bra
case 0x80: {
rd.l = op_readpc();
aa.w = regs.pc.d + (int8)rd.l;
regs.pc.w = aa.w;
op_io_cond6(aa.w);
last_cycle();
op_io();
} break;
//brl
case 0x82: {
rd.l = op_readpc();
rd.h = op_readpc();
last_cycle();
op_io();
regs.pc.w = regs.pc.d + (int16)rd.w;
} break;
//jmp_addr
case 0x4c: {
rd.l = op_readpc();
last_cycle();
rd.h = op_readpc();
regs.pc.w = rd.w;
} break;
//jmp_long
case 0x5c: {
rd.l = op_readpc();
rd.h = op_readpc();
last_cycle();
rd.b = op_readpc();
regs.pc.d = rd.d & 0xffffff;
} break;
//jmp_iaddr
case 0x6c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w);
last_cycle();
rd.h = op_readaddr(aa.w + 1);
regs.pc.w = rd.w;
} break;
//jmp_iaddrx
case 0x7c: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w);
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
} break;
//jmp_iladdr
case 0xdc: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readaddr(aa.w);
rd.h = op_readaddr(aa.w + 1);
last_cycle();
rd.b = op_readaddr(aa.w + 2);
regs.pc.d = rd.d & 0xffffff;
} break;
//jsr_addr
case 0x20: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
regs.pc.w--;
op_writestack(regs.pc.h);
last_cycle();
op_writestack(regs.pc.l);
regs.pc.w = aa.w;
} break;
//jsr_long
case 0x22: {
aa.l = op_readpc();
aa.h = op_readpc();
op_writestackn(regs.pc.b);
op_io();
aa.b = op_readpc();
regs.pc.w--;
op_writestackn(regs.pc.h);
last_cycle();
op_writestackn(regs.pc.l);
regs.pc.d = aa.d & 0xffffff;
if(regs.e) regs.s.h = 0x01;
} break;
//jsr_iaddrx
case 0xfc: {
aa.l = op_readpc();
op_writestackn(regs.pc.h);
op_writestackn(regs.pc.l);
aa.h = op_readpc();
op_io();
rd.l = op_readpbr(aa.w + regs.x.w);
last_cycle();
rd.h = op_readpbr(aa.w + regs.x.w + 1);
regs.pc.w = rd.w;
if(regs.e) regs.s.h = 0x01;
} break;
//rti
case 0x40: {
op_io();
op_io();
regs.p = op_readstack();
if(regs.e) regs.p |= 0x30;
if(regs.p.x) {
regs.x.h = 0x00;
regs.y.h = 0x00;
}
rd.l = op_readstack();
if(regs.e) last_cycle();
rd.h = op_readstack();
if(regs.e) {
regs.pc.w = rd.w;
break;
}
last_cycle();
rd.b = op_readstack();
regs.pc.d = rd.d & 0xffffff;
} break;
//rts
case 0x60: {
op_io();
op_io();
rd.l = op_readstack();
rd.h = op_readstack();
last_cycle();
op_io();
regs.pc.w = rd.w;
regs.pc.w++;
} break;
//rtl
case 0x6b: {
op_io();
op_io();
rd.l = op_readstackn();
rd.h = op_readstackn();
last_cycle();
rd.b = op_readstackn();
regs.pc.d = rd.d & 0xffffff;
regs.pc.w++;
if(regs.e) regs.s.h = 0x01;
} break;
#endif

View File

@ -1,317 +0,0 @@
adc_const(0x69, adc, regs.p.m),
and_const(0x29, and, regs.p.m),
cmp_const(0xc9, cmp, regs.p.m),
cpx_const(0xe0, cpx, regs.p.x),
cpy_const(0xc0, cpy, regs.p.x),
eor_const(0x49, eor, regs.p.m),
lda_const(0xa9, lda, regs.p.m),
ldx_const(0xa2, ldx, regs.p.x),
ldy_const(0xa0, ldy, regs.p.x),
ora_const(0x09, ora, regs.p.m),
sbc_const(0xe9, sbc, regs.p.m) {
1:if($2) last_cycle();
rd.l = op_readpc();
if($2) { op_$1_b(); end; }
2:last_cycle();
rd.h = op_readpc();
op_$1_w();
}
adc_addr(0x6d, adc, regs.p.m),
and_addr(0x2d, and, regs.p.m),
bit_addr(0x2c, bit, regs.p.m),
cmp_addr(0xcd, cmp, regs.p.m),
cpx_addr(0xec, cpx, regs.p.x),
cpy_addr(0xcc, cpy, regs.p.x),
eor_addr(0x4d, eor, regs.p.m),
lda_addr(0xad, lda, regs.p.m),
ldx_addr(0xae, ldx, regs.p.x),
ldy_addr(0xac, ldy, regs.p.x),
ora_addr(0x0d, ora, regs.p.m),
sbc_addr(0xed, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($2) last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_addrx(0x7d, adc, regs.p.m),
and_addrx(0x3d, and, regs.p.m),
bit_addrx(0x3c, bit, regs.p.m),
cmp_addrx(0xdd, cmp, regs.p.m),
eor_addrx(0x5d, eor, regs.p.m),
lda_addrx(0xbd, lda, regs.p.m),
ldy_addrx(0xbc, ldy, regs.p.x),
ora_addrx(0x1d, ora, regs.p.m),
sbc_addrx(0xfd, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.x.w);
4:if($2) last_cycle();
rd.l = op_readdbr(aa.w + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_$1_w();
}
adc_addry(0x79, adc, regs.p.m),
and_addry(0x39, and, regs.p.m),
cmp_addry(0xd9, cmp, regs.p.m),
eor_addry(0x59, eor, regs.p.m),
lda_addry(0xb9, lda, regs.p.m),
ldx_addry(0xbe, ldx, regs.p.x),
ora_addry(0x19, ora, regs.p.m),
sbc_addry(0xf9, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io_cond4(aa.w, aa.w + regs.y.w);
4:if($2) last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_long(0x6f, adc, regs.p.m),
and_long(0x2f, and, regs.p.m),
cmp_long(0xcf, cmp, regs.p.m),
eor_long(0x4f, eor, regs.p.m),
lda_long(0xaf, lda, regs.p.m),
ora_long(0x0f, ora, regs.p.m),
sbc_long(0xef, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2) last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_longx(0x7f, adc, regs.p.m),
and_longx(0x3f, and, regs.p.m),
cmp_longx(0xdf, cmp, regs.p.m),
eor_longx(0x5f, eor, regs.p.m),
lda_longx(0xbf, lda, regs.p.m),
ora_longx(0x1f, ora, regs.p.m),
sbc_longx(0xff, sbc, regs.p.m) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if($2) last_cycle();
rd.l = op_readlong(aa.d + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readlong(aa.d + regs.x.w + 1);
op_$1_w();
}
adc_dp(0x65, adc, regs.p.m),
and_dp(0x25, and, regs.p.m),
bit_dp(0x24, bit, regs.p.m),
cmp_dp(0xc5, cmp, regs.p.m),
cpx_dp(0xe4, cpx, regs.p.x),
cpy_dp(0xc4, cpy, regs.p.x),
eor_dp(0x45, eor, regs.p.m),
lda_dp(0xa5, lda, regs.p.m),
ldx_dp(0xa6, ldx, regs.p.x),
ldy_dp(0xa4, ldy, regs.p.x),
ora_dp(0x05, ora, regs.p.m),
sbc_dp(0xe5, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:if($2) last_cycle();
rd.l = op_readdp(dp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readdp(dp + 1);
op_$1_w();
}
adc_dpx(0x75, adc, regs.p.m),
and_dpx(0x35, and, regs.p.m),
bit_dpx(0x34, bit, regs.p.m),
cmp_dpx(0xd5, cmp, regs.p.m),
eor_dpx(0x55, eor, regs.p.m),
lda_dpx(0xb5, lda, regs.p.m),
ldy_dpx(0xb4, ldy, regs.p.x),
ora_dpx(0x15, ora, regs.p.m),
sbc_dpx(0xf5, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($2) last_cycle();
rd.l = op_readdp(dp + regs.x.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.x.w + 1);
op_$1_w();
}
ldx_dpy(0xb6, ldx, regs.p.x) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($2) last_cycle();
rd.l = op_readdp(dp + regs.y.w);
if($2) { op_$1_b(); end; }
5:last_cycle();
rd.h = op_readdp(dp + regs.y.w + 1);
op_$1_w();
}
adc_idp(0x72, adc, regs.p.m),
and_idp(0x32, and, regs.p.m),
cmp_idp(0xd2, cmp, regs.p.m),
eor_idp(0x52, eor, regs.p.m),
lda_idp(0xb2, lda, regs.p.m),
ora_idp(0x12, ora, regs.p.m),
sbc_idp(0xf2, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if($2) last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
6:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpx(0x61, adc, regs.p.m),
and_idpx(0x21, and, regs.p.m),
cmp_idpx(0xc1, cmp, regs.p.m),
eor_idpx(0x41, eor, regs.p.m),
lda_idpx(0xa1, lda, regs.p.m),
ora_idpx(0x01, ora, regs.p.m),
sbc_idpx(0xe1, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if($2) last_cycle();
rd.l = op_readdbr(aa.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + 1);
op_$1_w();
}
adc_idpy(0x71, adc, regs.p.m),
and_idpy(0x31, and, regs.p.m),
cmp_idpy(0xd1, cmp, regs.p.m),
eor_idpy(0x51, eor, regs.p.m),
lda_idpy(0xb1, lda, regs.p.m),
ora_idpy(0x11, ora, regs.p.m),
sbc_idpy(0xf1, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io_cond4(aa.w, aa.w + regs.y.w);
6:if($2) last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
adc_ildp(0x67, adc, regs.p.m),
and_ildp(0x27, and, regs.p.m),
cmp_ildp(0xc7, cmp, regs.p.m),
eor_ildp(0x47, eor, regs.p.m),
lda_ildp(0xa7, lda, regs.p.m),
ora_ildp(0x07, ora, regs.p.m),
sbc_ildp(0xe7, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2) last_cycle();
rd.l = op_readlong(aa.d);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + 1);
op_$1_w();
}
adc_ildpy(0x77, adc, regs.p.m),
and_ildpy(0x37, and, regs.p.m),
cmp_ildpy(0xd7, cmp, regs.p.m),
eor_ildpy(0x57, eor, regs.p.m),
lda_ildpy(0xb7, lda, regs.p.m),
ora_ildpy(0x17, ora, regs.p.m),
sbc_ildpy(0xf7, sbc, regs.p.m) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if($2) last_cycle();
rd.l = op_readlong(aa.d + regs.y.w);
if($2) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readlong(aa.d + regs.y.w + 1);
op_$1_w();
}
adc_sr(0x63, adc, regs.p.m),
and_sr(0x23, and, regs.p.m),
cmp_sr(0xc3, cmp, regs.p.m),
eor_sr(0x43, eor, regs.p.m),
lda_sr(0xa3, lda, regs.p.m),
ora_sr(0x03, ora, regs.p.m),
sbc_sr(0xe3, sbc, regs.p.m) {
1:sp = op_readpc();
2:op_io();
3:if($2) last_cycle();
rd.l = op_readsp(sp);
if($2) { op_$1_b(); end; }
4:last_cycle();
rd.h = op_readsp(sp + 1);
op_$1_w();
}
adc_isry(0x73, adc),
and_isry(0x33, and),
cmp_isry(0xd3, cmp),
eor_isry(0x53, eor),
lda_isry(0xb3, lda),
ora_isry(0x13, ora),
sbc_isry(0xf3, sbc) {
1:sp = op_readpc();
2:op_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:op_io();
6:if(regs.p.m) last_cycle();
rd.l = op_readdbr(aa.w + regs.y.w);
if(regs.p.m) { op_$1_b(); end; }
7:last_cycle();
rd.h = op_readdbr(aa.w + regs.y.w + 1);
op_$1_w();
}
bit_const(0x89) {
1:if(regs.p.m) last_cycle();
rd.l = op_readpc();
if(regs.p.m) {
regs.p.z = ((rd.l & regs.a.l) == 0);
end;
}
2:last_cycle();
rd.h = op_readpc();
regs.p.z = ((rd.w & regs.a.w) == 0);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,181 +0,0 @@
inc(0x1a, regs.p.m, a),
inx(0xe8, regs.p.x, x),
iny(0xc8, regs.p.x, y) {
1:last_cycle();
op_io_irq();
if($1) {
regs.$2.l++;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w++;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
dec(0x3a, regs.p.m, a),
dex(0xca, regs.p.x, x),
dey(0x88, regs.p.x, y) {
1:last_cycle();
op_io_irq();
if($1) {
regs.$2.l--;
regs.p.n = !!(regs.$2.l & 0x80);
regs.p.z = (regs.$2.l == 0);
} else {
regs.$2.w--;
regs.p.n = !!(regs.$2.w & 0x8000);
regs.p.z = (regs.$2.w == 0);
}
}
asl(0x0a) {
1:last_cycle();
op_io_irq();
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
lsr(0x4a) {
1:last_cycle();
op_io_irq();
if(regs.p.m) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
rol(0x2a) {
1:last_cycle();
op_io_irq();
uint16 c = regs.p.c;
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
ror(0x6a) {
1:last_cycle();
op_io_irq();
uint16 c;
if(regs.p.m) {
c = regs.p.c ? 0x80 : 0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = regs.p.c ? 0x8000 : 0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
}
inc_addr(0xee, inc),
dec_addr(0xce, dec),
asl_addr(0x0e, asl),
lsr_addr(0x4e, lsr),
rol_addr(0x2e, rol),
ror_addr(0x6e, ror),
trb_addr(0x1c, trb),
tsb_addr(0x0c, tsb) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:rd.l = op_readdbr(aa.w);
4:if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
5:op_io();
if(regs.p.m) { op_$1_b(); }
else { op_$1_w();
6:op_writedbr(aa.w + 1, rd.h); }
7:last_cycle();
op_writedbr(aa.w, rd.l);
}
inc_addrx(0xfe, inc),
dec_addrx(0xde, dec),
asl_addrx(0x1e, asl),
lsr_addrx(0x5e, lsr),
rol_addrx(0x3e, rol),
ror_addrx(0x7e, ror) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:rd.l = op_readdbr(aa.w + regs.x.w);
5:if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
6:op_io();
if(regs.p.m) { op_$1_b(); }
else { op_$1_w();
7:op_writedbr(aa.w + regs.x.w + 1, rd.h); }
8:last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
}
inc_dp(0xe6, inc),
dec_dp(0xc6, dec),
asl_dp(0x06, asl),
lsr_dp(0x46, lsr),
rol_dp(0x26, rol),
ror_dp(0x66, ror),
trb_dp(0x14, trb),
tsb_dp(0x04, tsb) {
1:dp = op_readpc();
2:op_io_cond2();
3:rd.l = op_readdp(dp);
4:if(!regs.p.m) rd.h = op_readdp(dp + 1);
5:op_io();
if(regs.p.m) { op_$1_b(); }
else { op_$1_w();
6:op_writedp(dp + 1, rd.h); }
7:last_cycle();
op_writedp(dp, rd.l);
}
inc_dpx(0xf6, inc),
dec_dpx(0xd6, dec),
asl_dpx(0x16, asl),
lsr_dpx(0x56, lsr),
rol_dpx(0x36, rol),
ror_dpx(0x76, ror) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:rd.l = op_readdp(dp + regs.x.w);
5:if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
6:op_io();
if(regs.p.m) { op_$1_b(); }
else { op_$1_w();
7:op_writedp(dp + regs.x.w + 1, rd.h); }
8:last_cycle();
op_writedp(dp + regs.x.w, rd.l);
}

View File

@ -1,573 +0,0 @@
#ifdef SCPU_CPP
//inc
case 0x1a: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.a.l++;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w++;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inx
case 0xe8: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l++;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w++;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//iny
case 0xc8: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.y.l++;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w++;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//dec
case 0x3a: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.a.l--;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.a.w--;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//dex
case 0xca: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.x.l--;
regs.p.n = !!(regs.x.l & 0x80);
regs.p.z = (regs.x.l == 0);
} else {
regs.x.w--;
regs.p.n = !!(regs.x.w & 0x8000);
regs.p.z = (regs.x.w == 0);
}
} break;
//dey
case 0x88: {
last_cycle();
op_io_irq();
if(regs.p.x) {
regs.y.l--;
regs.p.n = !!(regs.y.l & 0x80);
regs.p.z = (regs.y.l == 0);
} else {
regs.y.w--;
regs.p.n = !!(regs.y.w & 0x8000);
regs.p.z = (regs.y.w == 0);
}
} break;
//asl
case 0x0a: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//lsr
case 0x4a: {
last_cycle();
op_io_irq();
if(regs.p.m) {
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//rol
case 0x2a: {
last_cycle();
op_io_irq();
uint16 c = regs.p.c;
if(regs.p.m) {
regs.p.c = !!(regs.a.l & 0x80);
regs.a.l <<= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
regs.p.c = !!(regs.a.w & 0x8000);
regs.a.w <<= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//ror
case 0x6a: {
last_cycle();
op_io_irq();
uint16 c;
if(regs.p.m) {
c = regs.p.c ? 0x80 : 0;
regs.p.c = regs.a.l & 1;
regs.a.l >>= 1;
regs.a.l |= c;
regs.p.n = !!(regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
} else {
c = regs.p.c ? 0x8000 : 0;
regs.p.c = regs.a.w & 1;
regs.a.w >>= 1;
regs.a.w |= c;
regs.p.n = !!(regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
} break;
//inc_addr
case 0xee: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//dec_addr
case 0xce: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//asl_addr
case 0x0e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//lsr_addr
case 0x4e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//rol_addr
case 0x2e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//ror_addr
case 0x6e: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//trb_addr
case 0x1c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_trb_b(); }
else { op_trb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//tsb_addr
case 0x0c: {
aa.l = op_readpc();
aa.h = op_readpc();
rd.l = op_readdbr(aa.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + 1);
op_io();
if(regs.p.m) { op_tsb_b(); }
else { op_tsb_w();
op_writedbr(aa.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w, rd.l);
} break;
//inc_addrx
case 0xfe: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_inc_b(); }
else { op_inc_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//dec_addrx
case 0xde: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_dec_b(); }
else { op_dec_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//asl_addrx
case 0x1e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_asl_b(); }
else { op_asl_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//lsr_addrx
case 0x5e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//rol_addrx
case 0x3e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_rol_b(); }
else { op_rol_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//ror_addrx
case 0x7e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
rd.l = op_readdbr(aa.w + regs.x.w);
if(!regs.p.m) rd.h = op_readdbr(aa.w + regs.x.w + 1);
op_io();
if(regs.p.m) { op_ror_b(); }
else { op_ror_w();
op_writedbr(aa.w + regs.x.w + 1, rd.h); }
last_cycle();
op_writedbr(aa.w + regs.x.w, rd.l);
} break;
//inc_dp
case 0xe6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//dec_dp
case 0xc6: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//asl_dp
case 0x06: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//lsr_dp
case 0x46: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//rol_dp
case 0x26: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//ror_dp
case 0x66: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//trb_dp
case 0x14: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_trb_b(); }
else { op_trb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//tsb_dp
case 0x04: {
dp = op_readpc();
op_io_cond2();
rd.l = op_readdp(dp);
if(!regs.p.m) rd.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) { op_tsb_b(); }
else { op_tsb_w();
op_writedp(dp + 1, rd.h); }
last_cycle();
op_writedp(dp, rd.l);
} break;
//inc_dpx
case 0xf6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_inc_b(); }
else { op_inc_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//dec_dpx
case 0xd6: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_dec_b(); }
else { op_dec_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//asl_dpx
case 0x16: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_asl_b(); }
else { op_asl_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//lsr_dpx
case 0x56: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_lsr_b(); }
else { op_lsr_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//rol_dpx
case 0x36: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_rol_b(); }
else { op_rol_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
//ror_dpx
case 0x76: {
dp = op_readpc();
op_io_cond2();
op_io();
rd.l = op_readdp(dp + regs.x.w);
if(!regs.p.m) rd.h = op_readdp(dp + regs.x.w + 1);
op_io();
if(regs.p.m) { op_ror_b(); }
else { op_ror_w();
op_writedp(dp + regs.x.w + 1, rd.h); }
last_cycle();
op_writedp(dp + regs.x.w, rd.l);
} break;
#endif

View File

@ -1,181 +0,0 @@
sta_addr(0x8d, regs.p.m, regs.a.w),
stx_addr(0x8e, regs.p.x, regs.x.w),
sty_addr(0x8c, regs.p.x, regs.y.w),
stz_addr(0x9c, regs.p.m, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:if($1) last_cycle();
op_writedbr(aa.w, $2);
if($1) end;
4:last_cycle();
op_writedbr(aa.w + 1, $2 >> 8);
}
sta_addrx(0x9d, regs.p.m, regs.a.w),
stz_addrx(0x9e, regs.p.m, 0x0000) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:if($1) last_cycle();
op_writedbr(aa.w + regs.x.w, $2);
if($1) end;
5:last_cycle();
op_writedbr(aa.w + regs.x.w + 1, $2 >> 8);
}
sta_addry(0x99) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:op_io();
4:if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) end;
5:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_long(0x8f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m) last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m) end;
5:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_longx(0x9f) {
1:aa.l = op_readpc();
2:aa.h = op_readpc();
3:aa.b = op_readpc();
4:if(regs.p.m) last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m) end;
5:last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
}
sta_dp(0x85, regs.p.m, regs.a.w),
stx_dp(0x86, regs.p.x, regs.x.w),
sty_dp(0x84, regs.p.x, regs.y.w),
stz_dp(0x64, regs.p.m, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:if($1) last_cycle();
op_writedp(dp, $2);
if($1) end;
4:last_cycle();
op_writedp(dp + 1, $2 >> 8);
}
sta_dpx(0x95, regs.p.m, regs.a.w),
sty_dpx(0x94, regs.p.x, regs.y.w),
stz_dpx(0x74, regs.p.m, 0x0000) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if($1) last_cycle();
op_writedp(dp + regs.x.w, $2);
if($1) end;
5:last_cycle();
op_writedp(dp + regs.x.w + 1, $2 >> 8);
}
stx_dpy(0x96) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:if(regs.p.x) last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x) end;
5:last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
}
sta_idp(0x92) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:if(regs.p.m) last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m) end;
6:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_ildp(0x87) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m) last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m) end;
7:last_cycle();
op_writelong(aa.d + 1, regs.a.h);
}
sta_idpx(0x81) {
1:dp = op_readpc();
2:op_io_cond2();
3:op_io();
4:aa.l = op_readdp(dp + regs.x.w);
5:aa.h = op_readdp(dp + regs.x.w + 1);
6:if(regs.p.m) last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m) end;
7:last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
}
sta_idpy(0x91) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:op_io();
6:if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}
sta_ildpy(0x97) {
1:dp = op_readpc();
2:op_io_cond2();
3:aa.l = op_readdp(dp);
4:aa.h = op_readdp(dp + 1);
5:aa.b = op_readdp(dp + 2);
6:if(regs.p.m) last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m) end;
7:last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
}
sta_sr(0x83) {
1:sp = op_readpc();
2:op_io();
3:if(regs.p.m) last_cycle();
op_writesp(sp, regs.a.l);
if(regs.p.m) end;
4:last_cycle();
op_writesp(sp + 1, regs.a.h);
}
sta_isry(0x93) {
1:sp = op_readpc();
2:op_io();
3:aa.l = op_readsp(sp);
4:aa.h = op_readsp(sp + 1);
5:op_io();
6:if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) end;
7:last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
}

View File

@ -1,293 +0,0 @@
#ifdef SCPU_CPP
//sta_addr
case 0x8d: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.p.m) last_cycle();
op_writedbr(aa.w, regs.a.w);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.w >> 8);
} break;
//stx_addr
case 0x8e: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.p.x) last_cycle();
op_writedbr(aa.w, regs.x.w);
if(regs.p.x) break;
last_cycle();
op_writedbr(aa.w + 1, regs.x.w >> 8);
} break;
//sty_addr
case 0x8c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.p.x) last_cycle();
op_writedbr(aa.w, regs.y.w);
if(regs.p.x) break;
last_cycle();
op_writedbr(aa.w + 1, regs.y.w >> 8);
} break;
//stz_addr
case 0x9c: {
aa.l = op_readpc();
aa.h = op_readpc();
if(regs.p.m) last_cycle();
op_writedbr(aa.w, 0x0000);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + 1, 0x0000 >> 8);
} break;
//sta_addrx
case 0x9d: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.x.w, regs.a.w);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, regs.a.w >> 8);
} break;
//stz_addrx
case 0x9e: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.x.w, 0x0000);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + regs.x.w + 1, 0x0000 >> 8);
} break;
//sta_addry
case 0x99: {
aa.l = op_readpc();
aa.h = op_readpc();
op_io();
if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_long
case 0x8f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.p.m) last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_longx
case 0x9f: {
aa.l = op_readpc();
aa.h = op_readpc();
aa.b = op_readpc();
if(regs.p.m) last_cycle();
op_writelong(aa.d + regs.x.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writelong(aa.d + regs.x.w + 1, regs.a.h);
} break;
//sta_dp
case 0x85: {
dp = op_readpc();
op_io_cond2();
if(regs.p.m) last_cycle();
op_writedp(dp, regs.a.w);
if(regs.p.m) break;
last_cycle();
op_writedp(dp + 1, regs.a.w >> 8);
} break;
//stx_dp
case 0x86: {
dp = op_readpc();
op_io_cond2();
if(regs.p.x) last_cycle();
op_writedp(dp, regs.x.w);
if(regs.p.x) break;
last_cycle();
op_writedp(dp + 1, regs.x.w >> 8);
} break;
//sty_dp
case 0x84: {
dp = op_readpc();
op_io_cond2();
if(regs.p.x) last_cycle();
op_writedp(dp, regs.y.w);
if(regs.p.x) break;
last_cycle();
op_writedp(dp + 1, regs.y.w >> 8);
} break;
//stz_dp
case 0x64: {
dp = op_readpc();
op_io_cond2();
if(regs.p.m) last_cycle();
op_writedp(dp, 0x0000);
if(regs.p.m) break;
last_cycle();
op_writedp(dp + 1, 0x0000 >> 8);
} break;
//sta_dpx
case 0x95: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.p.m) last_cycle();
op_writedp(dp + regs.x.w, regs.a.w);
if(regs.p.m) break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.a.w >> 8);
} break;
//sty_dpx
case 0x94: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.p.x) last_cycle();
op_writedp(dp + regs.x.w, regs.y.w);
if(regs.p.x) break;
last_cycle();
op_writedp(dp + regs.x.w + 1, regs.y.w >> 8);
} break;
//stz_dpx
case 0x74: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.p.m) last_cycle();
op_writedp(dp + regs.x.w, 0x0000);
if(regs.p.m) break;
last_cycle();
op_writedp(dp + regs.x.w + 1, 0x0000 >> 8);
} break;
//stx_dpy
case 0x96: {
dp = op_readpc();
op_io_cond2();
op_io();
if(regs.p.x) last_cycle();
op_writedp(dp + regs.y.w, regs.x.l);
if(regs.p.x) break;
last_cycle();
op_writedp(dp + regs.y.w + 1, regs.x.h);
} break;
//sta_idp
case 0x92: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
if(regs.p.m) last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_ildp
case 0x87: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.p.m) last_cycle();
op_writelong(aa.d, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writelong(aa.d + 1, regs.a.h);
} break;
//sta_idpx
case 0x81: {
dp = op_readpc();
op_io_cond2();
op_io();
aa.l = op_readdp(dp + regs.x.w);
aa.h = op_readdp(dp + regs.x.w + 1);
if(regs.p.m) last_cycle();
op_writedbr(aa.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + 1, regs.a.h);
} break;
//sta_idpy
case 0x91: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
op_io();
if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
//sta_ildpy
case 0x97: {
dp = op_readpc();
op_io_cond2();
aa.l = op_readdp(dp);
aa.h = op_readdp(dp + 1);
aa.b = op_readdp(dp + 2);
if(regs.p.m) last_cycle();
op_writelong(aa.d + regs.y.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writelong(aa.d + regs.y.w + 1, regs.a.h);
} break;
//sta_sr
case 0x83: {
sp = op_readpc();
op_io();
if(regs.p.m) last_cycle();
op_writesp(sp, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writesp(sp + 1, regs.a.h);
} break;
//sta_isry
case 0x93: {
sp = op_readpc();
op_io();
aa.l = op_readsp(sp);
aa.h = op_readsp(sp + 1);
op_io();
if(regs.p.m) last_cycle();
op_writedbr(aa.w + regs.y.w, regs.a.l);
if(regs.p.m) break;
last_cycle();
op_writedbr(aa.w + regs.y.w + 1, regs.a.h);
} break;
#endif

View File

@ -1,12 +0,0 @@
#define CLASS_NAME "sCPU"
#include <tool/opgen_switch.cpp>
int main() {
generate("op_read.cpp", "op_read.b");
generate("op_write.cpp", "op_write.b");
generate("op_rmw.cpp", "op_rmw.b");
generate("op_pc.cpp", "op_pc.b");
generate("op_misc.cpp", "op_misc.b");
return 0;
}

View File

@ -3,6 +3,8 @@
void sCPU::dma_add_clocks(unsigned clocks) { void sCPU::dma_add_clocks(unsigned clocks) {
status.dma_clocks += clocks; status.dma_clocks += clocks;
add_clocks(clocks); add_clocks(clocks);
scheduler.sync_cpucop();
scheduler.sync_cpuppu();
} }
bool sCPU::dma_addr_valid(uint32 abus) { bool sCPU::dma_addr_valid(uint32 abus) {

View File

@ -1,13 +1,5 @@
#ifdef SCPU_CPP #ifdef SCPU_CPP
/*****
* These 3 functions control bus timing for the CPU.
* cpu_io is an I/O cycle, and always 6 clock cycles long.
* mem_read / mem_write indicate memory access bus cycles.
* they are either 6, 8, or 12 bus cycles long, depending
* both on location and the $420d.d0 FastROM enable bit.
*****/
void sCPU::op_io() { void sCPU::op_io() {
status.clock_count = 6; status.clock_count = 6;
precycle_edge(); precycle_edge();
@ -16,9 +8,10 @@ void sCPU::op_io() {
} }
uint8 sCPU::op_read(uint32 addr) { uint8 sCPU::op_read(uint32 addr) {
status.clock_count = bus.speed(addr); status.clock_count = speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count - 4); add_clocks(status.clock_count - 4);
scheduler.sync_cpucop();
regs.mdr = bus.read(addr); regs.mdr = bus.read(addr);
add_clocks(4); add_clocks(4);
cycle_edge(); cycle_edge();
@ -26,100 +19,23 @@ uint8 sCPU::op_read(uint32 addr) {
} }
void sCPU::op_write(uint32 addr, uint8 data) { void sCPU::op_write(uint32 addr, uint8 data) {
status.clock_count = bus.speed(addr); status.clock_count = speed(addr);
precycle_edge(); precycle_edge();
add_clocks(status.clock_count); add_clocks(status.clock_count);
regs.mdr = data; scheduler.sync_cpucop();
bus.write(addr, regs.mdr); bus.write(addr, regs.mdr = data);
cycle_edge(); cycle_edge();
} }
// unsigned sCPU::speed(unsigned addr) const {
if(addr & 0x408000) {
alwaysinline uint8 sCPU::op_readpc() { if(addr & 0x800000) return status.rom_speed;
return op_read((regs.pc.b << 16) + regs.pc.w++); return 8;
}
if((addr + 0x6000) & 0x4000) return 8;
if((addr - 0x4000) & 0x7e00) return 6;
return 12;
} }
alwaysinline uint8 sCPU::op_readstack() { #endif
if(regs.e) {
regs.s.l++;
} else {
regs.s.w++;
}
return op_read(regs.s.w);
}
alwaysinline uint8 sCPU::op_readstackn() {
return op_read(++regs.s.w);
}
alwaysinline uint8 sCPU::op_readaddr(uint32 addr) {
return op_read(addr & 0xffff);
}
alwaysinline uint8 sCPU::op_readlong(uint32 addr) {
return op_read(addr & 0xffffff);
}
alwaysinline uint8 sCPU::op_readdbr(uint32 addr) {
return op_read(((regs.db << 16) + addr) & 0xffffff);
}
alwaysinline uint8 sCPU::op_readpbr(uint32 addr) {
return op_read((regs.pc.b << 16) + (addr & 0xffff));
}
alwaysinline uint8 sCPU::op_readdp(uint32 addr) {
if(regs.e && regs.d.l == 0x00) {
return op_read((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff));
} else {
return op_read((regs.d + (addr & 0xffff)) & 0xffff);
}
}
alwaysinline uint8 sCPU::op_readsp(uint32 addr) {
return op_read((regs.s + (addr & 0xffff)) & 0xffff);
}
alwaysinline void sCPU::op_writestack(uint8 data) {
op_write(regs.s.w, data);
if(regs.e) {
regs.s.l--;
} else {
regs.s.w--;
}
}
alwaysinline void sCPU::op_writestackn(uint8 data) {
op_write(regs.s.w--, data);
}
alwaysinline void sCPU::op_writeaddr(uint32 addr, uint8 data) {
op_write(addr & 0xffff, data);
}
alwaysinline void sCPU::op_writelong(uint32 addr, uint8 data) {
op_write(addr & 0xffffff, data);
}
alwaysinline void sCPU::op_writedbr(uint32 addr, uint8 data) {
op_write(((regs.db << 16) + addr) & 0xffffff, data);
}
alwaysinline void sCPU::op_writepbr(uint32 addr, uint8 data) {
op_write((regs.pc.b << 16) + (addr & 0xffff), data);
}
alwaysinline void sCPU::op_writedp(uint32 addr, uint8 data) {
if(regs.e && regs.d.l == 0x00) {
op_write((regs.d & 0xff00) + ((regs.d + (addr & 0xffff)) & 0xff), data);
} else {
op_write((regs.d + (addr & 0xffff)) & 0xffff, data);
}
}
alwaysinline void sCPU::op_writesp(uint32 addr, uint8 data) {
op_write((regs.s + (addr & 0xffff)) & 0xffff, data);
}
#endif //ifdef SCPU_CPP

View File

@ -1,35 +1,16 @@
/***** //============================
* CPU<>APU communication ports //CPU<>APU communication ports
*****/ //============================
uint8 apu_port[4]; uint8 apu_port[4];
uint8 port_read(uint8 port) { return apu_port[port & 3]; } uint8 port_read(uint8 port) { return apu_port[port & 3]; }
void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; } void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
/***** //======================
* core CPU bus functions //core CPU bus functions
*****/ //======================
void op_io(); void op_io();
uint8 op_read(uint32 addr); uint8 op_read(uint32 addr);
void op_write(uint32 addr, uint8 data); void op_write(uint32 addr, uint8 data);
alwaysinline unsigned speed(unsigned addr) const;
/*****
* helper memory addressing functions used by CPU core
*****/
uint8 op_readpc ();
uint8 op_readstack ();
uint8 op_readstackn();
uint8 op_readaddr (uint32 addr);
uint8 op_readlong (uint32 addr);
uint8 op_readdbr (uint32 addr);
uint8 op_readpbr (uint32 addr);
uint8 op_readdp (uint32 addr);
uint8 op_readsp (uint32 addr);
void op_writestack (uint8 data);
void op_writestackn(uint8 data);
void op_writeaddr (uint32 addr, uint8 data);
void op_writelong (uint32 addr, uint8 data);
void op_writedbr (uint32 addr, uint8 data);
void op_writepbr (uint32 addr, uint8 data);
void op_writedp (uint32 addr, uint8 data);
void op_writesp (uint32 addr, uint8 data);

View File

@ -42,7 +42,7 @@ void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1); status.joypad_strobe_latch = !!(data & 1);
if(status.joypad_strobe_latch == 1) { if(status.joypad_strobe_latch == 1) {
snes.input.poll(); input.poll();
} }
} }
@ -54,7 +54,7 @@ void sCPU::mmio_w4016(uint8 data) {
//realtime or buffered status of joypadN.b //realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() { uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc; uint8 r = regs.mdr & 0xfc;
r |= snes.input.port_read(0) & 3; r |= input.port_read(0) & 3;
return r; return r;
} }
@ -64,7 +64,7 @@ uint8 sCPU::mmio_r4016() {
//1-0 = Joypad serial data //1-0 = Joypad serial data
uint8 sCPU::mmio_r4017() { uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c; uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= snes.input.port_read(1) & 3; r |= input.port_read(1) & 3;
return r; return r;
} }
@ -93,7 +93,7 @@ void sCPU::mmio_w4203(uint8 data) {
status.r4216 = status.mul_a * status.mul_b; status.r4216 = status.mul_a * status.mul_b;
status.alu_lock = true; status.alu_lock = true;
event.enqueue(snes.config.cpu.alu_mul_delay, EventAluLockRelease); event.enqueue(config.cpu.alu_mul_delay, EventAluLockRelease);
} }
//WRDIVL //WRDIVL
@ -113,7 +113,7 @@ void sCPU::mmio_w4206(uint8 data) {
status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a; status.r4216 = (status.div_b) ? status.div_a % status.div_b : status.div_a;
status.alu_lock = true; status.alu_lock = true;
event.enqueue(snes.config.cpu.alu_div_delay, EventAluLockRelease); event.enqueue(config.cpu.alu_div_delay, EventAluLockRelease);
} }
//HTIMEL //HTIMEL
@ -157,7 +157,7 @@ void sCPU::mmio_w420c(uint8 data) {
//MEMSEL //MEMSEL
void sCPU::mmio_w420d(uint8 data) { void sCPU::mmio_w420d(uint8 data) {
bus.set_speed(data & 1); status.rom_speed = (data & 1 ? 6 : 8);
} }
//RDNMI //RDNMI
@ -402,6 +402,9 @@ void sCPU::mmio_reset() {
status.hirq_pos = 0x01ff; status.hirq_pos = 0x01ff;
status.virq_pos = 0x01ff; status.virq_pos = 0x01ff;
//$420d
status.rom_speed = 8;
//$4214-$4217 //$4214-$4217
status.r4214 = 0x0000; status.r4214 = 0x0000;
status.r4216 = 0x0000; status.r4216 = 0x0000;

View File

@ -1,15 +1,54 @@
#include <../base.hpp> #include <../base.hpp>
#define SCPU_CPP
#include <nall/priorityqueue.hpp> #include <nall/priorityqueue.hpp>
#define SCPU_CPP
namespace SNES {
priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu)); priority_queue<unsigned> event(512, bind(&sCPU::queue_event, &cpu));
#include "core/core.cpp"
#include "dma/dma.cpp" #include "dma/dma.cpp"
#include "memory/memory.cpp" #include "memory/memory.cpp"
#include "mmio/mmio.cpp" #include "mmio/mmio.cpp"
#include "timing/timing.cpp" #include "timing/timing.cpp"
void sCPU::enter() {
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
add_clocks(186);
while(true) {
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.nmi_pending) {
status.nmi_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
} else if(status.irq_pending) {
status.irq_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
}
op_irq();
}
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
(this->*opcode_table[op_readpc()])();
}
}
void sCPU::op_irq() {
op_read(regs.pc.d);
op_io();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
op_writestack(regs.pc.l);
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
rd.l = op_read(status.interrupt_vector + 0);
regs.pc.b = 0x00;
regs.p.i = 1;
regs.p.d = 0;
rd.h = op_read(status.interrupt_vector + 1);
regs.pc.w = rd.w;
}
void sCPU::power() { void sCPU::power() {
CPU::power(); CPU::power();
@ -26,11 +65,8 @@ void sCPU::power() {
void sCPU::reset() { void sCPU::reset() {
CPU::reset(); CPU::reset();
regs.pc.d = 0x000000;
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
//note: some registers are not fully reset by SNES //note: some registers are not fully reset by SNES
regs.pc = 0x000000;
regs.x.h = 0x00; regs.x.h = 0x00;
regs.y.h = 0x00; regs.y.h = 0x00;
regs.s.h = 0x01; regs.s.h = 0x01;
@ -39,8 +75,9 @@ void sCPU::reset() {
regs.p = 0x34; regs.p = 0x34;
regs.e = 1; regs.e = 1;
regs.mdr = 0x00; regs.mdr = 0x00;
regs.wai = false;
update_table();
status.wai_lock = false;
status.interrupt_pending = false; status.interrupt_pending = false;
status.interrupt_vector = 0xfffc; //reset vector address status.interrupt_vector = 0xfffc; //reset vector address
@ -59,3 +96,5 @@ sCPU::sCPU() {
sCPU::~sCPU() { sCPU::~sCPU() {
} }
};

View File

@ -1,8 +1,9 @@
class sCPU : public CPU { class sCPU : public CPU, public CPUcore {
public: public:
void enter(); void enter();
void op_irq();
bool interrupt_pending() { return status.interrupt_pending; }
#include "core/core.hpp"
#include "dma/dma.hpp" #include "dma/dma.hpp"
#include "memory/memory.hpp" #include "memory/memory.hpp"
#include "mmio/mmio.hpp" #include "mmio/mmio.hpp"
@ -11,11 +12,6 @@ public:
enum DmaState { DmaInactive, DmaRun, DmaCpuSync }; enum DmaState { DmaInactive, DmaRun, DmaCpuSync };
struct { struct {
//core
uint8 opcode;
bool in_opcode;
bool wai_lock;
bool interrupt_pending; bool interrupt_pending;
uint16 interrupt_vector; uint16 interrupt_vector;
@ -75,6 +71,9 @@ public:
//$4207-$420a //$4207-$420a
uint16 hirq_pos, virq_pos; uint16 hirq_pos, virq_pos;
//$420d
unsigned rom_speed;
//$4214-$4217 //$4214-$4217
uint16 r4214; uint16 r4214;
uint16 r4216; uint16 r4216;

View File

@ -93,14 +93,14 @@ bool sCPU::timeup() {
bool sCPU::nmi_test() { bool sCPU::nmi_test() {
if(!status.nmi_transition) return false; if(!status.nmi_transition) return false;
status.nmi_transition = false; status.nmi_transition = false;
status.wai_lock = false; regs.wai = false;
return true; return true;
} }
bool sCPU::irq_test() { bool sCPU::irq_test() {
if(!status.irq_transition) return false; if(!status.irq_transition && !regs.irq) return false;
status.irq_transition = false; status.irq_transition = false;
status.wai_lock = false; regs.wai = false;
return !regs.p.i; return !regs.p.i;
} }

View File

@ -3,8 +3,8 @@
void sCPU::run_auto_joypad_poll() { void sCPU::run_auto_joypad_poll() {
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0; uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
for(unsigned i = 0; i < 16; i++) { for(unsigned i = 0; i < 16; i++) {
uint8 port0 = snes.input.port_read(0); uint8 port0 = input.port_read(0);
uint8 port1 = snes.input.port_read(1); uint8 port1 = input.port_read(1);
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0; joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0; joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;

View File

@ -13,19 +13,25 @@ void sCPU::add_clocks(unsigned clocks) {
unsigned ticks = clocks >> 1; unsigned ticks = clocks >> 1;
while(ticks--) { while(ticks--) {
ppu.tick(); ppu.tick();
if((ppu.hcounter() & 2) == 0) { if(ppu.hcounter() & 2) {
snes.input.tick(); input.tick();
} else {
poll_interrupts(); poll_interrupts();
} }
} }
scheduler.addclocks_cpu(clocks); scheduler.addclocks_cpu(clocks);
} }
//called by ppu.tick() when Hcounter=0
void sCPU::scanline() { void sCPU::scanline() {
status.dma_counter = (status.dma_counter + status.line_clocks) & 7; status.dma_counter = (status.dma_counter + status.line_clocks) & 7;
status.line_clocks = ppu.lineclocks(); status.line_clocks = ppu.lineclocks();
//forcefully sync S-CPU to other processors, in case chips are not communicating
scheduler.sync_cpuppu();
scheduler.sync_cpucop();
scheduler.sync_cpusmp();
system.scanline();
if(ppu.vcounter() == 0) { if(ppu.vcounter() == 0) {
//hdma init triggers once every frame //hdma init triggers once every frame
event.enqueue(cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter(), EventHdmaInit); event.enqueue(cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter(), EventHdmaInit);
@ -41,7 +47,7 @@ void sCPU::scanline() {
} }
if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) { if(status.auto_joypad_poll == true && ppu.vcounter() == (ppu.overscan() == false ? 227 : 242)) {
snes.input.poll(); input.poll();
run_auto_joypad_poll(); run_auto_joypad_poll();
} }
} }

View File

@ -1,5 +1,7 @@
#include <../base.hpp> #include <../base.hpp>
#define ADSP_CPP #define ADSP_CPP
namespaec SNES {
#include "adsp_tables.cpp" #include "adsp_tables.cpp"
@ -580,9 +582,13 @@ int32 fir_samplel, fir_sampler;
msampler = sclamp<16>(msampler); msampler = sclamp<16>(msampler);
} }
snes.audio.update(msamplel, msampler); audio.sample(msamplel, msampler);
scheduler.addclocks_dsp(32 * 3 * 8); scheduler.addclocks_dsp(32 * 3 * 8);
scheduler.sync_dspsmp();
} }
aDSP::aDSP() {} aDSP::aDSP() {}
aDSP::~aDSP() {} aDSP::~aDSP() {}
};

View File

@ -106,7 +106,7 @@ void sDSP::echo_27() {
} }
//output sample to DAC //output sample to DAC
snes.audio.update(outl, outr); audio.sample(outl, outr);
} }
void sDSP::echo_28() { void sDSP::echo_28() {

View File

@ -1,21 +1,21 @@
/* /*
S-DSP emulator S-DSP emulator
license: LGPLv2
Note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator. Note: this is basically a C++ cothreaded implementation of Shay Green's (blargg's) S-DSP emulator.
The actual algorithms, timing information, tables, variable names, etc were all from him. The actual algorithms, timing information, tables, variable names, etc were all from him.
*/ */
#include <../base.hpp> #include <../base.hpp>
#define SDSP_CPP #define SDSP_CPP
namespace SNES {
#define REG(n) state.regs[r_##n] #define REG(n) state.regs[r_##n]
#define VREG(n) state.regs[v.vidx + v_##n] #define VREG(n) state.regs[v.vidx + v_##n]
#if !defined(USE_STATE_MACHINE) #if !defined(DSP_STATE_MACHINE)
#define phase_start() while(true) { #define phase_start() while(true) {
#define phase(n) #define phase(n)
#define tick() scheduler.addclocks_dsp(3 * 8) #define tick() scheduler.addclocks_dsp(3 * 8); scheduler.sync_dspsmp()
#define phase_end() } #define phase_end() }
#else #else
#define phase_start() switch(phase_index) { #define phase_start() switch(phase_index) {
@ -324,3 +324,6 @@ sDSP::sDSP() {
sDSP::~sDSP() { sDSP::~sDSP() {
} }
};

View File

@ -1,17 +1,20 @@
namespace SNES {
#include "cheat/cheat.hpp" #include "cheat/cheat.hpp"
#include "memory/memory.hpp" #include "memory/memory.hpp"
#include "memory/smemory/smemory.hpp" #include "memory/smemory/smemory.hpp"
#include "cpu/cpu.hpp" #include "cpu/cpu.hpp"
#include "cpu/core/core.hpp"
#include "cpu/scpu/scpu.hpp" #include "cpu/scpu/scpu.hpp"
#include "smp/smp.hpp"
#include "smp/core/core.hpp"
#include "smp/ssmp/ssmp.hpp"
#include "ppu/ppu.hpp" #include "ppu/ppu.hpp"
#include "ppu/bppu/bppu.hpp" #include "ppu/bppu/bppu.hpp"
#include "smp/smp.hpp"
#include "smp/ssmp/ssmp.hpp"
#include "dsp/dsp.hpp" #include "dsp/dsp.hpp"
#include "dsp/sdsp/sdsp.hpp" #include "dsp/sdsp/sdsp.hpp"
@ -21,4 +24,8 @@ extern SMPCORE smp;
extern DSPCORE dsp; extern DSPCORE dsp;
extern PPUCORE ppu; extern PPUCORE ppu;
#include "snes/snes.hpp" #include "system/system.hpp"
#include "chip/chip.hpp"
#include "cartridge/cartridge.hpp"
};

175
tools/bsnes/lib/bpp/bpp.cpp Executable file
View File

@ -0,0 +1,175 @@
#include "bpp.hpp"
bool BPP::process_macro(Macro &macro, const lstring &arg) {
lstring linedata;
linedata.split("\n", macro.data);
for(unsigned i = 0; i < linedata.size(); i++) {
string line = linedata[i];
for(unsigned j = 0; j < macro.args; j++) {
line.replace(macro.arg[j], arg[j]);
}
for(unsigned j = 0; j < global.size(); j++) {
line.replace(global[j].name, global[j].data);
}
output.print(string() << line << "\n");
}
return true;
}
bool BPP::process(const char *inputfn) {
string filedata;
if(filedata.readfile(inputfn) == false) {
fprintf(stdout, "error: failed to open input file '%s'\n", inputfn);
return false;
}
filedata.replace("\r", "");
lstring linedata;
linedata.split("\n", filedata);
for(unsigned i = 0; i < linedata.size();) {
string line = linedata[i];
trim(line);
line.replace("\t", " ");
if(strbegin(line, "@") == false) {
output.print(string() << linedata[i] << "\n");
i++;
} else if(strbegin(line, "@include ")) {
ltrim(line, "@include ");
trim(line, "\"");
if(process(line) == false) return false;
i++;
} else if(strbegin(line, "@global ")) {
ltrim(line, "@global ");
while(qstrpos(line, " ") >= 0) line.replace(" ", " ");
lstring part;
part.qsplit(" ", line);
if(part.size() != 2) {
fprintf(stdout, "error: malformed global\n");
return false;
}
unsigned n = global.size();
global[n].name = string() << "{" << part[0] << "}";
global[n].data = trim(part[1], "\"");
i++;
} else if(strbegin(line, "@macro ")) {
ltrim(line, "@macro ");
int pos = strpos(line, "(");
if(pos < 0 || !strend(line, ")")) {
fprintf(stdout, "error: malformed macro\n");
return false;
}
string name = substr(line, 0, pos);
line = substr(line, pos);
ltrim(line, "(");
rtrim(line, ")");
line.qreplace(" ", "");
unsigned n = macro.size();
macro[n].name = name;
if(line == "") {
macro[n].args = 0;
} else {
lstring arg;
arg.split(",", line);
if(arg.size() >= 8) {
fprintf(stdout, "error: too many macro arguments\n");
return false;
}
macro[n].args = arg.size();
for(unsigned j = 0; j < arg.size(); j++) {
macro[n].arg[j] = string() << "{" << arg[j] << "}";
}
}
i++;
while(i < linedata.size()) {
string line = linedata[i];
trim(line);
if(line == "@endmacro") break;
macro[n].data << linedata[i++] << "\n";
}
i++;
} else {
ltrim(line, "@");
int pos = strpos(line, "(");
if(pos < 0 || !strend(line, ")")) {
fprintf(stdout, "error: malformed macro invocation\n");
return false;
}
string name = substr(line, 0, pos);
line = substr(line, pos);
ltrim(line, "(");
rtrim(line, ")");
line.qreplace(" ", "");
lstring arg;
if(line != "") arg.qsplit(",", line);
for(unsigned j = 0; j < arg.size(); j++) {
trim(arg[j], "\"");
}
bool success = false;
for(unsigned j = 0; j < macro.size(); j++) {
if(name == macro[j].name && arg.size() == macro[j].args) {
success = process_macro(macro[j], arg);
break;
}
}
if(success == false) {
fprintf(stdout, "error: unable to process macro '%s'\n", (const char*)name);
return false;
}
i++;
}
}
return true;
}
bool BPP::process(const char *outputfn, const char *inputfn) {
if(file::exists(inputfn) == false) {
fprintf(stdout, "error: failed to open input file\n");
return false;
}
if(output.open(outputfn, file::mode_write) == false) {
fprintf(stdout, "error: failed to open output file\n");
return false;
}
bool result = process(inputfn);
output.close();
return result;
}
int main(int argc, const char **argv) {
if(argc != 3) {
fprintf(stdout, "bpp v0.01\n");
fprintf(stdout, "author: byuu\n");
fprintf(stdout, "usage: bpp output input\n");
return 0;
}
BPP bpp;
bool success = bpp.process(argv[1], argv[2]);
if(success == false) fprintf(stdout, "error: pre-processing failed\n");
return 0;
}

31
tools/bsnes/lib/bpp/bpp.hpp Executable file
View File

@ -0,0 +1,31 @@
#include <nall/array.hpp>
#include <nall/file.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/vector.hpp>
using namespace nall;
class BPP {
public:
bool process(const char *outputfn, const char *inputfn);
private:
nall::file output;
struct Global {
string name;
string data;
};
vector<Global> global;
struct Macro {
string name;
unsigned args;
string arg[8];
string data;
};
vector<Macro> macro;
bool process_macro(Macro &macro, const lstring &arg);
bool process(const char *inputfn);
};

Some files were not shown because too many files have changed in this diff Show More