From ec367f17bee1819996e042b36396660f839cbf4b Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 8 Jan 2010 23:56:14 +0000 Subject: [PATCH] tools: add vio2sf; enable mute channels and add interpolation choice --- tools/vio2sf/OUTPUT/readme.txt | 6 + tools/vio2sf/foo_input_vio2sf.sln | 20 + tools/vio2sf/foo_input_vio2sf.vcproj | 258 + tools/vio2sf/foo_xsf8.vcproj | 369 + tools/vio2sf/in_xsf.vcproj | 376 + tools/vio2sf/in_xsfu.vcproj | 389 + tools/vio2sf/kpixsf.vcproj | 286 + tools/vio2sf/src/Winamp/DSP.H | 65 + tools/vio2sf/src/Winamp/GEN.H | 37 + tools/vio2sf/src/Winamp/IN2.H | 138 + tools/vio2sf/src/Winamp/OUT.H | 73 + tools/vio2sf/src/Winamp/ipc_pe.h | 56 + tools/vio2sf/src/Winamp/wa_dlg.h | 436 + tools/vio2sf/src/Winamp/wa_ipc.h | 2470 +++++ tools/vio2sf/src/kobarin/kmp_pi.h | 214 + tools/vio2sf/src/loadpe/COPYING.LIB | 481 + tools/vio2sf/src/loadpe/loadpe.c | 563 ++ tools/vio2sf/src/loadpe/loadpe.h | 32 + tools/vio2sf/src/pversion.h | 36 + tools/vio2sf/src/vio2sf/desmume/ARM9.h | 33 + tools/vio2sf/src/vio2sf/desmume/COPYING | 340 + tools/vio2sf/src/vio2sf/desmume/FIFO.c | 65 + tools/vio2sf/src/vio2sf/desmume/FIFO.h | 51 + tools/vio2sf/src/vio2sf/desmume/GPU.c | 98 + tools/vio2sf/src/vio2sf/desmume/GPU.h | 813 ++ tools/vio2sf/src/vio2sf/desmume/MMU.c | 3565 ++++++++ tools/vio2sf/src/vio2sf/desmume/MMU.h | 200 + tools/vio2sf/src/vio2sf/desmume/NDSSystem.c | 748 ++ tools/vio2sf/src/vio2sf/desmume/NDSSystem.h | 255 + tools/vio2sf/src/vio2sf/desmume/SPU.c | 951 ++ tools/vio2sf/src/vio2sf/desmume/SPU.cpp | 1114 +++ tools/vio2sf/src/vio2sf/desmume/SPU.h | 150 + .../src/vio2sf/desmume/arm_instructions.c | 7928 +++++++++++++++++ .../src/vio2sf/desmume/arm_instructions.h | 31 + tools/vio2sf/src/vio2sf/desmume/armcpu.c | 579 ++ tools/vio2sf/src/vio2sf/desmume/armcpu.h | 288 + tools/vio2sf/src/vio2sf/desmume/bios.c | 1080 +++ tools/vio2sf/src/vio2sf/desmume/bios.h | 32 + tools/vio2sf/src/vio2sf/desmume/bits.h | 44 + tools/vio2sf/src/vio2sf/desmume/config.h | 28 + tools/vio2sf/src/vio2sf/desmume/cp15.c | 590 ++ tools/vio2sf/src/vio2sf/desmume/cp15.h | 94 + tools/vio2sf/src/vio2sf/desmume/debug.h | 11 + tools/vio2sf/src/vio2sf/desmume/dscard.h | 34 + .../src/vio2sf/desmume/instruction_tabdef.inc | 4400 +++++++++ tools/vio2sf/src/vio2sf/desmume/matrix.c | 257 + tools/vio2sf/src/vio2sf/desmume/matrix.h | 51 + tools/vio2sf/src/vio2sf/desmume/mc.c | 121 + tools/vio2sf/src/vio2sf/desmume/mc.h | 94 + tools/vio2sf/src/vio2sf/desmume/mem.h | 141 + tools/vio2sf/src/vio2sf/desmume/registers.h | 333 + tools/vio2sf/src/vio2sf/desmume/spu_exports.h | 30 + .../src/vio2sf/desmume/thumb_instructions.c | 944 ++ .../src/vio2sf/desmume/thumb_instructions.h | 30 + .../src/vio2sf/desmume/thumb_tabdef.inc | 1111 +++ tools/vio2sf/src/vio2sf/desmume/types.h | 171 + tools/vio2sf/src/vio2sf/drvimpl.c | 856 ++ tools/vio2sf/src/vio2sf/zlib/adler32.c | 149 + .../src/vio2sf/zlib/contrib/README.contrib | 17 + .../vio2sf/zlib/contrib/inflate86/inffas86.c | 1157 +++ .../vio2sf/zlib/contrib/inflate86/inffast.S | 1368 +++ .../vio2sf/zlib/contrib/masmx64/bld_ml64.bat | 2 + .../vio2sf/zlib/contrib/masmx64/gvmat64.asm | 513 ++ .../vio2sf/zlib/contrib/masmx64/gvmat64.obj | Bin 0 -> 4119 bytes .../vio2sf/zlib/contrib/masmx64/inffas8664.c | 186 + .../vio2sf/zlib/contrib/masmx64/inffasx64.asm | 392 + .../vio2sf/zlib/contrib/masmx64/inffasx64.obj | Bin 0 -> 5913 bytes .../vio2sf/zlib/contrib/masmx64/readme.txt | 28 + .../vio2sf/zlib/contrib/masmx86/bld_ml32.bat | 2 + .../vio2sf/zlib/contrib/masmx86/gvmat32.asm | 972 ++ .../vio2sf/zlib/contrib/masmx86/gvmat32.obj | Bin 0 -> 10241 bytes .../vio2sf/zlib/contrib/masmx86/gvmat32c.c | 62 + .../vio2sf/zlib/contrib/masmx86/inffas32.asm | 1083 +++ .../vio2sf/zlib/contrib/masmx86/inffas32.obj | Bin 0 -> 14893 bytes .../src/vio2sf/zlib/contrib/masmx86/mkasm.bat | 3 + .../vio2sf/zlib/contrib/masmx86/readme.txt | 21 + tools/vio2sf/src/vio2sf/zlib/crc32.c | 423 + tools/vio2sf/src/vio2sf/zlib/crc32.h | 441 + tools/vio2sf/src/vio2sf/zlib/crypt.h | 132 + tools/vio2sf/src/vio2sf/zlib/infback.c | 623 ++ tools/vio2sf/src/vio2sf/zlib/inffast.c | 318 + tools/vio2sf/src/vio2sf/zlib/inffast.h | 11 + tools/vio2sf/src/vio2sf/zlib/inffixed.h | 94 + tools/vio2sf/src/vio2sf/zlib/inflate.c | 1368 +++ tools/vio2sf/src/vio2sf/zlib/inflate.h | 115 + tools/vio2sf/src/vio2sf/zlib/inftrees.c | 329 + tools/vio2sf/src/vio2sf/zlib/inftrees.h | 55 + tools/vio2sf/src/vio2sf/zlib/uncompr.c | 61 + tools/vio2sf/src/vio2sf/zlib/zconf.h | 332 + tools/vio2sf/src/vio2sf/zlib/zlib.h | 1357 +++ tools/vio2sf/src/vio2sf/zlib/zutil.c | 318 + tools/vio2sf/src/vio2sf/zlib/zutil.h | 269 + tools/vio2sf/src/xsfc/drvimpl.h | 18 + tools/vio2sf/src/xsfc/foo_input_xsf.cpp | 719 ++ tools/vio2sf/src/xsfc/foo_input_xsf8.cpp | 709 ++ tools/vio2sf/src/xsfc/foo_input_xsfcfg.cpp | 269 + tools/vio2sf/src/xsfc/foo_input_xsfcfg8.cpp | 255 + tools/vio2sf/src/xsfc/in_xsf.cpp | 1964 ++++ tools/vio2sf/src/xsfc/in_xsfcfg.cpp | 291 + tools/vio2sf/src/xsfc/in_xsfcfg.h | 17 + tools/vio2sf/src/xsfc/kpixsf.c | 353 + tools/vio2sf/src/xsfc/leakchk.h | 13 + tools/vio2sf/src/xsfc/tagget.h | 525 ++ tools/vio2sf/src/xsfc/winresx.h | 8 + tools/vio2sf/src/xsfc/xsfc.cpp | 534 ++ tools/vio2sf/src/xsfc/xsfc.h | 671 ++ tools/vio2sf/src/xsfc/xsfcfg.cpp | 286 + tools/vio2sf/src/xsfc/xsfcfg.h | 75 + tools/vio2sf/src/xsfc/xsfdrv.c | 112 + tools/vio2sf/src/xsfc/xsfdrv.h | 37 + tools/vio2sf/src/xsfc/xsfui.rc | 125 + tools/vio2sf/src/xsfc/xsfui.rh | 16 + tools/vio2sf/vio2sf.sln | 47 + tools/vio2sf/vio2sf.vcproj | 843 ++ 114 files changed, 54054 insertions(+) create mode 100644 tools/vio2sf/OUTPUT/readme.txt create mode 100644 tools/vio2sf/foo_input_vio2sf.sln create mode 100644 tools/vio2sf/foo_input_vio2sf.vcproj create mode 100644 tools/vio2sf/foo_xsf8.vcproj create mode 100644 tools/vio2sf/in_xsf.vcproj create mode 100644 tools/vio2sf/in_xsfu.vcproj create mode 100644 tools/vio2sf/kpixsf.vcproj create mode 100644 tools/vio2sf/src/Winamp/DSP.H create mode 100644 tools/vio2sf/src/Winamp/GEN.H create mode 100644 tools/vio2sf/src/Winamp/IN2.H create mode 100644 tools/vio2sf/src/Winamp/OUT.H create mode 100644 tools/vio2sf/src/Winamp/ipc_pe.h create mode 100644 tools/vio2sf/src/Winamp/wa_dlg.h create mode 100644 tools/vio2sf/src/Winamp/wa_ipc.h create mode 100644 tools/vio2sf/src/kobarin/kmp_pi.h create mode 100644 tools/vio2sf/src/loadpe/COPYING.LIB create mode 100644 tools/vio2sf/src/loadpe/loadpe.c create mode 100644 tools/vio2sf/src/loadpe/loadpe.h create mode 100644 tools/vio2sf/src/pversion.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/ARM9.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/COPYING create mode 100644 tools/vio2sf/src/vio2sf/desmume/FIFO.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/FIFO.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/GPU.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/GPU.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/MMU.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/MMU.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/NDSSystem.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/NDSSystem.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/SPU.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/SPU.cpp create mode 100644 tools/vio2sf/src/vio2sf/desmume/SPU.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/arm_instructions.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/arm_instructions.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/armcpu.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/armcpu.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/bios.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/bios.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/bits.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/config.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/cp15.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/cp15.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/debug.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/dscard.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/instruction_tabdef.inc create mode 100644 tools/vio2sf/src/vio2sf/desmume/matrix.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/matrix.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/mc.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/mc.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/mem.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/registers.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/spu_exports.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/thumb_instructions.c create mode 100644 tools/vio2sf/src/vio2sf/desmume/thumb_instructions.h create mode 100644 tools/vio2sf/src/vio2sf/desmume/thumb_tabdef.inc create mode 100644 tools/vio2sf/src/vio2sf/desmume/types.h create mode 100644 tools/vio2sf/src/vio2sf/drvimpl.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/adler32.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/README.contrib create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffas86.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffast.S create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/bld_ml64.bat create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.asm create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.obj create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffas8664.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.asm create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.obj create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/readme.txt create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/bld_ml32.bat create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.asm create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.obj create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32c.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.asm create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.obj create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/mkasm.bat create mode 100644 tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/readme.txt create mode 100644 tools/vio2sf/src/vio2sf/zlib/crc32.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/crc32.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/crypt.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/infback.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/inffast.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/inffast.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/inffixed.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/inflate.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/inflate.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/inftrees.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/inftrees.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/uncompr.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/zconf.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/zlib.h create mode 100644 tools/vio2sf/src/vio2sf/zlib/zutil.c create mode 100644 tools/vio2sf/src/vio2sf/zlib/zutil.h create mode 100644 tools/vio2sf/src/xsfc/drvimpl.h create mode 100644 tools/vio2sf/src/xsfc/foo_input_xsf.cpp create mode 100644 tools/vio2sf/src/xsfc/foo_input_xsf8.cpp create mode 100644 tools/vio2sf/src/xsfc/foo_input_xsfcfg.cpp create mode 100644 tools/vio2sf/src/xsfc/foo_input_xsfcfg8.cpp create mode 100644 tools/vio2sf/src/xsfc/in_xsf.cpp create mode 100644 tools/vio2sf/src/xsfc/in_xsfcfg.cpp create mode 100644 tools/vio2sf/src/xsfc/in_xsfcfg.h create mode 100644 tools/vio2sf/src/xsfc/kpixsf.c create mode 100644 tools/vio2sf/src/xsfc/leakchk.h create mode 100644 tools/vio2sf/src/xsfc/tagget.h create mode 100644 tools/vio2sf/src/xsfc/winresx.h create mode 100644 tools/vio2sf/src/xsfc/xsfc.cpp create mode 100644 tools/vio2sf/src/xsfc/xsfc.h create mode 100644 tools/vio2sf/src/xsfc/xsfcfg.cpp create mode 100644 tools/vio2sf/src/xsfc/xsfcfg.h create mode 100644 tools/vio2sf/src/xsfc/xsfdrv.c create mode 100644 tools/vio2sf/src/xsfc/xsfdrv.h create mode 100644 tools/vio2sf/src/xsfc/xsfui.rc create mode 100644 tools/vio2sf/src/xsfc/xsfui.rh create mode 100644 tools/vio2sf/vio2sf.sln create mode 100644 tools/vio2sf/vio2sf.vcproj diff --git a/tools/vio2sf/OUTPUT/readme.txt b/tools/vio2sf/OUTPUT/readme.txt new file mode 100644 index 000000000..4545070a0 --- /dev/null +++ b/tools/vio2sf/OUTPUT/readme.txt @@ -0,0 +1,6 @@ +drop directories in here for testing: (projects are configured to put plugins in here) +winamp2 +winamp5 + +tips: +run winamp /NEW myfile.mini2sf to test builds \ No newline at end of file diff --git a/tools/vio2sf/foo_input_vio2sf.sln b/tools/vio2sf/foo_input_vio2sf.sln new file mode 100644 index 000000000..cbcdcc6a5 --- /dev/null +++ b/tools/vio2sf/foo_input_vio2sf.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foo_input_vio2sf", "foo_input_vio2sf.vcproj", "{22752D82-8F89-4F87-B07E-D254D7BF675A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {22752D82-8F89-4F87-B07E-D254D7BF675A}.Debug|Win32.ActiveCfg = Debug|Win32 + {22752D82-8F89-4F87-B07E-D254D7BF675A}.Debug|Win32.Build.0 = Debug|Win32 + {22752D82-8F89-4F87-B07E-D254D7BF675A}.Release|Win32.ActiveCfg = Release|Win32 + {22752D82-8F89-4F87-B07E-D254D7BF675A}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/vio2sf/foo_input_vio2sf.vcproj b/tools/vio2sf/foo_input_vio2sf.vcproj new file mode 100644 index 000000000..49ebbc231 --- /dev/null +++ b/tools/vio2sf/foo_input_vio2sf.vcproj @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/foo_xsf8.vcproj b/tools/vio2sf/foo_xsf8.vcproj new file mode 100644 index 000000000..21fc8946f --- /dev/null +++ b/tools/vio2sf/foo_xsf8.vcproj @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/in_xsf.vcproj b/tools/vio2sf/in_xsf.vcproj new file mode 100644 index 000000000..251fe10e0 --- /dev/null +++ b/tools/vio2sf/in_xsf.vcproj @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/in_xsfu.vcproj b/tools/vio2sf/in_xsfu.vcproj new file mode 100644 index 000000000..f870e9acb --- /dev/null +++ b/tools/vio2sf/in_xsfu.vcproj @@ -0,0 +1,389 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/kpixsf.vcproj b/tools/vio2sf/kpixsf.vcproj new file mode 100644 index 000000000..ee22dc130 --- /dev/null +++ b/tools/vio2sf/kpixsf.vcproj @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/vio2sf/src/Winamp/DSP.H b/tools/vio2sf/src/Winamp/DSP.H new file mode 100644 index 000000000..54d90a337 --- /dev/null +++ b/tools/vio2sf/src/Winamp/DSP.H @@ -0,0 +1,65 @@ +#ifndef NULLSOFT_WINAMP_DSP_H +#define NULLSOFT_WINAMP_DSP_H +// DSP plugin interface + +// notes: +// any window that remains in foreground should optimally pass unused +// keystrokes to the parent (winamp's) window, so that the user +// can still control it. As for storing configuration, +// Configuration data should be stored in \plugin.ini +// (look at the vis plugin for configuration code) + +typedef struct winampDSPModule { + char *description; // description + HWND hwndParent; // parent window (filled in by calling app) + HINSTANCE hDllInstance; // instance handle to this DLL (filled in by calling app) + + void (*Config)(struct winampDSPModule *this_mod); // configuration dialog (if needed) + int (*Init)(struct winampDSPModule *this_mod); // 0 on success, creates window, etc (if needed) + + // modify waveform samples: returns number of samples to actually write + // (typically numsamples, but no more than twice numsamples, and no less than half numsamples) + // numsamples should always be at least 128. should, but I'm not sure + int (*ModifySamples)(struct winampDSPModule *this_mod, short int *samples, int numsamples, int bps, int nch, int srate); + + void (*Quit)(struct winampDSPModule *this_mod); // called when unloading + + void *userData; // user data, optional +} winampDSPModule; + +typedef struct { + int version; // DSP_HDRVER + char *description; // description of library + winampDSPModule* (*getModule)(int); // module retrieval function + int (*sf)(int key); // DSP_HDRVER == 0x21 +} winampDSPHeader; + +// exported symbols +#ifdef USE_DSP_HDR_HWND +typedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND); +#define DSP_HDRVER 0x22 + +#else + +typedef winampDSPHeader* (*winampDSPGetHeaderType)(HWND); +// header version: 0x20 == 0.20 == winamp 2.0 +#define DSP_HDRVER 0x20 +#endif + +// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param) +// which determine if we can uninstall the plugin immediately or on winamp restart +#define DSP_PLUGIN_UNINSTALL_NOW 0x0 +#define DSP_PLUGIN_UNINSTALL_REBOOT 0x1 +// +// uninstall support was added from 5.0+ and uninstall now support from 5.5+ +// it is down to you to ensure that if uninstall now is returned that it will not cause a crash +// (ie don't use if you've been subclassing the main window) + +// Version note: +// +// Added passing of Winamp's main hwnd in the call to the exported winampDSPHeader() +// which allows for primarily the use of localisation features with the bundled plugins. +// If you want to use the new version then either you can edit you version of dsp.h or +// you can add USE_DSP_HDR_HWND to your project's defined list or before use of dsp.h +// +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/GEN.H b/tools/vio2sf/src/Winamp/GEN.H new file mode 100644 index 000000000..a63da3461 --- /dev/null +++ b/tools/vio2sf/src/Winamp/GEN.H @@ -0,0 +1,37 @@ +#ifndef NULLSOFT_WINAMP_GEN_H +#define NULLSOFT_WINAMP_GEN_H + +#include + +#define GEN_INIT_SUCCESS 0 + +// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param) +// which determine if we can uninstall the plugin immediately or on winamp restart +// +// uninstall support was added from 5.0+ and uninstall now support from 5.5+ +// it is down to you to ensure that if uninstall now is returned that it will not cause a crash +// (ie don't use if you've been subclassing the main window) +#define GEN_PLUGIN_UNINSTALL_NOW 0x1 +#define GEN_PLUGIN_UNINSTALL_REBOOT 0x0 + +typedef struct { + int version; + char *description; + int (*init)(); + void (*config)(); + void (*quit)(); + HWND hwndParent; + HINSTANCE hDllInstance; +} winampGeneralPurposePlugin; + +#define GPPHDR_VER 0x10 +#ifdef __cplusplus +extern "C" { +#endif +//extern winampGeneralPurposePlugin *gen_plugins[256]; +typedef winampGeneralPurposePlugin * (*winampGeneralPurposePluginGetter)(); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/IN2.H b/tools/vio2sf/src/Winamp/IN2.H new file mode 100644 index 000000000..41617668e --- /dev/null +++ b/tools/vio2sf/src/Winamp/IN2.H @@ -0,0 +1,138 @@ + +#ifndef NULLSOFT_WINAMP_IN2H +#define NULLSOFT_WINAMP_IN2H +#include "out.h" + +// note: exported symbol is now winampGetInModule2. + +#define IN_UNICODE 0x0F000000 + +#ifdef UNICODE_INPUT_PLUGIN +#define in_char wchar_t +#define IN_VER (IN_UNICODE | 0x100) +#else +#define in_char char +#define IN_VER 0x100 +#endif + +#define IN_MODULE_FLAG_USES_OUTPUT_PLUGIN 1 +// By default, Winamp assumes that your input plugin wants to use Winamp's EQ, and doesn't do replay gain +// if you handle any of these yourself (EQ, Replay Gain adjustments), then set these flags accordingly +#define IN_MODULE_FLAG_EQ 2 // set this if you do your own EQ +#define IN_MODULE_FLAG_REPLAYGAIN 8 // set this if you adjusted volume for replay gain + // for tracks with no replay gain metadata, you should clear this flag + // UNLESS you handle "non_replaygain" gain adjustment yourself +#define IN_MODULE_FLAG_REPLAYGAIN_PREAMP 16 // use this if you queried for the replay gain preamp parameter and used it + // this parameter is new to 5.54 +typedef struct +{ + int version; // module type (IN_VER) + char *description; // description of module, with version string + + HWND hMainWindow; // winamp's main window (filled in by winamp) + HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp) + + char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0" + // May be altered from Config, so the user can select what they want + + int is_seekable; // is this stream seekable? + int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :) + // note that this has turned into a "flags" field + // see IN_MODULE_FLAG_* + + void (*Config)(HWND hwndParent); // configuration dialog + void (*About)(HWND hwndParent); // about dialog + + void (*Init)(); // called at program init + void (*Quit)(); // called at program quit + +#define GETFILEINFO_TITLE_LENGTH 2048 + void (*GetFileInfo)(const in_char *file, in_char *title, int *length_in_ms); // if file == NULL, current playing is used + +#define INFOBOX_EDITED 0 +#define INFOBOX_UNCHANGED 1 + int (*InfoBox)(const in_char *file, HWND hwndParent); + + int (*IsOurFile)(const in_char *fn); // called before extension checks, to allow detection of mms://, etc + // playback stuff + int (*Play)(const in_char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error + void (*Pause)(); // pause stream + void (*UnPause)(); // unpause stream + int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not + void (*Stop)(); // stop (unload) stream + + // time stuff + int (*GetLength)(); // get length in ms + int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime() + void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal your thread to seek, which seeks and calls outMod->Flush().. + + // volume stuff + void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume + void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan + + // in-window builtin vis stuff + + void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open() + // call after opening audio device with max latency in ms and samplerate + void (*SAVSADeInit)(); // call in Stop() + + + // simple vis supplying mode + void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); + // sets the spec data directly from PCM data + // quick and easy way to get vis working :) + // needs at least 576 samples :) + + // advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff. + int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec)) + // use when calling SAAdd() + int (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp + + + // vis stuff (plug-in) + // simple vis supplying mode + void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data + // quick and easy way to get vis working :) + // needs at least 576 samples :) + + // advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff. + int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd + int (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in + + + // call this in Play() to tell the vis plug-ins the current output params. + void (*VSASetInfo)(int srate, int nch); // <-- Correct (benski, dec 2005).. old declaration had the params backwards + + + // dsp plug-in processing: + // (filled in by winamp, calld by input plug) + + // returns 1 if active (which means that the number of samples returned by dsp_dosamples + // could be greater than went in.. Use it to estimate if you'll have enough room in the + // output buffer + int (*dsp_isactive)(); + + // returns number of samples to output. This can be as much as twice numsamples. + // be sure to allocate enough buffer for samples, then. + int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate); + + + // eq stuff + void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore. + + // info setting (filled in by winamp) + void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :) + + Out_Module *outMod; // filled in by winamp, optionally used :) +} In_Module; + +// return values from the winampUninstallPlugin(HINSTANCE hdll, HWND parent, int param) +// which determine if we can uninstall the plugin immediately or on winamp restart +// +// uninstall support was added from 5.0+ and uninstall now support from 5.5+ +// it is down to you to ensure that if uninstall now is returned that it will not cause a crash +// (ie don't use if you've been subclassing the main window) +#define IN_PLUGIN_UNINSTALL_NOW 0x1 +#define IN_PLUGIN_UNINSTALL_REBOOT 0x0 + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/OUT.H b/tools/vio2sf/src/Winamp/OUT.H new file mode 100644 index 000000000..af76e8273 --- /dev/null +++ b/tools/vio2sf/src/Winamp/OUT.H @@ -0,0 +1,73 @@ +#ifndef NULLSOFT_OUTH +#define NULLSOFT_OUTH +#include +#include +// ids: +// waveout: 32 +// gapless: 64 +// xfade: 63 +// disk: 33 +// dsound: 38 +// NULL: 65 +// mm2: 69 + +#if (_MSC_VER <= 1200) +typedef int intptr_t; +#endif + +#define OUT_VER 0x10 + +typedef struct +{ + int version; // module version (OUT_VER) + char *description; // description of module, with version string + intptr_t id; // module id. each input module gets its own. non-nullsoft modules should + // be >= 65536. + + HWND hMainWindow; // winamp's main window (filled in by winamp) + HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp) + + void (*Config)(HWND hwndParent); // configuration dialog + void (*About)(HWND hwndParent); // about dialog + + void (*Init)(); // called when loaded + void (*Quit)(); // called when unloaded + + int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms); + // returns >=0 on success, <0 on failure + + // NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins. + // ... so don't expect the max latency returned to be what you asked for. + // returns max latency in ms (0 for diskwriters, etc) + // bufferlenms and prebufferms must be in ms. 0 to use defaults. + // prebufferms must be <= bufferlenms + // pass bufferlenms==-666 to tell the output plugin that it's clock is going to be used to sync video + // out_ds turns off silence-eating when -666 is passed + + void (*Close)(); // close the ol' output device. + + int (*Write)(char *buf, int len); + // 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data. + // 1 returns not able to write (yet). Non-blocking, always. + + int (*CanWrite)(); // returns number of bytes possible to write at a given time. + // Never will decrease unless you call Write (or Close, heh) + + int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be + // written (i.e. closing while IsPlaying() returns 1 would truncate the song + + int (*Pause)(int pause); // returns previous pause state + + void (*SetVolume)(int volume); // volume is 0-255 + void (*SetPan)(int pan); // pan is -128 to 128 + + void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms) + // (used for seeking) + + int (*GetOutputTime)(); // returns played time in MS + int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff) + +} Out_Module; + + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/ipc_pe.h b/tools/vio2sf/src/Winamp/ipc_pe.h new file mode 100644 index 000000000..708d8a66d --- /dev/null +++ b/tools/vio2sf/src/Winamp/ipc_pe.h @@ -0,0 +1,56 @@ +#ifndef __IPC_PE_H +#define __IPC_PE_H + +#define IPC_PE_GETCURINDEX 100 // returns current idx +#define IPC_PE_GETINDEXTOTAL 101 // returns number of items +#define IPC_PE_GETINDEXINFO 102 // (copydata) lpData is of type callbackinfo, callback is called with copydata/fileinfo structure and msg IPC_PE_GETINDEXINFORESULT +#define IPC_PE_GETINDEXINFORESULT 103 // callback message for IPC_PE_GETINDEXINFO +#define IPC_PE_DELETEINDEX 104 // lParam = index +#define IPC_PE_SWAPINDEX 105 // (lParam & 0xFFFF0000) >> 16 = from, (lParam & 0xFFFF) = to +#define IPC_PE_INSERTFILENAME 106 // (copydata) lpData is of type fileinfo +#define IPC_PE_GETDIRTY 107 // returns 1 if the playlist changed since the last IPC_PE_SETCLEAN +#define IPC_PE_SETCLEAN 108 // resets the dirty flag until next modification +#define IPC_PE_GETIDXFROMPOINT 109 // pass a point parm, return a playlist index +#define IPC_PE_SAVEEND 110 // pass index to save from +#define IPC_PE_RESTOREEND 111 // no parm +#define IPC_PE_GETNEXTSELECTED 112 // same as IPC_PLAYLIST_GET_NEXT_SELECTED for the main window +#define IPC_PE_GETSELECTEDCOUNT 113 +#define IPC_PE_INSERTFILENAMEW 114 // (copydata) lpData is of type fileinfoW +#define IPC_PE_GETINDEXINFO_TITLE 115 // like IPC_PE_GETINDEXINFO, but writes the title to char file[MAX_PATH] instead of filename +#define IPC_PE_GETINDEXINFORESULT_TITLE 116 // callback message for IPC_PE_GETINDEXINFO +typedef struct { + char file[MAX_PATH]; + int index; + } fileinfo; + +typedef struct { + wchar_t file[MAX_PATH]; + int index; + } fileinfoW; + +typedef struct { + HWND callback; + int index; + } callbackinfo; + +// the following messages are in_process ONLY + +#define IPC_PE_GETINDEXTITLE 200 // lParam = pointer to fileinfo2 struct +#define IPC_PE_GETINDEXTITLEW 201 // lParam = pointer to fileinfo2W struct +#define IPC_PE_GETINDEXINFO_INPROC 202 // lParam = pointer to fileinfo struct +#define IPC_PE_GETINDEXINFOW_INPROC 203 // lParam = pointer to fileinfoW struct + +typedef struct { + int fileindex; + char filetitle[256]; + char filelength[16]; + } fileinfo2; + +typedef struct +{ + int fileindex; + wchar_t filetitle[256]; + wchar_t filelength[16]; + } fileinfo2W; + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/wa_dlg.h b/tools/vio2sf/src/Winamp/wa_dlg.h new file mode 100644 index 000000000..df912b257 --- /dev/null +++ b/tools/vio2sf/src/Winamp/wa_dlg.h @@ -0,0 +1,436 @@ +/* +** Copyright (C) 2003-2008 Nullsoft, Inc. +** +** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held +** liable for any damages arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to +** alter it and redistribute it freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +** +** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +** +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#ifndef _WA_DLG_H_ +#define _WA_DLG_H_ + +#include "wa_ipc.h" +#ifdef __cplusplus +extern "C" { +#endif +/* + 1) gen.bmp has a generic window frame for plugins to use. + its format is similar to the minibrowser's. + In addition gen.bmp includes a font for the titlebar, in both + highlight and no-highlight modes. The font is variable width, + and it uses the first color before the letter A as the delimiter. + The no-highlight form of letter must be the same width as the + highlight form. + 2) genex.bmp has button and scrollbar images, as well as some individual + pixels that describe the colors for the dialog. The button and + scrollbar images should be self explanatory (note that the buttons + have 4 pixel sized edges that are not stretched, and the center is + stretched), and the scrollbars do something similar. + The colors start at (48,0) and run every other pixel. The meaning + of each pixel is: + x=48: item background (background to edits, listviews etc) + x=50: item foreground (text color of edit/listview, etc) + x=52: window background (used to set the bg color for the dialog) + x=54: button text color + x=56: window text color + x=58: color of dividers and sunken borders + x=60: selection color for playlists + x=62: listview header background color + x=64: listview header text color + x=66: listview header frame top color + x=68: listview header frame middle color + x=70: listview header frame bottom color + x=72: listview header empty color + x=74: scrollbar foreground color + x=76: scrollbar background color + x=78: inverse scrollbar foreground color + x=80: inverse scrollbar background color + x=82: scrollbar dead area color + x=84: listview/treeview selection bar text color (active) + x=86: listview/treeview selection bar back color (active) + x=88: listview/treeview selection bar text color (inactive) + x=90: listview/treeview selection bar back color (inactive) + x=92: alternate item background + x=94: alternate item foreground +*/ + +#define DCW_SUNKENBORDER 0x00010000 +#define DCW_DIVIDER 0x00020000 + +enum +{ + WADLG_ITEMBG, + WADLG_ITEMFG, + WADLG_WNDBG, + WADLG_BUTTONFG, + WADLG_WNDFG, + WADLG_HILITE, + WADLG_SELCOLOR, + WADLG_LISTHEADER_BGCOLOR, + WADLG_LISTHEADER_FONTCOLOR, + WADLG_LISTHEADER_FRAME_TOPCOLOR, + WADLG_LISTHEADER_FRAME_MIDDLECOLOR, + WADLG_LISTHEADER_FRAME_BOTTOMCOLOR, + WADLG_LISTHEADER_EMPTY_BGCOLOR, + WADLG_SCROLLBAR_FGCOLOR, + WADLG_SCROLLBAR_BGCOLOR, + WADLG_SCROLLBAR_INV_FGCOLOR, + WADLG_SCROLLBAR_INV_BGCOLOR, + WADLG_SCROLLBAR_DEADAREA_COLOR, + WADLG_SELBAR_FGCOLOR, + WADLG_SELBAR_BGCOLOR, + WADLG_INACT_SELBAR_FGCOLOR, + WADLG_INACT_SELBAR_BGCOLOR, + WADLG_ITEMBG2, + WADLG_ITEMFG2, + WADLG_NUM_COLORS +}; + +typedef enum _WACURSOR // used in IPC_GETSKINCURSORS +{ + WACURSOR_VOLUME = 0, // volume & balane + WACURSOR_POSITION = 1, // position + WACURSOR_BTN_WINSHADE = 2, // winshade + WACURSOR_BTN_MINIMIZE = 3, // minimize + WACURSOR_BTN_CLOSE = 4, // close + WACURSOR_MENU = 5, // main menu + WACURSOR_TITLEBAR = 6, // title bar + WACURSOR_SONGNAME = 7, + WACURSOR_NORMAL = 8, + WACURSOR_WINSHADE_BTN_WINSHADE = 9, + WACURSOR_WINSHADE_BTN_MINIMIZE = 10, + WACURSOR_WINSHADE_POSITION = 11, + WACURSOR_WINSHADE_BTN_CLOSE = 12, + WACURSOR_WINSHADE_MENU = 13, + WACURSOR_WINSHADE_NORMAL = 14, + WACURSOR_PL_BTN_WINSHADE = 15, + WACURSOR_PL_BTN_CLOSE = 16, + WACURSOR_PL_TITLEBAR = 17, + WACURSOR_PL_VSCROLL = 18, + WACURSOR_PL_RESIZE = 19, + WACURSOR_PL_NORMAL = 20, + WACURSOR_PL_WINSHADE_BTN_WINSHADE = 21, + WACURSOR_PL_WINSHADE_BTN_CLOSE = 22, + WACURSOR_PL_WINSHADE_HSIZE = 23, + WACURSOR_PL_WINSHADE_NORMAL = 24, + WACURSOR_EQ_SLIDER = 25, + WACURSOR_EQ_BTN_CLOSE = 26, + WACURSOR_EQ_TITLEBAR = 27, + WACURSOR_EQ_NORMAL = 28, +} WACURSOR; + +void WADlg_init(HWND hwndWinamp); // call this on init, or on WM_DISPLAYCHANGE +void WADlg_close(); +int WADlg_getColor(int idx); +int WADlg_initted(); + +LRESULT WADlg_handleDialogMsgs(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize); // each entry in tab would be the id | DCW_* + +HBITMAP WADlg_getBitmap(); + +/// define WA_DLG_IMPLEMENT in one of your source files before including this .h +// if you are making a media library plugin, you dont need to do this, look at view_ex for +// an example of how to get the function *'s via an IPC message. +#ifdef __cplusplus +} +#endif + +#ifdef WA_DLG_IMPLEMENT + +static HBRUSH wadlg_lastbrush=0; +static HBITMAP wadlg_bitmap=0; // load this manually +static int wadlg_colors[WADLG_NUM_COLORS]; +static int wadlg_defcolors[WADLG_NUM_COLORS]= +{ + RGB(0,0,0), + RGB(0,255,0), + RGB(36,36,60), + RGB(57,56,66), + RGB(255,255,255), + RGB(132,148,165), + RGB(0,0,198), + RGB(36*2,36*2,60*2), + RGB(255,255,255), + RGB(36*3,36*3,60*3), + RGB(36,36,60), + RGB(36*0.5,36*0.5,60*0.5), + RGB(36,36,60), + RGB(36*1,36*1,60*1), + RGB(36*1,36*1,60*1), + RGB(121,130,150), + RGB(78,88,110), + RGB(36*1,36*1,60*1), + RGB(255,255,255), + RGB(0,0,180), + RGB(0,255,0), + RGB(0,0,128), + RGB(0,0,0), + RGB(0,255,0), +}; + +int WADlg_initted() +{ + return !!wadlg_bitmap; +} + +int WADlg_getColor(int idx) +{ + if (idx < 0 || idx >= WADLG_NUM_COLORS) return 0; + return wadlg_colors[idx]; +} + +HBITMAP WADlg_getBitmap() +{ + return wadlg_bitmap; +} + +void WADlg_init(HWND hwndWinamp) // call this on init, or on WM_DISPLAYCHANGE +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap = (HBITMAP) SendMessage(hwndWinamp,WM_WA_IPC,0,IPC_GET_GENSKINBITMAP); + if (wadlg_bitmap) + { + HDC tmpDC=CreateCompatibleDC(NULL); + HGDIOBJ o=SelectObject(tmpDC,(HGDIOBJ)wadlg_bitmap); + int defbgcol=GetPixel(tmpDC,111,0); + for (int x = 0; x < WADLG_NUM_COLORS; x ++) + { + int a=GetPixel(tmpDC,48+x*2,0); + if (a == CLR_INVALID || a == RGB(0,198,255) || a == defbgcol) + { + //defaults for old skins + if (x == WADLG_SELBAR_FGCOLOR || x == WADLG_INACT_SELBAR_FGCOLOR) a=wadlg_colors[WADLG_WNDFG]; + else if (x == WADLG_SELBAR_BGCOLOR || x == WADLG_INACT_SELBAR_BGCOLOR) + { + a=wadlg_colors[WADLG_SELCOLOR]; + if (x == WADLG_INACT_SELBAR_BGCOLOR) + a=((a/2)&0x7F7F7F)+(((wadlg_colors[WADLG_WNDBG])/2)&0x7F7F7F); + } + else if (x == WADLG_ITEMBG2) + { + a=wadlg_colors[WADLG_ITEMBG]; + } + else if (x == WADLG_ITEMFG2) + { + a=wadlg_colors[WADLG_ITEMFG]; + } + else a=wadlg_defcolors[x]; + } + wadlg_colors[x]=a; + } + + SelectObject(tmpDC,o); + DeleteDC(tmpDC); + } +} + +void WADlg_close() +{ + if (wadlg_bitmap) DeleteObject(wadlg_bitmap); + wadlg_bitmap=0; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=0; +} + +void WADlg_dotLine(HDC hdc, int left, int top, int len, int vert) +{ + for(int i=(top&1);iCtlType == ODT_BUTTON) { + wchar_t wt[256]; + RECT r; + GetDlgItemTextW(hwndDlg,(INT)wParam,wt,sizeof(wt)/sizeof(*wt)); + + HDC hdc = CreateCompatibleDC(di->hDC); + HBITMAP hbmpOld = (HBITMAP)SelectObject(hdc, wadlg_bitmap); + + r=di->rcItem; + SetStretchBltMode(di->hDC,COLORONCOLOR); + + int yoffs = (di->itemState & ODS_SELECTED) ? 15 : 0; + + BitBlt(di->hDC,r.left,r.top,4,4,hdc,0,yoffs,SRCCOPY); // top left + StretchBlt(di->hDC,r.left+4,r.top,r.right-r.left-4-4,4,hdc,4,yoffs,47-4-4,4,SRCCOPY); // top center + BitBlt(di->hDC,r.right-4,r.top,4,4,hdc,47-4,yoffs,SRCCOPY); // top right + + StretchBlt(di->hDC,r.left,r.top+4,4,r.bottom-r.top-4-4,hdc,0,4+yoffs,4,15-4-4,SRCCOPY); // left edge + StretchBlt(di->hDC,r.right-4,r.top+4,4,r.bottom-r.top-4-4,hdc,47-4,4+yoffs,4,15-4-4,SRCCOPY); // right edge + + // center + StretchBlt(di->hDC,r.left+4,r.top+4,r.right-r.left-4-4,r.bottom-r.top-4-4,hdc,4,4+yoffs,47-4-4,15-4-4,SRCCOPY); + + BitBlt(di->hDC,r.left,r.bottom-4,4,4,hdc,0,15-4+yoffs,SRCCOPY); // bottom left + StretchBlt(di->hDC,r.left+4,r.bottom-4,r.right-r.left-4-4,4,hdc,4,15-4+yoffs,47-4-4,4,SRCCOPY); // bottom center + BitBlt(di->hDC,r.right-4,r.bottom-4,4,4,hdc,47-4,15-4+yoffs,SRCCOPY); // bottom right + + // draw text + SetBkMode(di->hDC,TRANSPARENT); + + // this will do a different style for the button text depending on enabled state of the button + COLORREF colour = wadlg_colors[WADLG_BUTTONFG]; + if(!IsWindowEnabled(di->hwndItem)){ + COLORREF fg = wadlg_colors[WADLG_WNDFG], + bg = wadlg_colors[WADLG_WNDBG]; + colour = RGB((GetRValue(fg)+GetRValue(bg))/2, + (GetGValue(fg)+GetGValue(bg))/2, + (GetBValue(fg)+GetBValue(bg))/2); + } + SetTextColor(di->hDC,colour); + + if (di->itemState & ODS_SELECTED) {r.left+=2; r.top+=2;} + DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); + + SelectObject(hdc, hbmpOld); + DeleteDC(hdc); + + if(GetFocus()==di->hwndItem) { + HPEN hpen, hpenOld; + hpen =CreatePen(PS_SOLID,0,RGB(0,0,0)); + hpenOld = (HPEN)SelectObject(di->hDC, hpen); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.right-r.left-3,0); + WADlg_dotLine(di->hDC,r.right-3,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.top+2,r.bottom-r.top-3,1); + WADlg_dotLine(di->hDC,r.left+2,r.bottom-3,r.right-r.left-3,0); + SelectObject(di->hDC, hpenOld); + DeleteObject(hpen); + } + } + } + + switch(uMsg) + { + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORDLG: + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLOREDIT: + { + int bgcolor=(uMsg == WM_CTLCOLOREDIT || uMsg == WM_CTLCOLORLISTBOX) ? wadlg_colors[WADLG_ITEMBG] : (uMsg == WM_CTLCOLORBTN ? wadlg_colors[WADLG_ITEMBG] : wadlg_colors[WADLG_WNDBG]); + LOGBRUSH lb={BS_SOLID,GetNearestColor((HDC)wParam,bgcolor)}; + if (wadlg_lastbrush) DeleteObject(wadlg_lastbrush); + wadlg_lastbrush=CreateBrushIndirect(&lb); + SetTextColor((HDC)wParam,uMsg == WM_CTLCOLORSTATIC ? wadlg_colors[WADLG_WNDFG] : wadlg_colors[WADLG_ITEMFG]); + SetBkColor((HDC)wParam,lb.lbColor); + return (LRESULT)wadlg_lastbrush; + } + } + return 0; +} + +static int RectInRect(RECT *rect1, RECT *rect2) +{ + // this has a bias towards true + + // this could probably be optimized a lot + return ((rect1->top >= rect2->top && rect1->top <= rect2->bottom) || + (rect1->bottom >= rect2->top && rect1->bottom <= rect2->bottom) || + (rect2->top >= rect1->top && rect2->top <= rect1->bottom) || + (rect2->bottom >= rect1->top && rect2->bottom <= rect1->bottom)) // vertical intersect + && + ((rect1->left >= rect2->left && rect1->left <= rect2->right) || + (rect1->right >= rect2->left && rect1->right <= rect2->right) || + (rect2->left >= rect1->left && rect2->left <= rect1->right) || + (rect2->right >= rect1->left && rect2->right <= rect1->right)) // horiz intersect + ; +} + +static void WADlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom) +{ + HRGN rgn2=CreateRectRgn(left,top,right,bottom); + CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF); + DeleteObject(rgn2); +} + +void WADlg_DrawChildWindowBorders(HWND hwndDlg, int *tab, int tabsize) +{ + PAINTSTRUCT ps; + BeginPaint(hwndDlg,&ps); + HRGN hrgn = (ps.fErase) ? CreateRectRgnIndirect(&ps.rcPaint) : NULL; + HPEN pen = CreatePen(PS_SOLID, 0, wadlg_colors[WADLG_HILITE]); + HGDIOBJ o = SelectObject(ps.hdc, pen); + + while (tabsize--) + { + RECT r; + int a = *tab++; + GetWindowRect(GetDlgItem(hwndDlg, a & 0xffff),&r); + MapWindowPoints(HWND_DESKTOP, hwndDlg, (LPPOINT)&r, 2); + + if (RectInRect(&ps.rcPaint,&r)) + { + if ((a & 0xffff0000) == DCW_SUNKENBORDER) + { + MoveToEx(ps.hdc,r.left,r.bottom,NULL); + LineTo(ps.hdc,r.right,r.bottom); + LineTo(ps.hdc,r.right,r.top-1); + if(hrgn) + { + WADlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1); + WADlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom); + } + } + else if ((a & 0xffff0000) == DCW_DIVIDER) + { + if (r.right - r.left < r.bottom - r.top) // vertical + { + int left=(r.left+r.right)/2; + MoveToEx(ps.hdc,left,r.top,NULL); + LineTo(ps.hdc,left,r.bottom+1); + if(hrgn) WADlg_removeFromRgn(hrgn,left,r.top,left+1,r.bottom); + } + else // horiz + { + int top=(r.top+r.bottom)/2; + MoveToEx(ps.hdc,r.left,top,NULL); + LineTo(ps.hdc,r.right+1,top); + if(hrgn) WADlg_removeFromRgn(hrgn,r.left,top,r.right,top+1); + } + } + } + } + + SelectObject(ps.hdc, o); + DeleteObject(pen); + + if(hrgn) + { + //erase bkgnd while clipping out our own drawn stuff (for flickerless display) + HBRUSH b = CreateSolidBrush(wadlg_colors[WADLG_WNDBG]); + FillRgn(ps.hdc,hrgn,b); + DeleteObject(b); + DeleteObject(hrgn); + } + EndPaint(hwndDlg,&ps); +} +#endif + +#endif//_WA_DLG_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/Winamp/wa_ipc.h b/tools/vio2sf/src/Winamp/wa_ipc.h new file mode 100644 index 000000000..7e1f75d22 --- /dev/null +++ b/tools/vio2sf/src/Winamp/wa_ipc.h @@ -0,0 +1,2470 @@ +/* +** Copyright (C) 1997-2008 Nullsoft, Inc. +** +** This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held +** liable for any damages arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, including commercial applications, and to +** alter it and redistribute it freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +** If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +** +** 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +** +** 3. This notice may not be removed or altered from any source distribution. +** +*/ + +#ifndef _WA_IPC_H_ +#define _WA_IPC_H_ + +#include +#include +#if (_MSC_VER <= 1200) +typedef int intptr_t; +#endif +/* +** This is the modern replacement for the classic 'frontend.h'. Most of these +** updates are designed for in-process use, i.e. from a plugin. +** +*/ + +/* Most of the IPC_* messages involve sending the message in the form of: +** result = SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*); +** Where different then this is specified (typically with WM_COPYDATA variants) +** +** When you use SendMessage(hwnd_winamp,WM_WA_IPC,(parameter),IPC_*) and specify a IPC_* +** which is not currently implemented/supported by the Winamp version being used then it +** will return 1 for 'result'. This is a good way of helping to check if an api being +** used which returns a function pointer, etc is even going to be valid. +*/ + +#define WM_WA_IPC WM_USER + +#define WINAMP_VERSION_MAJOR(winampVersion) ((winampVersion & 0x0000FF00) >> 12) +#define WINAMP_VERSION_MINOR(winampVersion) (winampVersion & 0x000000FF) // returns, i.e. 0x12 for 5.12 and 0x10 for 5.1... + + +#define IPC_GETVERSION 0 +/* int version = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION); +** +** The version returned will be 0x20yx for Winamp 2.yx. +** Versions previous to Winamp 2.0 typically (but not always) use 0x1zyx for 1.zx. +** Just a bit weird but that's the way it goes. +** +** For Winamp 5.x it uses the format 0x50yx for Winamp 5.yx +** e.g. 5.01 -> 0x5001 +** 5.09 -> 0x5009 +** 5.1 -> 0x5010 +** +** Notes: For 5.02 this api will return the same value as for a 5.01 build. +** For 5.07 this api will return the same value as for a 5.06 build. +*/ + + +#define IPC_GETVERSIONSTRING 1 + + +#define IPC_GETREGISTEREDVERSION 770 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETREGISTEREDVERSION); +** +** This will open the Winamp Preferences and show the Winamp Pro page. +*/ + + +typedef struct { + const char *filename; + const char *title; + int length; +} enqueueFileWithMetaStruct; // send this to a IPC_PLAYFILE in a non WM_COPYDATA, +// and you get the nice desired result. if title is NULL, it is treated as a "thing", +// otherwise it's assumed to be a file (for speed) + +typedef struct { + const wchar_t *filename; + const wchar_t *title; + int length; +} enqueueFileWithMetaStructW; + +#define IPC_PLAYFILE 100 // dont be fooled, this is really the same as enqueufile +#define IPC_ENQUEUEFILE 100 +#define IPC_PLAYFILEW 1100 +#define IPC_ENQUEUEFILEW 1100 +/* This is sent as a WM_COPYDATA with IPC_PLAYFILE as the dwData member and the string +** of the file / playlist to be enqueued into the playlist editor as the lpData member. +** This will just enqueue the file or files since you can use this to enqueue a playlist. +** It will not clear the current playlist or change the playback state. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ENQUEUEFILE; +** cds.lpData = (void*)"c:\\test\\folder\\test.mp3"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** With 2.9+ and all of the 5.x versions you can send this as a normal WM_WA_IPC +** (non WM_COPYDATA) with an enqueueFileWithMetaStruct as the param. +** If the title member is null then it is treated as a "thing" otherwise it will be +** assumed to be a file (for speed). +** +** enqueueFileWithMetaStruct eFWMS = {0}; +** eFWMS.filename = "c:\\test\\folder\\test.mp3"; +** eFWMS.title = "Whipping Good"; +** eFWMS.length = 300; // this is the number of seconds for the track +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&eFWMS,IPC_ENQUEUEFILE); +*/ + + +#define IPC_DELETE 101 +#define IPC_DELETE_INT 1101 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_DELETE); +** Use this api to clear Winamp's internal playlist. +** You should not need to use IPC_DELETE_INT since it is used internally by Winamp when +** it is dealing with some lame Windows Explorer issues (hard to believe that!). +*/ + + +#define IPC_STARTPLAY 102 +#define IPC_STARTPLAY_INT 1102 +/* SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_STARTPLAY); +** Sending this will start playback and is almost the same as hitting the play button. +** The IPC_STARTPLAY_INT version is used internally and you should not need to use it +** since it won't be any fun. +*/ + + +#define IPC_CHDIR 103 +/* This is sent as a WM_COPYDATA type message with IPC_CHDIR as the dwData value and the +** directory you want to change to as the lpData member. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_CHDIR; +** cds.lpData = (void*)"c:\\download"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** The above example will make Winamp change to the directory 'C:\download'. +*/ + + +#define IPC_ISPLAYING 104 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING); +** This is sent to retrieve the current playback state of Winamp. +** If it returns 1, Winamp is playing. +** If it returns 3, Winamp is paused. +** If it returns 0, Winamp is not playing. +*/ + + +#define IPC_GETOUTPUTTIME 105 +/* int res = SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETOUTPUTTIME); +** This api can return two different sets of information about current playback status. +** +** If mode = 0 then it will return the position (in ms) of the currently playing track. +** Will return -1 if Winamp is not playing. +** +** If mode = 1 then it will return the current track length (in seconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +** +** If mode = 2 then it will return the current track length (in milliseconds). +** Will return -1 if there are no tracks (or possibly if Winamp cannot get the length). +*/ + + +#define IPC_JUMPTOTIME 106 +/* (requires Winamp 1.60+) +** SendMessage(hwnd_winamp,WM_WA_IPC,ms,IPC_JUMPTOTIME); +** This api sets the current position (in milliseconds) for the currently playing song. +** The resulting playback position may only be an approximate time since some playback +** formats do not provide exact seeking e.g. mp3 +** This returns -1 if Winamp is not playing, 1 on end of file, or 0 if it was successful. +*/ + + +#define IPC_GETMODULENAME 109 +#define IPC_EX_ISRIGHTEXE 666 +/* usually shouldnt bother using these, but here goes: +** send a WM_COPYDATA with IPC_GETMODULENAME, and an internal +** flag gets set, which if you send a normal WM_WA_IPC message with +** IPC_EX_ISRIGHTEXE, it returns whether or not that filename +** matches. lame, I know. +*/ + + +#define IPC_WRITEPLAYLIST 120 +/* (requires Winamp 1.666+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_WRITEPLAYLIST); +** +** IPC_WRITEPLAYLIST will write the current playlist to '\\Winamp.m3u' and +** will also return the current playlist position (see IPC_GETLISTPOS). +** +** This is kinda obsoleted by some of the newer 2.x api items but it still is good for +** use with a front-end program (instead of a plug-in) and you want to see what is in the +** current playlist. +** +** This api will only save out extended file information in the #EXTINF entry if Winamp +** has already read the data such as if the file was played of scrolled into view. If +** Winamp has not read the data then you will only find the file with its filepath entry +** (as is the base requirements for a m3u playlist). +*/ + + +#define IPC_SETPLAYLISTPOS 121 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,position,IPC_SETPLAYLISTPOS) +** IPC_SETPLAYLISTPOS sets the playlist position to the specified 'position'. +** It will not change playback status or anything else. It will just set the current +** position in the playlist and will update the playlist view if necessary. +** +** If you use SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_BUTTON2,0),0); +** after using IPC_SETPLAYLISTPOS then Winamp will start playing the file at 'position'. +*/ + + +#define IPC_SETVOLUME 122 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,volume,IPC_SETVOLUME); +** IPC_SETVOLUME sets the volume of Winamp (between the range of 0 to 255). +** +** If you pass 'volume' as -666 then the message will return the current volume. +** int curvol = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME); +*/ + + +#define IPC_GETVOLUME(hwnd_winamp) SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETVOLUME) +/* (requires Winamp 2.0+) +** int curvol = IPC_GETVOLUME(hwnd_winamp); +** This will return the current volume of Winamp or +*/ + + +#define IPC_SETPANNING 123 +/* (requires Winamp 2.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,panning,IPC_SETPANNING); +** IPC_SETPANNING sets the panning of Winamp from 0 (left) to 255 (right). +** +** At least in 5.x+ this works from -127 (left) to 127 (right). +** +** If you pass 'panning' as -666 to this api then it will return the current panning. +** int curpan = SendMessage(hwnd_winamp,WM_WA_IPC,-666,IPC_SETPANNING); +*/ + + +#define IPC_GETLISTLENGTH 124 +/* (requires Winamp 2.0+) +** int length = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTLENGTH); +** IPC_GETLISTLENGTH returns the length of the current playlist as the number of tracks. +*/ + + +#define IPC_GETLISTPOS 125 +/* (requires Winamp 2.05+) +** int pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** IPC_GETLISTPOS returns the current playlist position (which is shown in the playlist +** editor as a differently coloured text entry e.g is yellow for the classic skin). +** +** This api is a lot like IPC_WRITEPLAYLIST but a lot faster since it does not have to +** write out the whole of the current playlist first. +*/ + + +#define IPC_GETINFO 126 +/* (requires Winamp 2.05+) +** int inf=SendMessage(hwnd_winamp,WM_WA_IPC,mode,IPC_GETINFO); +** IPC_GETINFO returns info about the current playing song. The value +** it returns depends on the value of 'mode'. +** Mode Meaning +** ------------------ +** 0 Samplerate, in kilohertz (i.e. 44) +** 1 Bitrate (i.e. 128) +** 2 Channels (i.e. 2) +** 3 (5+) Video LOWORD=w HIWORD=h +** 4 (5+) > 65536, string (video description) +** 5 (5.25+) Samplerate, in hertz (i.e. 44100) +*/ + + +#define IPC_GETEQDATA 127 +/* (requires Winamp 2.05+) +** int data=SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** IPC_GETEQDATA queries the status of the EQ. +** The value returned depends on what 'pos' is set to: +** Value Meaning +** ------------------ +** 0-9 The 10 bands of EQ data. 0-63 (+20db - -20db) +** 10 The preamp value. 0-63 (+20db - -20db) +** 11 Enabled. zero if disabled, nonzero if enabled. +** 12 Autoload. zero if disabled, nonzero if enabled. +*/ + + +#define IPC_SETEQDATA 128 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,pos,IPC_GETEQDATA); +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SETEQDATA); +** IPC_SETEQDATA sets the value of the last position retrieved +** by IPC_GETEQDATA. This is pretty lame, and we should provide +** an extended version that lets you do a MAKELPARAM(pos,value). +** someday... + + new (2.92+): + if the high byte is set to 0xDB, then the third byte specifies + which band, and the bottom word specifies the value. +*/ + + +#define IPC_ADDBOOKMARK 129 +#define IPC_ADDBOOKMARKW 131 +/* (requires Winamp 2.4+) +** This is sent as a WM_COPYDATA using IPC_ADDBOOKMARK as the dwData value and the +** directory you want to change to as the lpData member. This will add the specified +** file / url to the Winamp bookmark list. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_ADDBOOKMARK; +** cds.lpData = (void*)"http://www.blah.com/listen.pls"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +** +** +** In Winamp 5.0+ we use this as a normal WM_WA_IPC and the string is null separated as +** the filename and then the title of the entry. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)"filename\0title\0",IPC_ADDBOOKMARK); +** +** This will notify the library / bookmark editor that a bookmark was added. +** Note that using this message in this context does not actually add the bookmark. +** Do not use, it is essentially just a notification type message :) +*/ + + +#define IPC_INSTALLPLUGIN 130 +/* This is not implemented (and is very unlikely to be done due to safety concerns). +** If it was then you could do a WM_COPYDATA with a path to a .wpz and it would then +** install the plugin for you. +** +** COPYDATASTRUCT cds = {0}; +** cds.dwData = IPC_INSTALLPLUGIN; +** cds.lpData = (void*)"c:\\path\\to\\file.wpz"; +** cds.cbData = lstrlen((char*)cds.lpData)+1; // include space for null char +** SendMessage(hwnd_winamp,WM_COPYDATA,0,(LPARAM)&cds); +*/ + + +#define IPC_RESTARTWINAMP 135 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_RESTARTWINAMP); +** IPC_RESTARTWINAMP will restart Winamp (isn't that obvious ? :) ) +** If this fails to make Winamp start after closing then there is a good chance one (or +** more) of the currently installed plugins caused Winamp to crash on exit (either as a +** silent crash or a full crash log report before it could call itself start again. +*/ + + +#define IPC_ISFULLSTOP 400 +/* (requires winamp 2.7+ I think) +** int ret=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISFULLSTOP); +** This is useful for when you're an output plugin and you want to see if the stop/close +** happening is a full stop or if you are just between tracks. This returns non zero if +** it is a full stop or zero if it is just a new track. +** benski> i think it's actually the other way around - +** !0 for EOF and 0 for user pressing stop +*/ + + +#define IPC_INETAVAILABLE 242 +/* (requires Winamp 2.05+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INETAVAILABLE); +** IPC_INETAVAILABLE will return 1 if an Internet connection is available for Winamp and +** relates to the internet connection type setting on the main general preferences page +** in the Winamp preferences. +*/ + + +#define IPC_UPDTITLE 243 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_UPDTITLE); +** IPC_UPDTITLE will ask Winamp to update the information about the current title and +** causes GetFileInfo(..) in the input plugin associated with the current playlist entry +** to be called. This can be called such as when an input plugin is buffering a file so +** that it can cause the buffer percentage to appear in the playlist. +*/ + + +#define IPC_REFRESHPLCACHE 247 +/* (requires Winamp 2.2+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REFRESHPLCACHE); +** IPC_REFRESHPLCACHE will flush the playlist cache buffer and you send this if you want +** Winamp to go refetch the titles for all of the entries in the current playlist. +** +** 5.3+: pass a wchar_t * string in wParam, and it'll do a strnicmp() before clearing the cache +*/ + + +#define IPC_GET_SHUFFLE 250 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_SHUFFLE); +** IPC_GET_SHUFFLE returns the status of the shuffle option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_GET_REPEAT 251 +/* (requires Winamp 2.4+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_REPEAT); +** IPC_GET_REPEAT returns the status of the repeat option. +** If set then it will return 1 and if not set then it will return 0. +*/ + + +#define IPC_SET_SHUFFLE 252 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_SHUFFLE); +** IPC_SET_SHUFFLE sets the status of the shuffle option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_SET_REPEAT 253 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_REPEAT); +** IPC_SET_REPEAT sets the status of the repeat option. +** If 'value' is 1 then shuffle is turned on. +** If 'value' is 0 then shuffle is turned off. +*/ + + +#define IPC_ENABLEDISABLE_ALL_WINDOWS 259 // 0xdeadbeef to disable +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(enable?0:0xdeadbeef),IPC_ENABLEDISABLE_ALL_WINDOWS); +** Sending this message with 0xdeadbeef as the param will disable all winamp windows and +** any other values will enable all of the Winamp windows again. When disabled you won't +** get any response on clicking or trying to do anything to the Winamp windows. If the +** taskbar icon is shown then you may still have control ;) +*/ + + +#define IPC_GETWND 260 +/* (requires Winamp 2.9+) +** HWND h=SendMessage(hwnd_winamp,WM_WA_IPC,IPC_GETWND_xxx,IPC_GETWND); +** returns the HWND of the window specified. +*/ + #define IPC_GETWND_EQ 0 // use one of these for the param + #define IPC_GETWND_PE 1 + #define IPC_GETWND_MB 2 + #define IPC_GETWND_VIDEO 3 +#define IPC_ISWNDVISIBLE 261 // same param as IPC_GETWND + + +/************************************************************************ +***************** in-process only (WE LOVE PLUGINS) +************************************************************************/ + +#define IPC_SETSKINW 199 +#define IPC_SETSKIN 200 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"skinname",IPC_SETSKIN); +** IPC_SETSKIN sets the current skin to "skinname". Note that skinname +** can be the name of a skin, a skin .zip file, with or without path. +** If path isn't specified, the default search path is the winamp skins +** directory. +*/ + + +#define IPC_GETSKIN 201 +#define IPC_GETSKINW 1201 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)skinname_buffer,IPC_GETSKIN); +** IPC_GETSKIN puts the directory where skin bitmaps can be found +** into skinname_buffer. +** skinname_buffer must be MAX_PATH characters in length. +** When using a .zip'd skin file, it'll return a temporary directory +** where the ZIP was decompressed. +*/ + + +#define IPC_EXECPLUG 202 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)"vis_file.dll",IPC_EXECPLUG); +** IPC_EXECPLUG executes a visualization plug-in pointed to by WPARAM. +** the format of this string can be: +** "vis_whatever.dll" +** "vis_whatever.dll,0" // (first mod, file in winamp plug-in dir) +** "C:\\dir\\vis_whatever.dll,1" +*/ + + +#define IPC_GETPLAYLISTFILE 211 +#define IPC_GETPLAYLISTFILEW 214 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTFILE); +** IPC_GETPLAYLISTFILE gets the filename of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETPLAYLISTTITLE 212 +#define IPC_GETPLAYLISTTITLEW 213 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); +** +** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ + + +#define IPC_GETHTTPGETTER 240 +/* retrieves a function pointer to a HTTP retrieval function. +** if this is unsupported, returns 1 or 0. +** the function should be: +** int (*httpRetrieveFile)(HWND hwnd, char *url, char *file, char *dlgtitle); +** if you call this function, with a parent window, a URL, an output file, and a dialog title, +** it will return 0 on successful download, 1 on error. +*/ + + +#define IPC_GETHTTPGETTERW 1240 +/* int (*httpRetrieveFileW)(HWND hwnd, char *url, wchar_t *file, wchar_t *dlgtitle); */ + + +#define IPC_MBOPEN 241 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_MBOPEN); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPEN); +** IPC_MBOPEN will open a new URL in the minibrowser. if url is NULL, it will open the Minibrowser window. +*/ + + +#define IPC_CHANGECURRENTFILE 245 +/* (requires Winamp 2.05+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILE); +** IPC_CHANGECURRENTFILE will set the current playlist item. +*/ + + +#define IPC_CHANGECURRENTFILEW 1245 +/* (requires Winamp 5.3+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)file,IPC_CHANGECURRENTFILEW); +** IPC_CHANGECURRENTFILEW will set the current playlist item. +*/ + + +#define IPC_GETMBURL 246 +/* (requires Winamp 2.2+) +** char buffer[4096]; // Urls can be VERY long +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)buffer,IPC_GETMBURL); +** IPC_GETMBURL will retrieve the current Minibrowser URL into buffer. +** buffer must be at least 4096 bytes long. +*/ + + +#define IPC_MBBLOCK 248 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_MBBLOCK); +** +** IPC_MBBLOCK will block the Minibrowser from updates if value is set to 1 +*/ + + +#define IPC_MBOPENREAL 249 +/* (requires Winamp 2.4+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)url,IPC_MBOPENREAL); +** +** IPC_MBOPENREAL works the same as IPC_MBOPEN except that it will works even if +** IPC_MBBLOCK has been set to 1 +*/ + + +#define IPC_ADJUST_OPTIONSMENUPOS 280 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_OPTIONSMENUPOS); +** moves where winamp expects the Options menu in the main menu. Useful if you wish to insert a +** menu item above the options/skins/vis menus. +*/ + + +#define IPC_GET_HMENU 281 +/* (requires Winamp 2.9+) +** HMENU hMenu=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0,IPC_GET_HMENU); +** values for data: +** 0 : main popup menu +** 1 : main menubar file menu +** 2 : main menubar options menu +** 3 : main menubar windows menu +** 4 : main menubar help menu +** other values will return NULL. +*/ + + +#define IPC_GET_EXTENDED_FILE_INFO 290 //pass a pointer to the following struct in wParam +#define IPC_GET_EXTENDED_FILE_INFO_HOOKABLE 296 +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to query, and ret to a buffer, with retlen to the +** length of that buffer, and then SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_GET_EXTENDED_FILE_INFO); +** the results should be in the buffer pointed to by ret. +** returns 1 if the decoder supports a getExtendedFileInfo method +*/ +typedef struct { + const char *filename; + const char *metadata; + char *ret; + size_t retlen; +} extendedFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFO 291 //pass a pointer to the following struct in wParam +typedef struct { + const char *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + char *title; + int titlelen; +} basicFileInfoStruct; + + +#define IPC_GET_BASIC_FILE_INFOW 1291 //pass a pointer to the following struct in wParam +typedef struct { + const wchar_t *filename; + + int quickCheck; // set to 0 to always get, 1 for quick, 2 for default (if 2, quickCheck will be set to 0 if quick wasnot used) + + // filled in by winamp + int length; + wchar_t *title; + int titlelen; +} basicFileInfoStructW; + + +#define IPC_GET_EXTLIST 292 //returns doublenull delimited. GlobalFree() it when done. if data is 0, returns raw extlist, if 1, returns something suitable for getopenfilename +#define IPC_GET_EXTLISTW 1292 // wide char version of above + + +#define IPC_INFOBOX 293 +typedef struct { + HWND parent; + char *filename; +} infoBoxParam; + + +#define IPC_INFOBOXW 1293 +typedef struct { + HWND parent; + const wchar_t *filename; +} infoBoxParamW; + + +#define IPC_SET_EXTENDED_FILE_INFO 294 //pass a pointer to the a extendedFileInfoStruct in wParam +/* (requires Winamp 2.9+) +** to use, create an extendedFileInfoStruct, point the values filename and metadata to the +** filename and metadata field you wish to write in ret. (retlen is not used). and then +** SendMessage(hwnd_winamp,WM_WA_IPC,&struct,IPC_SET_EXTENDED_FILE_INFO); +** returns 1 if the metadata is supported +** Call IPC_WRITE_EXTENDED_FILE_INFO once you're done setting all the metadata you want to update +*/ + + +#define IPC_WRITE_EXTENDED_FILE_INFO 295 +/* (requires Winamp 2.9+) +** writes all the metadata set thru IPC_SET_EXTENDED_FILE_INFO to the file +** returns 1 if the file has been successfully updated, 0 if error +*/ + + +#define IPC_FORMAT_TITLE 297 +typedef struct +{ + char *spec; // NULL=default winamp spec + void *p; + + char *out; + int out_len; + + char * (*TAGFUNC)(const char * tag, void * p); //return 0 if not found + void (*TAGFREEFUNC)(char * tag,void * p); +} waFormatTitle; + + +#define IPC_FORMAT_TITLE_EXTENDED 298 // similiar to IPC_FORMAT_TITLE, but falls back to Winamp's %tags% if your passed tag function doesn't handle it +typedef struct +{ + const wchar_t *filename; + int useExtendedInfo; // set to 1 if you want the Title Formatter to query the input plugins for any tags that your tag function fails on + const wchar_t *spec; // NULL=default winamp spec + void *p; + + wchar_t *out; + int out_len; + + wchar_t * (*TAGFUNC)(const wchar_t * tag, void * p); //return 0 if not found, -1 for empty tag + void (*TAGFREEFUNC)(wchar_t *tag, void *p); +} waFormatTitleExtended; + + +#define IPC_COPY_EXTENDED_FILE_INFO 299 +typedef struct +{ + const char *source; + const char *dest; +} copyFileInfoStruct; + + +#define IPC_COPY_EXTENDED_FILE_INFOW 1299 +typedef struct +{ + const wchar_t *source; + const wchar_t *dest; +} copyFileInfoStructW; + + +typedef struct { + int (*inflateReset)(void *strm); + int (*inflateInit_)(void *strm,const char *version, int stream_size); + int (*inflate)(void *strm, int flush); + int (*inflateEnd)(void *strm); + unsigned long (*crc32)(unsigned long crc, const unsigned char *buf, unsigned int len); +} wa_inflate_struct; + +#define IPC_GETUNCOMPRESSINTERFACE 331 +/* returns a function pointer to uncompress(). +** int (*uncompress)(unsigned char *dest, unsigned long *destLen, const unsigned char *source, unsigned long sourceLen); +** right out of zlib, useful for decompressing zlibbed data. +** if you pass the parm of 0x10100000, it will return a wa_inflate_struct * to an inflate API. +*/ + + +typedef struct _prefsDlgRec { + HINSTANCE hInst; // dll instance containing the dialog resource + int dlgID; // resource identifier of the dialog + void *proc; // window proceedure for handling the dialog defined as + // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) + + char *name; // name shown for the prefs page in the treelist + intptr_t where; // section in the treelist the prefs page is to be added to + // 0 for General Preferences + // 1 for Plugins + // 2 for Skins + // 3 for Bookmarks (no longer in the 5.0+ prefs) + // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) + + intptr_t _id; + struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means +} prefsDlgRec; + +typedef struct _prefsDlgRecW { + HINSTANCE hInst; // dll instance containing the dialog resource + int dlgID; // resource identifier of the dialog + void *proc; // window proceedure for handling the dialog defined as + // LRESULT CALLBACK PrefsPage(HWND,UINT,WPARAM,LPARAM) + + wchar_t *name; // name shown for the prefs page in the treelist + intptr_t where; // section in the treelist the prefs page is to be added to + // 0 for General Preferences + // 1 for Plugins + // 2 for Skins + // 3 for Bookmarks (no longer in the 5.0+ prefs) + // 4 for Prefs (the old 'Setup' section - no longer in 5.0+) + + intptr_t _id; + struct _prefsDlgRec *next; // no longer implemented as a linked list, now used by Winamp for other means +} prefsDlgRecW; + +#define IPC_ADD_PREFS_DLG 332 +#define IPC_ADD_PREFS_DLGW 1332 +#define IPC_REMOVE_PREFS_DLG 333 +/* (requires Winamp 2.9+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); +** +** IPC_ADD_PREFS_DLG: +** To use this you need to allocate a prefsDlgRec structure (either on the heap or with +** some global data but NOT on the stack) and then initialise the members of the structure +** (see the definition of the prefsDlgRec structure above). +** +** hInst - dll instance of where the dialog resource is located. +** dlgID - id of the dialog resource. +** proc - dialog window procedure for the prefs dialog. +** name - name of the prefs page as shown in the preferences list. +** where - see above for the valid locations the page can be added. +** +** Then you do SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** +** example: +** +** prefsDlgRec* prefsRec = 0; +** prefsRec = GlobalAlloc(GPTR,sizeof(prefsDlgRec)); +** prefsRec->hInst = hInst; +** prefsRec->dlgID = IDD_PREFDIALOG; +** prefsRec->name = "Pref Page"; +** prefsRec->where = 0; +** prefsRec->proc = PrefsPage; +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_ADD_PREFS_DLG); +** +** +** IPC_REMOVE_PREFS_DLG: +** To use you pass the address of the same prefsRec you used when adding the prefs page +** though you shouldn't really ever have to do this but it's good to clean up after you +** when you're plugin is being unloaded. +** +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_REMOVE_PREFS_DLG); +** +** IPC_ADD_PREFS_DLGW +** requires Winamp 5.53+ +*/ + + +#define IPC_OPENPREFSTOPAGE 380 +/* SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&prefsRec,IPC_OPENPREFSTOPAGE); +** +** There are two ways of opening a preferences page. +** +** The first is to pass an id of a builtin preferences page (see below for ids) or a +** &prefsDlgRec of the preferences page to open and this is normally done if you are +** opening a prefs page you added yourself. +** +** If the page id does not or the &prefsRec is not valid then the prefs dialog will be +** opened to the first page available (usually the Winamp Pro page). +** +** (requires Winamp 5.04+) +** Passing -1 for param will open the preferences dialog to the last page viewed. +** +** Note: v5.0 to 5.03 had a bug in this api +** +** On the first call then the correct prefs page would be opened to but on the next call +** the prefs dialog would be brought to the front but the page would not be changed to the +** specified. +** In 5.04+ it will change to the prefs page specified if the prefs dialog is already open. +*/ + +/* Builtin Preference page ids (valid for 5.0+) +** (stored in the lParam member of the TVITEM structure from the tree item) +** +** These can be useful if you want to detect a specific prefs page and add things to it +** yourself or something like that ;) +** +** Winamp Pro 20 +** General Preferences 0 +** File Types 1 +** Playlist 23 +** Titles 21 +** Playback 42 (added in 5.25) +** Station Info 41 (added in 5.11 & removed in 5.5) +** Video 24 +** Localization 25 (added in 5.5) +** Skins 40 +** Classic Skins 22 +** Plugins 30 +** Input 31 +** Output 32 +** Visualisation 33 +** DSP/Effect 34 +** General Purpose 35 +** +** Note: +** Custom page ids begin from 60 +** The value of the normal custom pages (Global Hotkeys, Jump To File, etc) is not +** guaranteed since it depends on the order in which the plugins are loaded which can +** change on different systems. +** +** Global Hotkeys, Jump To File, Media Library (under General Preferences and child pages), +** Media Library (under Plugins), Portables, CD Ripping and Modern Skins are custom pages +** created by the plugins shipped with Winamp. +*/ + + +#define IPC_GETINIFILE 334 +/* (requires Winamp 2.9+) +** char *ini=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE); +** This returns a pointer to the full file path of winamp.ini. +** +** char ini_path[MAX_PATH] = {0}; +** +** void GetIniFilePath(HWND hwnd){ +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION) >= 0x2900){ +** // this gets the string of the full ini file path +** lstrcpyn(ini_path,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIFILE),sizeof(ini_path)); +** } +** else{ +** char* p = ini_path; +** p += GetModuleFileName(0,ini_path,sizeof(ini_path)) - 1; +** while(p && *p != '.'){p--;} +** lstrcpyn(p+1,"ini",sizeof(ini_path)); +** } +** } +*/ + + +#define IPC_GETINIDIRECTORY 335 +/* (requires Winamp 2.9+) +** char *dir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIDIRECTORY); +** This returns a pointer to the directory where winamp.ini can be found and is +** useful if you want store config files but you don't want to use winamp.ini. +*/ + + +#define IPC_GETPLUGINDIRECTORY 336 +/* (requires Winamp 5.11+) +** char *plugdir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPLUGINDIRECTORY); +** This returns a pointer to the directory where Winamp has its plugins stored and is +** useful if you want store config files in plugins.ini in the plugins folder or for +** accessing any local files in the plugins folder. +*/ + + +#define IPC_GETM3UDIRECTORY 337 +/* (requires Winamp 5.11+) +** char *m3udir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORY); +** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. +*/ + + +#define IPC_GETM3UDIRECTORYW 338 +/* (requires Winamp 5.3+) +** wchar_t *m3udirW=(wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETM3UDIRECTORYW); +** This returns a pointer to the directory where winamp.m3u (and winamp.m3u8 if supported) is stored in. +*/ + + +#define IPC_SPAWNBUTTONPOPUP 361 // param = +// 0 = eject +// 1 = previous +// 2 = next +// 3 = pause +// 4 = play +// 5 = stop + + +#define IPC_OPENURLBOX 360 +/* (requires Winamp 5.0+) +** HGLOBAL hglobal = (HGLOBAL)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENURLBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +** This will return a HGLOBAL that needs to be freed with GlobalFree() if this worked. +*/ + + +#define IPC_OPENFILEBOX 362 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENFILEBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +*/ + + +#define IPC_OPENDIRBOX 363 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_OPENDIRBOX); +** You pass a hwnd for the dialog to be parented to (which modern skin support uses). +*/ + + +#define IPC_SETDIALOGBOXPARENT 364 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)parent,IPC_SETDIALOGBOXPARENT); +** Pass 'parent' as the window which will be used as the parent for a number of the built +** in Winamp dialogs and is useful when you are taking over the whole of the UI so that +** the dialogs will not appear at the bottom right of the screen since the main winamp +** window is located at 3000x3000 by gen_ff when this is used. Call this again with +** parent = null to reset the parent back to the orginal Winamp window. +*/ + +#define IPC_GETDIALOGBOXPARENT 365 +/* (requires Winamp 5.51+) +** HWND hwndParent = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)0, IPC_GETDIALOGBOXPARENT); +** hwndParent can/must be passed to all modal dialogs (including MessageBox) thats uses winamp as a parent +*/ + +#define IPC_UPDATEDIALOGBOXPARENT 366 +/* (requires Winamp 5.53+) +** if you previous called IPC_SETDIALOGBOXPARENT, call this every time your window resizes +*/ + +#define IPC_DRO_MIN 401 // reserved for DrO +#define IPC_SET_JTF_COMPARATOR 409 +/* pass me an int (__cdecl *)(const char *, const char *) in wParam */ +#define IPC_SET_JTF_COMPARATOR_W 410 +/* pass me an int (__cdecl *)(const wchar_t *, const wchar_t *) in wParam ... maybe someday :) */ +#define IPC_SET_JTF_DRAWTEXT 416 + +#define IPC_DRO_MAX 499 + + +// pass 0 for a copy of the skin HBITMAP +// pass 1 for name of font to use for playlist editor likeness +// pass 2 for font charset +// pass 3 for font size +#define IPC_GET_GENSKINBITMAP 503 + + +typedef struct +{ + HWND me; //hwnd of the window + + #define EMBED_FLAGS_NORESIZE 0x1 + // set this bit to keep window from being resizable + + #define EMBED_FLAGS_NOTRANSPARENCY 0x2 + // set this bit to make gen_ff turn transparency off for this window + + #define EMBED_FLAGS_NOWINDOWMENU 0x4 + // set this bit to prevent gen_ff from automatically adding your window to the right-click menu + + #define EMBED_FLAGS_GUID 0x8 + // (5.31+) call SET_EMBED_GUID(yourEmbedWindowStateStruct, GUID) to define a GUID for this window + + #define SET_EMBED_GUID(windowState, windowGUID) { windowState->flags |= EMBED_FLAGS_GUID; *((GUID *)&windowState->extra_data[4])=windowGUID; } + #define GET_EMBED_GUID(windowState) (*((GUID *)&windowState->extra_data[4])) + + int flags; // see above + + RECT r; + void *user_ptr; // for application use + int extra_data[64]; // for internal winamp use +} embedWindowState; + +#define IPC_GET_EMBEDIF 505 +/* (requires Winamp 2.9+) +** HWND myframe = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&wa_wnd,IPC_GET_EMBEDIF); +** +** or +** +** HWND myframe = 0; +** HWND (*embed)(embedWindowState *params)=0; +** *(void**)&embed = (void*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_EMBEDIF); +** myframe = embed(&wa_wnd); +** +** You pass an embedWindowState* and it will return a hwnd for the frame window or if you +** pass wParam as null then it will return a HWND embedWindow(embedWindowState *); +*/ + +#define IPC_SKINWINDOW 534 + +typedef struct __SKINWINDOWPARAM +{ + HWND hwndToSkin; + GUID windowGuid; +} SKINWINDOWPARAM; + + + +#define IPC_EMBED_ENUM 532 +typedef struct embedEnumStruct +{ + int (*enumProc)(embedWindowState *ws, struct embedEnumStruct *param); // return 1 to abort + int user_data; // or more :) +} embedEnumStruct; + // pass + + +#define IPC_EMBED_ISVALID 533 +/* (requires Winamp 2.9+) +** int valid = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)embedhwnd,IPC_EMBED_ISVALID); +** Pass a hwnd in the wParam to this to check if the hwnd is a valid embed window or not. +*/ + + +#define IPC_CONVERTFILE 506 +/* (requires Winamp 2.92+) +** Converts a given file to a different format (PCM, MP3, etc...) +** To use, pass a pointer to a waFileConvertStruct struct +** This struct can be either on the heap or some global +** data, but NOT on the stack. At least, until the conversion is done. +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE); +** +** Return value: +** 0: Can't start the conversion. Look at myConvertStruct->error for details. +** 1: Conversion started. Status messages will be sent to the specified callbackhwnd. +** Be sure to call IPC_CONVERTFILE_END when your callback window receives the +** IPC_CB_CONVERT_DONE message. +*/ +typedef struct +{ + char *sourcefile; // "c:\\source.mp3" + char *destfile; // "c:\\dest.pcm" + intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + char *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStruct; + + +#define IPC_CONVERTFILEW 515 +// (requires Winamp 5.36+) +typedef struct +{ + wchar_t *sourcefile; // "c:\\source.mp3" + wchar_t *destfile; // "c:\\dest.pcm" + intptr_t destformat[8]; // like 'PCM ',srate,nch,bps. + //hack alert! you can set destformat[6]=mmioFOURCC('I','N','I',' '); and destformat[7]=(int)my_ini_file; (where my_ini_file is a char*) + HWND callbackhwnd; // window that will receive the IPC_CB_CONVERT notification messages + + //filled in by winamp.exe + wchar_t *error; //if IPC_CONVERTFILE returns 0, the reason will be here + + int bytes_done; //you can look at both of these values for speed statistics + int bytes_total; + int bytes_out; + + int killswitch; // don't set it manually, use IPC_CONVERTFILE_END + intptr_t extra_data[64]; // for internal winamp use +} convertFileStructW; + + +#define IPC_CONVERTFILE_END 507 +/* (requires Winamp 2.92+) +** Stop/ends a convert process started from IPC_CONVERTFILE +** You need to call this when you receive the IPC_CB_CONVERTDONE message or when you +** want to abort a conversion process +** +** eg: SendMessage(hwnd_winamp,WM_WA_IPC,&myConvertStruct,IPC_CONVERTFILE_END); +** +** No return value +*/ + + +#define IPC_CONVERTFILEW_END 516 +// (requires Winamp 5.36+) + +typedef struct { + HWND hwndParent; + int format; + + //filled in by winamp.exe + HWND hwndConfig; + int extra_data[8]; + //hack alert! you can set extra_data[6]=mmioFOURCC('I','N','I',' '); and extra_data[7]=(int)my_ini_file; (where my_ini_file is a char*) +} convertConfigStruct; + + +#define IPC_CONVERT_CONFIG 508 +#define IPC_CONVERT_CONFIG_END 509 + +typedef struct +{ + void (*enumProc)(intptr_t user_data, const char *desc, int fourcc); + intptr_t user_data; +} converterEnumFmtStruct; +#define IPC_CONVERT_CONFIG_ENUMFMTS 510 +/* (requires Winamp 2.92+) +*/ + +typedef struct +{ + char cdletter; + char *playlist_file; + HWND callback_hwnd; + + //filled in by winamp.exe + char *error; +} burnCDStruct; +#define IPC_BURN_CD 511 +/* (requires Winamp 5.0+) +*/ + +typedef struct +{ + convertFileStruct *cfs; + int priority; +} convertSetPriority; + + +#define IPC_CONVERT_SET_PRIORITY 512 + +typedef struct +{ + convertFileStructW *cfs; + int priority; +} convertSetPriorityW; + + +#define IPC_CONVERT_SET_PRIORITYW 517 +// (requires Winamp 5.36+) + +typedef struct +{ + unsigned int format; //fourcc value + char *item; // config item, eg "bitrate" + char *data; // buffer to recieve, or buffer that contains the data + int len; // length of the data buffer (only used when getting a config item) + char *configfile; // config file to read from +} convertConfigItem; + + +#define IPC_CONVERT_CONFIG_SET_ITEM 513 // returns TRUE if successful +#define IPC_CONVERT_CONFIG_GET_ITEM 514 // returns TRUE if successful + + +typedef struct +{ + const char *filename; + char *title; // 2048 bytes + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStruct; + +#define IPC_HOOK_TITLES 850 +/* (requires Winamp 5.0+) +** If you hook this message and modify the information then make sure to return TRUE. +** If you don't hook the message then make sure you pass it on through the subclass chain. +** +** LRESULT CALLBACK WinampWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) +** { +** LRESULT ret = CallWindowProc((WNDPROC)WinampProc,hwnd,umsg,wParam,lParam); +** +** if(message==WM_WA_IPC && lParam==IPC_HOOK_TITLES) +** { +** waHookTitleStruct *ht = (waHookTitleStruct *) wParam; +** // Doing ATF stuff with ht->title, whatever... +** return TRUE; +** } +** return ret; +** } +*/ + +typedef struct +{ + const wchar_t *filename; + wchar_t *title; // 2048 characters + int length; + int force_useformatting; // can set this to 1 if you want to force a url to use title formatting shit +} waHookTitleStructW; +#define IPC_HOOK_TITLESW 851 +/* (requires Winamp 5.3+) +** See information on IPC_HOOK_TITLES for how to process this. +*/ + + +#define IPC_GETSADATAFUNC 800 +// 0: returns a char *export_sa_get() that returns 150 bytes of data +// 1: returns a export_sa_setreq(int want); + + +#define IPC_GETVUDATAFUNC 801 +// 0: returns a int export_vu_get(int channel) that returns 0-255 (or -1 for bad channel) + + +#define IPC_ISMAINWNDVISIBLE 900 +/* (requires Winamp 5.0+) +** int visible=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISMAINWNDVISIBLE); +** You send this to Winamp to query if the main window is visible or not such as by +** unchecking the option in the main right-click menu. If the main window is visible then +** this will return 1 otherwise it returns 0. +*/ + + +typedef struct +{ + int numElems; + int *elems; + HBITMAP bm; // set if you want to override +} waSetPlColorsStruct; + +#define IPC_SETPLEDITCOLORS 920 +/* (requires Winamp 5.0+) +** This is sent by gen_ff when a modern skin is being loaded to set the colour scheme for +** the playlist editor. When sent numElems is usually 6 and matches with the 6 possible +** colours which are provided be pledit.txt from the classic skins. The elems array is +** defined as follows: +** +** elems = 0 => normal text +** elems = 1 => current text +** elems = 2 => normal background +** elems = 3 => selected background +** elems = 4 => minibroswer foreground +** elems = 5 => minibroswer background +** +** if(uMsg == WM_WA_IPC && lParam == IPC_SETPLEDITCOLORS) +** { +** waSetPlColorsStruct* colStr = (waSetPlColorsStruct*)wp; +** if(colStr) +** { +** // set or inspect the colours being used (basically for gen_ff's benefit) +** } +** } +*/ + + +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; +} waSpawnMenuParms; + +// waSpawnMenuParms2 is used by the menubar submenus +typedef struct +{ + HWND wnd; + int xpos; // in screen coordinates + int ypos; + int width; + int height; +} waSpawnMenuParms2; + +// the following IPC use waSpawnMenuParms as parameter +#define IPC_SPAWNEQPRESETMENU 933 +#define IPC_SPAWNFILEMENU 934 //menubar +#define IPC_SPAWNOPTIONSMENU 935 //menubar +#define IPC_SPAWNWINDOWSMENU 936 //menubar +#define IPC_SPAWNHELPMENU 937 //menubar +#define IPC_SPAWNPLAYMENU 938 //menubar +#define IPC_SPAWNPEFILEMENU 939 //menubar +#define IPC_SPAWNPEPLAYLISTMENU 940 //menubar +#define IPC_SPAWNPESORTMENU 941 //menubar +#define IPC_SPAWNPEHELPMENU 942 //menubar +#define IPC_SPAWNMLFILEMENU 943 //menubar +#define IPC_SPAWNMLVIEWMENU 944 //menubar +#define IPC_SPAWNMLHELPMENU 945 //menubar +#define IPC_SPAWNPELISTOFPLAYLISTS 946 + + +#define WM_WA_SYSTRAY WM_USER+1 +/* This is sent by the system tray when an event happens (you might want to simulate it). +** +** if(uMsg == WM_WA_SYSTRAY) +** { +** switch(lParam) +** { +** // process the messages sent from the tray +** } +** } +*/ + + +#define WM_WA_MPEG_EOF WM_USER+2 +/* Input plugins send this when they are done playing back the current file to inform +** Winamp or anyother installed plugins that the current +** +** if(uMsg == WM_WA_MPEG_EOF) +** { +** // do what is needed here +** } +*/ + + +//// video stuff + +#define IPC_IS_PLAYING_VIDEO 501 // returns >1 if playing, 0 if not, 1 if old version (so who knows):) +#define IPC_GET_IVIDEOOUTPUT 500 // see below for IVideoOutput interface +#define VIDEO_MAKETYPE(A,B,C,D) ((A) | ((B)<<8) | ((C)<<16) | ((D)<<24)) +#define VIDUSER_SET_INFOSTRING 0x1000 +#define VIDUSER_GET_VIDEOHWND 0x1001 +#define VIDUSER_SET_VFLIP 0x1002 +#define VIDUSER_SET_TRACKSELINTERFACE 0x1003 // give your ITrackSelector interface as param2 +#define VIDUSER_OPENVIDEORENDERER 0x1004 +#define VIDUSER_CLOSEVIDEORENDERER 0x1005 +#define VIDUSER_GETPOPUPMENU 0x1006 +#define VIDUSER_SET_INFOSTRINGW 0x1007 + +typedef struct +{ + int w; + int h; + int vflip; + double aspectratio; + unsigned int fmt; +} VideoOpenStruct; + +#ifndef NO_IVIDEO_DECLARE +#ifdef __cplusplus + +class VideoOutput; +class SubsItem; + +#ifndef _NSV_DEC_IF_H_ +struct YV12_PLANE { + unsigned char* baseAddr; + long rowBytes; +} ; + +struct YV12_PLANES { + YV12_PLANE y; + YV12_PLANE u; + YV12_PLANE v; +}; +#endif + +class IVideoOutput +{ + public: + virtual ~IVideoOutput() { } + virtual int open(int w, int h, int vflip, double aspectratio, unsigned int fmt)=0; + virtual void setcallback(LRESULT (*msgcallback)(void *token, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam), void *token) { (void)token; (void)msgcallback; /* to eliminate warning C4100 */ } + virtual void close()=0; + virtual void draw(void *frame)=0; + virtual void drawSubtitle(SubsItem *item) {UNREFERENCED_PARAMETER(item); } + virtual void showStatusMsg(const char *text) {UNREFERENCED_PARAMETER(text); } + virtual int get_latency() { return 0; } + virtual void notifyBufferState(int bufferstate) { UNREFERENCED_PARAMETER(bufferstate); } /* 0-255*/ + virtual INT_PTR extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) { UNREFERENCED_PARAMETER(param1); UNREFERENCED_PARAMETER(param2); UNREFERENCED_PARAMETER(param3); return 0; } // Dispatchable, eat this! +}; + +class ITrackSelector +{ + public: + virtual int getNumAudioTracks()=0; + virtual void enumAudioTrackName(int n, const char *buf, int size)=0; + virtual int getCurAudioTrack()=0; + virtual int getNumVideoTracks()=0; + virtual void enumVideoTrackName(int n, const char *buf, int size)=0; + virtual int getCurVideoTrack()=0; + + virtual void setAudioTrack(int n)=0; + virtual void setVideoTrack(int n)=0; +}; + +#endif //cplusplus +#endif//NO_IVIDEO_DECLARE + +// these messages are callbacks that you can grab by subclassing the winamp window + +// wParam = +#define IPC_CB_WND_EQ 0 // use one of these for the param +#define IPC_CB_WND_PE 1 +#define IPC_CB_WND_MB 2 +#define IPC_CB_WND_VIDEO 3 +#define IPC_CB_WND_MAIN 4 + +#define IPC_CB_ONSHOWWND 600 +#define IPC_CB_ONHIDEWND 601 + +#define IPC_CB_GETTOOLTIP 602 + +#define IPC_CB_MISC 603 + #define IPC_CB_MISC_TITLE 0 // start of playing/stop/pause + #define IPC_CB_MISC_VOLUME 1 // volume/pan + #define IPC_CB_MISC_STATUS 2 // start playing/stop/pause/ffwd/rwd + #define IPC_CB_MISC_EQ 3 + #define IPC_CB_MISC_INFO 4 + #define IPC_CB_MISC_VIDEOINFO 5 + #define IPC_CB_MISC_TITLE_RATING 6 // (5.5+ for when the rating is changed via the songticker menu on current file) + +/* Example of using IPC_CB_MISC_STATUS to detect the start of track playback with 5.x +** +** if(lParam == IPC_CB_MISC && wParam == IPC_CB_MISC_STATUS) +** { +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISPLAYING) == 1 && +** !SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTTIME)) +** { +** char* file = (char*)SendMessage(hwnd_winamp,WM_WA_IPC, +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS),IPC_GETPLAYLISTFILE); +** // only output if a valid file was found +** if(file) +** { +** MessageBox(hwnd_winamp,file,"starting",0); +** // or do something else that you need to do +** } +** } +** } +*/ + + +#define IPC_CB_CONVERT_STATUS 604 // param value goes from 0 to 100 (percent) +#define IPC_CB_CONVERT_DONE 605 + + +#define IPC_ADJUST_FFWINDOWSMENUPOS 606 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFWINDOWSMENUPOS); +** This will move where Winamp expects the freeform windows in the menubar windows main +** menu. This is useful if you wish to insert a menu item above extra freeform windows. +*/ + + +#define IPC_ISDOUBLESIZE 608 +/* (requires Winamp 5.0+) +** int dsize=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISDOUBLESIZE); +** You send this to Winamp to query if the double size mode is enabled or not. +** If it is on then this will return 1 otherwise it will return 0. +*/ + + +#define IPC_ADJUST_FFOPTIONSMENUPOS 609 +/* (requires Winamp 2.9+) +** int newpos=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)adjust_offset,IPC_ADJUST_FFOPTIONSMENUPOS); +** moves where winamp expects the freeform preferences item in the menubar windows main +** menu. This is useful if you wish to insert a menu item above the preferences item. +** +** Note: This setting was ignored by gen_ff until it was fixed in 5.1 +** gen_ff would assume thatthe menu position was 11 in all cases and so when you +** had two plugins attempting to add entries into the main right click menu it +** would cause the 'colour themes' submenu to either be incorrectly duplicated or +** to just disappear.instead. +*/ + + +#define IPC_GETTIMEDISPLAYMODE 610 +/* (requires Winamp 5.0+) +** int mode=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETTIMEDISPLAYMODE); +** This will return the status of the time display i.e. shows time elapsed or remaining. +** This returns 0 if Winamp is displaying time elapsed or 1 for the time remaining. +*/ + + +#define IPC_SETVISWND 611 +/* (requires Winamp 5.0+) +** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)viswnd,IPC_SETVISWND); +** This allows you to set a window to receive the following message commands (which are +** used as part of the modern skin integration). +** When you have finished or your visualisation is closed then send wParam as zero to +** ensure that things are correctly tidied up. +*/ + +/* The following messages are received as the LOWORD(wParam) of the WM_COMMAND message. +** See %SDK%\winamp\wa5vis.txt for more info about visualisation integration in Winamp. +*/ +#define ID_VIS_NEXT 40382 +#define ID_VIS_PREV 40383 +#define ID_VIS_RANDOM 40384 +#define ID_VIS_FS 40389 +#define ID_VIS_CFG 40390 +#define ID_VIS_MENU 40391 + + +#define IPC_GETVISWND 612 +/* (requires Winamp 5.0+) +** int viswnd=(HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVISWND); +** This returns a HWND to the visualisation command handler window if set by IPC_SETVISWND. +*/ + + +#define IPC_ISVISRUNNING 613 +/* (requires Winamp 5.0+) +** int visrunning=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_ISVISRUNNING); +** This will return 1 if a visualisation is currently running and 0 if one is not running. +*/ + + +#define IPC_CB_VISRANDOM 628 // param is status of random + + +#define IPC_SETIDEALVIDEOSIZE 614 +/* (requires Winamp 5.0+) +** This is sent by Winamp back to itself so it can be trapped and adjusted as needed with +** the desired width in HIWORD(wParam) and the desired height in LOWORD(wParam). +** +** if(uMsg == WM_WA_IPC){ +** if(lParam == IPC_SETIDEALVIDEOSIZE){ +** wParam = MAKEWPARAM(height,width); +** } +** } +*/ + + +#define IPC_GETSTOPONVIDEOCLOSE 615 +/* (requires Winamp 5.0+) +** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETSTOPONVIDEOCLOSE); +** This will return 1 if 'stop on video close' is enabled and 0 if it is disabled. +*/ + + +#define IPC_SETSTOPONVIDEOCLOSE 616 +/* (requires Winamp 5.0+) +** int sovc=SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETSTOPONVIDEOCLOSE); +** Set enabled to 1 to enable and 0 to disable the 'stop on video close' option. +*/ + + +typedef struct { + HWND hwnd; + int uMsg; + WPARAM wParam; + LPARAM lParam; +} transAccelStruct; + +#define IPC_TRANSLATEACCELERATOR 617 +/* (requires Winamp 5.0+) +** (deprecated as of 5.53x+) +*/ + +typedef struct { + int cmd; + int x; + int y; + int align; +} windowCommand; // send this as param to an IPC_PLCMD, IPC_MBCMD, IPC_VIDCMD + + +#define IPC_CB_ONTOGGLEAOT 618 + + +#define IPC_GETPREFSWND 619 +/* (requires Winamp 5.0+) +** HWND prefs = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND); +** This will return a handle to the preferences dialog if it is open otherwise it will +** return zero. A simple check with the OS api IsWindow(..) is a good test if it's valid. +** +** e.g. this will open (or close if already open) the preferences dialog and show if we +** managed to get a valid +** SendMessage(hwnd_winamp,WM_COMMAND,MAKEWPARAM(WINAMP_OPTIONS_PREFS,0),0); +** MessageBox(hwnd_winamp,(IsWindow((HWND)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETPREFSWND))?"Valid":"Not Open"),0,MB_OK); +*/ + + +#define IPC_SET_PE_WIDTHHEIGHT 620 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)&point,IPC_SET_PE_WIDTHHEIGHT); +** You pass a pointer to a POINT structure which holds the width and height and Winamp +** will set the playlist editor to that size (this is used by gen_ff on skin changes). +** There does not appear to be any bounds limiting with this so it is possible to create +** a zero size playlist editor window (which is a pretty silly thing to do). +*/ + + +#define IPC_GETLANGUAGEPACKINSTANCE 621 +/* (requires Winamp 5.0+) +** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** This will return the HINSTANCE to the currently used language pack file for winamp.exe +** +** (5.5+) +** If you pass 1 in wParam then you will have zero returned if a language pack is in use. +** if(!SendMessage(hwnd_winamp,WM_WA_IPC,1,IPC_GETLANGUAGEPACKINSTANCE)){ +** // winamp is currently using a language pack +** } +** +** If you pass 2 in wParam then you will get the path to the language pack folder. +** wchar_t* lngpackfolder = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,2,IPC_GETLANGUAGEPACKINSTANCE); +** +** If you pass 3 in wParam then you will get the path to the currently extracted language pack. +** wchar_t* lngpack = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,3,IPC_GETLANGUAGEPACKINSTANCE); +** +** If you pass 4 in wParam then you will get the name of the currently used language pack. +** wchar_t* lngname = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,4,IPC_GETLANGUAGEPACKINSTANCE); +*/ +#define LANG_IDENT_STR 0 +#define LANG_LANG_CODE 1 +#define LANG_COUNTRY_CODE 2 +/* +** (5.51+) +** If you pass 5 in LOWORD(wParam) then you will get the ident string/code string +** (based on the param passed in the HIWORD(wParam) of the currently used language pack. +** The string returned with LANG_IDENT_STR is used to represent the language that the +** language pack is intended for following ISO naming conventions for consistancy. +** +** wchar_t* ident_str = (wchar_t*)SendMessage(hwnd_winamp,WM_WA_IPC,MAKEWPARAM(5,LANG_XXX),IPC_GETLANGUAGEPACKINSTANCE); +** +** e.g. +** For the default language it will return the following for the different LANG_XXX codes +** LANG_IDENT_STR -> "en-US" (max buffer size of this is 9 wchar_t) +** LANG_LANG_CODE -> "en" (language code) +** LANG_COUNTRY_CODE -> "US" (country code) +** +** On pre 5.51 installs you can get LANG_IDENT_STR using the following method +** (you'll have to custom process the string returned if you want the langugage or country but that's easy ;) ) +** +** #define LANG_PACK_LANG_ID 65534 (if you don't have lang.h) +** HINSTANCE hInst = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** TCHAR buffer[9] = {0}; +** LoadString(hInst,LANG_PACK_LANG_ID,buffer,sizeof(buffer)); +** +** +** +** The following example shows how using the basic api will allow you to load the playlist +** context menu resource from the currently loaded language pack or it will fallback to +** the default winamp.exe instance. +** +** HINSTANCE lang = (HINSTANCE)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLANGUAGEPACKINSTANCE); +** HMENU popup = GetSubMenu(GetSubMenu((LoadMenu(lang?lang:GetModuleHandle(0),MAKEINTRESOURCE(101))),2),5); +** // do processing as needed on the menu before displaying it +** TrackPopupMenuEx(orig,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,rc.left,rc.bottom,hwnd_owner,0); +** DestroyMenu(popup); +** +** If you need a specific menu handle then look at IPC_GET_HMENU for more information. +*/ + + +#define IPC_CB_PEINFOTEXT 622 // data is a string, ie: "04:21/45:02" + + +#define IPC_CB_OUTPUTCHANGED 623 // output plugin was changed in config + + +#define IPC_GETOUTPUTPLUGIN 625 +/* (requires Winamp 5.0+) +** char* outdll = (char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETOUTPUTPLUGIN); +** This returns a string of the current output plugin's dll name. +** e.g. if the directsound plugin was selected then this would return 'out_ds.dll'. +*/ + + +#define IPC_SETDRAWBORDERS 626 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_SETDRAWBORDERS); +** Set enabled to 1 to enable and 0 to disable drawing of the playlist editor and winamp +** gen class windows (used by gen_ff to allow it to draw its own window borders). +*/ + + +#define IPC_DISABLESKINCURSORS 627 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,enabled,IPC_DISABLESKINCURSORS); +** Set enabled to 1 to enable and 0 to disable the use of skinned cursors. +*/ + + +#define IPC_GETSKINCURSORS 628 +/* (requires Winamp 5.36+) +** data = (WACURSOR)cursorId. (check wa_dlg.h for values) +*/ + + +#define IPC_CB_RESETFONT 629 + + +#define IPC_IS_FULLSCREEN 630 +/* (requires Winamp 5.0+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_FULLSCREEN); +** This will return 1 if the video or visualisation is in fullscreen mode or 0 otherwise. +*/ + + +#define IPC_SET_VIS_FS_FLAG 631 +/* (requires Winamp 5.0+) +** A vis should send this message with 1/as param to notify winamp that it has gone to or has come back from fullscreen mode +*/ + + +#define IPC_SHOW_NOTIFICATION 632 + + +#define IPC_GETSKININFO 633 +#define IPC_GETSKININFOW 1633 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window by itself whenever it +** needs to get information to be shown about the current skin in the 'Current skin +** information' box on the main Skins page in the Winamp preferences. +** +** When this notification is received and the current skin is one you are providing the +** support for then you return a valid buffer for Winamp to be able to read from with +** information about it such as the name of the skin file. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_GETSKININFO){ +** if(is_our_skin()){ +** return is_our_skin_name(); +** } +** } +*/ + + +#define IPC_GET_MANUALPLADVANCE 634 +/* (requires Winamp 5.03+) +** int val=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_MANUALPLADVANCE); +** IPC_GET_MANUALPLADVANCE returns the status of the Manual Playlist Advance. +** If enabled this will return 1 otherwise it will return 0. +*/ + + +#define IPC_SET_MANUALPLADVANCE 635 +/* (requires Winamp 5.03+) +** SendMessage(hwnd_winamp,WM_WA_IPC,value,IPC_SET_MANUALPLADVANCE); +** IPC_SET_MANUALPLADVANCE sets the status of the Manual Playlist Advance option. +** Set value = 1 to turn it on and value = 0 to turn it off. +*/ + + +#define IPC_GET_NEXT_PLITEM 636 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_NEXT_PLITEM); +** +** Sent to Winamp's main window when an item has just finished playback or the next +** button has been pressed and requesting the new playlist item number to go to. +** +** Subclass this message in your application to return the new item number. +** Return -1 for normal Winamp operation (default) or the new item number in +** the playlist to be played instead of the originally selected next track. +** +** This is primarily provided for the JTFE plugin (gen_jumpex.dll). +*/ + + +#define IPC_GET_PREVIOUS_PLITEM 637 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_EOF_GET_PREVIOUS_PLITEM); +** +** Sent to Winamp's main window when the previous button has been pressed and Winamp is +** requesting the new playlist item number to go to. +** +** Return -1 for normal Winamp operation (default) or the new item number in +** the playlist to be played instead of the originally selected previous track. +** +** This is primarily provided for the JTFE plugin (gen_jumpex.dll). +*/ + + +#define IPC_IS_WNDSHADE 638 +/* (requires Winamp 5.04+) +** int is_shaded=SendMessage(hwnd_winamp,WM_WA_IPC,wnd,IPC_IS_WNDSHADE); +** Pass 'wnd' as an id as defined for IPC_GETWND or pass -1 to query the status of the +** main window. This returns 1 if the window is in winshade mode and 0 if it is not. +** Make sure you only test for this on a 5.04+ install otherwise you get a false result. +** (See the notes about unhandled WM_WA_IPC messages). +*/ + + +#define IPC_SETRATING 639 +/* (requires Winamp 5.04+ with ML) +** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,rating,IPC_SETRATING); +** This will allow you to set the 'rating' on the current playlist entry where 'rating' +** is an integer value from 0 (no rating) to 5 (5 stars). +** +** The following example should correctly allow you to set the rating for any specified +** playlist entry assuming of course that you're trying to get a valid playlist entry. +** +** void SetPlaylistItemRating(int item_to_set, int rating_to_set){ +** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS); +** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_set,IPC_SETPLAYLISTPOS); +** SendMessage(hwnd_winamp,WM_WA_IPC,rating_to_set,IPC_SETRATING); +** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); +** } +*/ + + +#define IPC_GETRATING 640 +/* (requires Winamp 5.04+ with ML) +** int rating=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** This returns the current playlist entry's rating between 0 (no rating) to 5 (5 stars). +** +** The following example should correctly allow you to get the rating for any specified +** playlist entry assuming of course that you're trying to get a valid playlist entry. +** +** int GetPlaylistItemRating(int item_to_get, int rating_to_set){ +** int cur_pos=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETLISTPOS), rating = 0; +** SendMessage(hwnd_winamp,WM_WA_IPC,item_to_get,IPC_SETPLAYLISTPOS); +** rating = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETRATING); +** SendMessage(hwnd_winamp,WM_WA_IPC,cur_pos,IPC_SETPLAYLISTPOS); +** return rating; +** } +*/ + + +#define IPC_GETNUMAUDIOTRACKS 641 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMAUDIOTRACKS); +** This will return the number of audio tracks available from the currently playing item. +*/ + + +#define IPC_GETNUMVIDEOTRACKS 642 +/* (requires Winamp 5.04+) +** int n = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETNUMVIDEOTRACKS); +** This will return the number of video tracks available from the currently playing item. +*/ + + +#define IPC_GETAUDIOTRACK 643 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETAUDIOTRACK); +** This will return the id of the current audio track for the currently playing item. +*/ + + +#define IPC_GETVIDEOTRACK 644 +/* (requires Winamp 5.04+) +** int cur = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVIDEOTRACK); +** This will return the id of the current video track for the currently playing item. +*/ + + +#define IPC_SETAUDIOTRACK 645 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETAUDIOTRACK); +** This allows you to switch to a new audio track (if supported) in the current playing file. +*/ + + +#define IPC_SETVIDEOTRACK 646 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,track,IPC_SETVIDEOTRACK); +** This allows you to switch to a new video track (if supported) in the current playing file. +*/ + + +#define IPC_PUSH_DISABLE_EXIT 647 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PUSH_DISABLE_EXIT); +** This will let you disable or re-enable the UI exit functions (close button, context +** menu, alt-f4). Remember to call IPC_POP_DISABLE_EXIT when you are done doing whatever +** was required that needed to prevent exit otherwise you have to kill the Winamp process. +*/ + + +#define IPC_POP_DISABLE_EXIT 648 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_POP_DISABLE_EXIT); +** See IPC_PUSH_DISABLE_EXIT +*/ + + +#define IPC_IS_EXIT_ENABLED 649 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_EXIT_ENABLED); +** This will return 0 if the 'exit' option of Winamp's menu is disabled and 1 otherwise. +*/ + + +#define IPC_IS_AOT 650 +/* (requires Winamp 5.04+) +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_IS_AOT); +** This will return the status of the always on top flag. +** Note: This may not match the actual TOPMOST window flag while another fullscreen +** application is focused if the user has the 'Disable always on top while fullscreen +** applications are focused' option under the General Preferences page is checked. +*/ + + +#define IPC_USES_RECYCLEBIN 651 +/* (requires Winamp 5.09+) +** int use_bin=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN); +** This will return 1 if the deleted file should be sent to the recycle bin or +** 0 if deleted files should be deleted permanently (default action for < 5.09). +** +** Note: if you use this on pre 5.09 installs of Winamp then it will return 1 which is +** not correct but is due to the way that SendMessage(..) handles un-processed messages. +** Below is a quick case for checking if the returned value is correct. +** +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USES_RECYCLEBIN) && +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETVERSION)>=0x5009) +** { +** // can safely follow the option to recycle the file +** } +** else +* { +** // need to do a permanent delete of the file +** } +*/ + + +#define IPC_FLUSHAUDITS 652 +/* +** SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_FLUSHAUDITS); +** +** Will flush any pending audits in the global audits queue +** +*/ + +#define IPC_GETPLAYITEM_START 653 +#define IPC_GETPLAYITEM_END 654 + + +#define IPC_GETVIDEORESIZE 655 +#define IPC_SETVIDEORESIZE 656 + + +#define IPC_INITIAL_SHOW_STATE 657 +/* (requires Winamp 5.36+) +** int show_state = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE); +** returns the processed value of nCmdShow when Winamp was started +** (see MSDN documentation the values passed to WinMain(..) for what this should be) +** +** e.g. +** if(SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_INITIAL_SHOW_STATE) == SW_SHOWMINIMIZED){ +** // we are starting minimised so process as needed (keep our window hidden) +** } +** +** Useful for seeing if winamp was run minimised on startup so you can act accordingly. +** On pre-5.36 versions this will effectively return SW_NORMAL/SW_SHOWNORMAL due to the +** handling of unknown apis returning 1 from Winamp. +*/ + +// >>>>>>>>>>> Next is 658 + +#define IPC_PLCMD 1000 + +#define PLCMD_ADD 0 +#define PLCMD_REM 1 +#define PLCMD_SEL 2 +#define PLCMD_MISC 3 +#define PLCMD_LIST 4 + +//#define IPC_MBCMD 1001 + +#define MBCMD_BACK 0 +#define MBCMD_FORWARD 1 +#define MBCMD_STOP 2 +#define MBCMD_RELOAD 3 +#define MBCMD_MISC 4 + +#define IPC_VIDCMD 1002 + +#define VIDCMD_FULLSCREEN 0 +#define VIDCMD_1X 1 +#define VIDCMD_2X 2 +#define VIDCMD_LIB 3 +#define VIDPOPUP_MISC 4 + +//#define IPC_MBURL 1003 //sets the URL +//#define IPC_MBGETCURURL 1004 //copies the current URL into wParam (have a 4096 buffer ready) +//#define IPC_MBGETDESC 1005 //copies the current URL description into wParam (have a 4096 buffer ready) +//#define IPC_MBCHECKLOCFILE 1006 //checks that the link file is up to date (otherwise updates it). wParam=parent HWND +//#define IPC_MBREFRESH 1007 //refreshes the "now playing" view in the library +//#define IPC_MBGETDEFURL 1008 //copies the default URL into wParam (have a 4096 buffer ready) + +#define IPC_STATS_LIBRARY_ITEMCNT 1300 // updates library count status + +/* +** IPC's in the message range 2000 - 3000 are reserved internally for freeform messages. +** These messages are taken from ff_ipc.h which is part of the Modern skin integration. +*/ + +#define IPC_FF_FIRST 2000 + +#define IPC_FF_COLOURTHEME_CHANGE IPC_FF_ONCOLORTHEMECHANGED +#define IPC_FF_ONCOLORTHEMECHANGED IPC_FF_FIRST + 3 +/* +** This is a notification message sent when the user changes the colour theme in a Modern +** skin and can also be detected when the Modern skin is first loaded as the gen_ff plugin +** applies relevant settings and styles (like the colour theme). +** +** The value of wParam is the name of the new color theme being switched to. +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)colour_theme_name,IPC_FF_ONCOLORTHEMECHANGED); +** +** (IPC_FF_COLOURTHEME_CHANGE is the name i (DrO) was using before getting a copy of +** ff_ipc.h with the proper name in it). +*/ + + +#define IPC_FF_ISMAINWND IPC_FF_FIRST + 4 +/* +** int ismainwnd = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_ISMAINWND); +** +** This allows you to determine if the window handle passed to it is a modern skin main +** window or not. If it is a main window or any of its windowshade variants then it will +** return 1. +** +** Because of the way modern skins are implemented, it is possible for this message to +** return a positive test result for a number of window handles within the current Winamp +** process. This appears to be because you can have a visible main window, a compact main +** window and also a winshaded version. +** +** The following code example below is one way of seeing how this api works since it will +** enumerate all windows related to Winamp at the time and allows you to process as +** required when a detection happens. +** +** +** EnumThreadWindows(GetCurrentThreadId(),enumWndProc,0); +** +** BOOL CALLBACK enumWndProc(HWND hwnd, LPARAM lParam){ +** +** if(SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)hwnd,IPC_FF_ISMAINWND)){ +** // do processing in here +** // or continue the enum for other main windows (if they exist) +** // and just comment out the line below +** return 0; +** } +** return 1; +** } +*/ + + +#define IPC_FF_GETCONTENTWND IPC_FF_FIRST + 5 +/* +** HWND wa2embed = (HWND)SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(HWND)test_wnd,IPC_FF_GETCONTENTWND); +** +** This will return the Winamp 2 window that is embedded in the window's container +** i.e. if hwnd is the playlist editor windowshade hwnd then it will return the Winamp 2 +** playlist editor hwnd. +** +** If no content is found such as the window has nothing embedded then this will return +** the hwnd passed to it. +*/ + + +#define IPC_FF_NOTIFYHOTKEY IPC_FF_FIRST + 6 +/* +** This is a notification message sent when the user uses a global hotkey combination +** which had been registered with the gen_hotkeys plugin. +** +** The value of wParam is the description of the hotkey as passed to gen_hotkeys. +** SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(const char*)hotkey_desc,IPC_FF_NOTIFYHOTKEY); +*/ + +#define IPC_FF_LAST 3000 + + +/* +** General IPC messages in Winamp +** +** All notification messages appear in the lParam of the main window message proceedure. +*/ + + +#define IPC_GETDROPTARGET 3001 +/* (requires Winamp 5.0+) +** IDropTarget* IDrop = (IDropTarget*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETDROPTARGET); +** +** You call this to retrieve a copy of the IDropTarget interface which Winamp created for +** handling external drag and drop operations on to it's Windows. This is only really +** useful if you're providing an alternate interface and want your Windows to provide the +** same drag and drop support as Winamp normally provides the user. Check out MSDN or +** your prefered search facility for more information about the IDropTarget interface and +** what's needed to handle it in your own instance. +*/ + + +#define IPC_PLAYLIST_MODIFIED 3002 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window whenever the playlist is +** modified in any way e.g. the addition/removal of a playlist entry. +** +** It is not a good idea to do large amounts of processing in this notification since it +** will slow down Winamp as playlist entries are modified (especially when you're adding +** in a large playlist). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYLIST_MODIFIED) +** { +** // do what you need to do here +** } +*/ + + +#define IPC_PLAYING_FILE 3003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILE) +** { +** // do what you need to do here, e.g. +** process_file((char*)wParam); +** } +*/ + + +#define IPC_PLAYING_FILEW 13003 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when playback begins for +** a file. This passes the full filepath in the wParam of the message received. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_PLAYING_FILEW) +** { +** // do what you need to do here, e.g. +** process_file((wchar_t*)wParam); +** } +*/ + + +#define IPC_FILE_TAG_MAY_HAVE_UPDATED 3004 +#define IPC_FILE_TAG_MAY_HAVE_UPDATEDW 3005 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window when a file's tag +** (e.g. id3) may have been updated. This appears to be sent when the InfoBox(..) function +** of the associated input plugin returns a 1 (which is the file information dialog/editor +** call normally). +** +** if(uMsg == WM_WA_IPC && lParam == IPC_FILE_TAG_MAY_HAVE_UPDATED) +** { +** // do what you need to do here, e.g. +** update_info_on_file_update((char*)wParam); +** } +*/ + + +#define IPC_ALLOW_PLAYTRACKING 3007 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,allow,IPC_ALLOW_PLAYTRACKING); +** Send allow as nonzero to allow play tracking and zero to disable the mode. +*/ + + +#define IPC_HOOK_OKTOQUIT 3010 +/* (requires Winamp 5.0+) +** This is a notification message sent to the main Winamp window asking if it's okay to +** close or not. Return zero to prevent Winamp from closing or return anything non-zero +** to allow Winamp to close. +** +** The best implementation of this option is to let the message pass through to the +** original window proceedure since another plugin may want to have a say in the matter +** with regards to Winamp closing. +** +** if(uMsg == WM_WA_IPC && lParam == IPC_HOOK_OKTOQUIT) +** { +** // do what you need to do here, e.g. +** if(no_shut_down()) +** { +** return 1; +** } +** } +*/ + + +#define IPC_WRITECONFIG 3011 +/* (requires Winamp 5.0+) +** SendMessage(hwnd_winamp,WM_WA_IPC,write_type,IPC_WRITECONFIG); +** +** Send write_type as 2 to write all config settings and the current playlist. +** +** Send write_type as 1 to write the playlist and common settings. +** This won't save the following ini settings:: +** +** defext, titlefmt, proxy, visplugin_name, dspplugin_name, check_ft_startup, +** visplugin_num, pe_fontsize, visplugin_priority, visplugin_autoexec, dspplugin_num, +** sticon, splash, taskbar, dropaotfs, ascb_new, ttips, riol, minst, whichicon, +** whichicon2, addtolist, snap, snaplen, parent, hilite, disvis, rofiob, shownumsinpl, +** keeponscreen, eqdsize, usecursors, fixtitles, priority, shuffle_morph_rate, +** useexttitles, bifont, inet_mode, ospb, embedwnd_freesize, no_visseh +** (the above was valid for 5.1) +** +** Send write_type as 0 to write the common and less common settings and no playlist. +*/ + + +#define IPC_UPDATE_URL 3012 +// pass the URL (char *) in lparam, will be free()'d on done. + + +#define IPC_GET_RANDFUNC 3015 // returns a function to get a random number +/* (requires Winamp 5.1+) +** int (*randfunc)(void) = (int(*)(void))SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GET_RANDFUNC); +** if(randfunc && randfunc != 1){ +** randfunc(); +** } +** +** This will return a positive 32-bit number (essentially 31-bit). +** The check for a returned value of 1 is because that's the default return value from +** SendMessage(..) when it is not handled so is good to check for it in this situation. +*/ + + +#define IPC_METADATA_CHANGED 3017 +/* (requires Winamp 5.1+) +** int changed=SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)(char*)field,IPC_METADATA_CHANGED); +** a plugin can SendMessage this to winamp if internal metadata has changes. +** wParam should be a char * of what field changed +** +** Currently used for internal actions (and very few at that) the intent of this api is +** to allow a plugin to call it when metadata has changed in the current playlist entry +** e.g.a new id3v2 tag was found in a stream +** +** The wparam value can either be NULL or a pointer to an ansi string for the metadata +** which has changed. This can be thought of as an advanced version of IPC_UPDTITLE and +** could be used to allow for update of the current title when a specific tag changed. +** +** Not recommended to be used since there is not the complete handling implemented in +** Winamp for it at the moment. +*/ + + +#define IPC_SKIN_CHANGED 3018 +/* (requires Winamp 5.1+) +** This is a notification message sent to the main Winamp window by itself whenever +** the skin in use is changed. There is no information sent by the wParam for this. +** +** if(message == WM_WA_IPC && lparam == IPC_SKIN_CHANGED) +** { +** // do what you need to do to handle skin changes, e.g. call WADlg_init(hwnd_winamp); +** } +*/ + + +#define IPC_REGISTER_LOWORD_COMMAND 3019 +/* (requires Winamp 5.1+) +** WORD id = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_REGISTER_LOWORD_COMMAND); +** This will assign you a unique id for making your own commands such as for extra menu +** entries. The starting value returned by this message will potentially change as and +** when the main resource file of Winamp is updated with extra data so assumptions cannot +** be made on what will be returned and plugin loading order will affect things as well. + +** 5.33+ +** If you want to reserve more than one id, you can pass the number of ids required in wParam +*/ + + +#define IPC_GET_DISPATCH_OBJECT 3020 // gets winamp main IDispatch * (for embedded webpages) +#define IPC_GET_UNIQUE_DISPATCH_ID 3021 // gives you a unique dispatch ID that won't conflict with anything in winamp's IDispatch * +#define IPC_ADD_DISPATCH_OBJECT 3022 // add your own dispatch object into winamp's. This lets embedded webpages access your functions +// pass a pointer to DispatchInfo (see below). Winamp makes a copy of all this data so you can safely delete it later +typedef struct +{ + wchar_t *name; // filled in by plugin, make sure it's a unicode string!! (i.e. L"myObject" instead of "myObject). + struct IDispatch *dispatch; // filled in by plugin + DWORD id; // filled in by winamp on return +} DispatchInfo; + +// see IPC_JSAPI2_GET_DISPATCH_OBJECT for version 2 of the Dispatchable scripting interface + +#define IPC_GET_PROXY_STRING 3023 +/* (requires Winamp 5.11+) +** char* proxy_string=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_PROXY_STRING); +** This will return the same string as is shown on the General Preferences page. +*/ + + +#define IPC_USE_REGISTRY 3024 +/* (requires Winamp 5.11+) +** int reg_enabled=SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_USE_REGISTRY); +** This will return 0 if you should leave your grubby hands off the registry (i.e. for +** lockdown mode). This is useful if Winamp is run from a USB drive and you can't alter +** system settings, etc. +*/ + + +#define IPC_GET_API_SERVICE 3025 +/* (requires Winamp 5.12+) +** api_service* api_service = (api_service)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GET_API_SERVICE); +** This api will return Winamp's api_service pointer (which is what Winamp3 used, heh). +** If this api is not supported in the Winamp version that is being used at the time then +** the returned value from this api will be 1 which is a good version check. +** +** As of 5.12 there is support for .w5s plugins which reside in %WinampDir%\System and +** are intended for common code that can be shared amongst other plugins e.g. jnetlib.w5s +** which contains jnetlib in one instance instead of being duplicated multiple times in +** all of the plugins which need internet access. +** +** Details on the .w5s specifications will come at some stage (possibly). +*/ + + +typedef struct { + const wchar_t *filename; + const wchar_t *metadata; + wchar_t *ret; + size_t retlen; +} extendedFileInfoStructW; + +#define IPC_GET_EXTENDED_FILE_INFOW 3026 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + + +#define IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE 3027 +#define IPC_SET_EXTENDED_FILE_INFOW 3028 +/* (requires Winamp 5.13+) +** Pass a pointer to the above struct in wParam +*/ + + +#define IPC_PLAYLIST_GET_NEXT_SELECTED 3029 +/* (requires 5.2+) +** int pl_item = SendMessage(hwnd_winamp,WM_WA_IPC,start,IPC_PLAYLIST_GET_NEXT_SELECTED); +** +** This works just like the ListView_GetNextItem(..) macro for ListView controls. +** 'start' is the index of the playlist item that you want to begin the search after or +** set this as -1 for the search to begin with the first item of the current playlist. +** +** This will return the index of the selected playlist according to the 'start' value or +** it returns -1 if there is no selection or no more selected items according to 'start'. +** +** Quick example: +** +** int sel = -1; +** // keep incrementing the start of the search so we get all of the selected entries +** while((sel = SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_PLAYLIST_GET_NEXT_SELECTED))!=-1){ +** // show the playlist file entry of the selected item(s) if there were any +** MessageBox(hwnd_winamp,(char*)SendMessage(hwnd_winamp,WM_WA_IPC,sel,IPC_GETPLAYLISTFILE),0,0); +** } +*/ + + +#define IPC_PLAYLIST_GET_SELECTED_COUNT 3030 +/* (requires 5.2+) +** int selcnt = SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_PLAYLIST_GET_SELECTED_COUNT); +** This will return the number of selected playlist entries. +*/ + + +#define IPC_GET_PLAYING_FILENAME 3031 +// returns wchar_t * of the currently playing filename + +#define IPC_OPEN_URL 3032 +// send either ANSI or Unicode string (it'll figure it out, but it MUST start with "h"!, so don't send ftp:// or anything funny) +// you can also send this one from another process via WM_COPYDATA (unicode only) + + +#define IPC_USE_UXTHEME_FUNC 3033 +/* (requires Winamp 5.35+) +** int ret = SendMessage(hwnd_winamp,WM_WA_IPC,param,IPC_USE_UXTHEME_FUNC); +** param can be IPC_ISWINTHEMEPRESENT or IPC_ISAEROCOMPOSITIONACTIVE or a valid hwnd. +** +** If you pass a hwnd then it will apply EnableThemeDialogTexture(ETDT_ENABLETAB) +** so your tabbed dialogs can use the correct theme (on supporting OSes ie XP+). +** +** Otherwise this will return a value based on the param passed (as defined below). +** For compatability, the return value will be zero on success (as 1 is returned +** for unsupported ipc calls on older Winamp versions) +*/ + #define IPC_ISWINTHEMEPRESENT 0 +/* This will return 0 if uxtheme.dll is present +** int isthemethere = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC); +*/ + #define IPC_ISAEROCOMPOSITIONACTIVE 1 +/* This will return 0 if aero composition is active +** int isaero = !SendMessage(hwnd_winamp,WM_WA_IPC,IPC_ISAEROCOMPOSITIONACTIVE,IPC_USE_UXTHEME_FUNC); +*/ + + +#define IPC_GET_PLAYING_TITLE 3034 +// returns wchar_t * of the current title + + +#define IPC_CANPLAY 3035 +// pass const wchar_t *, returns an in_mod * or 0 + + +typedef struct { + // fill these in... + size_t size; // init to sizeof(artFetchData) + HWND parent; // parent window of the dialogue + + // fill as much of these in as you can, otherwise leave them 0 + const wchar_t *artist; + const wchar_t *album; + int year, amgArtistId, amgAlbumId; + + int showCancelAll; // if set to 1, this shows a "Cancel All" button on the dialogue + + // winamp will fill these in if the call returns successfully: + void* imgData; // a buffer filled with compressed image data. free with WASABI_API_MEMMGR->sysFree() + int imgDataLen; // the size of the buffer + wchar_t type[10]; // eg: "jpg" + const wchar_t *gracenoteFileId; // if you know it +} artFetchData; + +#define IPC_FETCH_ALBUMART 3036 +/* pass an artFetchData*. This will show a dialog guiding the use through choosing art, and return when it's finished +** return values: +** 1: error showing dialog +** 0: success +** -1: cancel was pressed +** -2: cancel all was pressed +*/ + +#define IPC_JSAPI2_GET_DISPATCH_OBJECT 3037 +/* pass your service's unique ID, as a wchar_t * string, in wParam +** Winamp will copy the string, so don't worry about keeping it around +** An IDispatch * object will be returned (cast the return value from SendMessage) +** This IDispatch can be used for scripting/automation/VB interaction +** Pass to IE via IDocHostUIHandler::GetExternal and it will become window.external in javscript +*/ + +#define IPC_REGISTER_WINAMP_IPCMESSAGE 65536 +/* (requires Winamp 5.0+) +** DWORD id = SendMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)name,IPC_REGISTER_WINAMP_IPCMESSAGE); +** The value 'id' returned is > 65536 and is incremented on subsequent calls for unique +** 'name' values passed to it. By using the same 'name' in different plugins will allow a +** common runtime api to be provided for the currently running instance of Winamp +** e.g. +** PostMessage(hwnd_winamp,WM_WA_IPC,(WPARAM)my_param,registered_ipc); +** Have a look at wa_hotkeys.h for an example on how this api is used in practice for a +** custom WM_WA_IPC message. +** +** if(uMsg == WM_WA_IPC && lParam == id_from_register_winamp_ipcmessage){ +** // do things +** } +*/ + +#endif//_WA_IPC_H_ \ No newline at end of file diff --git a/tools/vio2sf/src/kobarin/kmp_pi.h b/tools/vio2sf/src/kobarin/kmp_pi.h new file mode 100644 index 000000000..64c1811d3 --- /dev/null +++ b/tools/vio2sf/src/kobarin/kmp_pi.h @@ -0,0 +1,214 @@ +#ifndef KMP_PI_H +#define KMP_PI_H + +/* + + KbMedia Player Plugin SDK (2005/10/08 ) + + JҌłB + KbMedia Player ̃vOCJĂ݂lǂ݉B + 蔲ŃRg C++ pɂȂĂ܂ÃRpCȂ C łvł傤B + + ۂ̃vOC̃\[XR[h + + http://hp.vector.co.jp/authors/VA015058/source/ + + ɂ܂B + + Kvŏ̋@\Ȃ߁Ao邱Ƃ͂Ȃ萧܂A + ̕vOĈ͊ȒPȂ͂łBvOCĝȒPł傤B + +*/ + +#define KMPMODULE_VERSION 100 /* KMPMODULE ̃o[W */ +#define KMP_GETMODULE kmp_GetTestModule /* ܂i‚܂ŁHjeXg... */ +#define SZ_KMP_GETMODULE "kmp_GetTestModule" /* ܂i‚܂ŁHjeXg... */ +#define SZ_KMP_CONFIG "kmp_Config" /* vOCݒpiv2.38beta2 ȍ~őΉj */ + +typedef void* HKMP;/* 'K'b'M'edia 'P'layer Plugin Handle */ + +typedef struct +{/* I[vTEhf[^̏ */ + DWORD dwSamplesPerSec;/* TvOg(44100, 22050 Ȃ) */ + DWORD dwChannels; /* `l( mono = 1, stereo = 2) */ + DWORD dwBitsPerSample;/* ʎqrbg( 8 or 16 or 24 or 32 or -32(32bit float) ) */ + DWORD dwLength; /* Ȃ̒ivZs”\ȏꍇ 0xFFFFFFFFj */ + /* Pt@CȁidwReserved2 == 1ĵƂ́AȐ 1000 {lɂB */ + /* Ⴆ 10 Ȃ̏ꍇ dwLength == 10000 ƂB */ + /* Pt@CȂ̏ꍇAȖ̉tԂ擾邱Ƃ͏oȂB */ + /* ʖڂȎdlŃX~}Z */ + DWORD dwSeekable; /* V[NɑΉĂꍇ 1AȂꍇ 0 */ + DWORD dwUnitRender; /* Render ֐̑R͂̒lniǂȒlłǂꍇ 0j */ + DWORD dwReserved1; /* [vĉtIȂȂ̏ꍇ 1, łȂꍇ 0 */ + /* Render ̌ĂяoJԂĂtIȂꍇ 1 ɂ */ + /* dwReserved1 == 1 ̏ꍇA */ + /* EvC[{̂́uPȃs[gvLɂȂĂꍇ͖[v */ + /* EdwLength != 0xFFFFFFFF ̏ꍇ dwLength ĐɃvC[ */ + /* {̂ɂătF[hAEgEtI */ + /* EdwLength == 0xFFFFFFFF ̏ꍇ̓vC[̐ݒ́uftHg̒v */ + /* ĐɃtF[hAEgEtI */ + /* dwReserved1 == 0 ̏ꍇA */ + /* ERender ̖߂lR(dwSize)菬lԂ܂ōĐ */ + DWORD dwReserved2; /* Pt@CȂ̏ꍇ 1, Pt@CPȂ̂Ƃ 0 */ + /* dwReserved2 == 1 ̏ꍇAdwLength ɂ͋Ȑ 1000 {lԂƁB */ + /* dwReserved2 == 1 ̏ꍇASetPosition dwPos (Ȕԍ * 1000)n */ + /* 悤ɂȂAV[N͏oȂȂ̂ dwSeek == 0 Ƃ邱ƁB */ + /* ݂̎dlł́APt@CȂ̊gq KbMedia Player {̂Ōߑł */ + /* ĂA{̂mȂgqɑ΂Ă̒l 1 ɂĂɂ͓ */ + /* ȂA{̂Pt@CȂƂĈĂ`ɑ΂Ă̒l 0 */ + /* ĂA͂萳퓮삵Ȃi */ + /* ʖڂȎdlŃX~}Z */ +}SOUNDINFO; + + +typedef struct +{ + DWORD dwVersion; + /* W[̃o[WBvOC̃o[Wł͂ȂB */ + /* K KMPMODULE_VERSION(=100) ɂ邱ƁB */ + /* ̒l KbMedia Player ҂lƈvȂꍇ́AKbMedia Player */ + /* ɂĒ FreeLibrary Ă΂B */ + /* ̏ꍇAInit() Deinit() Ă΂ȂƂɒӁB */ + + DWORD dwPluginVersion; + /* vOC̃o[W */ + /* ΉgqvOC‚ꍇ́A傫̂DIɎg */ + + const char *pszCopyright; + /* 쌠 */ + /* o[Wł̕̕\ */ + /* NULL ɂĂ悢 */ + + const char *pszDescription; + /* */ + /* o[Wł̕̕\ */ + /* NULL ɂĂ悢 */ + + const char **ppszSupportExts; + /* Ήgq̔̕z(sIh܂) */ + /* NULL ŏI悤ɂ */ + /* FppszSupportExts = {".mp1", ".mp2", ".mp3", "rmp", NULL}; */ + /* */ + /* ppszSupportExts == {NULL} (ppszSupportExts == NULL ͕sjŁA Init Deinit */ + /* NULL ̏ꍇ͏풓vOCƂĈAKbMedia Player 쒆͏Ƀ[h */ + /* ꂽ܂܂ɂȂi̋@\j */ + /* 풓vOCƂĂ̓ Init ďoɊJnADeinit ďoɏI邱ƁB */ + /* iLoadLibrary ɓJnAFreeLibrary ɓI͕sj */ + /* */ + /* LȊOőΉgqP‚ȂꍇAsȃvOCƌȂAKbMedia Player */ + /* ɂĒ FreeLibrary B */ + /* ̏ꍇ Init() Deinit() Ă΂ȂƂɒӁB */ + + DWORD dwReentrant; + /* t@C̓Д\ȏꍇ 1, s”\ȏꍇ 0 */ + /* Open ̖߂l HKMP Qˆȏ㓯ɎĂȂꍇ 0 ɂ */ + /* ʂȎȂAo邾 dwReentrant == 1 ƂȂ悤Ɏׂł */ + /* ̒l 0 ̏ꍇAQ–ڈȍ~̃t@C̓vC[{̂Ƃ͕ EXE oRĊJ */ + /* 悤ɂȂB */ + /* 炩̗RɂAɃvC[{̂Ƃ͕ EXE Ńt@CJ悤ɂꍇ */ + /* dwReentrant == 0xFFFFFFFF Ƃ邱 */ + /* Ⴆ΁Aaaa.kpi bbb.kpi ccc.dll ɈˑAccc.dll mGggł */ + /* ꍇ́Aaaa.kpi bbb.kpi dwReentrant == 0xFFFFFFFF ɂȂĂ]܂B */ + + void (WINAPI *Init)(void); + /* vOCBOpen ĂяoO KbMedia Player ɂĈxĂ΂B */ + /* KvȂꍇ NULL ɂĂǂB */ + /* A풓vOCi̋@\j̏ꍇ͕K邱ƁB */ + /* Init ̌Ăяoŏ풓vOC𓮍JnB */ + /* LoadLibrary ɏ풓vOC𓮍JnĂ͂ȂB */ + + void (WINAPI *Deinit)(void); + /* vOČnBFreeLibrary ̒OɈxĂ΂B */ + /* Init() xĂ΂ Deinit() Ăԉ”\邱ƂɒӁB */ + /* KvȂꍇ NULL ɂĂǂB */ + /* A풓vOCi̋@\j̏ꍇ͕K邱ƁB */ + /* Deinit ̌Ăяoŏ풓vOC𓮍I */ + /* FreeLibrary ɏ풓vOC𓮍IĂ͂ȂB */ + + HKMP (WINAPI *Open)(const char *cszFileName, SOUNDINFO *pInfo); + /* t@CJBK邱ƁB */ + /* G[̏ꍇ NULL ԂB */ + /* G[łȂꍇ pInfo ɓK؂ȏ邱ƁBK؂ȏ񂪓 */ + /* ȂꍇidwBitsPerSample 0 Ȃǁj KbMedia Player ɂĒ Close */ + /* Ă΂B */ + /* Open ɓnꂽ pInfo->dwSampleRate/dwBitsPerSample/dwChannels ̊el 0 ȊO */ + /* ꍇA”\Ȃ炻ɏ]`i܂͍ł߂`jŃt@CJ悤ɂ邱ƁB */ + /* iႦ pInfo->dwBitsPerSample == -32(32bit float) ɂȂĂꍇA”\Ȃ */ + /* 32bit float ŁA32bit float s”\ł 32bit int ȂΉĂȂ 32bit int */ + /* ŕԂȂǁj */ + + + HKMP (WINAPI *OpenFromBuffer)(const BYTE *Buffer, DWORD dwSize, SOUNDINFO *pInfo); + /* gpBNULL ɂ邱ƁB NULL łG[ɂ͂ȂȂAgpȂB */ + + void (WINAPI *Close)(HKMP hKMP); + /* nh‚BK邱ƁB */ + + DWORD (WINAPI *Render)(HKMP hKMP, BYTE* Buffer, DWORD dwSize); + /* Buffer PCM BK邱ƁB */ + /* dwSize Buffer ̃TCỸoCgBiTvł͂Ȃj */ + /* ߂l Buffer ɏ񂾃oCgBiTvł͂Ȃj */ + /* dwSize 菬lԂ牉tIB */ + /* dwSize SOUNDINFO::dwUnitRender ̒lnB */ + /* SOUNDINFO::dwUnitRender == 0 ̏ꍇ dwSize ɂ͔Cӂ̒lnB */ + /* idwSize ̓TṽoCg̔{ł邱Ƃۏ؂Ăj */ + + DWORD (WINAPI *SetPosition)(HKMP hKMP, DWORD dwPos); + /* V[NBK邱ƁB */ + /* dwPos ̓V[N̍ĐʒuB߂l̓V[N̍ĐʒuBPʂ̓~bB */ + /* dwPos Ɩ߂l͊SɈvKv͂ȂB߂lƖ{̍Đʒu */ + /* 덷傫Ȃi̎Ƃ̓ĐɎxjꍇ Open */ + /* SOUNDINFO dwSeekable 0 ɂĂƁB덷ȂAĂ */ + /* ɏꍇ dwSeekable 1 ɂĂƁB߂lmȂ */ + /* ΁AdwPos Ɩ߂l̍傫Ă dwSeekable=1 ƂėǂB */ + /* Aۂ̃V[Nʒu dwPos ɂȂ邱Ƃ͔邱ƁB */ + /* iCueSheet Đɖ肪N₷j */ + /* */ + /* V[NɑSΉȂꍇ́A擪ʒuɖ߂ 0 ԂƁB */ + /* */ + /* Pt@CȁiSOUNDINFO::dwReserved2 == 1j̏ꍇÅ֐őI */ + /* 邱ƂɂȂBȔԍ 1 x[XiȔԍ 0 ݂͑ȂjŁAdwPos */ + /* ɂ́AȔԍ 1000 {lBႦ 5 Ԗڂ̋Ȃɐ؂ւꍇ */ + /* dwPos == 5000 ƂȂB */ + /* ؂ւ̍Đʒu͐擪ɖ߂ 0 ԂƁB */ + /* AdwPos == 0 ̏ꍇ͋Ȃ؂ւɍĐʒu擪ɖ߂ƁB */ + /* SetPosition xĂ΂ĂȂԂł 1 ȖڂIĂ悤 */ + /* 邱ƁB */ + /* ؂ւƓɃV[N邱Ƃ͏oȂBiʖڂȎdlŃX~}Zj */ + +}KMPMODULE; + +typedef KMPMODULE* (WINAPI *pfnGetKMPModule)(void); +/* KMPMODULE* WINAPI kmp_GetTestModule(void); */ +/* */ +/* KMPMODULE \̂ւ̃|C^ԂBKGNX|[g邱ƁB */ +/* ̊֐̓vOC LoadLibrary Ă FreeLibrary ܂ł̊Ԃ */ +/* KbMedia Player {̂͂P񂾂Ă΂ȂB */ +/* ̊֐Ԃ KMPMODULE \̂̃f[^óAFreeLibrary ܂ */ +/* ύXĂ͂ȂB */ +/* ]āAႦΑΉgqݒɂĕύX悤ɂꍇAΉgq */ +/* ̕ύX KbMedia Player {̂ɔF̂́AvOCă[hƂ */ +/* ɂȂB */ + +typedef DWORD (WINAPI *pfnKmpConfig)(HWND hWnd, DWORD dwVersion, DWORD dwReserved); +/* DWORD WINAPI kmp_Config(HWND hWnd, DWORD dwVersion, DWORD dwReserved); */ +/* */ +/* KbMedia Player Version 2.38beta2 ȍ~őΉB */ +/* vOC̐ݒsBɐݒ̕KvȂꍇ̓GNX|[gȂĂǂB */ +/* EdwVersion/dwReserved Ƃ 0 n */ +/* E߂l͌ł 0 Ԃ̂ */ +/* EHKMP ̃CX^XƂ̐ݒ͌ł͖ΉiΉ̕Kv̂Hj */ +/* Ekmp_Config Ă΂O KMPMODULE::Init() Ă΂ */ +/* Ekmp_Config ߂ĂȂiݒ_CAO\ĂjԂł́A */ +/* Ed kmp_Config Ă΂邱Ƃ͂Ȃ */ +/* EKMPMODULE::Deinit() ͌Ă΂Ȃ */ +/* EFreeLibrary ͌Ă΂Ȃ */ +/* Ekmp_Config ĂяoA_CAO\܂ܒɃ^[ꍇ */ +/* ̌ł͂Ȃȉꍇ̓vOCœK؂ɏ邱Ɓj */ +/* */ +/* ݒ͂ kmp_Config ̎ʓ|AƂꍇ́AvOCƓꏊ */ +/* vOCƓ INI t@Cu΁AKbMedia Player {̂̃vOCݒ */ +/* _CAO INI t@CJ INI t@C𒼐ڕҏWo悤ɂȂĂB */ + +#endif + diff --git a/tools/vio2sf/src/loadpe/COPYING.LIB b/tools/vio2sf/src/loadpe/COPYING.LIB new file mode 100644 index 000000000..b6bd51763 --- /dev/null +++ b/tools/vio2sf/src/loadpe/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/tools/vio2sf/src/loadpe/loadpe.c b/tools/vio2sf/src/loadpe/loadpe.c new file mode 100644 index 000000000..4abbbd7ad --- /dev/null +++ b/tools/vio2sf/src/loadpe/loadpe.c @@ -0,0 +1,563 @@ +/* + libloadpe + Copyright (C)2007 Ku-Zu + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + loadpe.c + + 0.5 (2008/03/19) + Added support for WindowsNT4.0/NT3.x/Win32s. + + 0.4 (2008/02/07) + Leak checker. + + 0.3 (2008/01/08) + Fixed to protect memory after relocation and importing. + + 0.2 (2007/12/25) + Fixed not to free depending libraries before DLL_PROCESS_DETACH. + + 0.1 (2007/12/24) + First release. + +*/ + + +#define STRICT +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include "loadpe.h" + +#define MEMORY_CHECK 0 +/* + 0:Off + 1:Check MSVCRT.DLL + 2:Check CRTDLL.DLL +*/ + +#if MEMORY_CHECK +static int chkload = 0; +static int chkcnt = 0; + +typedef void * (__cdecl *LPFNMALLOC)(size_t s); +typedef void (__cdecl *LPFNFREE)(void *p); +typedef void * (__cdecl *LPFNREALLOC)(void *p, size_t s); +typedef const char * (__cdecl *LPFNSTRDUP)(const char *s); +typedef void * (__cdecl *LPFNCALLOC)(size_t num, size_t size); + +static LPFNMALLOC pmalloc = 0; +static LPFNFREE pfree = 0; +static LPFNREALLOC prealloc = 0; +static LPFNSTRDUP pstrdup = 0; +/* +functions not implemented yet + +calloc +_wcsdup,_mbsdup +_getcwd,_wgetcwd +_tempnam,_wtempnam,tmpnam,_wtmpnam +_fullpath,_wfullpath + +*/ + +static void * __cdecl lpe_chk_malloc(size_t s) +{ + void *r = (pmalloc) ? pmalloc(s) : 0; + if (r) chkcnt++; + return r; +} +static void __cdecl lpe_chk_free(void *p) +{ + if (p) + { + if (pfree) + { + chkcnt--; + pfree(p); + } + } +} +static void * __cdecl lpe_chk_realloc(void *p, size_t s) +{ + if (p) + { + if (s) + return prealloc(p, s); + else + lpe_chk_free(p); + } + else + { + if (s) + return lpe_chk_malloc(s); + } + return 0; +} +static const char * __cdecl lpe_chk_strdup(const char *p) +{ + char *r = 0; + if (p) + { + size_t s = lstrlenA(p) + 1; + r = lpe_chk_malloc(s); + if (r) MoveMemory(r, p, s); + } + return r; +} +#endif + +typedef BOOL (WINAPI *LPFNDLLENTRY)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); +typedef struct +{ + LPBYTE lpImageBase; + DWORD dwImageSize; + LPFNDLLENTRY lpEntry; + LPBYTE lpImport; + LPBYTE lpExport; + HMODULE *hModules; +} LOADPE; + +static WORD getwordle(BYTE *pData) +{ + return (WORD)(pData[0] | (((WORD)pData[1]) << 8)); +} + +static DWORD getdwordle(BYTE *pData) +{ + return pData[0] | (((DWORD)pData[1]) << 8) | (((DWORD)pData[2]) << 16) | (((DWORD)pData[3]) << 24); +} + +static void setdwordle(LPBYTE lpPtr, DWORD dwDat) +{ + lpPtr[0] = (BYTE)((dwDat >> 0) & 0xff); + lpPtr[1] = (BYTE)((dwDat >> 8) & 0xff); + lpPtr[2] = (BYTE)((dwDat >> 16) & 0xff); + lpPtr[3] = (BYTE)((dwDat >> 24) & 0xff); +} + +static void setwordle(LPBYTE lpPtr, WORD wDat) +{ + lpPtr[0] = (BYTE)((wDat >> 0) & 0xff); + lpPtr[1] = (BYTE)((wDat >> 8) & 0xff); +} + +static void *XLoadLibraryH(HANDLE h) +{ + LOADPE *ret = NULL; + LOADPE *lpe = NULL; + HMODULE *hModules = NULL; + LPBYTE lpImageBase = 0; + LPBYTE lpHeader = 0; + +#define iMZHeaderSize (0x40) +#define iPEHeaderSize (4 + 20 + 224) + DWORD dwOffsetPE; + DWORD dwNumberOfBytesRead; + + DWORD dwNumberOfSections; + DWORD dwSizeOfOptionalHeader; + DWORD dwAddressOfEntryPoint; + DWORD dwImageBase; + DWORD dwSizeOfImage; + DWORD dwSizeOfHeaders; + DWORD dwExportRVA; + DWORD dwExportSize; + DWORD dwImportRVA; + DWORD dwImportSize; + DWORD dwRelocationRVA; + DWORD dwRelocationSize; + DWORD dwIATRVA; + DWORD dwIATSize; + + LPBYTE lpSectionHeader; + LPBYTE lpSectionHeaderTop; + LPBYTE lpSectionHeaderEnd; + + DWORD i; + + BYTE peheader[iPEHeaderSize]; + + switch ((INT_PTR)h) + { + case (INT_PTR)INVALID_HANDLE_VALUE: + return 0; + default: + if (!ReadFile(h, peheader, iMZHeaderSize, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < iMZHeaderSize) + break; + dwOffsetPE = getdwordle(peheader + 0x3c); + if (0xffffffff == SetFilePointer(h, dwOffsetPE, 0, FILE_BEGIN)) + break; + if (!ReadFile(h, peheader, iPEHeaderSize, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < iPEHeaderSize) + break; + + /* check PE signature */ + if (getdwordle(peheader) != 0x00004550) + break; + + /* COFF file header */ + dwNumberOfSections = getwordle(peheader + 4 + 2); + dwSizeOfOptionalHeader = getwordle(peheader + 4 + 16); + /* optional header standard field */ + dwAddressOfEntryPoint = getdwordle(peheader + 4 + 20 + 16); + /* optional header WindowsNT field */ + dwImageBase = getdwordle(peheader + 4 + 20 + 28); + dwSizeOfImage = getdwordle(peheader + 4 + 20 + 56); + dwSizeOfHeaders = getdwordle(peheader + 4 + 20 + 60); + /* optinal header data directory */ + dwExportRVA = getdwordle(peheader + 4 + 20 + 96); + dwExportSize = getdwordle(peheader + 4 + 20 + 100); + dwImportRVA = getdwordle(peheader + 4 + 20 + 104); + dwImportSize = getdwordle(peheader + 4 + 20 + 108); + dwRelocationRVA = getdwordle(peheader + 4 + 20 + 136); + dwRelocationSize = getdwordle(peheader + 4 + 20 + 140); + dwIATRVA = getdwordle(peheader + 4 + 20 + 192); + dwIATSize = getdwordle(peheader + 4 + 20 + 196); + + lpImageBase = VirtualAlloc(0, dwSizeOfImage + dwSizeOfHeaders, MEM_RESERVE, PAGE_NOACCESS); + if (!lpImageBase) + break; + + if (0xffffffff == SetFilePointer(h, 0, 0, FILE_BEGIN)) + break; + + lpHeader = VirtualAlloc(lpImageBase, dwSizeOfHeaders, MEM_COMMIT, PAGE_READWRITE); + if (lpHeader != lpImageBase) + break; + + if (!ReadFile(h, lpImageBase, dwSizeOfHeaders, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < dwSizeOfHeaders) + break; + + if (0xffffffff == SetFilePointer(h, dwOffsetPE + 4 + 20 + dwSizeOfOptionalHeader, 0, FILE_BEGIN)) + break; + + lpSectionHeaderTop = lpImageBase + dwOffsetPE + 4 + 20 + dwSizeOfOptionalHeader; + lpSectionHeaderEnd = lpSectionHeaderTop + dwNumberOfSections * 40; + + if (lpSectionHeaderEnd >= lpImageBase + dwSizeOfHeaders) + break; + + /* load sections */ + lpSectionHeader = lpSectionHeaderTop; + for (i = 0; i < dwNumberOfSections; i++) + { + DWORD dwVirtualSize; + DWORD dwVirtualAddress; + DWORD dwSizeOfRawData; + DWORD dwPointerToRawData; + LPBYTE lpSection; + + dwVirtualSize = getdwordle(lpSectionHeader + 8); + dwVirtualAddress = getdwordle(lpSectionHeader + 12); + dwSizeOfRawData = getdwordle(lpSectionHeader + 16); + dwPointerToRawData = getdwordle(lpSectionHeader + 20); + + lpSection = VirtualAlloc(lpImageBase + dwVirtualAddress, dwVirtualSize, MEM_COMMIT, PAGE_READWRITE); + if (!lpSection) + break; + + ZeroMemory(lpImageBase + dwVirtualAddress, dwVirtualSize); + if (0xffffffff == SetFilePointer(h, dwPointerToRawData, 0, FILE_BEGIN)) + break; + + if (!ReadFile(h, lpImageBase + dwVirtualAddress, dwSizeOfRawData, &dwNumberOfBytesRead, NULL) || dwNumberOfBytesRead < dwSizeOfRawData) + break; + + lpSectionHeader += 40; + } + if (lpSectionHeader != lpSectionHeaderEnd) break; + + /* resolve relocations */ + if (dwRelocationRVA) + { + int iERROR = 0; + LPBYTE lpReloc = lpImageBase + dwRelocationRVA; + while (lpReloc < lpImageBase + dwRelocationRVA + dwRelocationSize) + { + DWORD dwPageRVA = getdwordle(lpReloc + 0); + DWORD dwBlockSize = getdwordle(lpReloc + 4); + for (i = 4; i < (dwBlockSize >> 1); i++) + { + DWORD dwOffset = getwordle(lpReloc + (i << 1)); + DWORD dwType = (dwOffset >> 12) & 0xf; + LPBYTE lpRPtr = lpImageBase + dwPageRVA + (dwOffset & 0xfff); + DWORD dwRDat; + switch (dwType) + { + case IMAGE_REL_BASED_ABSOLUTE: + break; + case IMAGE_REL_BASED_HIGHLOW: + dwRDat = getdwordle(lpRPtr); + dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase; + setdwordle(lpRPtr, dwRDat); + break; + case IMAGE_REL_BASED_HIGH: + dwRDat = getwordle(lpRPtr) << 16; + dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase; + setwordle(lpRPtr, (WORD)((dwRDat >> 16) & 0xffff)); + break; + case IMAGE_REL_BASED_LOW: + dwRDat = getwordle(lpRPtr); + dwRDat = dwRDat + ((INT_PTR)lpImageBase) - dwImageBase; + setwordle(lpRPtr, (WORD)(dwRDat & 0xffff)); + break; + case IMAGE_REL_BASED_HIGHADJ: + default: + iERROR = 1; + break; + } + } + lpReloc += dwBlockSize; + } + if (iERROR) + break; + } + + /* resolve imports */ + if (dwImportRVA) + { + int iError = 0; + LPBYTE lpImport; + DWORD dwModuleNumber = 0; + lpImport = lpImageBase + dwImportRVA; + while (getdwordle(lpImport + 12) && getdwordle(lpImport + 16)) + { + dwModuleNumber++; + lpImport += 20; + } + hModules = malloc(sizeof(HMODULE) * (dwModuleNumber + 1)); + if (!hModules) + break; + + i = 0; + lpImport = lpImageBase + dwImportRVA; + while (getdwordle(lpImport + 12) && getdwordle(lpImport + 16)) + { + LPCSTR lpszDllName = (LPCSTR)(lpImageBase + getdwordle(lpImport + 12)); + LPBYTE lpIAT = lpImageBase + getdwordle(lpImport + 16); + HMODULE hDll = LoadLibraryA(lpszDllName); + if (!hDll) + { + iError = 1; + break; + } +#if MEMORY_CHECK +#if MEMORY_CHECK == 2 + if (!lstrcmpi(lpszDllName, "CRTDLL.DLL")) +#else + if (!lstrcmpi(lpszDllName, "MSVCRT.DLL")) +#endif + { + pmalloc = (LPFNMALLOC)GetProcAddress(hDll, "malloc"); + pfree = (LPFNFREE)GetProcAddress(hDll, "free"); + prealloc = (LPFNREALLOC)GetProcAddress(hDll, "realloc"); + pstrdup = (LPFNSTRDUP)GetProcAddress(hDll, "_strdup"); + } +#endif + hModules[i++] = hDll; + while (getdwordle(lpIAT)) + { + DWORD dwIA = getdwordle(lpIAT); + LPCSTR lpszProcName = (dwIA & 0x80000000) ? MAKEINTRESOURCEA(dwIA & 0x7fffffff) : (LPCSTR)(lpImageBase + dwIA + 2); + DWORD dwProc = (DWORD)(INT_PTR)GetProcAddress(hDll, lpszProcName); +#if MEMORY_CHECK + if (dwProc && dwProc == (DWORD)pmalloc) + dwProc = (DWORD)lpe_chk_malloc; + if (dwProc && dwProc == (DWORD)pfree) + dwProc = (DWORD)lpe_chk_free; + if (dwProc && dwProc == (DWORD)prealloc) + dwProc = (DWORD)lpe_chk_realloc; + if (dwProc && dwProc == (DWORD)pstrdup) + dwProc = (DWORD)lpe_chk_strdup; +#endif + if (dwProc) + setdwordle(lpIAT, dwProc); + else + iError = 1; + lpIAT += 4; + } + lpImport += 20; + } + hModules[i] = 0; + + if (iError) + break; + } + + lpe = malloc(sizeof(LOADPE)); + if (!lpe) + break; + + lpe->lpEntry = (LPFNDLLENTRY)(INT_PTR)(dwAddressOfEntryPoint ? lpImageBase + dwAddressOfEntryPoint: 0); + lpe->lpImageBase = lpImageBase; + lpe->lpImport = dwImportRVA ? lpImageBase + dwImportRVA: 0; + lpe->dwImageSize = dwSizeOfImage + dwSizeOfHeaders; + lpe->lpExport = dwExportRVA ? lpImageBase + dwExportRVA: 0; + lpe->hModules = hModules; + + /* protect sections */ + lpSectionHeader = lpSectionHeaderTop; + for (i = 0; i < dwNumberOfSections; i++) + { + DWORD dwVirtualSize; + DWORD dwVirtualAddress; + DWORD dwCharacteristics; + + DWORD fNewProtect; + DWORD fOldProtect; + + dwVirtualSize = getdwordle(lpSectionHeader + 8); + dwVirtualAddress = getdwordle(lpSectionHeader + 12); + dwCharacteristics = getdwordle(lpSectionHeader + 36); + + switch ((dwCharacteristics >> 29) & 7) + { + default: + case 0: fNewProtect = PAGE_NOACCESS; break; + case 1: fNewProtect = PAGE_EXECUTE; break; + case 2: fNewProtect = PAGE_READONLY; break; + case 3: fNewProtect = PAGE_EXECUTE_READ; break; + case 4: + case 6: fNewProtect = PAGE_READWRITE; break; + case 5: + case 7: fNewProtect = PAGE_EXECUTE_READWRITE; break; + } + VirtualProtect(lpImageBase + dwVirtualAddress, dwVirtualSize, fNewProtect, &fOldProtect); + + lpSectionHeader += 40; + } + + /* call entry point */ + if (lpe->lpEntry) + { + BOOL fResult; + fResult = lpe->lpEntry((HMODULE)lpe->lpImageBase, DLL_PROCESS_ATTACH, 0); + if (fResult == FALSE) + break; + } + + ret = lpe; + lpe = 0; + lpImageBase = 0; + hModules = 0; + break; + } + if (hModules) + { + for (i = 0; hModules[i]; i++) + FreeLibrary(hModules[i]); + free(hModules); + } + if (lpImageBase) + { + VirtualFree(lpImageBase, dwSizeOfImage + dwSizeOfHeaders, MEM_DECOMMIT); + VirtualFree(lpImageBase, 0, MEM_RELEASE); + } + if (lpe) + free(lpe); + CloseHandle(h); +#if MEMORY_CHECK + if (ret) chkload++; +#endif + return ret; +} + +void *XLoadLibraryA(const char *lpszFileName) +{ + HANDLE h = CreateFileA(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + return XLoadLibraryH(h); +} + +void *XLoadLibraryW(const WCHAR *lpszFileName) +{ + HANDLE h = CreateFileW(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + return XLoadLibraryH(h); +} + +void XFreeLibrary(void *hModule) +{ + LOADPE *lpe = hModule; + if (lpe) + { + if (lpe->lpEntry) + { + lpe->lpEntry((HMODULE)lpe->lpImageBase, DLL_PROCESS_DETACH, 0); + } + + if (lpe->hModules) + { + HMODULE *hModules; + for (hModules = lpe->hModules; *hModules; hModules++) + FreeLibrary(*hModules); + free(lpe->hModules); + } + + if (lpe->lpImageBase) + { + VirtualFree(lpe->lpImageBase, lpe->dwImageSize, MEM_DECOMMIT); + VirtualFree(lpe->lpImageBase, 0, MEM_RELEASE); + } + free(lpe); +#if MEMORY_CHECK + if (--chkload == 0) + { + if (chkcnt) + { + char buf[1024]; + wsprintfA(buf, "loadpe - memory leak - count %d\n", chkcnt); + OutputDebugStringA(buf); + } + } +#endif + } +} + +FARPROC XGetProcAddress(void *hModule, const char *lpfn) +{ + LOADPE *lpe = hModule; + if (lpe) + { + if (lpe->lpExport) + { + DWORD dwOrdinal; + DWORD dwOrdinalBase = getdwordle(lpe->lpExport + 20); + DWORD dwAddressTableEntries = getdwordle(lpe->lpExport + 20); + DWORD dwNumberofNamePointers = getdwordle(lpe->lpExport + 24); + LPBYTE lpEAT = lpe->lpImageBase + getdwordle(lpe->lpExport + 28); + LPBYTE lpNPT = lpe->lpImageBase + getdwordle(lpe->lpExport + 32); + LPBYTE lpOT = lpe->lpImageBase + getdwordle(lpe->lpExport + 36); + if (((INT_PTR)lpfn) & (~((INT_PTR)0xffff))) + { + DWORD i; + for (i = 0; i < dwNumberofNamePointers; i++) + { + if (lstrcmpA(lpfn, (LPCSTR)(lpe->lpImageBase + getdwordle(lpNPT + (i << 2)))) == 0) + break; + } + if (i == dwNumberofNamePointers) + return 0; + dwOrdinal = getwordle(lpOT + (i << 1)) + dwOrdinalBase; + } + else + dwOrdinal = (DWORD)(((INT_PTR)lpfn) & 0xffff); + if (dwOrdinal >= dwOrdinalBase && dwOrdinal < dwOrdinalBase + dwAddressTableEntries) + return (FARPROC)(INT_PTR)(lpe->lpImageBase + getdwordle(lpEAT + ((dwOrdinal - dwOrdinalBase) << 3) + 0)); + } + } + return 0; +} diff --git a/tools/vio2sf/src/loadpe/loadpe.h b/tools/vio2sf/src/loadpe/loadpe.h new file mode 100644 index 000000000..a19575c3d --- /dev/null +++ b/tools/vio2sf/src/loadpe/loadpe.h @@ -0,0 +1,32 @@ +/* + libloadpe + Copyright (C)2007 Ku-Zu + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void *XLoadLibraryA(const char *lpszFileName); +void *XLoadLibraryW(const WCHAR *lpszFileName); +void XFreeLibrary(void *hModule); +FARPROC XGetProcAddress(void *hModule, const char *lpfn); + +#ifdef __cplusplus +} +#endif + diff --git a/tools/vio2sf/src/pversion.h b/tools/vio2sf/src/pversion.h new file mode 100644 index 000000000..37f377d15 --- /dev/null +++ b/tools/vio2sf/src/pversion.h @@ -0,0 +1,36 @@ +#define XSFDRIVER_VERSIONS "0.22" +#define XSFDRIVER_MODULENAME "vio2sf.bin" +#define XSFDRIVER_ENTRYNAME "XSFSetup" +#define XSFDRIVER_ISSYSTEMTAG(taglen, tag) (((taglen) > 0) && ((tag)[0] == '_') && !(((taglen) > 8) && _strnicmp(tag, "_vio2sf_", 8))) +#define XSFDRIVER_GUID1 { 0xcfa2ca5c, 0xd9a3, 0x49a6, { 0x93, 0x31, 0xf4, 0x09, 0xa2, 0xc1, 0x67, 0xdc } } /* {CFA2CA5C-D9A3-49a6-9331-F409A2C167DC} */ +#define XSFDRIVER_GUID2 { 0x5ae3d5fd, 0x0f4b, 0x4ca8, { 0xa9, 0x87, 0xca, 0x60, 0xc0, 0x97, 0x8b, 0x6a } } /* {5AE3D5FD-0F4B-4ca8-A987-CA60C0978B6A} */ +#define XSFDRIVER_CHANNELMAP { { 16, "SPU %2d" } , { 0, 0 } } +#define XSFDRIVER_SIMPLENAME "2SF Decoder" + +#define DESMUME_VERSIONS "0.8.0" +#define DESMUME_COPYRIGHT "Copyright (C) 2006 yopyop\nCopyright (C) 2006-2007 DeSmuME team" + +#define WINAMPPLUGIN_COPYRIGHT DESMUME_COPYRIGHT +#define WINAMPPLUGIN_NAME "2SF Decorder " XSFDRIVER_VERSIONS "/ DeSmuME v" DESMUME_VERSIONS " (x86)" +#define WINAMPPLUGIN_EXTS "2SF;MINI2SF\0Double Screen Sound Format files(*.2SF;*.MINI2SF)\0\0\0" +#define WINAMPPLUGIN_TAG_XSFBY "2sfby" + +#define KBMEDIAPLUGIN_VERSION 22 +#define KBMEDIAPLUGIN_COPYRIGHT DESMUME_COPYRIGHT +#define KBMEDIAPLUGIN_NAME "2SF plugin " XSFDRIVER_VERSIONS " / DeSmuME v" DESMUME_VERSIONS +#define KBMEDIAPLUGIN_EXTS(n) \ + static const char n##_2sfext[] = ".2sf"; \ + static const char n##_mini2sfext[] = ".mini2sf"; \ + static const char * const (n) [] = { \ + n##_2sfext, \ + n##_mini2sfext, \ + 0, \ + }; + +#define FOOBAR2000COMPONENT_NAME "2SF decoder / DeSmuME v" DESMUME_VERSIONS +#define FOOBAR2000COMPONENT_VERSION XSFDRIVER_VERSIONS +#define FOOBAR2000COMPONENT_ABOUT "DeSmuME v" DESMUME_VERSIONS "\n" DESMUME_COPYRIGHT "\n" +#define FOOBAR2000COMPONENT_TYPE "Double Screen Sound Format files" +#define FOOBAR2000COMPONENT_EXTS "*.2SF;*.MINI2SF" +#define FOOBAR2000COMPONENT_EXT_CHECK (!stricmp_utf8(p_extension,"2SF") || !stricmp_utf8(p_extension,"MINI2SF")) +#define FOOBAR2000COMPONENT_ENCODING "2sf" diff --git a/tools/vio2sf/src/vio2sf/desmume/ARM9.h b/tools/vio2sf/src/vio2sf/desmume/ARM9.h new file mode 100644 index 000000000..4dae037d8 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/ARM9.h @@ -0,0 +1,33 @@ +#ifndef ARM9_H +#define ARM9_H + +#include "types.h" + +typedef struct { + //ARM9 mem + u8 ARM9_ITCM[0x8000]; + u8 ARM9_DTCM[0x4000]; + u8 ARM9_WRAM[0x1000000]; + u8 MAIN_MEM[0x400000]; + u8 ARM9_REG[0x1000000]; + u8 ARM9_BIOS[0x8000]; + u8 ARM9_VMEM[0x800]; + u8 ARM9_ABG[0x80000]; + u8 ARM9_BBG[0x20000]; + u8 ARM9_AOBJ[0x40000]; + u8 ARM9_BOBJ[0x20000]; + u8 ARM9_LCD[0xA4000]; + u8 ARM9_OAM[0x800]; + + u8 * ExtPal[2][4]; + u8 * ObjExtPal[2][2]; + u8 * texPalSlot[4]; + + const u8 *textureSlotAddr[4]; + + u8 *blank_memory[0x20000]; +} ARM9_struct; + +extern ARM9_struct ARM9Mem; + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/COPYING b/tools/vio2sf/src/vio2sf/desmume/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/vio2sf/src/vio2sf/desmume/FIFO.c b/tools/vio2sf/src/vio2sf/desmume/FIFO.c new file mode 100644 index 000000000..c86017f71 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/FIFO.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "FIFO.h" + +void FIFOInit(FIFO * fifo) +{ + u32 i; + + fifo->begin = 0; + fifo->end = 0; + for(i = 0; i<0x8000; ++i) + fifo->data[i] = 0; + fifo->full = FALSE; + fifo->empty = TRUE; + fifo->error = FALSE; +} + +void FIFOAdd(FIFO * fifo, u32 v) +{ + if(fifo->full) + { + fifo->error = TRUE; + return; + } + fifo->data[fifo->end] = v; + fifo->end = (fifo->end + 1)& 0x7FFF; + fifo->full = (fifo->end == fifo->begin); + fifo->empty = FALSE; +} + +u32 FIFOValue(FIFO * fifo) +{ + u32 v; + + if(fifo->empty) + { + fifo->error = TRUE; + return 0; + } + v = fifo->data[fifo->begin]; + fifo->begin = (fifo->begin + 1)& 0x7FFF; + fifo->empty = (fifo->begin == fifo->end); + return v; +} diff --git a/tools/vio2sf/src/vio2sf/desmume/FIFO.h b/tools/vio2sf/src/vio2sf/desmume/FIFO.h new file mode 100644 index 000000000..86e282902 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/FIFO.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef FIFO_H +#define FIFO_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + u32 data[0x8000]; + u32 begin; + u32 end; + BOOL full; + BOOL empty; + BOOL error; +} FIFO; + +void FIFOInit(FIFO * fifo); +void FIFOAdd(FIFO * fifo, u32 v); +u32 FIFOValue(FIFO * fifo); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/GPU.c b/tools/vio2sf/src/vio2sf/desmume/GPU.c new file mode 100644 index 000000000..4dcfe6c39 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/GPU.c @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// CONTENTS +// INITIALIZATION +// ENABLING / DISABLING LAYERS +// PARAMETERS OF BACKGROUNDS +// PARAMETERS OF ROTOSCALE +// PARAMETERS OF EFFECTS +// PARAMETERS OF WINDOWS +// ROUTINES FOR INSIDE / OUTSIDE WINDOW CHECKS +// PIXEL RENDERING +// BACKGROUND RENDERING -TEXT- +// BACKGROUND RENDERING -ROTOSCALE- +// BACKGROUND RENDERING -HELPER FUNCTIONS- +// SPRITE RENDERING -HELPER FUNCTIONS- +// SPRITE RENDERING +// SCREEN FUNCTIONS +// GRAPHICS CORE +// GPU_ligne + +#include +#include +#include +#include "MMU.h" +#include "GPU.h" + +ARM9_struct ARM9Mem; + +NDS_Screen MainScreen; +NDS_Screen SubScreen; + +//#define DEBUG_TRI + +/*****************************************************************************/ +// INITIALIZATION +/*****************************************************************************/ + +GPU * GPU_Init(u8 l) +{ + GPU * g; + + if ((g = (GPU *) malloc(sizeof(GPU))) == NULL) + return NULL; + + GPU_Reset(g, l); + return g; +} + +void GPU_Reset(GPU *g, u8 l) +{ + memset(g, 0, sizeof(GPU)); +} + +void GPU_DeInit(GPU * gpu) +{ + if (gpu) free(gpu); +} + + +int Screen_Init(int coreid) { + MainScreen.gpu = GPU_Init(0); + SubScreen.gpu = GPU_Init(1); + + return 0; +} + +void Screen_Reset(void) { + GPU_Reset(MainScreen.gpu, 0); + GPU_Reset(SubScreen.gpu, 1); +} + +void Screen_DeInit(void) { + GPU_DeInit(MainScreen.gpu); + GPU_DeInit(SubScreen.gpu); + +} diff --git a/tools/vio2sf/src/vio2sf/desmume/GPU.h b/tools/vio2sf/src/vio2sf/desmume/GPU.h new file mode 100644 index 000000000..ac89d9543 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/GPU.h @@ -0,0 +1,813 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 Theo Berkau + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef GPU_H +#define GPU_H + +#include "ARM9.h" +#include +#include "mem.h" +#include "registers.h" +#include "FIFO.h" +#include "MMU.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + this structure is for display control, + it holds flags for general display +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _DISPCNT +{ +/* 7*/ u8 ForceBlank:1; // A+B: +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 0*/ u8 BG_Mode:3; // A+B: +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +}; +#else +struct _DISPCNT +{ +/* 0*/ u8 BG_Mode:3; // A+B: +/* 3*/ u8 BG0_3D:1; // A : 0=2D, 1=3D +/* 4*/ u8 OBJ_Tile_1D:1; // A+B: 0=2D (32KB), 1=1D (32..256KB) +/* 5*/ u8 OBJ_BMP_2D_dim:1; // A+B: 0=128x512, 1=256x256 pixels +/* 6*/ u8 OBJ_BMP_mapping:1; // A+B: 0=2D (128KB), 1=1D (128..256KB) + + // 7-15 same as GBA +/* 7*/ u8 ForceBlank:1; // A+B: +/* 8*/ u8 BG0_Enable:1; // A+B: 0=disable, 1=Enable +/* 9*/ u8 BG1_Enable:1; // A+B: 0=disable, 1=Enable +/*10*/ u8 BG2_Enable:1; // A+B: 0=disable, 1=Enable +/*11*/ u8 BG3_Enable:1; // A+B: 0=disable, 1=Enable +/*12*/ u8 OBJ_Enable:1; // A+B: 0=disable, 1=Enable +/*13*/ u8 Win0_Enable:1; // A+B: 0=disable, 1=Enable +/*14*/ u8 Win1_Enable:1; // A+B: 0=disable, 1=Enable +/*15*/ u8 WinOBJ_Enable:1; // A+B: 0=disable, 1=Enable + +/*16*/ u8 DisplayMode:2; // A+B: coreA(0..3) coreB(0..1) GBA(Green Swap) + // 0=off (white screen) + // 1=on (normal BG & OBJ layers) + // 2=VRAM display (coreA only) + // 3=RAM display (coreA only, DMA transfers) + +/*18*/ u8 VRAM_Block:2; // A : VRAM block (0..3=A..D) +/*20*/ u8 OBJ_Tile_1D_Bound:2; // A+B: +/*22*/ u8 OBJ_BMP_1D_Bound:1; // A : +/*23*/ u8 OBJ_HBlank_process:1; // A+B: OBJ processed during HBlank (GBA bit5) +/*24*/ u8 CharacBase_Block:3; // A : Character Base (64K step) +/*27*/ u8 ScreenBase_Block:3; // A : Screen Base (64K step) +/*30*/ u8 ExBGxPalette_Enable:1; // A+B: 0=disable, 1=Enable BG extended Palette +/*31*/ u8 ExOBJPalette_Enable:1; // A+B: 0=disable, 1=Enable OBJ extended Palette +}; +#endif + +typedef union +{ + struct _DISPCNT bits; + u32 val; +} DISPCNT; +#define BGxENABLED(cnt,num) ((num<8)? ((cnt.val>>8) & num):0) + + + + +/******************************************************************************* + this structure is for display control of a specific layer, + there are 4 background layers + their priority indicate which one to draw on top of the other + some flags indicate special drawing mode, size, FX +*******************************************************************************/ + +#ifdef WORDS_BIGENDIAN +struct _BGxCNT +{ +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 0*/ u8 Priority:2; // 0..3=high..low +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +}; +#else +struct _BGxCNT +{ +/* 0*/ u8 Priority:2; // 0..3=high..low +/* 2*/ u8 CharacBase_Block:4; // individual character base offset (n*16KB) +/* 6*/ u8 Mosaic_Enable:1; // 0=disable, 1=Enable mosaic +/* 7*/ u8 Palette_256:1; // 0=16x16, 1=1*256 palette +/* 8*/ u8 ScreenBase_Block:5; // individual screen base offset (text n*2KB, BMP n*16KB) +/*13*/ u8 PaletteSet_Wrap:1; // BG0 extended palette set 0=set0, 1=set2 + // BG1 extended palette set 0=set1, 1=set3 + // BG2 overflow area wraparound 0=off, 1=wrap + // BG3 overflow area wraparound 0=off, 1=wrap +/*14*/ u8 ScreenSize:2; // text : 256x256 512x256 256x512 512x512 + // x/rot/s : 128x128 256x256 512x512 1024x1024 + // bmp : 128x128 256x256 512x256 512x512 + // large : 512x1024 1024x512 - - +}; +#endif + + +typedef union +{ + struct _BGxCNT bits; + u16 val; +} BGxCNT; + +/******************************************************************************* + this structure is for background offset +*******************************************************************************/ + +typedef struct { + u16 BGxHOFS; + u16 BGxVOFS; +} BGxOFS; + +/******************************************************************************* + this structure is for rotoscale parameters +*******************************************************************************/ + +typedef struct { + s16 BGxPA; + s16 BGxPB; + s16 BGxPC; + s16 BGxPD; + s32 BGxX; + s32 BGxY; +} BGxPARMS; + + +/******************************************************************************* + these structures are for window description, + windows are square regions and can "subclass" + background layers or object layers (i.e window controls the layers) + + screen + | + +-- Window0/Window1/OBJwindow/OutOfWindows + | + +-- BG0/BG1/BG2/BG3/OBJ +*******************************************************************************/ + +typedef union { + struct { + u8 end:8; + u8 start:8; + } bits ; + u16 val; +} WINxDIM; + +#ifdef WORDS_BIGENDIAN +typedef struct { +/* 6*/ u8 :2; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 0*/ u8 WINx_BG0_Enable:1; +} WINxBIT; +#else +typedef struct { +/* 0*/ u8 WINx_BG0_Enable:1; +/* 1*/ u8 WINx_BG1_Enable:1; +/* 2*/ u8 WINx_BG2_Enable:1; +/* 3*/ u8 WINx_BG3_Enable:1; +/* 4*/ u8 WINx_OBJ_Enable:1; +/* 5*/ u8 WINx_Effect_Enable:1; +/* 6*/ u8 :2; +} WINxBIT; +#endif + +#ifdef WORDS_BIGENDIAN +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 :3; + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#else +typedef union { + struct { + WINxBIT win0; + WINxBIT win1; + } bits; + struct { + u8 win0_en:5; + u8 :3; + u8 win1_en:5; + u8 :3; + } packed_bits; + struct { + u8 low; + u8 high; + } bytes; + u16 val ; +} WINxCNT ; +#endif + +/* +typedef struct { + WINxDIM WIN0H; + WINxDIM WIN1H; + WINxDIM WIN0V; + WINxDIM WIN1V; + WINxCNT WININ; + WINxCNT WINOUT; +} WINCNT; +*/ + +/******************************************************************************* + this structure is for miscellanous settings + //TODO: needs further description +*******************************************************************************/ + +typedef struct { + u16 MOSAIC; + u16 unused1; + u16 unused2;//BLDCNT; + u16 unused3;//BLDALPHA; + u16 unused4;//BLDY; + u16 unused5; + /* + u16 unused6; + u16 unused7; + u16 unused8; + u16 unused9; + */ +} MISCCNT; + + +/******************************************************************************* + this structure is for 3D settings +*******************************************************************************/ + +struct _DISP3DCNT +{ +/* 0*/ u8 EnableTexMapping:1; // +/* 1*/ u8 PolygonShading:1; // 0=Toon Shading, 1=Highlight Shading +/* 2*/ u8 EnableAlphaTest:1; // see ALPHA_TEST_REF +/* 3*/ u8 EnableAlphaBlending:1; // see various Alpha values +/* 4*/ u8 EnableAntiAliasing:1; // +/* 5*/ u8 EnableEdgeMarking:1; // see EDGE_COLOR +/* 6*/ u8 FogOnlyAlpha:1; // 0=Alpha and Color, 1=Only Alpha (see FOG_COLOR) +/* 7*/ u8 EnableFog:1; // Fog Master Enable +/* 8*/ u8 FogShiftSHR:4; // 0..10 SHR-Divider (see FOG_OFFSET) +/*12*/ u8 AckColorBufferUnderflow:1; // Color Buffer RDLINES Underflow (0=None, 1=Underflow/Acknowledge) +/*13*/ u8 AckVertexRAMOverflow:1; // Polygon/Vertex RAM Overflow (0=None, 1=Overflow/Acknowledge) +/*14*/ u8 RearPlaneMode:1; // 0=Blank, 1=Bitmap +/*15*/ u8 :1; +/*16*/ u16 :16; +}; + +typedef union +{ + struct _DISP3DCNT bits; + u32 val; +} DISP3DCNT; + +/******************************************************************************* + this structure is for capture control (core A only) + + source: + http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode +*******************************************************************************/ + +struct _DISPCAPCNT +{ +/* 0*/ u8 BlendFactor_A:5; // 0..16 = Blending Factor for Source A +/* 5*/ u8 :3; // +/* 8*/ u8 BlendFactor_B:5; // 0..16 = Blending Factor for Source B +/*13*/ u8 :3; // +/*16*/ u8 VRAM_Write_Block:2; // 0..3 = VRAM A..D +/*18*/ u8 VRAM_Write_Offset:2; // n x 0x08000 +/*20*/ u8 Capture_Size:2; // 0=128x128, 1=256x64, 2=256x128, 3=256x192 dots +/*22*/ u8 :2; // +/*24*/ u8 Source_A:1; // 0=Graphics Screen BG+3D+OBJ, 1=3D Screen +/*25*/ u8 Source_B:1; // 0=VRAM, 1=Main Memory Display FIFO +/*26*/ u8 VRAM_Read_Offset:2; // n x 0x08000 +/*28*/ u8 :1; // +/*29*/ u8 Capture_Source:2; // 0=Source A, 1=Source B, 2/3=Sources A+B blended +/*31*/ u8 Capture_Enable:1; // 0=Disable/Ready, 1=Enable/Busy +}; + +typedef union +{ + struct _DISPCAPCNT bits; + u32 val; +} DISPCAPCNT; + + +/******************************************************************************* + this structure holds everything and should be mapped to + * core A : 0x04000000 + * core B : 0x04001000 +*******************************************************************************/ + +typedef struct _reg_dispx { + DISPCNT dispx_DISPCNT; // 0x0400x000 + u16 dispA_DISPSTAT; // 0x04000004 + u16 dispx_VCOUNT; // 0x0400x006 + BGxCNT dispx_BGxCNT[4]; // 0x0400x008 + BGxOFS dispx_BGxOFS[4]; // 0x0400x010 + BGxPARMS dispx_BG2PARMS; // 0x0400x020 + BGxPARMS dispx_BG3PARMS; // 0x0400x030 + u8 filler[12]; // 0x0400x040 + MISCCNT dispx_MISC; // 0x0400x04C + DISP3DCNT dispA_DISP3DCNT; // 0x04000060 + DISPCAPCNT dispA_DISPCAPCNT; // 0x04000064 + u32 dispA_DISPMMEMFIFO; // 0x04000068 +} REG_DISPx ; + + + + + + + + +#ifndef min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif + +typedef BOOL (*fun_gl_Begin) (int screen); +typedef void (*fun_gl_End) (int screen); +// the GUI should use this function prior to all gl calls +// if call to beg succeeds opengl draw +void register_gl_fun(fun_gl_Begin beg,fun_gl_End end); + +#define GPU_MAIN 0 +#define GPU_SUB 1 + +/* human readable bitmask names */ +#define ADDRESS_STEP_512B 0x00200 +#define ADDRESS_STEP_1KB 0x00400 +#define ADDRESS_STEP_2KB 0x00800 +#define ADDRESS_STEP_4KB 0x01000 +#define ADDRESS_STEP_8KB 0x02000 +#define ADDRESS_STEP_16KB 0x04000 +#define ADDRESS_STEP_32KB 0x08000 +#define ADDRESS_STEP_64kB 0x10000 + +#ifdef WORDS_BIGENDIAN +struct _TILEENTRY +{ +/*14*/ unsigned Palette:4; +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/* 0*/ unsigned TileNum:10; +}; +#else +struct _TILEENTRY +{ +/* 0*/ unsigned TileNum:10; +/*12*/ unsigned HFlip:1; // HORIZONTAL FLIP (left<-->right) +/*13*/ unsigned VFlip:1; // VERTICAL FLIP (top<-->bottom) +/*14*/ unsigned Palette:4; +}; +#endif +typedef union +{ + struct _TILEENTRY bits; + u16 val; +} TILEENTRY; + +struct _ROTOCOORD +{ +/* 0*/ unsigned Fraction:8; +/* 8*/ signed Integer:24; +// /*28*/ unsigned :4; +}; +typedef union +{ + struct _ROTOCOORD bits; + s32 val; +} ROTOCOORD; + + +/* + this structure is for color representation, + it holds 5 meaningful bits per color channel (red,green,blue) + and 1 meaningful bit for alpha representation + this bit can be unused or used for special FX +*/ + +struct _COLOR { // abgr x555 +#ifdef WORDS_BIGENDIAN + unsigned alpha:1; // sometimes it is unused (pad) + unsigned blue:5; + unsigned green:5; + unsigned red:5; +#else + unsigned red:5; + unsigned green:5; + unsigned blue:5; + unsigned alpha:1; // sometimes it is unused (pad) +#endif +}; +struct _COLORx { // abgr x555 + unsigned bgr:15; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR bits; + struct _COLORx bitx; + u16 val; +} COLOR; + +struct _COLOR32 { // ARGB + unsigned :3; + unsigned blue:5; + unsigned :3; + unsigned green:5; + unsigned :3; + unsigned red:5; + unsigned :7; + unsigned alpha:1; // sometimes it is unused (pad) +}; + +typedef union +{ + struct _COLOR32 bits; + u32 val; +} COLOR32; + +#define COLOR_16_32(w,i) \ + /* doesnt matter who's 16bit who's 32bit */ \ + i.bits.red = w.bits.red; \ + i.bits.green = w.bits.green; \ + i.bits.blue = w.bits.blue; \ + i.bits.alpha = w.bits.alpha; + + + + + + +/* + this structure is for Sprite description, + it holds flags & transformations for 1 sprite + (max 128 OBJs / screen) +ref: http://www.bottledlight.com/ds/index.php/Video/Sprites +*/ + +typedef struct +{ +#ifdef WORDS_BIGENDIAN +// attr0 +/* 0*/ unsigned Y:8; +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +// attr1 +/* 0*/ signed X:9; +/*14*/ unsigned Size:2; +/*13*/ unsigned VFlip:1; +/*12*/ unsigned HFlip:1; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +// attr2 +/* 0*/ unsigned TileIndex:10; +/*12*/ unsigned PaletteIndex:4; +/*10*/ unsigned Priority:2; +// attr3 +unsigned attr3:16; +#else +// attr0 +/* 0*/ unsigned Y:8; +/* 8*/ unsigned RotScale:2; // (00: Normal, 01: Rot/scale, 10: Disabled, 11: Double-size rot/scale) +/*10*/ unsigned Mode:2; // (00: Normal, 01: Transparent, 10: Object window, 11: Bitmap) +/*12*/ unsigned Mosaic:1; // (1: Enabled) +/*13*/ unsigned Depth:1; // (0: 16, 1: 256) +/*14*/ unsigned Shape:2; // (00: Square, 01: Wide, 10: Tall, 11: Illegal) +// attr1 +/* 0*/ signed X:9; +/* 9*/ unsigned RotScalIndex:3; // Rot/scale matrix index +/*12*/ unsigned HFlip:1; +/*13*/ unsigned VFlip:1; +/*14*/ unsigned Size:2; +// attr2 +/* 0*/ unsigned TileIndex:10; +/*10*/ unsigned Priority:2; +/*12*/ unsigned PaletteIndex:4; +// attr3 + unsigned attr3:16; +#endif +} _OAM_; + +typedef struct +{ + u16 attr0; + u16 attr1; + u16 attr2; + u16 attr3; +} OAM; + + + +typedef struct +{ + s16 x; + s16 y; +} size; + + + + +/* + this structure holds information + for rendering. +*/ + +#define NB_PRIORITIES 4 +#define NB_BG 4 +typedef struct +{ + u8 BGs[NB_BG], nbBGs; + u8 PixelsX[256]; + // doh ! yoda says : 256 pixels we can have... + u16 nbPixelsX; +} itemsForPriority_t; + + +typedef struct _GPU GPU; + +struct _GPU +{ + // some structs are becoming redundant + // some functions too (no need to recopy some vars as it is done by MMU) + REG_DISPx * dispx_st; + + DISPCAPCNT dispCapCnt; + BOOL LayersEnable[5]; + itemsForPriority_t itemsForPriority[NB_PRIORITIES]; + u8 sprWin[256][256]; + +#define BGBmpBB BG_bmp_ram +#define BGChBB BG_tile_ram + + u8 *(BG_bmp_ram[4]); + u8 *(BG_tile_ram[4]); + u8 *(BG_map_ram[4]); + + u8 BGExtPalSlot[4]; + u32 BGSize[4][2]; + + u8 lcd; + u8 core; + + u8 dispMode; + u8 vramBlock; + + BOOL dispBG[4]; + BOOL dispOBJ; + + OAM * oam; + u8 * sprMem; + u8 sprBoundary; + u8 sprBMPBoundary; + u8 sprBMPMode; + u32 sprEnable; + + u8 WIN0H0; + u8 WIN0H1; + u8 WIN0V0; + u8 WIN0V1; + + u8 WIN1H0; + u8 WIN1H1; + u8 WIN1V0; + u8 WIN1V1; + + u8 WININ0; + u8 WININ0_SPECIAL; + u8 WININ1; + u8 WININ1_SPECIAL; + + u8 WINOUT; + u8 WINOUT_SPECIAL; + u8 WINOBJ; + u8 WINOBJ_SPECIAL; + + u8 WIN0_ENABLED; + u8 WIN1_ENABLED; + u8 WINOBJ_ENABLED; + + u16 BLDCNT; + u8 BLDALPHA_EVA; + u8 BLDALPHA_EVB; + u8 BLDY_EVY; + + u8 MasterBrightMode; + u32 MasterBrightFactor; + + BOOL (*setFinalColorSpr)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y); + BOOL (*setFinalColorBck)(const GPU *gpu, u32 passing, u8 bgnum, u8 *dst, u16 color, u16 x, u16 y); + void (*spriteRender) (GPU * gpu, u16 l, u8 * dst, u8 * prioTab); +}; +/* +// normally should have same addresses +static void REG_DISPx_pack_test(GPU * gpu) +{ + REG_DISPx * r = gpu->dispx_st; + printf ("%08x %02x\n", r, (long)(&r->dispx_DISPCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPSTAT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_VCOUNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BGxCNT[0]) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BGxOFS[0]) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BG2PARMS) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_BG3PARMS) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_WINCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispx_MISC) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISP3DCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPCAPCNT) - (long)r); + printf ("\t%02x\n", (long)(&r->dispA_DISPMMEMFIFO) - (long)r); +} +*/ + +extern u8 GPU_screen[4*256*192]; + + +GPU * GPU_Init(u8 l); +void GPU_Reset(GPU *g, u8 l); +void GPU_DeInit(GPU *); + +void textBG(const GPU * gpu, u8 num, u8 * DST); //Draw text based background +void rotBG(GPU * gpu, u8 num, u8 * DST); +void extRotBG(GPU * gpu, u8 num, u8 * DST); +void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab); +void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * prioTab); + +extern short sizeTab[4][4][2]; +extern size sprSizeTab[4][4]; +extern s8 mode2type[8][4]; +extern void (*modeRender[8][4])(GPU * gpu, u8 num, u16 l, u8 * DST); + +typedef struct { + GPU * gpu; + u16 offset; +} NDS_Screen; + +extern NDS_Screen MainScreen; +extern NDS_Screen SubScreen; + +int Screen_Init(int coreid); +void Screen_Reset(void); +void Screen_DeInit(void); + +extern MMU_struct MMU; + + + +#define GFXCORE_DEFAULT -1 +#define GFXCORE_DUMMY 0 + +#define GFXCORE_FULLSCREEN (1 << 0) + +typedef struct +{ + int id; // ID number for core(see above defines) + const char *Name; // Name of core + int flags; // What features the core supports(full screen, etc.) + int (*Init)(); // Initializes stuff related to core + void (*DeInit)(); // Deinitializes stuff related to core + void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen + void (*OnScreenText)(char *string, ...); // For handling save state messages, etc. +} GraphicsInterface_struct; + +extern GraphicsInterface_struct GFXDummy; + +void GPU_setVideoProp(GPU *, u32 p); +void GPU_setBGProp(GPU *, u16 num, u16 p); + +void GPU_setBLDCNT(GPU *gpu, u16 v) ; +void GPU_setBLDALPHA(GPU *gpu, u16 v) ; +void GPU_setBLDY(GPU *gpu, u16 v) ; +void GPU_setMOSAIC(GPU *gpu, u16 v) ; + + +void GPU_remove(GPU *, u8 num); +void GPU_addBack(GPU *, u8 num); + +int GPU_ChangeGraphicsCore(int coreid); + +void GPU_set_DISPCAPCNT(GPU * gpu, u32 val) ; +void GPU_ligne(NDS_Screen * screen, u16 l) ; +void GPU_setMasterBrightness (GPU *gpu, u16 val); + +void GPU_setWIN0_H (GPU *gpu, u16 val); +void GPU_setWIN0_H0 (GPU *gpu, u8 val); +void GPU_setWIN0_H1 (GPU *gpu, u8 val); + +void GPU_setWIN0_V (GPU *gpu, u16 val); +void GPU_setWIN0_V0 (GPU *gpu, u8 val); +void GPU_setWIN0_V1 (GPU *gpu, u8 val); + +void GPU_setWIN1_H (GPU *gpu, u16 val); +void GPU_setWIN1_H0 (GPU *gpu, u8 val); +void GPU_setWIN1_H1 (GPU *gpu, u8 val); + +void GPU_setWIN1_V (GPU *gpu, u16 val); +void GPU_setWIN1_V0 (GPU *gpu, u8 val); +void GPU_setWIN1_V1 (GPU *gpu, u8 val); + +void GPU_setWININ (GPU *gpu, u16 val); +void GPU_setWININ0 (GPU *gpu, u8 val); +void GPU_setWININ1 (GPU *gpu, u8 val); + +void GPU_setWINOUT16(GPU *gpu, u16 val); +void GPU_setWINOUT (GPU *gpu, u8 val); +void GPU_setWINOBJ (GPU *gpu, u8 val); + +void GPU_setBLDCNT_LOW (GPU *gpu, u8 val); +void GPU_setBLDCNT_HIGH (GPU *gpu, u8 val); +void GPU_setBLDCNT (GPU *gpu, u16 val); + +void GPU_setBLDALPHA (GPU *gpu, u16 val); +void GPU_setBLDALPHA_EVA(GPU *gpu, u8 val); +void GPU_setBLDALPHA_EVB(GPU *gpu, u8 val); + +void GPU_setBLDY_EVY (GPU *gpu, u8 val); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/tools/vio2sf/src/vio2sf/desmume/MMU.c b/tools/vio2sf/src/vio2sf/desmume/MMU.c new file mode 100644 index 000000000..361af02bb --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/MMU.c @@ -0,0 +1,3565 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +//#define RENDER3D + +#include +#include +#include + +//#include "gl_vertex.h" + +#include "debug.h" +#include "NDSSystem.h" +//#include "cflash.h" +#define cflash_read(a) 0 +#define cflash_write(a,d) +#include "cp15.h" +//#include "wifi.h" +#include "registers.h" + +#if VIO2SF_GPU_ENABLE +#include "render3D.h" +#else +#define GPU_setVideoProp(p1, p2) +#define GPU_setBGProp(p1, p2, p3) + +#define GPU_setBLDCNT(p1, p2) +#define GPU_setBLDALPHA(p1, p2) +#define GPU_setBLDY(p1, p2) +#define GPU_setMOSAIC(p1, p2) + + +#define GPU_remove(p1,p2) +#define GPU_addBack(p1,p2) + +#define GPU_ChangeGraphicsCore(p1) 0 + +#define GPU_set_DISPCAPCNT(p1, p2) +#define GPU_ligne(p1, p2) +#define GPU_setMasterBrightness(p1, p2) + +#define GPU_setWIN0_H(p1, p2) +#define GPU_setWIN0_H0(p1, p2) +#define GPU_setWIN0_H1(p1, p2) + +#define GPU_setWIN0_V(p1, p2) +#define GPU_setWIN0_V0(p1, p2) +#define GPU_setWIN0_V1(p1, p2) + +#define GPU_setWIN1_H(p1, p2) +#define GPU_setWIN1_H0(p1, p2) +#define GPU_setWIN1_H1(p1, p2) + +#define GPU_setWIN1_V(p1, p2) +#define GPU_setWIN1_V0(p1, p2) +#define GPU_setWIN1_V1(p1, p2) + +#define GPU_setWININ(p1, p2) +#define GPU_setWININ0(p1, p2) +#define GPU_setWININ1(p1, p2) + +#define GPU_setWINOUT16(p1, p2) +#define GPU_setWINOUT(p1, p2) +#define GPU_setWINOBJ(p1, p2) + +#define GPU_setBLDCNT_LOW(p1, p2) +#define GPU_setBLDCNT_HIGH(p1, p2) +#define GPU_setBLDCNT(p1, p2) + +#define GPU_setBLDALPHA(p1, p2) +#define GPU_setBLDALPHA_EVA(p1, p2) +#define GPU_setBLDALPHA_EVB(p1, p2) + +#define GPU_setBLDY_EVY(p1, p2) +#endif + +#define ROM_MASK 3 + +/* + * + */ +//#define PROFILE_MEMORY_ACCESS 1 +#define EARLY_MEMORY_ACCESS 1 + +#define INTERNAL_DTCM_READ 1 +#define INTERNAL_DTCM_WRITE 1 + +//#define LOG_CARD +//#define LOG_GPU +//#define LOG_DMA +//#define LOG_DMA2 +//#define LOG_DIV + +char szRomPath[512]; +char szRomBaseName[512]; + +#define DUP2(x) x, x +#define DUP4(x) x, x, x, x +#define DUP8(x) x, x, x, x, x, x, x, x +#define DUP16(x) x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x + +MMU_struct MMU; + +u8 * MMU_ARM9_MEM_MAP[256]={ +/* 0X*/ DUP16(ARM9Mem.ARM9_ITCM), +/* 1X*/ //DUP16(ARM9Mem.ARM9_ITCM) +/* 1X*/ DUP16(ARM9Mem.ARM9_WRAM), +/* 2X*/ DUP16(ARM9Mem.MAIN_MEM), +/* 3X*/ DUP16(MMU.SWIRAM), +/* 4X*/ DUP16(ARM9Mem.ARM9_REG), +/* 5X*/ DUP16(ARM9Mem.ARM9_VMEM), +/* 6X*/ DUP2(ARM9Mem.ARM9_ABG), + DUP2(ARM9Mem.ARM9_BBG), + DUP2(ARM9Mem.ARM9_AOBJ), + DUP2(ARM9Mem.ARM9_BOBJ), + DUP8(ARM9Mem.ARM9_LCD), +/* 7X*/ DUP16(ARM9Mem.ARM9_OAM), +/* 8X*/ DUP16(NULL), +/* 9X*/ DUP16(NULL), +/* AX*/ DUP16(MMU.CART_RAM), +/* BX*/ DUP16(MMU.UNUSED_RAM), +/* CX*/ DUP16(MMU.UNUSED_RAM), +/* DX*/ DUP16(MMU.UNUSED_RAM), +/* EX*/ DUP16(MMU.UNUSED_RAM), +/* FX*/ DUP16(ARM9Mem.ARM9_BIOS) +}; + +u32 MMU_ARM9_MEM_MASK[256]={ +/* 0X*/ DUP16(0x00007FFF), +/* 1X*/ //DUP16(0x00007FFF) +/* 1X*/ DUP16(0x00FFFFFF), +/* 2X*/ DUP16(0x003FFFFF), +/* 3X*/ DUP16(0x00007FFF), +/* 4X*/ DUP16(0x00FFFFFF), +/* 5X*/ DUP16(0x000007FF), +/* 6X*/ DUP2(0x0007FFFF), + DUP2(0x0001FFFF), + DUP2(0x0003FFFF), + DUP2(0x0001FFFF), + DUP8(0x000FFFFF), +/* 7X*/ DUP16(0x000007FF), +/* 8X*/ DUP16(ROM_MASK), +/* 9X*/ DUP16(ROM_MASK), +/* AX*/ DUP16(0x0000FFFF), +/* BX*/ DUP16(0x00000003), +/* CX*/ DUP16(0x00000003), +/* DX*/ DUP16(0x00000003), +/* EX*/ DUP16(0x00000003), +/* FX*/ DUP16(0x00007FFF) +}; + +u8 * MMU_ARM7_MEM_MAP[256]={ +/* 0X*/ DUP16(MMU.ARM7_BIOS), +/* 1X*/ DUP16(MMU.UNUSED_RAM), +/* 2X*/ DUP16(ARM9Mem.MAIN_MEM), +/* 3X*/ DUP8(MMU.SWIRAM), + DUP8(MMU.ARM7_ERAM), +/* 4X*/ DUP8(MMU.ARM7_REG), + DUP8(MMU.ARM7_WIRAM), +/* 5X*/ DUP16(MMU.UNUSED_RAM), +/* 6X*/ DUP16(ARM9Mem.ARM9_ABG), +/* 7X*/ DUP16(MMU.UNUSED_RAM), +/* 8X*/ DUP16(NULL), +/* 9X*/ DUP16(NULL), +/* AX*/ DUP16(MMU.CART_RAM), +/* BX*/ DUP16(MMU.UNUSED_RAM), +/* CX*/ DUP16(MMU.UNUSED_RAM), +/* DX*/ DUP16(MMU.UNUSED_RAM), +/* EX*/ DUP16(MMU.UNUSED_RAM), +/* FX*/ DUP16(MMU.UNUSED_RAM) +}; + +u32 MMU_ARM7_MEM_MASK[256]={ +/* 0X*/ DUP16(0x00003FFF), +/* 1X*/ DUP16(0x00000003), +/* 2X*/ DUP16(0x003FFFFF), +/* 3X*/ DUP8(0x00007FFF), + DUP8(0x0000FFFF), +/* 4X*/ DUP8(0x00FFFFFF), + DUP8(0x0000FFFF), +/* 5X*/ DUP16(0x00000003), +/* 6X*/ DUP16(0x0003FFFF), +/* 7X*/ DUP16(0x00000003), +/* 8X*/ DUP16(ROM_MASK), +/* 9X*/ DUP16(ROM_MASK), +/* AX*/ DUP16(0x0000FFFF), +/* BX*/ DUP16(0x00000003), +/* CX*/ DUP16(0x00000003), +/* DX*/ DUP16(0x00000003), +/* EX*/ DUP16(0x00000003), +/* FX*/ DUP16(0x00000003) +}; + +u32 MMU_ARM9_WAIT16[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM9_WAIT32[16]={ + 1, 1, 1, 1, 1, 2, 2, 1, 8, 8, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM7_WAIT16[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 1, 1, 1, 1, 1, +}; + +u32 MMU_ARM7_WAIT32[16]={ + 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 5, 1, 1, 1, 1, 1, +}; + +void MMU_Init(void) { + int i; + + LOG("MMU init\n"); + + memset(&MMU, 0, sizeof(MMU_struct)); + + MMU.CART_ROM = MMU.UNUSED_RAM; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = MMU.CART_ROM; + MMU_ARM7_MEM_MAP[i] = MMU.CART_ROM; + } + + MMU.MMU_MEM[0] = MMU_ARM9_MEM_MAP; + MMU.MMU_MEM[1] = MMU_ARM7_MEM_MAP; + MMU.MMU_MASK[0]= MMU_ARM9_MEM_MASK; + MMU.MMU_MASK[1] = MMU_ARM7_MEM_MASK; + + MMU.ITCMRegion = 0x00800000; + + MMU.MMU_WAIT16[0] = MMU_ARM9_WAIT16; + MMU.MMU_WAIT16[1] = MMU_ARM7_WAIT16; + MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32; + MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32; + + for(i = 0;i < 16;i++) + FIFOInit(MMU.fifos + i); + + mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ + mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); + MMU.fw.fp = NULL; + + // Init Backup Memory device, this should really be done when the rom is loaded + mc_init(&MMU.bupmem, MC_TYPE_AUTODETECT); + mc_alloc(&MMU.bupmem, 1); + MMU.bupmem.fp = NULL; + +} + +void MMU_DeInit(void) { + LOG("MMU deinit\n"); +// if (MMU.fw.fp) +// fclose(MMU.fw.fp); + mc_free(&MMU.fw); +// if (MMU.bupmem.fp) +// fclose(MMU.bupmem.fp); + mc_free(&MMU.bupmem); +} + +//Card rom & ram + +u16 SPI_CNT = 0; +u16 SPI_CMD = 0; +u16 AUX_SPI_CNT = 0; +u16 AUX_SPI_CMD = 0; + +u32 rom_mask = 0; + +u32 DMASrc[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; +u32 DMADst[2][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}}; + +void MMU_clearMem() +{ + int i; + + memset(ARM9Mem.ARM9_ABG, 0, 0x080000); + memset(ARM9Mem.ARM9_AOBJ, 0, 0x040000); + memset(ARM9Mem.ARM9_BBG, 0, 0x020000); + memset(ARM9Mem.ARM9_BOBJ, 0, 0x020000); + memset(ARM9Mem.ARM9_DTCM, 0, 0x4000); + memset(ARM9Mem.ARM9_ITCM, 0, 0x8000); + memset(ARM9Mem.ARM9_LCD, 0, 0x0A4000); + memset(ARM9Mem.ARM9_OAM, 0, 0x0800); + memset(ARM9Mem.ARM9_REG, 0, 0x01000000); + memset(ARM9Mem.ARM9_VMEM, 0, 0x0800); + memset(ARM9Mem.ARM9_WRAM, 0, 0x01000000); + memset(ARM9Mem.MAIN_MEM, 0, 0x400000); + + memset(ARM9Mem.blank_memory, 0, 0x020000); + + memset(MMU.ARM7_ERAM, 0, 0x010000); + memset(MMU.ARM7_REG, 0, 0x010000); + + for(i = 0;i < 16;i++) + FIFOInit(MMU.fifos + i); + + MMU.DTCMRegion = 0; + MMU.ITCMRegion = 0x00800000; + + memset(MMU.timer, 0, sizeof(u16) * 2 * 4); + memset(MMU.timerMODE, 0, sizeof(s32) * 2 * 4); + memset(MMU.timerON, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerRUN, 0, sizeof(u32) * 2 * 4); + memset(MMU.timerReload, 0, sizeof(u16) * 2 * 4); + + memset(MMU.reg_IME, 0, sizeof(u32) * 2); + memset(MMU.reg_IE, 0, sizeof(u32) * 2); + memset(MMU.reg_IF, 0, sizeof(u32) * 2); + + memset(MMU.DMAStartTime, 0, sizeof(u32) * 2 * 4); + memset(MMU.DMACycle, 0, sizeof(s32) * 2 * 4); + memset(MMU.DMACrt, 0, sizeof(u32) * 2 * 4); + memset(MMU.DMAing, 0, sizeof(BOOL) * 2 * 4); + + memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); + + MainScreen.offset = 192; + SubScreen.offset = 0; + + /* setup the texture slot pointers */ +#if 0 + ARM9Mem.textureSlotAddr[0] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[1] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[2] = ARM9Mem.blank_memory; + ARM9Mem.textureSlotAddr[3] = ARM9Mem.blank_memory; +#else + ARM9Mem.textureSlotAddr[0] = &ARM9Mem.ARM9_LCD[0x20000 * 0]; + ARM9Mem.textureSlotAddr[1] = &ARM9Mem.ARM9_LCD[0x20000 * 1]; + ARM9Mem.textureSlotAddr[2] = &ARM9Mem.ARM9_LCD[0x20000 * 2]; + ARM9Mem.textureSlotAddr[3] = &ARM9Mem.ARM9_LCD[0x20000 * 3]; +#endif +} + +/* the VRAM blocks keep their content even when not blended in */ +/* to ensure that we write the content back to the LCD ram */ +/* FIXME: VRAM Bank E,F,G,H,I missing */ +void MMU_VRAMWriteBackToLCD(u8 block) +{ + u8 *destination; + u8 *source; + u32 size ; + u8 VRAMBankCnt; + #if 1 + return ; + #endif + destination = 0 ; + source = 0; + VRAMBankCnt = MMU_read8(ARMCPU_ARM9,REG_VRAMCNTA+block) ; + switch (block) + { + case 0: // Bank A + destination = ARM9Mem.ARM9_LCD ; + size = 0x20000 ; + break ; + case 1: // Bank B + destination = ARM9Mem.ARM9_LCD + 0x20000 ; + size = 0x20000 ; + break ; + case 2: // Bank C + destination = ARM9Mem.ARM9_LCD + 0x40000 ; + size = 0x20000 ; + break ; + case 3: // Bank D + destination = ARM9Mem.ARM9_LCD + 0x60000 ; + size = 0x20000 ; + break ; + case 4: // Bank E + destination = ARM9Mem.ARM9_LCD + 0x80000 ; + size = 0x10000 ; + break ; + case 5: // Bank F + destination = ARM9Mem.ARM9_LCD + 0x90000 ; + size = 0x4000 ; + break ; + case 6: // Bank G + destination = ARM9Mem.ARM9_LCD + 0x94000 ; + size = 0x4000 ; + break ; + case 8: // Bank H + destination = ARM9Mem.ARM9_LCD + 0x98000 ; + size = 0x8000 ; + break ; + case 9: // Bank I + destination = ARM9Mem.ARM9_LCD + 0xA0000 ; + size = 0x4000 ; + break ; + default: + return ; + } + switch (VRAMBankCnt & 7) { + case 0: + /* vram is allready stored at LCD, we dont need to write it back */ + MMU.vScreen = 1; + break ; + case 1: + switch(block){ + case 0: + case 1: + case 2: + case 3: + /* banks are in use for BG at ABG + ofs * 0x20000 */ + source = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + break ; + case 4: + /* bank E is in use at ABG */ + source = ARM9Mem.ARM9_ABG ; + break; + case 5: + case 6: + /* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/ + source = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ; + break; + case 8: + /* bank H is in use at BBG */ + source = ARM9Mem.ARM9_BBG ; + break ; + case 9: + /* bank I is in use at BBG */ + source = ARM9Mem.ARM9_BBG + 0x8000 ; + break; + default: return ; + } + break ; + case 2: + if (block < 2) + { + /* banks A,B are in use for OBJ at AOBJ + ofs * 0x20000 */ + source = ARM9Mem.ARM9_AOBJ + ((VRAMBankCnt >> 3) & 1) * 0x20000 ; + } else return ; + break ; + case 4: + switch(block){ + case 2: + /* bank C is in use at BBG */ + source = ARM9Mem.ARM9_BBG ; + break ; + case 3: + /* bank D is in use at BOBJ */ + source = ARM9Mem.ARM9_BOBJ ; + break ; + default: return ; + } + break ; + default: + return ; + } + if (!destination) return ; + if (!source) return ; + memcpy(destination,source,size) ; +} + +void MMU_VRAMReloadFromLCD(u8 block,u8 VRAMBankCnt) +{ + u8 *destination; + u8 *source; + u32 size; + #if 1 + return ; + #endif + destination = 0; + source = 0; + size = 0; + switch (block) + { + case 0: // Bank A + source = ARM9Mem.ARM9_LCD ; + size = 0x20000 ; + break ; + case 1: // Bank B + source = ARM9Mem.ARM9_LCD + 0x20000 ; + size = 0x20000 ; + break ; + case 2: // Bank C + source = ARM9Mem.ARM9_LCD + 0x40000 ; + size = 0x20000 ; + break ; + case 3: // Bank D + source = ARM9Mem.ARM9_LCD + 0x60000 ; + size = 0x20000 ; + break ; + case 4: // Bank E + source = ARM9Mem.ARM9_LCD + 0x80000 ; + size = 0x10000 ; + break ; + case 5: // Bank F + source = ARM9Mem.ARM9_LCD + 0x90000 ; + size = 0x4000 ; + break ; + case 6: // Bank G + source = ARM9Mem.ARM9_LCD + 0x94000 ; + size = 0x4000 ; + break ; + case 8: // Bank H + source = ARM9Mem.ARM9_LCD + 0x98000 ; + size = 0x8000 ; + break ; + case 9: // Bank I + source = ARM9Mem.ARM9_LCD + 0xA0000 ; + size = 0x4000 ; + break ; + default: + return ; + } + switch (VRAMBankCnt & 7) { + case 0: + /* vram is allready stored at LCD, we dont need to write it back */ + MMU.vScreen = 1; + break ; + case 1: + if (block < 4) + { + /* banks are in use for BG at ABG + ofs * 0x20000 */ + destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + } else return ; + break ; + case 2: + switch(block){ + case 0: + case 1: + case 2: + case 3: + /* banks are in use for BG at ABG + ofs * 0x20000 */ + destination = ARM9Mem.ARM9_ABG + ((VRAMBankCnt >> 3) & 3) * 0x20000 ; + break ; + case 4: + /* bank E is in use at ABG */ + destination = ARM9Mem.ARM9_ABG ; + break; + case 5: + case 6: + /* banks are in use for BG at ABG + (0x4000*OFS.0)+(0x10000*OFS.1)*/ + destination = ARM9Mem.ARM9_ABG + (((VRAMBankCnt >> 3) & 1) * 0x4000) + (((VRAMBankCnt >> 2) & 1) * 0x10000) ; + break; + case 8: + /* bank H is in use at BBG */ + destination = ARM9Mem.ARM9_BBG ; + break ; + case 9: + /* bank I is in use at BBG */ + destination = ARM9Mem.ARM9_BBG + 0x8000 ; + break; + default: return ; + } + break ; + case 4: + switch(block){ + case 2: + /* bank C is in use at BBG */ + destination = ARM9Mem.ARM9_BBG ; + break ; + case 3: + /* bank D is in use at BOBJ */ + destination = ARM9Mem.ARM9_BOBJ ; + break ; + default: return ; + } + break ; + default: + return ; + } + if (!destination) return ; + if (!source) return ; + memcpy(destination,source,size) ; +} + +void MMU_setRom(u8 * rom, u32 mask) +{ + unsigned int i; + MMU.CART_ROM = rom; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = rom; + MMU_ARM7_MEM_MAP[i] = rom; + MMU_ARM9_MEM_MASK[i] = mask; + MMU_ARM7_MEM_MASK[i] = mask; + } + rom_mask = mask; +} + +void MMU_unsetRom() +{ + unsigned int i; + MMU.CART_ROM=MMU.UNUSED_RAM; + + for(i = 0x80; i<0xA0; ++i) + { + MMU_ARM9_MEM_MAP[i] = MMU.UNUSED_RAM; + MMU_ARM7_MEM_MAP[i] = MMU.UNUSED_RAM; + MMU_ARM9_MEM_MASK[i] = ROM_MASK; + MMU_ARM7_MEM_MASK[i] = ROM_MASK; + } + rom_mask = ROM_MASK; +} +char txt[80]; + +u8 FASTCALL MMU_read8(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion)) + { + return ARM9Mem.ARM9_DTCM[adr&0x3FFF]; + } +#endif + + // CFlash reading, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) + return (unsigned char)cflash_read(adr); + +#ifdef EXPERIMENTAL_WIFI + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + { + if (adr & 1) + return (WIFI_read16(&wifiMac,adr) >> 8) & 0xFF; + else + return WIFI_read16(&wifiMac,adr) & 0xFF; + } +#endif + + return MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]; +} + + + +u16 FASTCALL MMU_read16(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } +#endif + + // CFlash reading, Mic + if ((adr>=0x08800000)&&(adr<0x09900000)) + return (unsigned short)cflash_read(adr); + +#ifdef EXPERIMENTAL_WIFI + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + return WIFI_read16(&wifiMac,adr) ; +#endif + + adr &= 0x0FFFFFFF; + + if(adr&0x04000000) + { + /* Adress is an IO register */ + switch(adr) + { + +#if VIO2SF_GPU_ENABLE + case 0x04000604: + return (gpu3D->NDS_3D_GetNumPolys()&2047); + case 0x04000606: + return (gpu3D->NDS_3D_GetNumVertex()&8191); +#endif + + case REG_IPCFIFORECV : /* TODO (clear): ??? */ + execute = FALSE; + return 1; + + case REG_IME : + return (u16)MMU.reg_IME[proc]; + + case REG_IE : + return (u16)MMU.reg_IE[proc]; + case REG_IE + 2 : + return (u16)(MMU.reg_IE[proc]>>16); + + case REG_IF : + return (u16)MMU.reg_IF[proc]; + case REG_IF + 2 : + return (u16)(MMU.reg_IF[proc]>>16); + + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + return MMU.timer[proc][(adr&0xF)>>2]; + + case 0x04000630 : + LOG("vect res\r\n"); /* TODO (clear): ??? */ + //execute = FALSE; + return 0; + case REG_POSTFLG : + return 1; + default : + break; + } + } + + /* Returns data from memory */ + return T1ReadWord(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]); +} + +u32 FASTCALL MMU_read32(u32 proc, u32 adr) +{ +#ifdef INTERNAL_DTCM_READ + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } +#endif + + // CFlash reading, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) + return (unsigned long)cflash_read(adr); + + adr &= 0x0FFFFFFF; + + if((adr >> 24) == 4) + { + /* Adress is an IO register */ + switch(adr) + { + // This is hacked due to the only current 3D core + case 0x04000600: + { + u32 fifonum = IPCFIFO+proc; + + u32 gxstat = (MMU.fifos[fifonum].empty<<26) | + (1<<25) | + (MMU.fifos[fifonum].full<<24) | + /*((NDS_nbpush[0]&1)<<13) | ((NDS_nbpush[2]&0x1F)<<8) |*/ + 2; + + LOG ("GXSTAT: 0x%X", gxstat); + + return gxstat; + } + + case 0x04000640: + case 0x04000644: + case 0x04000648: + case 0x0400064C: + case 0x04000650: + case 0x04000654: + case 0x04000658: + case 0x0400065C: + case 0x04000660: + case 0x04000664: + case 0x04000668: + case 0x0400066C: + case 0x04000670: + case 0x04000674: + case 0x04000678: + case 0x0400067C: + { + //LOG("4000640h..67Fh - CLIPMTX_RESULT - Read Current Clip Coordinates Matrix (R)"); +#if VIO2SF_GPU_ENABLE + return gpu3D->NDS_3D_GetClipMatrix ((adr-0x04000640)/4); +#else + return 0; +#endif + } + case 0x04000680: + case 0x04000684: + case 0x04000688: + case 0x0400068C: + case 0x04000690: + case 0x04000694: + case 0x04000698: + case 0x0400069C: + case 0x040006A0: + { +#if VIO2SF_GPU_ENABLE + //LOG("4000680h..6A3h - VECMTX_RESULT - Read Current Directional Vector Matrix (R)"); + return gpu3D->NDS_3D_GetDirectionalMatrix ((adr-0x04000680)/4); +#else + return 0; +#endif + } + + case 0x4000604: + { +#if VIO2SF_GPU_ENABLE + return (gpu3D->NDS_3D_GetNumPolys()&2047) & ((gpu3D->NDS_3D_GetNumVertex()&8191) << 16); + //LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[proc][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF])>>2]); +#else + return 0; +#endif + } + + case REG_IME : + return MMU.reg_IME[proc]; + case REG_IE : + return MMU.reg_IE[proc]; + case REG_IF : + return MMU.reg_IF[proc]; + case REG_IPCFIFORECV : + { + u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if(IPCFIFO_CNT&0x8000) + { + //execute = FALSE; + u32 fifonum = IPCFIFO+proc; + u32 val = FIFOValue(MMU.fifos + fifonum); + u32 remote = (proc+1) & 1; + u16 IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); + IPCFIFO_CNT |= (MMU.fifos[fifonum].empty<<8) | (MMU.fifos[fifonum].full<<9) | (MMU.fifos[fifonum].error<<14); + IPCFIFO_CNT_remote |= (MMU.fifos[fifonum].empty) | (MMU.fifos[fifonum].full<<1); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote); + if ((MMU.fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2))) + NDS_makeInt(remote,17) ; /* remote: SEND FIFO EMPTY */ + return val; + } + } + return 0; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + { + u32 val = T1ReadWord(MMU.MMU_MEM[proc][0x40], (adr + 2) & 0xFFF); + return MMU.timer[proc][(adr&0xF)>>2] | (val<<16); + } + /* + case 0x04000640 : // TODO (clear): again, ??? + LOG("read proj\r\n"); + return 0; + case 0x04000680 : + LOG("read roat\r\n"); + return 0; + case 0x04000620 : + LOG("point res\r\n"); + return 0; + */ + case REG_GCDATAIN: + { + u32 val; + + if(!MMU.dscard[proc].adress) return 0; + + val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].adress); + + MMU.dscard[proc].adress += 4; /* increment adress */ + + MMU.dscard[proc].transfer_count--; /* update transfer counter */ + if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */ + { + return val; /* return data */ + } + else /* transfer is done */ + { + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, T1ReadLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff) & ~(0x00800000 | 0x80000000)); + /* = 0x7f7fffff */ + + /* if needed, throw irq for the end of transfer */ + if(T1ReadWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff) & 0x4000) + { + if(proc == ARMCPU_ARM7) NDS_makeARM7Int(19); + else NDS_makeARM9Int(19); + } + + return val; + } + } + + default : + break; + } + } + + /* Returns data from memory */ + return T1ReadLong(MMU.MMU_MEM[proc][(adr >> 20) & 0xFF], adr & MMU.MMU_MASK[proc][(adr >> 20) & 0xFF]); +} + +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Writes data in DTCM (ARM9 only) */ + ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val; + return ; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) { + cflash_write(adr,val); + return; + } + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteByte(adr, val); + return; + } + } + + if (adr & 0xFF800000 == 0x04800000) + { + /* is wifi hardware, dont intermix with regular hardware registers */ + /* FIXME handle 8 bit writes */ + return ; + } + + switch(adr) + { + case REG_DISPA_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H1 (MainScreen.gpu, val); + break ; + case REG_DISPA_WIN0H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H0 (MainScreen.gpu, val); + break ; + case REG_DISPA_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H1 (MainScreen.gpu,val); + break ; + case REG_DISPA_WIN1H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H0 (MainScreen.gpu,val); + break ; + + case REG_DISPB_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN0H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H0(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H1(SubScreen.gpu,val); + break ; + case REG_DISPB_WIN1H+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H0(SubScreen.gpu,val); + break ; + + case REG_DISPA_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(MainScreen.gpu,val) ; + break ; + + case REG_DISPB_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V+1: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V0(SubScreen.gpu,val) ; + break ; + + case REG_DISPA_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ0(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WININ+1: + if(proc == ARMCPU_ARM9) GPU_setWININ1(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WINOUT+1: + if(proc == ARMCPU_ARM9) GPU_setWINOBJ(MainScreen.gpu,val); + break ; + + case REG_DISPB_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ0(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WININ+1: + if(proc == ARMCPU_ARM9) GPU_setWININ1(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WINOUT+1: + if(proc == ARMCPU_ARM9) GPU_setWINOBJ(SubScreen.gpu,val) ; + break ; + + + case REG_DISPA_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH(MainScreen.gpu,val); + break; + case REG_DISPA_BLDCNT+1: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (MainScreen.gpu,val); + break; + + case REG_DISPB_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_HIGH (SubScreen.gpu,val); + break; + case REG_DISPB_BLDCNT+1: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT_LOW (SubScreen.gpu,val); + break; + + case REG_DISPA_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(MainScreen.gpu,val) ; + break; + case REG_DISPA_BLDALPHA+1: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(MainScreen.gpu,val) ; + break; + + case REG_DISPB_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVB(SubScreen.gpu,val) ; + break; + case REG_DISPB_BLDALPHA+1: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA_EVA(SubScreen.gpu,val); + break; + + case REG_DISPA_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + + /* TODO: EEEK ! Controls for VRAMs A, B, C, D are missing ! */ + /* TODO: Not all mappings of VRAMs are handled... (especially BG and OBJ modes) */ + case REG_VRAMCNTA: + case REG_VRAMCNTB: + case REG_VRAMCNTC: + case REG_VRAMCNTD: + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD(0) ; + MMU_VRAMWriteBackToLCD(1) ; + MMU_VRAMWriteBackToLCD(2) ; + MMU_VRAMWriteBackToLCD(3) ; + switch(val & 0x1F) + { + case 1 : + MMU.vram_mode[adr-REG_VRAMCNTA] = 0; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*0); // BG-VRAM + break; + case 1 | (1 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 1; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*1); // BG-VRAM + break; + case 1 | (2 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 2; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*2); // BG-VRAM + break; + case 1 | (3 << 3) : + MMU.vram_mode[adr-REG_VRAMCNTA] = 3; // BG-VRAM + //MMU.vram_offset[0] = ARM9Mem.ARM9_ABG+(0x20000*3); // BG-VRAM + break; + case 0: /* mapped to lcd */ + MMU.vram_mode[adr-REG_VRAMCNTA] = 4 | (adr-REG_VRAMCNTA) ; + break ; + } + /* + * FIXME: simply texture slot handling + * This is a first stab and is not correct. It does + * not handle a VRAM texture slot becoming + * unconfigured. + * Revisit all of VRAM control handling for future + * release? + */ + if ( val & 0x80) { + if ( (val & 0x7) == 3) { + int slot_index = (val >> 3) & 0x3; + + ARM9Mem.textureSlotAddr[slot_index] = + &ARM9Mem.ARM9_LCD[0x20000 * (adr - REG_VRAMCNTA)]; + } + } + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTA,val) ; + } + break; + case REG_VRAMCNTE : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTE) ; + if((val & 7) == 5) + { + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; + } + else if((val & 7) == 3) + { + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x86000; + } + else if((val & 7) == 4) + { + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x80000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x82000; + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x84000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x86000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTE,val) ; + } + break; + + case REG_VRAMCNTF : + if(proc == ARMCPU_ARM9) + { + switch(val & 0x1F) + { + case 4 : + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; + break; + + case 4 | (1 << 3) : + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x92000; + break; + + case 3 : + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (1 << 3) : + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (2 << 3) : + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 3 | (3 << 3) : + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x90000; + break; + + case 5 : + case 5 | (1 << 3) : + case 5 | (2 << 3) : + case 5 | (3 << 3) : + ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x90000; + ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x92000; + break; + } + } + break; + case REG_VRAMCNTG : + if(proc == ARMCPU_ARM9) + { + switch(val & 0x1F) + { + case 4 : + ARM9Mem.ExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; + break; + + case 4 | (1 << 3) : + ARM9Mem.ExtPal[0][2] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ExtPal[0][3] = ARM9Mem.ARM9_LCD + 0x96000; + break; + + case 3 : + ARM9Mem.texPalSlot[0] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (1 << 3) : + ARM9Mem.texPalSlot[1] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (2 << 3) : + ARM9Mem.texPalSlot[2] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 3 | (3 << 3) : + ARM9Mem.texPalSlot[3] = ARM9Mem.ARM9_LCD + 0x94000; + break; + + case 5 : + case 5 | (1 << 3) : + case 5 | (2 << 3) : + case 5 | (3 << 3) : + ARM9Mem.ObjExtPal[0][0] = ARM9Mem.ARM9_LCD + 0x94000; + ARM9Mem.ObjExtPal[0][1] = ARM9Mem.ARM9_LCD + 0x96000; + break; + } + } + break; + + case REG_VRAMCNTH : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTH) ; + + if((val & 7) == 2) + { + ARM9Mem.ExtPal[1][0] = ARM9Mem.ARM9_LCD + 0x98000; + ARM9Mem.ExtPal[1][1] = ARM9Mem.ARM9_LCD + 0x9A000; + ARM9Mem.ExtPal[1][2] = ARM9Mem.ARM9_LCD + 0x9C000; + ARM9Mem.ExtPal[1][3] = ARM9Mem.ARM9_LCD + 0x9E000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTH,val) ; + } + break; + + case REG_VRAMCNTI : + if(proc == ARMCPU_ARM9) + { + MMU_VRAMWriteBackToLCD((u8)REG_VRAMCNTI) ; + + if((val & 7) == 3) + { + ARM9Mem.ObjExtPal[1][0] = ARM9Mem.ARM9_LCD + 0xA0000; + ARM9Mem.ObjExtPal[1][1] = ARM9Mem.ARM9_LCD + 0xA2000; + } + + MMU_VRAMReloadFromLCD(adr-REG_VRAMCNTI,val) ; + } + break; + +#ifdef LOG_CARD + case 0x040001A0 : /* TODO (clear): ??? */ + case 0x040001A1 : + case 0x040001A2 : + case 0x040001A8 : + case 0x040001A9 : + case 0x040001AA : + case 0x040001AB : + case 0x040001AC : + case 0x040001AD : + case 0x040001AE : + case 0x040001AF : + LOG("%08X : %02X\r\n", adr, val); +#endif + + default : + break; + } + + MMU.MMU_MEM[proc][(adr>>20)&0xFF][adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF]]=val; +} + +u16 partie = 1; + +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc == ARMCPU_ARM9) && ((adr & ~0x3FFF) == MMU.DTCMRegion)) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x08800000)&&(adr<0x09900000)) + { + cflash_write(adr,val); + return; + } + +#ifdef EXPERIMENTAL_WIFI + + /* wifi mac access */ + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + { + WIFI_write16(&wifiMac,adr,val) ; + return ; + } +#else + if ((proc==ARMCPU_ARM7) && (adr>=0x04800000)&&(adr<0x05000000)) + return ; +#endif + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteWord(adr, val); + return; + } + } + + if((adr >> 24) == 4) + { + /* Adress is an IO register */ + switch(adr) + { +#if VIO2SF_GPU_ENABLE + case 0x0400035C: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogOffset (val); + } + return; + } + case 0x04000340: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_AlphaFunc(val); + } + return; + } + case 0x04000060: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x060>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Control(val); + } + return; + } + case 0x04000354: + { + ((u16 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>1] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearDepth(val); + } + return; + } +#endif + + case REG_DISPA_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDCNT: + if(proc == ARMCPU_ARM9) GPU_setBLDCNT(SubScreen.gpu,val) ; + break ; + case REG_DISPA_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDALPHA: + if(proc == ARMCPU_ARM9) GPU_setBLDALPHA(SubScreen.gpu,val) ; + break ; + case REG_DISPA_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(MainScreen.gpu,val) ; + break ; + case REG_DISPB_BLDY: + if(proc == ARMCPU_ARM9) GPU_setBLDY_EVY(SubScreen.gpu,val) ; + break; + case REG_DISPA_MASTERBRIGHT: + GPU_setMasterBrightness (MainScreen.gpu, val); + break; + /* + case REG_DISPA_MOSAIC: + if(proc == ARMCPU_ARM9) GPU_setMOSAIC(MainScreen.gpu,val) ; + break ; + case REG_DISPB_MOSAIC: + if(proc == ARMCPU_ARM9) GPU_setMOSAIC(SubScreen.gpu,val) ; + break ; + */ + + case REG_DISPA_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H (MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0H: + if(proc == ARMCPU_ARM9) GPU_setWIN0_H(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1H: + if(proc == ARMCPU_ARM9) GPU_setWIN1_H(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V(MainScreen.gpu,val) ; + break ; + case REG_DISPA_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V(MainScreen.gpu,val) ; + break ; + case REG_DISPB_WIN0V: + if(proc == ARMCPU_ARM9) GPU_setWIN0_V(SubScreen.gpu,val) ; + break ; + case REG_DISPB_WIN1V: + if(proc == ARMCPU_ARM9) GPU_setWIN1_V(SubScreen.gpu,val) ; + break ; + case REG_DISPA_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ(MainScreen.gpu, val) ; + break ; + case REG_DISPA_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT16(MainScreen.gpu, val) ; + break ; + case REG_DISPB_WININ: + if(proc == ARMCPU_ARM9) GPU_setWININ(SubScreen.gpu, val) ; + break ; + case REG_DISPB_WINOUT: + if(proc == ARMCPU_ARM9) GPU_setWINOUT16(SubScreen.gpu, val) ; + break ; + + case REG_DISPB_MASTERBRIGHT: + GPU_setMasterBrightness (SubScreen.gpu, val); + break; + + case REG_POWCNT1 : + if(proc == ARMCPU_ARM9) + { + if(val & (1<<15)) + { + LOG("Main core on top\n"); + MainScreen.offset = 0; + SubScreen.offset = 192; + //nds.swapScreen(); + } + else + { + LOG("Main core on bottom (%04X)\n", val); + MainScreen.offset = 192; + SubScreen.offset = 0; + } + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x304, val); + return; + + case REG_AUXSPICNT: + T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPICNT >> 20) & 0xff], REG_AUXSPICNT & 0xfff, val); + AUX_SPI_CNT = val; + + if (val == 0) + mc_reset_com(&MMU.bupmem); /* reset backup memory device communication */ + return; + + case REG_AUXSPIDATA: + if(val!=0) + { + AUX_SPI_CMD = val & 0xFF; + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_AUXSPIDATA >> 20) & 0xff], REG_AUXSPIDATA & 0xfff, bm_transfer(&MMU.bupmem, val)); + return; + + case REG_SPICNT : + if(proc == ARMCPU_ARM7) + { + int reset_firmware = 1; + + if ( ((SPI_CNT >> 8) & 0x3) == 1) { + if ( ((val >> 8) & 0x3) == 1) { + if ( BIT11(SPI_CNT)) { + /* select held */ + reset_firmware = 0; + } + } + } + + //MMU.fw.com == 0; /* reset fw device communication */ + if ( reset_firmware) { + /* reset fw device communication */ + mc_reset_com(&MMU.fw); + } + SPI_CNT = val; + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff, val); + return; + + case REG_SPIDATA : + if(proc==ARMCPU_ARM7) + { + u16 spicnt; + + if(val!=0) + { + SPI_CMD = val; + } + + spicnt = T1ReadWord(MMU.MMU_MEM[proc][(REG_SPICNT >> 20) & 0xff], REG_SPICNT & 0xfff); + + switch((spicnt >> 8) & 0x3) + { + case 0 : + break; + + case 1 : /* firmware memory device */ + if(spicnt & 0x3 != 0) /* check SPI baudrate (must be 4mhz) */ + { + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, 0); + break; + } + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, fw_transfer(&MMU.fw, val)); + + return; + + case 2 : + switch(SPI_CMD & 0x70) + { + case 0x00 : + val = 0; + break; + case 0x10 : + //execute = FALSE; + if(SPI_CNT&(1<<11)) + { + if(partie) + { + val = ((nds.touchY<<3)&0x7FF); + partie = 0; + //execute = FALSE; + break; + } + val = (nds.touchY>>5); + partie = 1; + break; + } + val = ((nds.touchY<<3)&0x7FF); + partie = 1; + break; + case 0x20 : + val = 0; + break; + case 0x30 : + val = 0; + break; + case 0x40 : + val = 0; + break; + case 0x50 : + if(spicnt & 0x800) + { + if(partie) + { + val = ((nds.touchX<<3)&0x7FF); + partie = 0; + break; + } + val = (nds.touchX>>5); + partie = 1; + break; + } + val = ((nds.touchX<<3)&0x7FF); + partie = 1; + break; + case 0x60 : + val = 0; + break; + case 0x70 : + val = 0; + break; + } + break; + + case 3 : + /* NOTICE: Device 3 of SPI is reserved (unused and unusable) */ + break; + } + } + + T1WriteWord(MMU.MMU_MEM[proc][(REG_SPIDATA >> 20) & 0xff], REG_SPIDATA & 0xfff, val); + return; + + /* NOTICE: Perhaps we have to use gbatek-like reg names instead of libnds-like ones ...*/ + + case REG_DISPA_BG0CNT : + //GPULOG("MAIN BG0 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x8, val); + return; + case REG_DISPA_BG1CNT : + //GPULOG("MAIN BG1 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xA, val); + return; + case REG_DISPA_BG2CNT : + //GPULOG("MAIN BG2 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC, val); + return; + case REG_DISPA_BG3CNT : + //GPULOG("MAIN BG3 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(MainScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xE, val); + return; + case REG_DISPB_BG0CNT : + //GPULOG("SUB BG0 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 0, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x1008, val); + return; + case REG_DISPB_BG1CNT : + //GPULOG("SUB BG1 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 1, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100A, val); + return; + case REG_DISPB_BG2CNT : + //GPULOG("SUB BG2 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 2, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100C, val); + return; + case REG_DISPB_BG3CNT : + //GPULOG("SUB BG3 SETPROP 16B %08X\r\n", val); + if(proc == ARMCPU_ARM9) GPU_setBGProp(SubScreen.gpu, 3, val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x100E, val); + return; + case REG_IME : { + u32 old_val = MMU.reg_IME[proc]; + u32 new_val = val & 1; + MMU.reg_IME[proc] = new_val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val); + if ( new_val && old_val != new_val) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + } + case REG_VRAMCNTA: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTC: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTE: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTG: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + return ; + case REG_VRAMCNTI: + MMU_write8(proc,adr,val & 0xFF) ; + return ; + + case REG_IE : + MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF0000) | val; + if ( MMU.reg_IME[proc]) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + case REG_IE + 2 : + execute = FALSE; + MMU.reg_IE[proc] = (MMU.reg_IE[proc]&0xFFFF) | (((u32)val)<<16); + return; + + case REG_IF : + execute = FALSE; + MMU.reg_IF[proc] &= (~((u32)val)); + return; + case REG_IF + 2 : + execute = FALSE; + MMU.reg_IF[proc] &= (~(((u32)val)<<16)); + return; + + case REG_IPCSYNC : + { + u32 remote = (proc+1)&1; + u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF)); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF)); + MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));// + //execute = FALSE; + } + return; + case REG_IPCFIFOCNT : + { + u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; + u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; + if ((val & 0x8000) && !(cnt_l & 0x8000)) + { + /* this is the first init, the other side didnt init yet */ + /* so do a complete init */ + FIFOInit(MMU.fifos + (IPCFIFO+proc)); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; + /* and then handle it as usual */ + } + + if(val & 0x4008) + { + FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); + MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// + return; + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4)); + } + return; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[proc][(adr>>2)&3] = val; + return; + case REG_TM0CNTH : + case REG_TM1CNTH : + case REG_TM2CNTH : + case REG_TM3CNTH : + if(val&0x80) + { + MMU.timer[proc][((adr-2)>>2)&0x3] = MMU.timerReload[proc][((adr-2)>>2)&0x3]; + } + MMU.timerON[proc][((adr-2)>>2)&0x3] = val & 0x80; + switch(val&7) + { + case 0 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0+1;//proc; + break; + case 1 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 6+1;//proc; + break; + case 2 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 8+1;//proc; + break; + case 3 : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 10+1;//proc; + break; + default : + MMU.timerMODE[proc][((adr-2)>>2)&0x3] = 0xFFFF; + break; + } + if(!(val & 0x80)) + MMU.timerRUN[proc][((adr-2)>>2)&0x3] = FALSE; + T1WriteWord(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val); + return; + case REG_DISPA_DISPCNT+2 : + { + //execute = FALSE; + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v); + } + return; + case REG_DISPA_DISPCNT : + if(proc == ARMCPU_ARM9) + { + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0) & 0xFFFF0000) | val; + GPU_setVideoProp(MainScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, v); + } + return; + case REG_DISPA_DISPCAPCNT : + if(proc == ARMCPU_ARM9) + { + GPU_set_DISPCAPCNT(MainScreen.gpu,val); + } + return; + case REG_DISPB_DISPCNT+2 : + if(proc == ARMCPU_ARM9) + { + //execute = FALSE; + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF) | ((u32) val << 16); + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v); + } + return; + case REG_DISPB_DISPCNT : + { + u32 v = (T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x1000) & 0xFFFF0000) | val; + GPU_setVideoProp(SubScreen.gpu, v); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, v); + } + return; + //case 0x020D8460 : + /*case 0x0235A904 : + LOG("ECRIRE %d %04X\r\n", proc, val); + execute = FALSE;*/ + case REG_DMA0CNTH : + { + u32 v; + + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma0 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xBA, val); + DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0); + DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8); + MMU.DMAStartTime[proc][0] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][0] = v; + if(MMU.DMAStartTime[proc][0] == 0) + MMU_doDMA(proc, 0); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA1CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma1 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xC6, val); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC4); + MMU.DMAStartTime[proc][1] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][1] = v; + if(MMU.DMAStartTime[proc][1] == 0) + MMU_doDMA(proc, 1); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA2CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma2 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xD2, val); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD0); + MMU.DMAStartTime[proc][2] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][2] = v; + if(MMU.DMAStartTime[proc][2] == 0) + MMU_doDMA(proc, 2); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + case REG_DMA3CNTH : + { + u32 v; + //if(val&0x8000) execute = FALSE; + //LOG("16 bit dma3 %04X\r\n", val); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0xDE, val); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8); + v = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xDC); + MMU.DMAStartTime[proc][3] = (proc ? (v>>28) & 0x3 : (v>>27) & 0x7); + MMU.DMACrt[proc][3] = v; + + if(MMU.DMAStartTime[proc][3] == 0) + MMU_doDMA(proc, 3); + #ifdef LOG_DMA2 + //else + { + LOG("proc %d, dma %d src %08X dst %08X %s\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], (val&(1<<25))?"ON":"OFF"); + } + #endif + } + return; + //case REG_AUXSPICNT : execute = FALSE; + default : + T1WriteWord(MMU.MMU_MEM[proc][0x40], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); + return; + } + } + T1WriteWord(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); +} + + +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) +{ +#ifdef INTERNAL_DTCM_WRITE + if((proc==ARMCPU_ARM9)&((adr&(~0x3FFF))==MMU.DTCMRegion)) + { + T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return ; + } +#endif + + // CFlash writing, Mic + if ((adr>=0x9000000)&&(adr<0x9900000)) { + cflash_write(adr,val); + return; + } + + adr &= 0x0FFFFFFF; + + // This is bad, remove it + if(proc == ARMCPU_ARM7) + { + if ((adr>=0x04000400)&&(adr<0x0400051D)) + { + SPU_WriteLong(adr, val); + return; + } + } + + if (adr & 0xFF800000 == 0x04800000) { + /* access to non regular hw registers */ + /* return to not overwrite valid data */ + return ; + } ; + + + if((adr>>24)==4) + { + if (adr >= 0x04000400 && adr < 0x04000440) + { + // Geometry commands (aka Dislay Lists) - Parameters:X + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x400>>2] = val; +#if VIO2SF_GPU_ENABLE + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_CallList(val); + } +#endif + } + else + switch(adr) + { +#if VIO2SF_GPU_ENABLE + // Alpha test reference value - Parameters:1 + case 0x04000340: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x340>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_AlphaFunc(val); + } + return; + } + // Clear background color setup - Parameters:2 + case 0x04000350: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x350>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearColor(val); + } + return; + } + // Clear background depth setup - Parameters:2 + case 0x04000354: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x354>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ClearDepth(val); + } + return; + } + // Fog Color - Parameters:4b + case 0x04000358: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x358>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogColor(val); + } + return; + } + case 0x0400035C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x35C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_FogOffset(val); + } + return; + } + // Matrix mode - Parameters:1 + case 0x04000440: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x440>>2] = val; + + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MatrixMode(val); + } + return; + } + // Push matrix - Parameters:0 + case 0x04000444: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x444>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PushMatrix(); + } + return; + } + // Pop matrix/es - Parameters:1 + case 0x04000448: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x448>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PopMatrix(val); + } + return; + } + // Store matrix in the stack - Parameters:1 + case 0x0400044C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x44C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_StoreMatrix(val); + } + return; + } + // Restore matrix from the stack - Parameters:1 + case 0x04000450: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x450>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_RestoreMatrix(val); + } + return; + } + // Load Identity matrix - Parameters:0 + case 0x04000454: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x454>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadIdentity(); + } + return; + } + // Load 4x4 matrix - Parameters:16 + case 0x04000458: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x458>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadMatrix4x4(val); + } + return; + } + // Load 4x3 matrix - Parameters:12 + case 0x0400045C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x45C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LoadMatrix4x3(val); + } + return; + } + // Multiply 4x4 matrix - Parameters:16 + case 0x04000460: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x460>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix4x4(val); + } + return; + } + // Multiply 4x4 matrix - Parameters:12 + case 0x04000464: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x464>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix4x3(val); + } + return; + } + // Multiply 3x3 matrix - Parameters:9 + case 0x04000468 : + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x468>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_MultMatrix3x3(val); + } + return; + } + // Multiply current matrix by scaling matrix - Parameters:3 + case 0x0400046C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x46C>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Scale(val); + } + return; + } + // Multiply current matrix by translation matrix - Parameters:3 + case 0x04000470: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x470>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Translate(val); + } + return; + } + // Set vertex color - Parameters:1 + case 0x04000480: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x480>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Color3b(val); + } + return; + } + // Set vertex normal - Parameters:1 + case 0x04000484: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x484>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Normal(val); + } + return; + } + // Set vertex texture coordinate - Parameters:1 + case 0x04000488: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x488>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexCoord(val); + } + return; + } + // Set vertex position 16b/coordinate - Parameters:2 + case 0x0400048C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x48C>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex16b(val); + } + return; + } + // Set vertex position 10b/coordinate - Parameters:1 + case 0x04000490: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x490>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex10b(val); + } + return; + } + // Set vertex XY position - Parameters:1 + case 0x04000494: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x494>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(0,1,val); + } + return; + } + // Set vertex XZ position - Parameters:1 + case 0x04000498: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x498>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(0,2,val); + } + return; + } + // Set vertex YZ position - Parameters:1 + case 0x0400049C: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x49C>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex3_cord(1,2,val); + } + return; + } + // Set vertex difference position (offset from the last vertex) - Parameters:1 + case 0x040004A0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A0>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_Vertex_rel (val); + } + return; + } + // Set polygon attributes - Parameters:1 + case 0x040004A4: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A4>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_PolygonAttrib(val); + } + return; + } + // Set texture parameteres - Parameters:1 + case 0x040004A8: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4A8>>2] = val; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexImage(val); + } + return; + } + // Set palette base address - Parameters:1 + case 0x040004AC: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4AC>>2] = val&0x1FFF; + if(proc==ARMCPU_ARM9) + { + gpu3D->NDS_3D_TexPalette(val&0x1FFFF); + } + return; + } + // Set material diffuse/ambient parameters - Parameters:1 + case 0x040004C0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C0>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Material0 (val); + } + return; + } + // Set material reflection/emission parameters - Parameters:1 + case 0x040004C4: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C4>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Material1 (val); + } + return; + } + // Light direction vector - Parameters:1 + case 0x040004C8: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4C8>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LightDirection (val); + } + return; + } + // Light color - Parameters:1 + case 0x040004CC: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4CC>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_LightColor(val); + } + return; + } + // Material Shininess - Parameters:32 + case 0x040004D0: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x4D0>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Shininess(val); + } + return; + } + // Begin vertex list - Parameters:1 + case 0x04000500: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x500>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Begin(val); + } + return; + } + // End vertex list - Parameters:0 + case 0x04000504: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x504>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_End(); + } + return; + } + // Swap rendering engine buffers - Parameters:1 + case 0x04000540: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x540>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_Flush(val); + } + return; + } + // Set viewport coordinates - Parameters:1 + case 0x04000580: + { + ((u32 *)(MMU.MMU_MEM[proc][0x40]))[0x580>>2] = val; + if(proc == ARMCPU_ARM9) + { + gpu3D->NDS_3D_ViewPort(val); + } + return; + } +#endif + + case REG_DISPA_WININ: + { + if(proc == ARMCPU_ARM9) + { + GPU_setWININ (MainScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16 (MainScreen.gpu, (val >> 16) & 0xFFFF) ; + } + break; + } + case REG_DISPB_WININ: + { + if(proc == ARMCPU_ARM9) + { + GPU_setWININ (SubScreen.gpu, val & 0xFFFF) ; + GPU_setWINOUT16 (SubScreen.gpu, (val >> 16) & 0xFFFF) ; + } + break; + } + + case REG_DISPA_BLDCNT: + { + if (proc == ARMCPU_ARM9) + { + GPU_setBLDCNT (MainScreen.gpu,val&0xffff); + GPU_setBLDALPHA (MainScreen.gpu,val>>16); + } + break; + } + case REG_DISPB_BLDCNT: + { + if (proc == ARMCPU_ARM9) + { + GPU_setBLDCNT (SubScreen.gpu,val&0xffff); + GPU_setBLDALPHA (SubScreen.gpu,val>>16); + } + break; + } +/* + // Commented out, as this doesn't use the plug-in system, neither works + case cmd_3D_MTX_MODE // 0x04000440 : + if (proc == ARMCPU_ARM9) gl_MTX_MODE(val); + return; + case cmd_3D_MTX_PUSH // 0x04000444 : + case cmd_3D_MTX_POP // 0x04000448 : + case cmd_3D_MTX_STORE // 0x0400044C : + case cmd_3D_MTX_RESTORE // 0x04000450 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_MTX_IDENTITY // 0x04000454 : + if (proc == ARMCPU_ARM9) gl_MTX_IDENTITY(); + return; + case cmd_3D_MTX_LOAD_4x4 // 0x04000458 : + if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x4(val); + return; + case cmd_3D_MTX_LOAD_4x3 // 0x0400045C : + if (proc == ARMCPU_ARM9) gl_MTX_LOAD_4x3(val); + return; + case cmd_3D_MTX_MULT_4x4 // 0x04000460 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x4(val); + return; + case cmd_3D_MTX_MULT_4x3 // 0x04000464 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_4x3(val); + return; + case cmd_3D_MTX_MULT_3x3 // 0x04000468 : + if (proc == ARMCPU_ARM9) gl_MTX_MULT_3x3(val); + return; + case cmd_3D_MTX_SCALE // 0x0400046C : + case cmd_3D_MTX_TRANS // 0x04000470 : + case cmd_3D_COLOR // 0x04000480 : + case cmd_3D_NORMA // 0x04000484 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_TEXCOORD // 0x04000488 : + if (proc == ARMCPU_ARM9) gl_TEXCOORD(val); + return; + case cmd_3D_VTX_16 // 0x0400048C : + if (proc == ARMCPU_ARM9) gl_VTX_16(val); + return; + case cmd_3D_VTX_10 // 0x04000490 : + if (proc == ARMCPU_ARM9) gl_VTX_10(val); + return; + case cmd_3D_VTX_XY // 0x04000494 : + if (proc == ARMCPU_ARM9) gl_VTX_XY(val); + return; + case cmd_3D_VTX_XZ // 0x04000498 : + if (proc == ARMCPU_ARM9) gl_VTX_XZ(val); + return; + case cmd_3D_VTX_YZ // 0x0400049C : + if (proc == ARMCPU_ARM9) gl_VTX_YZ(val); + return; + case cmd_3D_VTX_DIFF // 0x040004A0 : + if (proc == ARMCPU_ARM9) gl_VTX_DIFF(val); + return; + case cmd_3D_POLYGON_ATTR // 0x040004A4 : + case cmd_3D_TEXIMAGE_PARAM // 0x040004A8 : + case cmd_3D_PLTT_BASE // 0x040004AC : + case cmd_3D_DIF_AMB // 0x040004C0 : + case cmd_3D_SPE_EMI // 0x040004C4 : + case cmd_3D_LIGHT_VECTOR // 0x040004C8 : + case cmd_3D_LIGHT_COLOR // 0x040004CC : + case cmd_3D_SHININESS // 0x040004D0 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; + case cmd_3D_BEGIN_VTXS // 0x04000500 : + if (proc == ARMCPU_ARM9) gl_VTX_begin(val); + return; + case cmd_3D_END_VTXS // 0x04000504 : + if (proc == ARMCPU_ARM9) gl_VTX_end(); + return; + case cmd_3D_SWAP_BUFFERS // 0x04000540 : + case cmd_3D_VIEWPORT // 0x04000580 : + case cmd_3D_BOX_TEST // 0x040005C0 : + case cmd_3D_POS_TEST // 0x040005C4 : + case cmd_3D_VEC_TEST // 0x040005C8 : + if (proc == ARMCPU_ARM9) gl_print_cmd(adr); + return; +*/ + case REG_DISPA_DISPCNT : + if(proc == ARMCPU_ARM9) GPU_setVideoProp(MainScreen.gpu, val); + + //GPULOG("MAIN INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0, val); + return; + + case REG_DISPB_DISPCNT : + if (proc == ARMCPU_ARM9) GPU_setVideoProp(SubScreen.gpu, val); + //GPULOG("SUB INIT 32B %08X\r\n", val); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x1000, val); + return; + case REG_VRAMCNTA: + case REG_VRAMCNTE: + MMU_write8(proc,adr,val & 0xFF) ; + MMU_write8(proc,adr+1,val >> 8) ; + MMU_write8(proc,adr+2,val >> 16) ; + MMU_write8(proc,adr+3,val >> 24) ; + return ; + case REG_VRAMCNTI: + MMU_write8(proc,adr,val & 0xFF) ; + return ; + + case REG_IME : { + u32 old_val = MMU.reg_IME[proc]; + u32 new_val = val & 1; + MMU.reg_IME[proc] = new_val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x208, val); + if ( new_val && old_val != new_val) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + } + + case REG_IE : + MMU.reg_IE[proc] = val; + if ( MMU.reg_IME[proc]) { + /* raise an interrupt request to the CPU if needed */ + if ( MMU.reg_IE[proc] & MMU.reg_IF[proc]) { + NDS_ARM7.wIRQ = TRUE; + NDS_ARM7.waitIRQ = FALSE; + } + } + return; + + case REG_IF : + MMU.reg_IF[proc] &= (~val); + return; + case REG_TM0CNTL : + case REG_TM1CNTL : + case REG_TM2CNTL : + case REG_TM3CNTL : + MMU.timerReload[proc][(adr>>2)&0x3] = (u16)val; + if(val&0x800000) + { + MMU.timer[proc][(adr>>2)&0x3] = MMU.timerReload[proc][(adr>>2)&0x3]; + } + MMU.timerON[proc][(adr>>2)&0x3] = val & 0x800000; + switch((val>>16)&7) + { + case 0 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 0+1;//proc; + break; + case 1 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 6+1;//proc; + break; + case 2 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 8+1;//proc; + break; + case 3 : + MMU.timerMODE[proc][(adr>>2)&0x3] = 10+1;//proc; + break; + default : + MMU.timerMODE[proc][(adr>>2)&0x3] = 0xFFFF; + break; + } + if(!(val & 0x800000)) + { + MMU.timerRUN[proc][(adr>>2)&0x3] = FALSE; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & 0xFFF, val); + return; + case REG_DIVDENOM : + { + u16 cnt; + s64 num = 0; + s64 den = 1; + s64 res; + s64 mod; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x298, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280); + switch(cnt&3) + { + case 0: + { + num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + case 1: + { + num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + case 2: + { + return; + } + break; + default: + break; + } + if(den==0) + { + res = 0; + mod = 0; + cnt |= 0x4000; + cnt &= 0x7FFF; + } + else + { + res = num / den; + mod = num % den; + cnt &= 0x3FFF; + } + DIVLOG("BOUT1 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, + (u32)(den>>32), (u32)den, + (u32)(res>>32), (u32)res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt); + } + return; + case REG_DIVDENOM+4 : + { + u16 cnt; + s64 num = 0; + s64 den = 1; + s64 res; + s64 mod; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x29C, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x280); + switch(cnt&3) + { + case 0: + { + return; + } + break; + case 1: + { + return; + } + break; + case 2: + { + num = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x290); + den = (s64) T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x298); + } + break; + default: + break; + } + if(den==0) + { + res = 0; + mod = 0; + cnt |= 0x4000; + cnt &= 0x7FFF; + } + else + { + res = num / den; + mod = num % den; + cnt &= 0x3FFF; + } + DIVLOG("BOUT2 %08X%08X / %08X%08X = %08X%08X\r\n", (u32)(num>>32), (u32)num, + (u32)(den>>32), (u32)den, + (u32)(res>>32), (u32)res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A0, (u32) res); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A4, (u32) (res >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2A8, (u32) mod); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2AC, (u32) (mod >> 32)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x280, cnt); + } + return; + case REG_SQRTPARAM : + { + u16 cnt; + u64 v = 1; + //execute = FALSE; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B8, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0); + switch(cnt&1) + { + case 0: + v = (u64) T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B8); + break; + case 1: + return; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF); + SQRTLOG("BOUT1 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, + T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4)); + } + return; + case REG_SQRTPARAM+4 : + { + u16 cnt; + u64 v = 1; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2BC, val); + cnt = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x2B0); + switch(cnt&1) + { + case 0: + return; + //break; + case 1: + v = T1ReadQuad(MMU.MMU_MEM[proc][0x40], 0x2B8); + break; + } + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B4, (u32) sqrt((s64)v)); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x2B0, cnt & 0x7FFF); + SQRTLOG("BOUT2 sqrt(%08X%08X) = %08X\r\n", (u32)(v>>32), (u32)v, + T1ReadLong(MMU.MMU_MEM[proc][0x40], 0x2B4)); + } + return; + case REG_IPCSYNC : + { + //execute=FALSE; + u32 remote = (proc+1)&1; + u32 IPCSYNC_remote = T1ReadLong(MMU.MMU_MEM[remote][0x40], 0x180); + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF)); + T1WriteLong(MMU.MMU_MEM[remote][0x40], 0x180, (IPCSYNC_remote&0xFFF0)|((val>>8)&0xF)); + MMU.reg_IF[remote] |= ((IPCSYNC_remote & (1<<14))<<2) & ((val & (1<<13))<<3);// & (MMU.reg_IME[remote] << 16);// & (MMU.reg_IE[remote] & (1<<16));// + } + return; + case REG_IPCFIFOCNT : + { + u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; + u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; + if ((val & 0x8000) && !(cnt_l & 0x8000)) + { + /* this is the first init, the other side didnt init yet */ + /* so do a complete init */ + FIFOInit(MMU.fifos + (IPCFIFO+proc)); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; + /* and then handle it as usual */ + } + if(val & 0x4008) + { + FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); + T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); + MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// + return; + } + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4); + //execute = FALSE; + return; + } + case REG_IPCFIFOSEND : + { + u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); + if(IPCFIFO_CNT&0x8000) + { + //if(val==43) execute = FALSE; + u32 remote = (proc+1)&1; + u32 fifonum = IPCFIFO+remote; + u16 IPCFIFO_CNT_remote; + FIFOAdd(MMU.fifos + fifonum, val); + IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (MMU.fifos[fifonum].full<<1); + IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); + IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (MMU.fifos[fifonum].full<<10); + T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT); + T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote); + MMU.reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU.reg_IME[remote] << 18);// & (MMU.reg_IE[remote] & 0x40000);// + //execute = FALSE; + } + } + return; + case REG_DMA0CNTL : + //LOG("32 bit dma0 %04X\r\n", val); + DMASrc[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB0); + DMADst[proc][0] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB4); + MMU.DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][0] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8, val); + if( MMU.DMAStartTime[proc][0] == 0 || + MMU.DMAStartTime[proc][0] == 7) // Start Immediately + MMU_doDMA(proc, 0); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 0, DMASrc[proc][0], DMADst[proc][0], 0, ((MMU.DMACrt[proc][0]>>27)&7)); + } + #endif + //execute = FALSE; + return; + case REG_DMA1CNTL: + //LOG("32 bit dma1 %04X\r\n", val); + DMASrc[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xBC); + DMADst[proc][1] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC0); + MMU.DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][1] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xC4, val); + if(MMU.DMAStartTime[proc][1] == 0 || + MMU.DMAStartTime[proc][1] == 7) // Start Immediately + MMU_doDMA(proc, 1); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 1, DMASrc[proc][1], DMADst[proc][1], 0, ((MMU.DMACrt[proc][1]>>27)&7)); + } + #endif + return; + case REG_DMA2CNTL : + //LOG("32 bit dma2 %04X\r\n", val); + DMASrc[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xC8); + DMADst[proc][2] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xCC); + MMU.DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][2] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xD0, val); + if(MMU.DMAStartTime[proc][2] == 0 || + MMU.DMAStartTime[proc][2] == 7) // Start Immediately + MMU_doDMA(proc, 2); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 2, DMASrc[proc][2], DMADst[proc][2], 0, ((MMU.DMACrt[proc][2]>>27)&7)); + } + #endif + return; + case 0x040000DC : + //LOG("32 bit dma3 %04X\r\n", val); + DMASrc[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD4); + DMADst[proc][3] = T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xD8); + MMU.DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); + MMU.DMACrt[proc][3] = val; + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xDC, val); + if( MMU.DMAStartTime[proc][3] == 0 || + MMU.DMAStartTime[proc][3] == 7) // Start Immediately + MMU_doDMA(proc, 3); + #ifdef LOG_DMA2 + else + { + LOG("proc %d, dma %d src %08X dst %08X start taille %d %d\r\n", proc, 3, DMASrc[proc][3], DMADst[proc][3], 0, ((MMU.DMACrt[proc][3]>>27)&7)); + } + #endif + return; + case REG_GCROMCTRL : + { + int i; + + if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7) + { + MMU.dscard[proc].adress = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4)); + MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7)); + } + else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8) + { + // Get ROM chip ID + val |= 0x800000; // Data-Word Status + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + MMU.dscard[proc].adress = 0; + } + else + { + LOG("CARD command: %02X\n", MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT)); + } + + //CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]); + val |= 0x00800000; + + if(MMU.dscard[proc].adress == 0) + { + val &= ~0x80000000; + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + return; + } + T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); + + /* launch DMA if start flag was set to "DS Cart" */ + if(proc == ARMCPU_ARM7) i = 2; + else i = 5; + + if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][0] == i) /* dma0/1 on arm7 can't start on ds cart event */ + { + MMU_doDMA(proc, 0); + return; + } + else if(proc == ARMCPU_ARM9 && MMU.DMAStartTime[proc][1] == i) + { + MMU_doDMA(proc, 1); + return; + } + else if(MMU.DMAStartTime[proc][2] == i) + { + MMU_doDMA(proc, 2); + return; + } + else if(MMU.DMAStartTime[proc][3] == i) + { + MMU_doDMA(proc, 3); + return; + } + return; + + } + return; + case REG_DISPA_DISPCAPCNT : + if(proc == ARMCPU_ARM9) + { + GPU_set_DISPCAPCNT(MainScreen.gpu,val); + T1WriteLong(ARM9Mem.ARM9_REG, 0x64, val); + } + return; + + case REG_DISPA_BG0CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(MainScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 1, (val>>16)); + } + //if((val>>16)==0x400) execute = FALSE; + T1WriteLong(ARM9Mem.ARM9_REG, 8, val); + return; + case REG_DISPA_BG2CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(MainScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(MainScreen.gpu, 3, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0xC, val); + return; + case REG_DISPB_BG0CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(SubScreen.gpu, 0, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 1, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0x1008, val); + return; + case REG_DISPB_BG2CNT : + if (proc == ARMCPU_ARM9) + { + GPU_setBGProp(SubScreen.gpu, 2, (val&0xFFFF)); + GPU_setBGProp(SubScreen.gpu, 3, (val>>16)); + } + T1WriteLong(ARM9Mem.ARM9_REG, 0x100C, val); + return; + case REG_DISPA_DISPMMEMFIFO: + { + // NOTE: right now, the capture unit is not taken into account, + // I don't know is it should be handled here or + + FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val); + break; + } + //case 0x21FDFF0 : if(val==0) execute = FALSE; + //case 0x21FDFB0 : if(val==0) execute = FALSE; + default : + T1WriteLong(MMU.MMU_MEM[proc][0x40], adr & MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); + return; + } + } + T1WriteLong(MMU.MMU_MEM[proc][(adr>>20)&0xFF], adr&MMU.MMU_MASK[proc][(adr>>20)&0xFF], val); +} + + +void FASTCALL MMU_doDMA(u32 proc, u32 num) +{ + u32 src = DMASrc[proc][num]; + u32 dst = DMADst[proc][num]; + u32 taille; + + if(src==dst) + { + T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num), T1ReadLong(MMU.MMU_MEM[proc][0x40], 0xB8 + (0xC*num)) & 0x7FFFFFFF); + return; + } + + if((!(MMU.DMACrt[proc][num]&(1<<31)))&&(!(MMU.DMACrt[proc][num]&(1<<25)))) + { /* not enabled and not to be repeated */ + MMU.DMAStartTime[proc][num] = 0; + MMU.DMACycle[proc][num] = 0; + //MMU.DMAing[proc][num] = FALSE; + return; + } + + + /* word count */ + taille = (MMU.DMACrt[proc][num]&0xFFFF); + + // If we are in "Main memory display" mode just copy an entire + // screen (256x192 pixels). + // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode + // (under DISP_MMEM_FIFO) + if ((MMU.DMAStartTime[proc][num]==4) && // Must be in main memory display mode + (taille==4) && // Word must be 4 + (((MMU.DMACrt[proc][num]>>26)&1) == 1)) // Transfer mode must be 32bit wide + taille = 256*192/2; + + if(MMU.DMAStartTime[proc][num] == 5) + taille *= 0x80; + + MMU.DMACycle[proc][num] = taille + nds.cycles; + MMU.DMAing[proc][num] = TRUE; + + DMALOG("proc %d, dma %d src %08X dst %08X start %d taille %d repeat %s %08X\r\n", + proc, num, src, dst, MMU.DMAStartTime[proc][num], taille, + (MMU.DMACrt[proc][num]&(1<<25))?"on":"off",MMU.DMACrt[proc][num]); + + if(!(MMU.DMACrt[proc][num]&(1<<25))) + MMU.DMAStartTime[proc][num] = 0; + + // transfer + { + u32 i=0; + // 32 bit or 16 bit transfer ? + int sz = ((MMU.DMACrt[proc][num]>>26)&1)? 4 : 2; + int dstinc,srcinc; + int u=(MMU.DMACrt[proc][num]>>21); + switch(u & 0x3) { + case 0 : dstinc = sz; break; + case 1 : dstinc = -sz; break; + case 2 : dstinc = 0; break; + case 3 : dstinc = sz; break; //reload + } + switch((u >> 2)&0x3) { + case 0 : srcinc = sz; break; + case 1 : srcinc = -sz; break; + case 2 : srcinc = 0; break; + case 3 : // reserved + return; + } + if ((MMU.DMACrt[proc][num]>>26)&1) + for(; i < taille; ++i) + { + MMU_write32(proc, dst, MMU_read32(proc, src)); + dst += dstinc; + src += srcinc; + } + else + for(; i < taille; ++i) + { + MMU_write16(proc, dst, MMU_read16(proc, src)); + dst += dstinc; + src += srcinc; + } + } +} + +#ifdef MMU_ENABLE_ACL + +INLINE void check_access(u32 adr, u32 access) { + /* every other mode: sys */ + access |= 1; + if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { + /* is user mode access */ + access ^= 1 ; + } + if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { + execute = FALSE ; + } +} +INLINE void check_access_write(u32 adr) { + u32 access = CP15_ACCESS_WRITE; + check_access(adr, access) +} + +u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read8(proc,adr); +} +u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read16(proc,adr); +} +u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access) +{ + /* on arm9 we need to check the MPU regions */ + if (proc == ARMCPU_ARM9) + check_access(u32 adr, u32 access); + return MMU_read32(proc,adr); +} + +void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write8(proc,adr,val); +} +void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write16(proc,adr,val) ; +} +void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val) +{ + /* check MPU region on ARM9 */ + if (proc == ARMCPU_ARM9) + check_access_write(adr); + MMU_write32(proc,adr,val) ; +} +#endif + + + +#ifdef PROFILE_MEMORY_ACCESS + +#define PROFILE_PREFETCH 0 +#define PROFILE_READ 1 +#define PROFILE_WRITE 2 + +struct mem_access_profile { + u64 num_accesses; + u32 address_mask; + u32 masked_value; +}; + +#define PROFILE_NUM_MEM_ACCESS_PROFILES 4 + +static u64 profile_num_accesses[2][3]; +static u64 profile_unknown_addresses[2][3]; +static struct mem_access_profile +profile_memory_accesses[2][3][PROFILE_NUM_MEM_ACCESS_PROFILES]; + +static void +setup_profiling( void) { + int i; + + for ( i = 0; i < 2; i++) { + int access_type; + + for ( access_type = 0; access_type < 3; access_type++) { + profile_num_accesses[i][access_type] = 0; + profile_unknown_addresses[i][access_type] = 0; + + /* + * Setup the access testing structures + */ + profile_memory_accesses[i][access_type][0].address_mask = 0x0e000000; + profile_memory_accesses[i][access_type][0].masked_value = 0x00000000; + profile_memory_accesses[i][access_type][0].num_accesses = 0; + + /* main memory */ + profile_memory_accesses[i][access_type][1].address_mask = 0x0f000000; + profile_memory_accesses[i][access_type][1].masked_value = 0x02000000; + profile_memory_accesses[i][access_type][1].num_accesses = 0; + + /* shared memory */ + profile_memory_accesses[i][access_type][2].address_mask = 0x0f800000; + profile_memory_accesses[i][access_type][2].masked_value = 0x03000000; + profile_memory_accesses[i][access_type][2].num_accesses = 0; + + /* arm7 memory */ + profile_memory_accesses[i][access_type][3].address_mask = 0x0f800000; + profile_memory_accesses[i][access_type][3].masked_value = 0x03800000; + profile_memory_accesses[i][access_type][3].num_accesses = 0; + } + } +} + +static void +profile_memory_access( int arm9, u32 adr, int access_type) { + static int first = 1; + int mem_profile; + int address_found = 0; + + if ( first) { + setup_profiling(); + first = 0; + } + + profile_num_accesses[arm9][access_type] += 1; + + for ( mem_profile = 0; + mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES && + !address_found; + mem_profile++) { + if ( (adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask) == + profile_memory_accesses[arm9][access_type][mem_profile].masked_value) { + /*printf( "adr %08x mask %08x res %08x expected %08x\n", + adr, + profile_memory_accesses[arm9][access_type][mem_profile].address_mask, + adr & profile_memory_accesses[arm9][access_type][mem_profile].address_mask, + profile_memory_accesses[arm9][access_type][mem_profile].masked_value);*/ + address_found = 1; + profile_memory_accesses[arm9][access_type][mem_profile].num_accesses += 1; + } + } + + if ( !address_found) { + profile_unknown_addresses[arm9][access_type] += 1; + } +} + + +static const char *access_type_strings[] = { + "prefetch", + "read ", + "write " +}; + +void +print_memory_profiling( void) { + int arm; + + printf("------ Memory access profile ------\n"); + + for ( arm = 0; arm < 2; arm++) { + int access_type; + + for ( access_type = 0; access_type < 3; access_type++) { + int mem_profile; + printf("ARM%c: num of %s %lld\n", + arm ? '9' : '7', + access_type_strings[access_type], + profile_num_accesses[arm][access_type]); + + for ( mem_profile = 0; + mem_profile < PROFILE_NUM_MEM_ACCESS_PROFILES; + mem_profile++) { + printf( "address %08x: %lld\n", + profile_memory_accesses[arm][access_type][mem_profile].masked_value, + profile_memory_accesses[arm][access_type][mem_profile].num_accesses); + } + + printf( "unknown addresses %lld\n", + profile_unknown_addresses[arm][access_type]); + + printf( "\n"); + } + } + + printf("------ End of Memory access profile ------\n\n"); +} +#else +void +print_memory_profiling( void) { +} +#endif /* End of PROFILE_MEMORY_ACCESS area */ + +static u16 FASTCALL +arm9_prefetch16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM9, adr); +} +static u32 FASTCALL +arm9_prefetch32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM9, adr); +} + +static u8 FASTCALL +arm9_read8( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if( (adr&(~0x3FFF)) == MMU.DTCMRegion) + { + return ARM9Mem.ARM9_DTCM[adr&0x3FFF]; + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF] + [adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]]; + } +#endif + + return MMU_read8( ARMCPU_ARM9, adr); +} +static u16 FASTCALL +arm9_read16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM9, adr); +} +static u32 FASTCALL +arm9_read32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_READ); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Returns data from DTCM (ARM9 only) */ + return T1ReadLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF); + } + /* access to main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + return T1ReadLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM9][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM9, adr); +} + + +static void FASTCALL +arm9_write8(void *data, u32 adr, u8 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if( (adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes data in DTCM (ARM9 only) */ + ARM9Mem.ARM9_DTCM[adr&0x3FFF] = val; + return ; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF] + [adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF]] = val; + return; + } +#endif + + MMU_write8( ARMCPU_ARM9, adr, val); +} +static void FASTCALL +arm9_write16(void *data, u32 adr, u16 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteWord(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + T1WriteWord( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF], + adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val); + return; + } +#endif + + MMU_write16( ARMCPU_ARM9, adr, val); +} +static void FASTCALL +arm9_write32(void *data, u32 adr, u32 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 1, adr, PROFILE_WRITE); +#endif + +#ifdef EARLY_MEMORY_ACCESS + if((adr & ~0x3FFF) == MMU.DTCMRegion) + { + /* Writes in DTCM (ARM9 only) */ + T1WriteLong(ARM9Mem.ARM9_DTCM, adr & 0x3FFF, val); + return; + } + /* main memory */ + if ( (adr & 0x0f000000) == 0x02000000) { + T1WriteLong( MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF], + adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF], val); + return; + } +#endif + + MMU_write32( ARMCPU_ARM9, adr, val); +} + + + + +static u16 FASTCALL +arm7_prefetch16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + /* ARM7 private memory */ + if ( (adr & 0x0f800000) == 0x03800000) { + T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read16( ARMCPU_ARM7, adr); +} +static u32 FASTCALL +arm7_prefetch32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_PREFETCH); +#endif + +#ifdef EARLY_MEMORY_ACCESS + /* ARM7 private memory */ + if ( (adr & 0x0f800000) == 0x03800000) { + T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF], + adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); + } +#endif + + return MMU_read32( ARMCPU_ARM7, adr); +} + +static u8 FASTCALL +arm7_read8( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read8( ARMCPU_ARM7, adr); +} +static u16 FASTCALL +arm7_read16( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read16( ARMCPU_ARM7, adr); +} +static u32 FASTCALL +arm7_read32( void *data, u32 adr) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_READ); +#endif + + return MMU_read32( ARMCPU_ARM7, adr); +} + + +static void FASTCALL +arm7_write8(void *data, u32 adr, u8 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write8( ARMCPU_ARM7, adr, val); +} +static void FASTCALL +arm7_write16(void *data, u32 adr, u16 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write16( ARMCPU_ARM7, adr, val); +} +static void FASTCALL +arm7_write32(void *data, u32 adr, u32 val) { +#ifdef PROFILE_MEMORY_ACCESS + profile_memory_access( 0, adr, PROFILE_WRITE); +#endif + + MMU_write32( ARMCPU_ARM7, adr, val); +} + + + +/* + * the base memory interfaces + */ +struct armcpu_memory_iface arm9_base_memory_iface = { +#ifdef __GNUC__ + .prefetch32 = arm9_prefetch32, + .prefetch16 = arm9_prefetch16, + + .read8 = arm9_read8, + .read16 = arm9_read16, + .read32 = arm9_read32, + + .write8 = arm9_write8, + .write16 = arm9_write16, + .write32 = arm9_write32 +#else + arm9_prefetch32, + arm9_prefetch16, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +#endif +}; + +struct armcpu_memory_iface arm7_base_memory_iface = { +#ifdef __GNUC__ + .prefetch32 = arm7_prefetch32, + .prefetch16 = arm7_prefetch16, + + .read8 = arm7_read8, + .read16 = arm7_read16, + .read32 = arm7_read32, + + .write8 = arm7_write8, + .write16 = arm7_write16, + .write32 = arm7_write32 +#else + arm7_prefetch32, + arm7_prefetch16, + + arm7_read8, + arm7_read16, + arm7_read32, + + arm7_write8, + arm7_write16, + arm7_write32 +#endif +}; + +/* + * The direct memory interface for the ARM9. + * This avoids the ARM9 protection unit when accessing + * memory. + */ +struct armcpu_memory_iface arm9_direct_memory_iface = { +#ifdef __GNUC__ + /* the prefetch is not used */ + .prefetch32 = NULL, + .prefetch16 = NULL, + + .read8 = arm9_read8, + .read16 = arm9_read16, + .read32 = arm9_read32, + + .write8 = arm9_write8, + .write16 = arm9_write16, + .write32 = arm9_write32 +#else + NULL, + NULL, + + arm9_read8, + arm9_read16, + arm9_read32, + + arm9_write8, + arm9_write16, + arm9_write32 +#endif +}; diff --git a/tools/vio2sf/src/vio2sf/desmume/MMU.h b/tools/vio2sf/src/vio2sf/desmume/MMU.h new file mode 100644 index 000000000..8cdbacc43 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/MMU.h @@ -0,0 +1,200 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MMU_H +#define MMU_H + +#include "FIFO.h" +#include "dscard.h" + +#include "ARM9.h" +#include "mc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern char szRomPath[512]; +extern char szRomBaseName[512]; + +/* theses macros are designed for reading/writing in memory (m is a pointer to memory, like MMU.MMU_MEM[proc], and a is an adress, like 0x04000000 */ +#define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)]) + +/* theses ones for reading in rom data */ +#define ROM_8(m, a) (((u8*)(m))[(a)]) + +#define IPCFIFO 0 +#define MAIN_MEMORY_DISP_FIFO 2 + +typedef struct { + //ARM7 mem + u8 ARM7_BIOS[0x4000]; + u8 ARM7_ERAM[0x10000]; + u8 ARM7_REG[0x10000]; + u8 ARM7_WIRAM[0x10000]; + + u8 vram_mode[9]; + u8 vScreen; + + //Shared ram + u8 SWIRAM[0x8000]; + + //Card rom & ram + u8 * CART_ROM; + u8 CART_RAM[0x10000]; + + //Unused ram + u8 UNUSED_RAM[4]; + + u8 * * MMU_MEM[2]; + u32 * MMU_MASK[2]; + + u8 ARM9_RW_MODE; + + FIFO fifos[16]; + + u32 * MMU_WAIT16[2]; + u32 * MMU_WAIT32[2]; + + u32 DTCMRegion; + u32 ITCMRegion; + + u16 timer[2][4]; + s32 timerMODE[2][4]; + u32 timerON[2][4]; + u32 timerRUN[2][4]; + u16 timerReload[2][4]; + + u32 reg_IME[2]; + u32 reg_IE[2]; + u32 reg_IF[2]; + + u32 DMAStartTime[2][4]; + s32 DMACycle[2][4]; + u32 DMACrt[2][4]; + BOOL DMAing[2][4]; + + memory_chip_t fw; + memory_chip_t bupmem; + + nds_dscard dscard[2]; + u32 CheckTimers; + u32 CheckDMAs; + +} MMU_struct; + +extern MMU_struct MMU; + + +struct armcpu_memory_iface { + /** the 32 bit instruction prefetch */ + u32 FASTCALL (*prefetch32)( void *data, u32 adr); + + /** the 16 bit instruction prefetch */ + u16 FASTCALL (*prefetch16)( void *data, u32 adr); + + /** read 8 bit data value */ + u8 FASTCALL (*read8)( void *data, u32 adr); + /** read 16 bit data value */ + u16 FASTCALL (*read16)( void *data, u32 adr); + /** read 32 bit data value */ + u32 FASTCALL (*read32)( void *data, u32 adr); + + /** write 8 bit data value */ + void FASTCALL (*write8)( void *data, u32 adr, u8 val); + /** write 16 bit data value */ + void FASTCALL (*write16)( void *data, u32 adr, u16 val); + /** write 32 bit data value */ + void FASTCALL (*write32)( void *data, u32 adr, u32 val); + + void *data; +}; + + + +static void mmu_select_savetype(int type, int *bmemtype, u32 *bmemsize) { + if (type<0 || type > 5) return; + *bmemtype=save_types[type][0]; + *bmemsize=save_types[type][1]; + mc_realloc(&MMU.bupmem, *bmemtype, *bmemsize); +} + +void MMU_Init(void); +void MMU_DeInit(void); + +void MMU_clearMem( void); + +void MMU_setRom(u8 * rom, u32 mask); +void MMU_unsetRom( void); + + +/** + * Memory reading + */ +u8 FASTCALL MMU_read8(u32 proc, u32 adr); +u16 FASTCALL MMU_read16(u32 proc, u32 adr); +u32 FASTCALL MMU_read32(u32 proc, u32 adr); + +#ifdef MMU_ENABLE_ACL + u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access); + u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access); + u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access); +#else + #define MMU_read8_acl(proc,adr,access) MMU_read8(proc,adr) + #define MMU_read16_acl(proc,adr,access) MMU_read16(proc,adr) + #define MMU_read32_acl(proc,adr,access) MMU_read32(proc,adr) +#endif + +/** + * Memory writing + */ +void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val); +void FASTCALL MMU_write16(u32 proc, u32 adr, u16 val); +void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val); + +#ifdef MMU_ENABLE_ACL + void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val); + void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val); + void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val); +#else + #define MMU_write8_acl MMU_write8 + #define MMU_write16_acl MMU_write16 + #define MMU_write32_acl MMU_write32 +#endif + +void FASTCALL MMU_doDMA(u32 proc, u32 num); + + +/* + * The base ARM memory interfaces + */ +extern struct armcpu_memory_iface arm9_base_memory_iface; +extern struct armcpu_memory_iface arm7_base_memory_iface; +extern struct armcpu_memory_iface arm9_direct_memory_iface; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/NDSSystem.c b/tools/vio2sf/src/vio2sf/desmume/NDSSystem.c new file mode 100644 index 000000000..76850fa7f --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/NDSSystem.c @@ -0,0 +1,748 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include "NDSSystem.h" +#include "MMU.h" +//#include "cflash.h" + +//#include "ROMReader.h" + +/* the count of bytes copied from the firmware into memory */ +#define NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT 0x70 + +NDSSystem nds; + +static u32 +calc_CRC16( u32 start, const u8 *data, int count) { + int i,j; + u32 crc = start & 0xffff; + static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; + for(i = 0; i < count; i++) + { + crc = crc ^ data[i]; + + for(j = 0; j < 8; j++) { + int do_bit = 0; + + if ( crc & 0x1) + do_bit = 1; + + crc = crc >> 1; + + if ( do_bit) { + crc = crc ^ (val[j] << (7-j)); + } + } + } + return crc; +} + +static int +copy_firmware_user_data( u8 *dest_buffer, const u8 *fw_data) { + /* + * Determine which of the two user settings in the firmware is the current + * and valid one and then copy this into the destination buffer. + * + * The current setting will have a greater count. + * Settings are only valid if its CRC16 is correct. + */ + int user1_valid = 0; + int user2_valid = 0; + u32 user_settings_offset; + u32 fw_crc; + u32 crc; + int copy_good = 0; + + user_settings_offset = fw_data[0x20]; + user_settings_offset |= fw_data[0x21] << 8; + user_settings_offset <<= 3; + + if ( user_settings_offset <= 0x3FE00) { + s32 copy_settings_offset = -1; + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x73] << 8; + if ( crc == fw_crc) { + user1_valid = 1; + } + + crc = calc_CRC16( 0xffff, &fw_data[user_settings_offset + 0x100], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + fw_crc = fw_data[user_settings_offset + 0x100 + 0x72]; + fw_crc |= fw_data[user_settings_offset + 0x100 + 0x73] << 8; + if ( crc == fw_crc) { + user2_valid = 1; + } + + if ( user1_valid) { + if ( user2_valid) { + u16 count1, count2; + + count1 = fw_data[user_settings_offset + 0x70]; + count1 |= fw_data[user_settings_offset + 0x71] << 8; + + count2 = fw_data[user_settings_offset + 0x100 + 0x70]; + count2 |= fw_data[user_settings_offset + 0x100 + 0x71] << 8; + + if ( count2 > count1) { + copy_settings_offset = user_settings_offset + 0x100; + } + else { + copy_settings_offset = user_settings_offset; + } + } + else { + copy_settings_offset = user_settings_offset; + } + } + else if ( user2_valid) { + /* copy the second user settings */ + copy_settings_offset = user_settings_offset + 0x100; + } + + if ( copy_settings_offset > 0) { + memcpy( dest_buffer, &fw_data[copy_settings_offset], + NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT); + copy_good = 1; + } + } + + return copy_good; +} + + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface) { +#else +int NDS_Init( void) { +#endif + nds.ARM9Cycle = 0; + nds.ARM7Cycle = 0; + nds.cycles = 0; + MMU_Init(); + nds.nextHBlank = 3168; + nds.VCount = 0; + nds.lignerendu = FALSE; + + if (Screen_Init(GFXCORE_DUMMY) != 0) + return -1; + + #ifdef GDB_STUB + armcpu_new(&NDS_ARM7,1, arm7_mem_if, arm7_ctrl_iface); + armcpu_new(&NDS_ARM9,0, arm9_mem_if, arm9_ctrl_iface); +#else + armcpu_new(&NDS_ARM7,1); + armcpu_new(&NDS_ARM9,0); +#endif + + if (SPU_Init(0, 0) != 0) + return -1; + +#ifdef EXPERIMENTAL_WIFI + WIFI_Init(&wifiMac) ; +#endif + + return 0; +} + +static void armcpu_deinit(armcpu_t *armcpu) +{ + if(armcpu->coproc[15]) + { + free(armcpu->coproc[15]); + armcpu->coproc[15] = 0; + } +} + +void NDS_DeInit(void) { + if(MMU.CART_ROM != MMU.UNUSED_RAM) + NDS_FreeROM(); + + armcpu_deinit(&NDS_ARM7); + armcpu_deinit(&NDS_ARM9); + + nds.nextHBlank = 3168; + SPU_DeInit(); + Screen_DeInit(); + MMU_DeInit(); +} + +BOOL NDS_SetROM(u8 * rom, u32 mask) +{ + MMU_setRom(rom, mask); + + return TRUE; +} + +NDS_header * NDS_getROMHeader(void) +{ + NDS_header * header = malloc(sizeof(NDS_header)); + + memcpy(header->gameTile, MMU.CART_ROM, 12); + memcpy(header->gameCode, MMU.CART_ROM + 12, 4); + header->makerCode = T1ReadWord(MMU.CART_ROM, 16); + header->unitCode = MMU.CART_ROM[18]; + header->deviceCode = MMU.CART_ROM[19]; + header->cardSize = MMU.CART_ROM[20]; + memcpy(header->cardInfo, MMU.CART_ROM + 21, 8); + header->flags = MMU.CART_ROM[29]; + header->ARM9src = T1ReadLong(MMU.CART_ROM, 32); + header->ARM9exe = T1ReadLong(MMU.CART_ROM, 36); + header->ARM9cpy = T1ReadLong(MMU.CART_ROM, 40); + header->ARM9binSize = T1ReadLong(MMU.CART_ROM, 44); + header->ARM7src = T1ReadLong(MMU.CART_ROM, 48); + header->ARM7exe = T1ReadLong(MMU.CART_ROM, 52); + header->ARM7cpy = T1ReadLong(MMU.CART_ROM, 56); + header->ARM7binSize = T1ReadLong(MMU.CART_ROM, 60); + header->FNameTblOff = T1ReadLong(MMU.CART_ROM, 64); + header->FNameTblSize = T1ReadLong(MMU.CART_ROM, 68); + header->FATOff = T1ReadLong(MMU.CART_ROM, 72); + header->FATSize = T1ReadLong(MMU.CART_ROM, 76); + header->ARM9OverlayOff = T1ReadLong(MMU.CART_ROM, 80); + header->ARM9OverlaySize = T1ReadLong(MMU.CART_ROM, 84); + header->ARM7OverlayOff = T1ReadLong(MMU.CART_ROM, 88); + header->ARM7OverlaySize = T1ReadLong(MMU.CART_ROM, 92); + header->unknown2a = T1ReadLong(MMU.CART_ROM, 96); + header->unknown2b = T1ReadLong(MMU.CART_ROM, 100); + header->IconOff = T1ReadLong(MMU.CART_ROM, 104); + header->CRC16 = T1ReadWord(MMU.CART_ROM, 108); + header->ROMtimeout = T1ReadWord(MMU.CART_ROM, 110); + header->ARM9unk = T1ReadLong(MMU.CART_ROM, 112); + header->ARM7unk = T1ReadLong(MMU.CART_ROM, 116); + memcpy(header->unknown3c, MMU.CART_ROM + 120, 8); + header->ROMSize = T1ReadLong(MMU.CART_ROM, 128); + header->HeaderSize = T1ReadLong(MMU.CART_ROM, 132); + memcpy(header->unknown5, MMU.CART_ROM + 136, 56); + memcpy(header->logo, MMU.CART_ROM + 192, 156); + header->logoCRC16 = T1ReadWord(MMU.CART_ROM, 348); + header->headerCRC16 = T1ReadWord(MMU.CART_ROM, 350); + memcpy(header->reserved, MMU.CART_ROM + 352, 160); + + return header; + + //return (NDS_header *)MMU.CART_ROM; +} + + + +void NDS_FreeROM(void) +{ + if (MMU.CART_ROM != MMU.UNUSED_RAM) + free(MMU.CART_ROM); + MMU_unsetRom(); +// if (MMU.bupmem.fp) +// fclose(MMU.bupmem.fp); +// MMU.bupmem.fp = NULL; +} + + + +void NDS_Reset( void) +{ + BOOL oldexecute=execute; + int i; + u32 src; + u32 dst; + NDS_header * header = NDS_getROMHeader(); + + if (!header) return ; + + execute = FALSE; + + MMU_clearMem(); + + src = header->ARM9src; + dst = header->ARM9cpy; + + for(i = 0; i < (header->ARM9binSize>>2); ++i) + { + MMU_write32(0, dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + src = header->ARM7src; + dst = header->ARM7cpy; + + for(i = 0; i < (header->ARM7binSize>>2); ++i) + { + MMU_write32(1, dst, T1ReadLong(MMU.CART_ROM, src)); + dst += 4; + src += 4; + } + + armcpu_init(&NDS_ARM7, header->ARM7exe); + armcpu_init(&NDS_ARM9, header->ARM9exe); + + nds.ARM9Cycle = 0; + nds.ARM7Cycle = 0; + nds.cycles = 0; + memset(nds.timerCycle, 0, sizeof(s32) * 2 * 4); + memset(nds.timerOver, 0, sizeof(BOOL) * 2 * 4); + nds.nextHBlank = 3168; + nds.VCount = 0; + nds.old = 0; + nds.diff = 0; + nds.lignerendu = FALSE; + nds.touchX = nds.touchY = 0; + + MMU_write16(0, 0x04000130, 0x3FF); + MMU_write16(1, 0x04000130, 0x3FF); + MMU_write8(1, 0x04000136, 0x43); + + /* + * Setup a copy of the firmware user settings in memory. + * (this is what the DS firmware would do). + */ + { + u8 temp_buffer[NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT]; + int fw_index; + + if ( copy_firmware_user_data( temp_buffer, MMU.fw.data)) { + for ( fw_index = 0; fw_index < NDS_FW_USER_SETTINGS_MEM_BYTE_COUNT; fw_index++) { + MMU_write8( 0, 0x027FFC80 + fw_index, temp_buffer[fw_index]); + } + } + } + + // Copy the whole header to Main RAM 0x27FFE00 on startup. + // Reference: http://nocash.emubase.de/gbatek.htm#dscartridgeheader + for (i = 0; i < ((0x170+0x90)/4); i++) + { + MMU_write32 (0, 0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); + } + + MainScreen.offset = 0; + SubScreen.offset = 192; + + //MMU_write32(0, 0x02007FFC, 0xE92D4030); + + //ARM7 BIOS IRQ HANDLER + MMU_write32(1, 0x00, 0xE25EF002); + MMU_write32(1, 0x04, 0xEAFFFFFE); + MMU_write32(1, 0x18, 0xEA000000); + MMU_write32(1, 0x20, 0xE92D500F); + MMU_write32(1, 0x24, 0xE3A00301); + MMU_write32(1, 0x28, 0xE28FE000); + MMU_write32(1, 0x2C, 0xE510F004); + MMU_write32(1, 0x30, 0xE8BD500F); + MMU_write32(1, 0x34, 0xE25EF004); + + //ARM9 BIOS IRQ HANDLER + MMU_write32(0, 0xFFFF0018, 0xEA000000); + MMU_write32(0, 0xFFFF0020, 0xE92D500F); + MMU_write32(0, 0xFFFF0024, 0xEE190F11); + MMU_write32(0, 0xFFFF0028, 0xE1A00620); + MMU_write32(0, 0xFFFF002C, 0xE1A00600); + MMU_write32(0, 0xFFFF0030, 0xE2800C40); + MMU_write32(0, 0xFFFF0034, 0xE28FE000); + MMU_write32(0, 0xFFFF0038, 0xE510F004); + MMU_write32(0, 0xFFFF003C, 0xE8BD500F); + MMU_write32(0, 0xFFFF0040, 0xE25EF004); + + MMU_write32(0, 0x0000004, 0xE3A0010E); + MMU_write32(0, 0x0000008, 0xE3A01020); +// MMU_write32(0, 0x000000C, 0xE1B02110); + MMU_write32(0, 0x000000C, 0xE1B02040); + MMU_write32(0, 0x0000010, 0xE3B02020); +// MMU_write32(0, 0x0000010, 0xE2100202); + + free(header); + + GPU_Reset(MainScreen.gpu, 0); + GPU_Reset(SubScreen.gpu, 1); + SPU_Reset(); + + execute = oldexecute; +} + +static void dma_check(void) +{ + if((MMU.DMAing[0][0])&&(MMU.DMACycle[0][0]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][0])&(1<<30)) NDS_makeARM9Int(8); + MMU.DMAing[0][0] = FALSE; + } + + if((MMU.DMAing[0][1])&&(MMU.DMACycle[0][1]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][1])&(1<<30)) NDS_makeARM9Int(9); + MMU.DMAing[0][1] = FALSE; + } + + if((MMU.DMAing[0][2])&&(MMU.DMACycle[0][2]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][2])&(1<<30)) NDS_makeARM9Int(10); + MMU.DMAing[0][2] = FALSE; + } + + if((MMU.DMAing[0][3])&&(MMU.DMACycle[0][3]<=nds.cycles)) + { + T1WriteLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3), T1ReadLong(ARM9Mem.ARM9_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF); + if((MMU.DMACrt[0][3])&(1<<30)) NDS_makeARM9Int(11); + MMU.DMAing[0][3] = FALSE; + } + + if((MMU.DMAing[1][0])&&(MMU.DMACycle[1][0]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*0), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*0)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][0])&(1<<30)) NDS_makeARM7Int(8); + MMU.DMAing[1][0] = FALSE; + } + + if((MMU.DMAing[1][1])&&(MMU.DMACycle[1][1]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*1), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*1)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][1])&(1<<30)) NDS_makeARM7Int(9); + MMU.DMAing[1][1] = FALSE; + } + + if((MMU.DMAing[1][2])&&(MMU.DMACycle[1][2]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*2), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*2)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][2])&(1<<30)) NDS_makeARM7Int(10); + MMU.DMAing[1][2] = FALSE; + } + + if((MMU.DMAing[1][3])&&(MMU.DMACycle[1][3]<=nds.cycles)) + { + T1WriteLong(MMU.ARM7_REG, 0xB8 + (0xC*3), T1ReadLong(MMU.ARM7_REG, 0xB8 + (0xC*3)) & 0x7FFFFFFF); + if((MMU.DMACrt[1][3])&(1<<30)) NDS_makeARM7Int(11); + MMU.DMAing[1][3] = FALSE; + } + + if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0])) + { +#ifdef GDB_STUB + if ( armcpu_flagIrq( &NDS_ARM9)) +#else + if ( armcpu_irqExeption(&NDS_ARM9)) +#endif + { + nds.ARM9Cycle = nds.cycles; + } + } + + if((MMU.reg_IF[1]&MMU.reg_IE[1]) && (MMU.reg_IME[1])) + { +#ifdef GDB_STUB + if ( armcpu_flagIrq( &NDS_ARM7)) +#else + if ( armcpu_irqExeption(&NDS_ARM7)) +#endif + { + nds.ARM7Cycle = nds.cycles; + } + } + +} + +static void timer_check(void) +{ + int p, t; + for (p = 0; p < 2; p++) + { + for (t = 0; t < 4; t++) + { + nds.timerOver[p][t] = 0; + if(MMU.timerON[p][t]) + { + if(MMU.timerRUN[p][t]) + { + switch(MMU.timerMODE[p][t]) + { + case 0xFFFF : + if(t > 0 && nds.timerOver[p][t - 1]) + { + ++(MMU.timer[p][t]); + nds.timerOver[p][t] = !MMU.timer[p][t]; + if (nds.timerOver[p][t]) + { + if (p == 0) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM9Int(3 + t); + } + else + { + if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM7Int(3 + t); + } + MMU.timer[p][t] = MMU.timerReload[p][t]; + } + } + break; + default : + { + nds.diff = (nds.cycles >> MMU.timerMODE[p][t]) - (nds.timerCycle[p][t] >> MMU.timerMODE[p][t]); + nds.old = MMU.timer[p][t]; + MMU.timer[p][t] += nds.diff; + nds.timerCycle[p][t] += nds.diff << MMU.timerMODE[p][t]; + nds.timerOver[p][t] = nds.old >= MMU.timer[p][t]; + if(nds.timerOver[p][t]) + { + if (p == 0) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM9Int(3 + t); + } + else + { + if(T1ReadWord(MMU.ARM7_REG, 0x102 + (t << 2)) & 0x40) + NDS_makeARM7Int(3 + t); + } + MMU.timer[p][t] = MMU.timerReload[p][t] + MMU.timer[p][t] - nds.old; + } + } + break; + } + } + else + { + MMU.timerRUN[p][t] = TRUE; + nds.timerCycle[p][t] = nds.cycles; + } + } + } + } +} + +void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7) +{ + int h; + for (h = 0; h < 2; h++) + { + s32 nb = nds.cycles + (h ? (99 * 12) : (256 * 12)); + + while (nb > nds.ARM9Cycle && !NDS_ARM9.waitIRQ) + nds.ARM9Cycle += armcpu_exec(&NDS_ARM9) << (cpu_clockdown_level_arm9); + if (NDS_ARM9.waitIRQ) nds.ARM9Cycle = nb; + while (nb > nds.ARM7Cycle && !NDS_ARM7.waitIRQ) + nds.ARM7Cycle += armcpu_exec(&NDS_ARM7) << (1 + (cpu_clockdown_level_arm7)); + if (NDS_ARM7.waitIRQ) nds.ARM7Cycle = nb; + nds.cycles = (nds.ARM9Cycle>8)|((vmatch<<1)&(1<<8)))) + { + T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) | 4); + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 32) + NDS_makeARM9Int(2); + } + else + T1WriteWord(ARM9Mem.ARM9_REG, 4, T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0xFFFB); + + vmatch = T1ReadWord(MMU.ARM7_REG, 4); + if((nds.VCount==(vmatch>>8)|((vmatch<<1)&(1<<8)))) + { + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 4); + if(T1ReadWord(MMU.ARM7_REG, 4) & 32) + NDS_makeARM7Int(2); + } + else + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFB); + + timer_check(); + dma_check(); + } + } +} + +void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7) +{ + int v; + for (v = 0; v < 263; v++) + { + NDS_exec_hframe(cpu_clockdown_level_arm9, cpu_clockdown_level_arm7); + } +} + diff --git a/tools/vio2sf/src/vio2sf/desmume/NDSSystem.h b/tools/vio2sf/src/vio2sf/desmume/NDSSystem.h new file mode 100644 index 000000000..e583fe5b7 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/NDSSystem.h @@ -0,0 +1,255 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef NDSSYSTEM_H +#define NDSSYSTEM_H + +#include "armcpu.h" +#include "MMU.h" + +#include "GPU.h" +#include "SPU_exports.h" + +#include "mem.h" +//#include "wifi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +extern volatile BOOL execute; +extern BOOL click; + +/* + * The firmware language values + */ +#define NDS_FW_LANG_JAP 0 +#define NDS_FW_LANG_ENG 1 +#define NDS_FW_LANG_FRE 2 +#define NDS_FW_LANG_GER 3 +#define NDS_FW_LANG_ITA 4 +#define NDS_FW_LANG_SPA 5 +#define NDS_FW_LANG_CHI 6 +#define NDS_FW_LANG_RES 7 + + +//#define LOG_ARM9 +//#define LOG_ARM7 + +typedef struct +{ + char gameTile[12]; + char gameCode[4]; + u16 makerCode; + u8 unitCode; + u8 deviceCode; + u8 cardSize; + u8 cardInfo[8]; + u8 flags; + + u32 ARM9src; + u32 ARM9exe; + u32 ARM9cpy; + u32 ARM9binSize; + + u32 ARM7src; + u32 ARM7exe; + u32 ARM7cpy; + u32 ARM7binSize; + + u32 FNameTblOff; + u32 FNameTblSize; + + u32 FATOff; + u32 FATSize; + + u32 ARM9OverlayOff; + u32 ARM9OverlaySize; + u32 ARM7OverlayOff; + u32 ARM7OverlaySize; + + u32 unknown2a; + u32 unknown2b; + + u32 IconOff; + u16 CRC16; + u16 ROMtimeout; + u32 ARM9unk; + u32 ARM7unk; + + u8 unknown3c[8]; + u32 ROMSize; + u32 HeaderSize; + u8 unknown5[56]; + u8 logo[156]; + u16 logoCRC16; + u16 headerCRC16; + u8 reserved[160]; +} NDS_header; + +extern void debug(); + +typedef struct +{ + s32 ARM9Cycle; + s32 ARM7Cycle; + s32 cycles; + s32 timerCycle[2][4]; + BOOL timerOver[2][4]; + s32 nextHBlank; + u32 VCount; + u32 old; + s32 diff; + BOOL lignerendu; + + u16 touchX; + u16 touchY; +} NDSSystem; + +/** /brief A touchscreen calibration point. + */ +struct NDS_fw_touchscreen_cal { + u16 adc_x; + u16 adc_y; + + u8 screen_x; + u8 screen_y; +}; + +/** /brief The type of DS + */ +enum nds_fw_ds_type { + NDS_FW_DS_TYPE_FAT, + NDS_FW_DS_TYPE_LITE +}; + +#define MAX_FW_NICKNAME_LENGTH 10 +#define MAX_FW_MESSAGE_LENGTH 26 + +struct NDS_fw_config_data { + enum nds_fw_ds_type ds_type; + + u8 fav_colour; + u8 birth_month; + u8 birth_day; + + u16 nickname[MAX_FW_NICKNAME_LENGTH]; + u8 nickname_len; + + u16 message[MAX_FW_MESSAGE_LENGTH]; + u8 message_len; + + u8 language; + + /* touchscreen calibration */ + struct NDS_fw_touchscreen_cal touch_cal[2]; +}; + +extern NDSSystem nds; + +#ifdef GDB_STUB +int NDS_Init( struct armcpu_memory_iface *arm9_mem_if, + struct armcpu_ctrl_iface **arm9_ctrl_iface, + struct armcpu_memory_iface *arm7_mem_if, + struct armcpu_ctrl_iface **arm7_ctrl_iface); +#else +int NDS_Init ( void); +#endif + +void NDS_DeInit(void); +void +NDS_FillDefaultFirmwareConfigData( struct NDS_fw_config_data *fw_config); + +BOOL NDS_SetROM(u8 * rom, u32 mask); +NDS_header * NDS_getROMHeader(void); + +void NDS_setTouchPos(u16 x, u16 y); +void NDS_releasTouch(void); + +int NDS_LoadROM(const char *filename, int bmtype, u32 bmsize, + const char *cflash_disk_image_file); +void NDS_FreeROM(void); +void NDS_Reset(void); +int NDS_ImportSave(const char *filename); + +int NDS_WriteBMP(const char *filename); +int NDS_LoadFirmware(const char *filename); +int NDS_CreateDummyFirmware( struct NDS_fw_config_data *user_settings); +u32 +NDS_exec(s32 nb, BOOL force); + + static INLINE void NDS_ARM9HBlankInt(void) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x10) + { + MMU.reg_IF[0] |= 2;// & (MMU.reg_IME[0] << 1);// (MMU.reg_IE[0] & (1<<1)); + NDS_ARM9.wIRQ = TRUE; + } + } + + static INLINE void NDS_ARM7HBlankInt(void) + { + if(T1ReadWord(MMU.ARM7_REG, 4) & 0x10) + { + MMU.reg_IF[1] |= 2;// & (MMU.reg_IME[1] << 1);// (MMU.reg_IE[1] & (1<<1)); + NDS_ARM7.wIRQ = TRUE; + } + } + + static INLINE void NDS_ARM9VBlankInt(void) + { + if(T1ReadWord(ARM9Mem.ARM9_REG, 4) & 0x8) + { + MMU.reg_IF[0] |= 1;// & (MMU.reg_IME[0]);// (MMU.reg_IE[0] & 1); + NDS_ARM9.wIRQ = TRUE; + //execute = FALSE; + /*logcount++;*/ + } + } + + static INLINE void NDS_ARM7VBlankInt(void) + { + if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) + MMU.reg_IF[1] |= 1;// & (MMU.reg_IME[1]);// (MMU.reg_IE[1] & 1); + NDS_ARM7.wIRQ = TRUE; + //execute = FALSE; + } + + static INLINE void NDS_swapScreen(void) + { + u16 tmp = MainScreen.offset; + MainScreen.offset = SubScreen.offset; + SubScreen.offset = tmp; + } + + + +void NDS_exec_frame(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7); +void NDS_exec_hframe(int cpu_clockdown_level_arm9, int cpu_clockdown_level_arm7); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/tools/vio2sf/src/vio2sf/desmume/SPU.c b/tools/vio2sf/src/vio2sf/desmume/SPU.c new file mode 100644 index 000000000..b9db8a078 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/SPU.c @@ -0,0 +1,951 @@ +/* Copyright (C) 2006 Theo Berkau + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include "ARM9.h" +#include "MMU.h" +#include "SPU.h" +#include "mem.h" + +#include "armcpu.h" + +enum +{ + FORMAT_PCM8 = 0, + FORMAT_PCM16 = 1, + FORMAT_ADPCM = 2, + FORMAT_PSG = 3 +}; + +#define VOL_SHIFT 10 + +typedef struct +{ + int id; + int status; + int format; + u8 *buf8; s16 *buf16; + double pos, inc; + int loopend, looppos; + int loop, length; + s32 adpcm; + int adpcm_pos, adpcm_index; + s32 adpcm_loop; + int adpcm_loop_pos, adpcm_loop_index; + int psg_duty; + int timer; + int volume; + int pan; + int shift; + int repeat, hold; + u32 addr; + s32 volumel; + s32 volumer; + s16 output; +} SChannel; + +typedef struct +{ + s32 *pmixbuf; + s16 *pclipingbuf; + u32 buflen; + SChannel ch[16]; +} SPU_struct; + +static SPU_struct spu = { 0, 0, 0 }; + +static SoundInterface_struct *SNDCore=NULL; +extern SoundInterface_struct *SNDCoreList[]; + +int SPU_ChangeSoundCore(int coreid, int buffersize) +{ + int i; + SPU_DeInit(); + + // Allocate memory for sound buffer + spu.buflen = buffersize * 2; /* stereo */ + spu.pmixbuf = malloc(spu.buflen * sizeof(s32)); + if (!spu.pmixbuf) + { + SPU_DeInit(); + return -1; + } + + spu.pclipingbuf = malloc(spu.buflen * sizeof(s16)); + if (!spu.pclipingbuf) + { + SPU_DeInit(); + return -1; + } + + // So which core do we want? + if (coreid == SNDCORE_DEFAULT) + coreid = 0; // Assume we want the first one + + // Go through core list and find the id + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (SNDCoreList[i]->id == coreid) + { + // Set to current core + SNDCore = SNDCoreList[i]; + break; + } + } + + if (SNDCore == NULL) + { + SPU_DeInit(); + return -1; + } + + if (SNDCore->Init(spu.buflen) == -1) + { + // Since it failed, instead of it being fatal, we'll just use the dummy + // core instead + SNDCore = &SNDDummy; + } + + return 0; +} +int SPU_Init(int coreid, int buffersize) +{ + SPU_DeInit(); + SPU_Reset(); + return SPU_ChangeSoundCore(coreid, buffersize); +} +void SPU_Pause(int pause) +{ + if(pause) + SNDCore->MuteAudio(); + else + SNDCore->UnMuteAudio(); +} +void SPU_SetVolume(int volume) +{ + if (SNDCore) + SNDCore->SetVolume(volume); +} +void SPU_DeInit(void) +{ + spu.buflen = 0; + if (spu.pmixbuf) + { + free(spu.pmixbuf); + spu.pmixbuf = 0; + } + if (spu.pclipingbuf) + { + free(spu.pclipingbuf); + spu.pclipingbuf = 0; + } + if (SNDCore) + { + SNDCore->DeInit(); + } + SNDCore = &SNDDummy; +} + +static const short g_adpcm_index[16] = { -1, -1, -1, -1, -1, -1, -1, -1, 2, 2, 4, 4, 6, 6, 8, 8 }; + +static const int g_adpcm_mult[89] = +{ + 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011, + 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D, + 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076, + 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133, + 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C, + 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812, + 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE, + 0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B, + 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF, +}; + +static const s16 g_psg_duty[8][8] = { + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF, +0x7FFF }, + { -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF }, +}; + + +static void reset_channel(SChannel *ch, int id) +{ + ch->status = 0; + ch->id = id; +} + +void SPU_Reset(void) +{ + int i; + for (i = 0;i < 16; i++) + reset_channel(&spu.ch[i], i); + + for (i = 0x400; i < 0x51D; i++) + T1WriteByte(MMU.ARM7_REG, i, 0); +} +void SPU_KeyOn(int channel) +{ +} + +static INLINE void adjust_channel_timer(SChannel *ch) +{ + ch->inc = (((double)33512000) / (44100 * 2)) / (double)(0x10000 - ch->timer); +} + +static int check_valid(u32 addr, u32 size) +{ + u32 t1, t2; + + if(size > MMU.MMU_MASK[1][(addr >> 20) & 0xff]) return 0; + + t1 = addr; + t2 = (addr + size); + t1 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff]; + t2 &= MMU.MMU_MASK[1][(addr >> 20) & 0xff]; + + if(t2 < t1) return 0; + + return 1; +} + +static void start_channel(SChannel *ch) +{ + + switch(ch->format) + { + case FORMAT_PCM8: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 2); + if((p != NULL) && check_valid(ch->addr, size)) + { + ch->buf8 = p + ofs; + ch->looppos = ch->loop << 2; + ch->loopend = size; + ch->pos = 0; + ch->status = 1; + } + } + break; + case FORMAT_PCM16: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 1); + if((p != NULL) && check_valid(ch->addr, size << 1)) + { + ch->buf16 = (s16 *)(p + ofs - (ofs & 1)); + ch->looppos = ch->loop << 1; + ch->loopend = size; + ch->pos = 0; + ch->status = 1; + } + } + break; + case FORMAT_ADPCM: + { + u8 *p = MMU.MMU_MEM[1][(ch->addr >> 20) & 0xff]; + u32 ofs = MMU.MMU_MASK[1][(ch->addr >> 20) & 0xff] & ch->addr; + u32 size = ((ch->length + ch->loop) << 3); + if((p != NULL) && check_valid(ch->addr, size >> 1)) + { + ch->buf8 = p + ofs; +#ifdef WORDS_BIGENDIAN + ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3; +#else + ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3; +#endif + ch->adpcm_index = (ch->buf8[2] & 0x7F); + ch->adpcm_pos = 8; + ch->pos = 9; + ch->looppos = ch->loop << 3; + ch->loopend = size; + ch->adpcm_loop_index = -1; + ch->status = 1; + } + } + break; + case FORMAT_PSG: + ch->status = 1; + if(ch->id < 14) + { + ch->pos = 0; + } + else + { + ch->pos = 0x7FFF; + } + break; + } +} + +static void stop_channel(SChannel *ch) +{ + u32 addr = 0x400 + (ch->id << 4) + 3; + ch->status = 0; + T1WriteByte(MMU.ARM7_REG, addr, (u8)(T1ReadByte(MMU.ARM7_REG, addr) & ~0x80)); +} +static void set_channel_volume(SChannel *ch) +{ + s32 vol1 = (T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F) * ch->volume; + s32 vol2; + vol2 = vol1 * ch->pan; + vol1 = vol1 * (127-ch->pan); + ch->volumel = vol1 >> (21 - VOL_SHIFT + ch->shift); + ch->volumer = vol2 >> (21 - VOL_SHIFT + ch->shift); +} + +void SPU_WriteByte(u32 addr, u8 x) +{ + addr &= 0x00000FFF; + T1WriteByte(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x0F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x7F); + set_channel_volume(ch); + break; + case 0x1: + ch = spu.ch + (addr >> 4 & 0xF); + ch->shift = (x & 0x03); + ch->hold = (x >> 7 & 0x01); + set_channel_volume(ch); + break; + case 0x2: + ch = spu.ch + (addr >> 4 & 0xF); + ch->pan = (x & 0x7F); + set_channel_volume(ch); + break; + case 0x3: + ch = spu.ch + (addr >> 4 & 0xF); + ch->psg_duty = (x & 0x07); + ch->repeat = (x >> 3 & 0x03); + ch->format = (x >> 5 & 0x03); + if(x & 0x80) start_channel(ch); else stop_channel(ch); + break; +#if !DISABLE_XSF_TESTS + case 0x04: + case 0x05: + case 0x06: + case 0x07: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF); + break; + case 0x08: + case 0x09: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = T1ReadWord(MMU.ARM7_REG, addr & ~1); + adjust_channel_timer(ch); + break; + case 0x0a: + case 0x0b: + ch = spu.ch + (addr >> 4 & 0xF); + ch->loop = T1ReadWord(MMU.ARM7_REG, addr & ~1); + break; + case 0x0c: + case 0x0e: + case 0x0d: + case 0x0f: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF); + break; +#endif + } + } + +} + + +void SPU_WriteWord(u32 addr, u16 x) +{ + addr &= 0x00000FFF; + T1WriteWord(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x00F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x007F); + ch->shift = (x >> 8 & 0x0003); + ch->hold = (x >> 15 & 0x0001); + set_channel_volume(ch); + break; + case 0x2: + ch = spu.ch + (addr >> 4 & 0xF); + ch->pan = (x & 0x007F); + ch->psg_duty = (x >> 8 & 0x0007); + ch->repeat = (x >> 11 & 0x0003); + ch->format = (x >> 13 & 0x0003); + set_channel_volume(ch); + if(x & 0x8000) start_channel(ch); else stop_channel(ch); + break; + case 0x08: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = x; + adjust_channel_timer(ch); + break; + case 0x0a: + ch = spu.ch + (addr >> 4 & 0xF); + ch->loop = x; + break; +#if !DISABLE_XSF_TESTS + case 0x04: + case 0x06: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x07FFFFFF); + break; + case 0x0c: + case 0x0e: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (T1ReadLong(MMU.ARM7_REG, addr & ~3) & 0x003FFFFF); + break; +#endif + } + } +} + + +void SPU_WriteLong(u32 addr, u32 x) +{ + addr &= 0x00000FFF; + T1WriteLong(MMU.ARM7_REG, addr, x); + + if(addr < 0x500) + { + SChannel *ch; + switch(addr & 0x00F) + { + case 0x0: + ch = spu.ch + (addr >> 4 & 0xF); + ch->volume = (x & 0x7F); + ch->shift = (x >> 8 & 0x00000003); + ch->hold = (x >> 15 & 0x00000001); + ch->pan = (x >> 16 & 0x0000007F); + ch->psg_duty = (x >> 24 & 0x00000007); + ch->repeat = (x >> 27 & 0x00000003); + ch->format = (x >> 29 & 0x00000003); + set_channel_volume(ch); + if(x & 0x80000000) start_channel(ch); else stop_channel(ch); + break; + case 0x04: + ch = spu.ch + (addr >> 4 & 0xF); + ch->addr = (x & 0x07FFFFFF); + break; + case 0x08: + ch = spu.ch + (addr >> 4 & 0xF); + ch->timer = (x & 0x0000FFFF); + ch->loop = (x >> 16 & 0x0000FFFF); + adjust_channel_timer(ch); + break; + case 0x0C: + ch = spu.ch + (addr >> 4 & 0xF); + ch->length = (x & 0x003FFFFF); + break; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SPU_ReadLong(u32 addr) +{ + addr &= 0xFFF; + return T1ReadLong(MMU.ARM7_REG, addr); +} + +static INLINE s32 clipping(s32 x, s32 min, s32 max) { +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if (x < min) + { + return (min); + } + else if (x > max) + { + return (max); + } + return (x); +#else + return x ^ ((-(x < min)) & (x ^ min)) ^ ((-(x > max)) & (x ^ max)); +#endif +} + +extern unsigned long dwChannelMute; + +static void decode_pcm8(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + if (!ch->buf8) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { + ch->output = ((s16)(s8)ch->buf8[(int)pos]) << 8; + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { +#if !DISABLE_XSF_TESTS + case 0: +#endif + case 1: + pos += ch->looppos - len; + break; + default: + stop_channel(ch); + oi = length; + break; + } + } + } + + ch->pos = pos; + return; +} + +static void decode_pcm16(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + + if (!ch->buf16) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { +#ifdef WORDS_BIGENDIAN + ch->output = (s16)T1ReadWord((u8 *)ch->buf16, pos << 1); +#else + ch->output = (s16)ch->buf16[(int)pos]; +#endif + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { +#if !DISABLE_XSF_TESTS + case 0: +#endif + case 1: + pos += ch->looppos - len; + break; + default: + stop_channel(ch); + oi = length; + break; + } + } + } + + ch->pos = pos; +} + +static INLINE void decode_adpcmone_P4(SChannel *ch, int m) +{ + int i, ci0; + u8 *p; + s32 s; + int N; + + i = ch->adpcm_pos; + p = (ch->buf8 + (i >> 1)); + ci0 = ch->adpcm_index; + s = ch->adpcm; + + if (ch->adpcm_loop_index < 0 && m >= ch->looppos) + { + ch->adpcm_loop_index = ci0; + ch->adpcm_loop = s; + ch->adpcm_loop_pos = i; + } + + if(i++ & 1) + { + s32 x1, d1; + x1 = ((*(p++) >> 3) & 0x1F | 1); + d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x1 & 0x10) d1 = -d1; +#else + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + } + + N = (((m & ~1) - (i & ~1)) >> 1); + for(i = 0; i < N; i++) + { + s32 x0, d0; + s32 x1, d1; + int ci1; + x0 = ((*p << 1) & 0x1F | 1); + x1 = ((*p >> 3) & 0x1F | 1); + ci1 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88); + d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci1 + g_adpcm_index[x1 & 0xE]), 0, 88); + d1 = ((x1 & 0xF) * g_adpcm_mult[ci1] & ~7); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x0 & 0x10) d0 = -d0; + if(x1 & 0x10) d1 = -d1; +#else + d0 -= (d0 + d0) & (-(((x0 >> 4) & 1))); + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + s = clipping((s + d0), (-32768 << 3), (32767 << 3)); + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + p++; + } + if(m & 1) + { + s32 x0, d0; + x0 = ((*p << 1) & 0x1F | 1); + d0 = ((x0 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x0 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x0 & 0x10) d0 = -d0; +#else + d0 -= (d0 + d0) & (-(((x0 >> 4) & 1))); +#endif + s = clipping((s + d0), (-32768 << 3), (32767 << 3)); + } + + ch->output = (s16)(s >> 3); + + ch->adpcm = s; + ch->adpcm_index = ci0; + ch->adpcm_pos = m; +} + +static INLINE void decode_adpcmone_XX(SChannel *ch, int m) +{ + int i, ci0; + u8 *p; + s32 s; + + i = ch->adpcm_pos; + p = (ch->buf8 + (i >> 1)); + ci0 = ch->adpcm_index; + s = ch->adpcm; + + if (ch->adpcm_loop_index < 0 && m >= ch->looppos) + { + ch->adpcm_loop_index = ci0; + ch->adpcm_loop = s; + ch->adpcm_loop_pos = i; + } + + while (i < m) + { + s32 x1, d1; + x1 = ((s32)*p) >> ((i & 1) << 2) & 0xf; + x1 = x1 + x1 + 1; + d1 = ((x1 & 0xF) * g_adpcm_mult[ci0] & ~7); + ci0 = clipping((ci0 + g_adpcm_index[x1 & 0xE]), 0, 88); +#if 1 || defined(SIGNED_IS_NOT_2S_COMPLEMENT) + if(x1 & 0x10) d1 = -d1; +#else + d1 -= (d1 + d1) & (-(((x1 >> 4) & 1))); +#endif + + s = clipping((s + d1), (-32768 << 3), (32767 << 3)); + p += (i & 1); + i++; + } + + ch->output = (s16)(s >> 3); + + ch->adpcm = s; + ch->adpcm_index = ci0; + ch->adpcm_pos = m; +} + +#define decode_adpcmone decode_adpcmone_P4 + +static void decode_adpcm(SChannel *ch, s32 *out, int length) +{ + int oi; + double pos, inc, len; + if (!ch->buf8) return; + + pos = ch->pos; inc = ch->inc; len = ch->loopend; + + for(oi = 0; oi < length; oi++) + { + int m = (int)pos; + int i = ch->adpcm_pos; + if(i < m) + decode_adpcmone(ch, m); + + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + if(pos >= len) + { + switch(ch->repeat) + { + case 1: + if (ch->adpcm_loop_index >= 0) + { + pos += ch->looppos - len; + ch->adpcm_pos = ch->adpcm_loop_pos; + ch->adpcm_index = ch->adpcm_loop_index; + ch->adpcm = ch->adpcm_loop; + break; + } +#if !DISABLE_XSF_TESTS + case 0: + pos = 9 - len; +#ifdef WORDS_BIGENDIAN + ch->adpcm = ((s32)(s16)T1ReadWord((u8 *)ch->buf8, 0)) << 3; +#else + ch->adpcm = ((s32)*(s16 *)ch->buf8) << 3; +#endif + ch->adpcm_index = (ch->buf8[2] & 0x7F); + ch->adpcm_pos = 8; + break; +#endif + default: + stop_channel(ch); + oi = length; + break; + } + } + } + ch->pos = pos; +} + +static void decode_psg(SChannel *ch, s32 *out, int length) +{ + int oi; + + if(ch->id < 14) + { + // NOTE: square wave. + double pos, inc, len; + pos = ch->pos; inc = ch->inc; len = ch->length; + for(oi = 0; oi < length; oi++) + { + ch->output = (s16)g_psg_duty[ch->psg_duty][(int)pos & 0x00000007]; + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + pos += inc; + } + ch->pos = pos; + } + else + { + // NOTE: noise. + u16 X; + X = (u16)ch->pos; + for(oi = 0; oi < length; oi++) + { + if(X & 1) + { + X >>= 1; + X ^= 0x6000; + ch->output = -0x8000; + } + else + { + X >>= 1; + ch->output = +0x7FFF; + } + } + if (dwChannelMute & (1 << ch->id)) + { + out++; + out++; + } + else + { + *(out++) += (ch->output * ch->volumel) >> VOL_SHIFT; + *(out++) += (ch->output * ch->volumer) >> VOL_SHIFT; + } + ch->pos = X; + } +} + + + +void SPU_EmulateSamples(u32 numsamples) +{ + u32 sizesmp = numsamples; + u32 sizebyte = sizesmp << 2; + if (sizebyte > spu.buflen * sizeof(s16)) sizebyte = spu.buflen * sizeof(s16); + sizesmp = sizebyte >> 2; + sizebyte = sizesmp << 2; + if (sizesmp > 0) + { + unsigned i; + SChannel *ch = spu.ch; + memset(spu.pmixbuf, 0, spu.buflen * sizeof(s32)); + for (i = 0; i < 16; i++) + { + if (ch->status) + { + switch (ch->format) + { + case 0: + decode_pcm8(ch, spu.pmixbuf, sizesmp); + break; + case 1: + decode_pcm16(ch, spu.pmixbuf, sizesmp); + break; + case 2: + decode_adpcm(ch, spu.pmixbuf, sizesmp); + break; + case 3: + decode_psg(ch, spu.pmixbuf, sizesmp); + break; + } + } + ch++; + } + for (i = 0; i < sizesmp * 2; i++) + spu.pclipingbuf[i] = (s16)clipping(spu.pmixbuf[i], -0x8000, 0x7fff); + SNDCore->UpdateAudio(spu.pclipingbuf, sizesmp); + } +} + +void SPU_Emulate(void) +{ + SPU_EmulateSamples(SNDCore->GetAudioSpace()); +} + + +////////////////////////////////////////////////////////////////////////////// +// Dummy Sound Interface +////////////////////////////////////////////////////////////////////////////// + +static int SNDDummyInit(int buffersize) +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyDeInit() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static u32 SNDDummyGetAudioSpace() +{ + return 735; +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummyUnMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static void SNDDummySetVolume(int volume) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +SoundInterface_struct SNDDummy = +{ + SNDCORE_DUMMY, + "Dummy Sound Interface", + SNDDummyInit, + SNDDummyDeInit, + SNDDummyUpdateAudio, + SNDDummyGetAudioSpace, + SNDDummyMuteAudio, + SNDDummyUnMuteAudio, + SNDDummySetVolume +}; + diff --git a/tools/vio2sf/src/vio2sf/desmume/SPU.cpp b/tools/vio2sf/src/vio2sf/desmume/SPU.cpp new file mode 100644 index 000000000..6f0c99feb --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/SPU.cpp @@ -0,0 +1,1114 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + Copyright (C) 2006 Theo Berkau + Copyright (C) 2008-2009 DeSmuME team + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include + +//#undef FORCEINLINE +//#define FORCEINLINE + +#define _SPU_CPP_ + +#define _USE_MATH_DEFINES +#include +#ifndef M_PI +#define M_PI 3.1415926535897932386 +#endif + +#define K_ADPCM_LOOPING_RECOVERY_INDEX 99999 + +#include "debug.h" +#include "MMU.h" +#include "SPU.h" +#include "mem.h" +#include "armcpu.h" +#include "NDSSystem.h" +#include "matrix.h" + +FORCEINLINE u32 u32floor(float f) +{ +#ifdef ENABLE_SSE2 + return (u32)_mm_cvtt_ss2si(_mm_set_ss(f)); +#else + return (u32)f; +#endif +} +FORCEINLINE u32 u32floor(double d) +{ +#ifdef ENABLE_SSE2 + return (u32)_mm_cvttsd_si32(_mm_set_sd(d)); +#else + return (u32)d; +#endif +} + +//same as above but works for negative values too. +//be sure that the results are the same thing as floorf! +FORCEINLINE s32 s32floor(float f) +{ +#ifdef ENABLE_SSE2 + return _mm_cvtss_si32( _mm_add_ss(_mm_set_ss(-0.5f),_mm_add_ss(_mm_set_ss(f), _mm_set_ss(f))) ) >> 1; +#else + return (s32)floorf(f); +#endif +} + +static FORCEINLINE u32 sputrunc(float f) { return u32floor(f); } +static FORCEINLINE u32 sputrunc(double d) { return u32floor(d); } +static FORCEINLINE s32 spumuldiv7(s32 val, u8 multiplier) { + assert(multiplier <= 127); + return (multiplier == 127) ? val : ((val * multiplier) >> 7); +} + +//===================CONFIGURATION======================== +#include "src/xsfc/drvimpl.h" +extern "C" unsigned long dwInterpolation; +bool isChannelMuted(int num) { return dwChannelMute&(1< +static FORCEINLINE T MinMax(T val, T min, T max) +{ + if (val < min) + return min; + else if (val > max) + return max; + + return val; +} + +////////////////////////////////////////////////////////////////////////////// + +extern "C" int SPU_ChangeSoundCore(int coreid, int buffersize) +{ + int i; + + delete SPU_user; SPU_user = 0; + + // Make sure the old core is freed + if (SNDCore) + SNDCore->DeInit(); + + // So which core do we want? + if (coreid == SNDCORE_DEFAULT) + coreid = 0; // Assume we want the first one + + SPU_currentCoreNum = coreid; + + // Go through core list and find the id + for (i = 0; SNDCoreList[i] != NULL; i++) + { + if (SNDCoreList[i]->id == coreid) + { + // Set to current core + SNDCore = SNDCoreList[i]; + break; + } + } + + //If the user picked the dummy core, disable the user spu + if(SNDCore == &SNDDummy) + return 0; + + //If the core wasnt found in the list for some reason, disable the user spu + if (SNDCore == NULL) + return -1; + + // Since it failed, instead of it being fatal, disable the user spu + if (SNDCore->Init(buffersize * 2) == -1) + { + SNDCore = 0; + return -1; + } + + //enable the user spu + //well, not really + //SPU_user = new SPU_struct(buffersize); + + return 0; +} + +SoundInterface_struct *SPU_SoundCore() +{ + return SNDCore; +} + +extern "C" void SPU_Reset(void) +{ + int i; + + SPU_core->reset(); + if(SPU_user) SPU_user->reset(); + + if(SNDCore && SPU_user) { + SNDCore->DeInit(); + SNDCore->Init(SPU_user->bufsize*2); + //todo - check success? + } + + // Reset Registers + for (i = 0x400; i < 0x51D; i++) + T1WriteByte(MMU.ARM7_REG, i, 0); + + samples = 0; +} + + +////////////////////////////////////////////////////////////////////////////// + +//static double cos_lut[256]; + +extern "C" int SPU_Init(int coreid, int buffersize) +{ + int i, j; + + //__asm int 3; + + //for(int i=0;i<256;i++) + // cos_lut[i] = cos(i/256.0*M_PI); + + SPU_core = new SPU_struct(44100); //pick a really big number just to make sure the plugin doesnt request more + SPU_Reset(); + + for(i = 0; i < 16; i++) + { + for(j = 0; j < 89; j++) + { + precalcdifftbl[j][i] = (((i & 0x7) * 2 + 1) * adpcmtbl[j] / 8); + if(i & 0x8) precalcdifftbl[j][i] = -precalcdifftbl[j][i]; + } + } + + for(i = 0; i < 8; i++) + { + for(j = 0; j < 89; j++) + { + precalcindextbl[j][i] = MinMax((j + indextbl[i]), 0, 88); + } + } + + //return SPU_ChangeSoundCore(coreid, buffersize); + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_Pause(int pause) +{ + if (SNDCore == NULL) return; + + if(pause) + SNDCore->MuteAudio(); + else + SNDCore->UnMuteAudio(); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_SetVolume(int volume) +{ + if (SNDCore) + SNDCore->SetVolume(volume); +} + +////////////////////////////////////////////////////////////////////////////// + + + +void SPU_struct::reset() +{ + memset(sndbuf,0,bufsize*2*4); + memset(outbuf,0,bufsize*2*2); + + memset((void *)channels, 0, sizeof(channel_struct) * 16); + + for(int i = 0; i < 16; i++) + { + channels[i].num = i; + } +} + +SPU_struct::SPU_struct(int buffersize) + : bufpos(0) + , buflength(0) + , sndbuf(0) + , outbuf(0) + , bufsize(buffersize) +{ + sndbuf = new s32[buffersize*2]; + outbuf = new s16[buffersize*2]; + reset(); +} + +SPU_struct::~SPU_struct() +{ + if(sndbuf) delete[] sndbuf; + if(outbuf) delete[] outbuf; +} + +extern "C" void SPU_DeInit(void) +{ + if(SNDCore) + SNDCore->DeInit(); + SNDCore = 0; + + delete SPU_core; SPU_core=0; + delete SPU_user; SPU_user=0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::ShutUp() +{ + for(int i=0;i<16;i++) + channels[i].status = CHANSTAT_STOPPED; +} + +static FORCEINLINE void adjust_channel_timer(channel_struct *chan) +{ + chan->sampinc = (((double)ARM7_CLOCK) / (44100 * 2)) / (double)(0x10000 - chan->timer); +} + +void SPU_struct::KeyOn(int channel) +{ + channel_struct &thischan = channels[channel]; + + adjust_channel_timer(&thischan); + + // LOG("Channel %d key on: vol = %d, datashift = %d, hold = %d, pan = %d, waveduty = %d, repeat = %d, format = %d, source address = %07X, timer = %04X, loop start = %04X, length = %06X, MMU.ARM7_REG[0x501] = %02X\n", channel, chan->vol, chan->datashift, chan->hold, chan->pan, chan->waveduty, chan->repeat, chan->format, chan->addr, chan->timer, chan->loopstart, chan->length, T1ReadByte(MMU.ARM7_REG, 0x501)); + switch(thischan.format) + { + case 0: // 8-bit + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + // thischan.loopstart = thischan.loopstart << 2; + // thischan.length = (thischan.length << 2) + thischan.loopstart; + thischan.sampcnt = 0; + break; + case 1: // 16-bit + thischan.buf16 = (s16 *)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + // thischan.loopstart = thischan.loopstart << 1; + // thischan.length = (thischan.length << 1) + thischan.loopstart; + thischan.sampcnt = 0; + break; + case 2: // ADPCM + { + thischan.buf8 = (s8*)&MMU.MMU_MEM[1][(thischan.addr>>20)&0xFF][(thischan.addr & MMU.MMU_MASK[1][(thischan.addr >> 20) & 0xFF])]; + thischan.pcm16b = (s16)((thischan.buf8[1] << 8) | thischan.buf8[0]); + thischan.pcm16b_last = thischan.pcm16b; + thischan.index = thischan.buf8[2] & 0x7F; + thischan.lastsampcnt = 7; + thischan.sampcnt = 8; + thischan.loop_index = K_ADPCM_LOOPING_RECOVERY_INDEX; + // thischan.loopstart = thischan.loopstart << 3; + // thischan.length = (thischan.length << 3) + thischan.loopstart; + break; + } + case 3: // PSG + { + thischan.x = 0x7FFF; + break; + } + default: break; + } + + if(thischan.format != 3) + { + if(thischan.double_totlength_shifted == 0) + { + printf("INFO: Stopping channel %d due to zero length\n",channel); + thischan.status = CHANSTAT_STOPPED; + } + } + + thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::WriteByte(u32 addr, u8 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) { + case 0x0: + thischan.vol = val & 0x7F; + break; + case 0x1: { + thischan.datashift = val & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 7) & 0x1; + break; + } + case 0x2: + thischan.pan = val & 0x7F; + break; + case 0x3: { + thischan.waveduty = val & 0x7; + thischan.repeat = (val >> 3) & 0x3; + thischan.format = (val >> 5) & 0x3; + thischan.status = (val >> 7) & 0x1; + if(thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + } + } + +} + +extern "C" void SPU_WriteByte(u32 addr, u8 val) +{ + addr &= 0xFFF; + + if (addr < 0x500) + { + SPU_core->WriteByte(addr,val); + if(SPU_user) SPU_user->WriteByte(addr,val); + } + + T1WriteByte(MMU.ARM7_REG, addr, val); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::WriteWord(u32 addr, u16 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) + { + case 0x0: + thischan.vol = val & 0x7F; + thischan.datashift = (val >> 8) & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 15) & 0x1; + break; + case 0x2: + thischan.pan = val & 0x7F; + thischan.waveduty = (val >> 8) & 0x7; + thischan.repeat = (val >> 11) & 0x3; + thischan.format = (val >> 13) & 0x3; + thischan.status = (val >> 15) & 0x1; + if (thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + case 0x8: + thischan.timer = val & 0xFFFF; + adjust_channel_timer(&thischan); + break; + case 0xA: + thischan.loopstart = val; + thischan.totlength = thischan.length + thischan.loopstart; + thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]); + break; + case 0xC: + WriteLong(addr,((u32)T1ReadWord(MMU.ARM7_REG, addr+2) << 16) | val); + break; + case 0xE: + WriteLong(addr,((u32)T1ReadWord(MMU.ARM7_REG, addr-2)) | ((u32)val<<16)); + break; + } +} + +extern "C" void SPU_WriteWord(u32 addr, u16 val) +{ + addr &= 0xFFF; + + if (addr < 0x500) + { + SPU_core->WriteWord(addr,val); + if(SPU_user) SPU_user->WriteWord(addr,val); + } + + T1WriteWord(MMU.ARM7_REG, addr, val); +} + +////////////////////////////////////////////////////////////////////////////// + +void SPU_struct::WriteLong(u32 addr, u32 val) +{ + channel_struct &thischan=channels[(addr >> 4) & 0xF]; + switch(addr & 0xF) + { + case 0x0: + thischan.vol = val & 0x7F; + thischan.datashift = (val >> 8) & 0x3; + if (thischan.datashift == 3) + thischan.datashift = 4; + thischan.hold = (val >> 15) & 0x1; + thischan.pan = (val >> 16) & 0x7F; + thischan.waveduty = (val >> 24) & 0x7; + thischan.repeat = (val >> 27) & 0x3; + thischan.format = (val >> 29) & 0x3; + thischan.status = (val >> 31) & 0x1; + if (thischan.status) + KeyOn((addr >> 4) & 0xF); + break; + case 0x4: + thischan.addr = val & 0x7FFFFFF; + break; + case 0x8: + thischan.timer = val & 0xFFFF; + thischan.loopstart = val >> 16; + adjust_channel_timer(&thischan); + break; + case 0xC: + thischan.length = val & 0x3FFFFF; + thischan.totlength = thischan.length + thischan.loopstart; + thischan.double_totlength_shifted = (double)(thischan.totlength << format_shift[thischan.format]); + break; + } +} + +extern "C" void SPU_WriteLong(u32 addr, u32 val) +{ + addr &= 0xFFF; + + if (addr < 0x500) + { + SPU_core->WriteLong(addr,val); + if(SPU_user) SPU_user->WriteLong(addr,val); + } + + T1WriteLong(MMU.ARM7_REG, addr, val); +} + +////////////////////////////////////////////////////////////////////////////// + +static FORCEINLINE s32 Interpolate(SPUInterpolationMode INTERPOLATE_MODE, s32 a, s32 b, double _ratio) +{ + float ratio = (float)_ratio; + if(INTERPOLATE_MODE == SPUInterpolation_Cosine) + { + //why did we change it away from the lookup table? somebody should research that + ratio = ratio - (int)ratio; + double ratio2 = ((1.0 - cos(ratio * M_PI)) * 0.5); + //double ratio2 = (1.0f - cos_lut[((int)(ratio*256.0))&0xFF]) / 2.0f; + return (s32)(((1-ratio2)*a) + (ratio2*b)); + } + else + { + //linear interpolation + ratio = ratio - sputrunc(ratio); + return s32floor((1-ratio)*a + ratio*b); + } +} + +////////////////////////////////////////////////////////////////////////////// + +static FORCEINLINE void Fetch8BitData(SPUInterpolationMode INTERPOLATE_MODE, channel_struct *chan, s32 *data) +{ + u32 loc = sputrunc(chan->sampcnt); + if(INTERPOLATE_MODE != SPUInterpolation_None) + { + s32 a = (s32)(chan->buf8[loc] << 8); + if(loc < (chan->totlength << 2) - 1) { + s32 b = (s32)(chan->buf8[loc + 1] << 8); + a = Interpolate(INTERPOLATE_MODE, a, b, chan->sampcnt); + } + *data = a; + } + else + *data = (s32)chan->buf8[loc] << 8; +} + +static FORCEINLINE void Fetch16BitData(SPUInterpolationMode INTERPOLATE_MODE, const channel_struct * const chan, s32 *data) +{ + const s16* const buf16 = chan->buf16; + const int shift = 1; + if(INTERPOLATE_MODE != SPUInterpolation_None) + { + u32 loc = sputrunc(chan->sampcnt); + s32 a = (s32)buf16[loc], b; + if(loc < (chan->totlength << shift) - 1) + { + b = (s32)buf16[loc + 1]; + a = Interpolate(INTERPOLATE_MODE,a, b, chan->sampcnt); + } + *data = a; + } + else + *data = (s32)buf16[sputrunc(chan->sampcnt)]; +} + +static FORCEINLINE void FetchADPCMData(SPUInterpolationMode INTERPOLATE_MODE, channel_struct * const chan, s32 * const data) +{ + // No sense decoding, just return the last sample + if (chan->lastsampcnt != sputrunc(chan->sampcnt)){ + + const u32 endExclusive = sputrunc(chan->sampcnt+1); + for (u32 i = chan->lastsampcnt+1; i < endExclusive; i++) + { + const u32 shift = (i&1)<<2; + const u32 data4bit = (((u32)chan->buf8[i >> 1]) >> shift); + + const s32 diff = precalcdifftbl[chan->index][data4bit & 0xF]; + chan->index = precalcindextbl[chan->index][data4bit & 0x7]; + + chan->pcm16b_last = chan->pcm16b; + chan->pcm16b = (s16)(MinMax(chan->pcm16b+diff, -0x8000L, 0x7FFFL)); + + if(i == (chan->loopstart<<3)) { + if(chan->loop_index != K_ADPCM_LOOPING_RECOVERY_INDEX) printf("over-snagging\n"); + chan->loop_pcm16b = chan->pcm16b; + chan->loop_index = chan->index; + } + } + + chan->lastsampcnt = sputrunc(chan->sampcnt); + } + + if(INTERPOLATE_MODE != SPUInterpolation_None) + *data = Interpolate(INTERPOLATE_MODE,(s32)chan->pcm16b_last,(s32)chan->pcm16b,chan->sampcnt); + else + *data = (s32)chan->pcm16b; +} + +static FORCEINLINE void FetchPSGData(channel_struct *chan, s32 *data) +{ + if(chan->num < 8) + { + *data = 0; + } + else if(chan->num < 14) + { + *data = (s32)wavedutytbl[chan->waveduty][(sputrunc(chan->sampcnt)) & 0x7]; + } + else + { + if(chan->lastsampcnt == sputrunc(chan->sampcnt)) + { + *data = (s32)chan->psgnoise_last; + return; + } + + u32 max = sputrunc(chan->sampcnt); + for(u32 i = chan->lastsampcnt; i < max; i++) + { + if(chan->x & 0x1) + { + chan->x = (chan->x >> 1); + chan->psgnoise_last = -0x7FFF; + } + else + { + chan->x = ((chan->x >> 1) ^ 0x6000); + chan->psgnoise_last = 0x7FFF; + } + } + + chan->lastsampcnt = sputrunc(chan->sampcnt); + + *data = (s32)chan->psgnoise_last; + } +} + +////////////////////////////////////////////////////////////////////////////// + +static FORCEINLINE void MixL(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += data; +} + +static FORCEINLINE void MixR(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[(SPU->bufpos<<1)+1] += data; +} + +static FORCEINLINE void MixLR(SPU_struct* SPU, channel_struct *chan, s32 data) +{ + data = spumuldiv7(data, chan->vol) >> chan->datashift; + SPU->sndbuf[SPU->bufpos<<1] += spumuldiv7(data, 127 - chan->pan); + SPU->sndbuf[(SPU->bufpos<<1)+1] += spumuldiv7(data, chan->pan); +} + +////////////////////////////////////////////////////////////////////////////// + +static FORCEINLINE void TestForLoop(int FORMAT, SPU_struct *SPU, channel_struct *chan) +{ + const int shift = (FORMAT == 0 ? 2 : 1); + + chan->sampcnt += chan->sampinc; + + if (chan->sampcnt > chan->double_totlength_shifted) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + { + while (chan->sampcnt > chan->double_totlength_shifted) + chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << shift); + //chan->sampcnt = (double)(chan->loopstart << shift); + } + else + { + chan->status = CHANSTAT_STOPPED; + + if(SPU == SPU_core) + MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->bufpos = SPU->buflength; + } + } +} + +static FORCEINLINE void TestForLoop2(SPU_struct *SPU, channel_struct *chan) +{ + chan->sampcnt += chan->sampinc; + + if (chan->sampcnt > chan->double_totlength_shifted) + { + // Do we loop? Or are we done? + if (chan->repeat == 1) + { + while (chan->sampcnt > chan->double_totlength_shifted) + chan->sampcnt -= chan->double_totlength_shifted - (double)(chan->loopstart << 3); + + if(chan->loop_index == K_ADPCM_LOOPING_RECOVERY_INDEX) + { + chan->pcm16b = (s16)((chan->buf8[1] << 8) | chan->buf8[0]); + chan->index = chan->buf8[2] & 0x7F; + chan->lastsampcnt = 7; + } + else + { + chan->pcm16b = chan->loop_pcm16b; + chan->index = chan->loop_index; + chan->lastsampcnt = (chan->loopstart << 3); + } + } + else + { + chan->status = CHANSTAT_STOPPED; + if(SPU == SPU_core) + MMU.ARM7_REG[0x403 + (((chan-SPU->channels) ) * 0x10)] &= 0x7F; + SPU->bufpos = SPU->buflength; + } + } +} + +FORCEINLINE static void SPU_Mix(int CHANNELS, SPU_struct* SPU, channel_struct *chan, s32 data) +{ + switch(CHANNELS) + { + case 0: MixL(SPU, chan, data); break; + case 1: MixLR(SPU, chan, data); break; + case 2: MixR(SPU, chan, data); break; + } +} + +FORCEINLINE static void ____SPU_ChanUpdate(int CHANNELS, int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, SPU_struct* const SPU, channel_struct* const chan) +{ + for (; SPU->bufpos < SPU->buflength; SPU->bufpos++) + { + if(CHANNELS != -1) + { + s32 data; + switch(FORMAT) + { + case 0: Fetch8BitData(INTERPOLATE_MODE, chan, &data); break; + case 1: Fetch16BitData(INTERPOLATE_MODE, chan, &data); break; + case 2: FetchADPCMData(INTERPOLATE_MODE, chan, &data); break; + case 3: FetchPSGData(chan, &data); break; + } + SPU_Mix(CHANNELS, SPU, chan, data); + } + + switch(FORMAT) { + case 0: case 1: TestForLoop(FORMAT, SPU, chan); break; + case 2: TestForLoop2(SPU, chan); break; + case 3: chan->sampcnt += chan->sampinc; break; + } + } +} + +FORCEINLINE static void ___SPU_ChanUpdate(int FORMAT, SPUInterpolationMode INTERPOLATE_MODE, const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + if(!actuallyMix) + ____SPU_ChanUpdate(-1,FORMAT,INTERPOLATE_MODE,SPU,chan); + else if (chan->pan == 0) + ____SPU_ChanUpdate(0,FORMAT,INTERPOLATE_MODE,SPU,chan); + else if (chan->pan == 127) + ____SPU_ChanUpdate(2,FORMAT,INTERPOLATE_MODE,SPU,chan); + else + ____SPU_ChanUpdate(1,FORMAT,INTERPOLATE_MODE,SPU,chan); +} + +FORCEINLINE static void __SPU_ChanUpdate(SPUInterpolationMode INTERPOLATE_MODE, const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + ___SPU_ChanUpdate(chan->format,INTERPOLATE_MODE,actuallyMix, SPU, chan); +} + +FORCEINLINE static void _SPU_ChanUpdate(const bool actuallyMix, SPU_struct* const SPU, channel_struct* const chan) +{ + __SPU_ChanUpdate(spuInterpolationMode(),actuallyMix, SPU, chan); +} + + +static void SPU_MixAudio(bool actuallyMix, SPU_struct *SPU, int length) +{ + u8 vol; + + if(actuallyMix) + { + memset(SPU->sndbuf, 0, length*4*2); + memset(SPU->outbuf, 0, length*2*2); + } + + //---not appropriate for 2sf player + // If the sound speakers are disabled, don't output audio + //if(!(T1ReadWord(MMU.ARM7_REG, 0x304) & 0x01)) + // return; + + // If Master Enable isn't set, don't output audio + //if (!(T1ReadByte(MMU.ARM7_REG, 0x501) & 0x80)) + // return; + //------------------------ + + vol = T1ReadByte(MMU.ARM7_REG, 0x500) & 0x7F; + + for(int i=0;i<16;i++) + { + channel_struct *chan = &SPU->channels[i]; + + if (chan->status != CHANSTAT_PLAY) + continue; + + SPU->bufpos = 0; + SPU->buflength = length; + + // Mix audio + _SPU_ChanUpdate(!isChannelMuted(i) && actuallyMix, SPU, chan); + } + + // convert from 32-bit->16-bit + if(actuallyMix) + for (int i = 0; i < length*2; i++) + { + // Apply Master Volume + SPU->sndbuf[i] = spumuldiv7(SPU->sndbuf[i], vol); + + if (SPU->sndbuf[i] > 0x7FFF) + SPU->outbuf[i] = 0x7FFF; + else if (SPU->sndbuf[i] < -0x8000) + SPU->outbuf[i] = -0x8000; + else + SPU->outbuf[i] = (s16)SPU->sndbuf[i]; + } +} + +////////////////////////////////////////////////////////////////////////////// + + +//emulates one hline of the cpu core. +//this will produce a variable number of samples, calculated to keep a 44100hz output +//in sync with the emulator framerate +static const int dots_per_clock = 6; +static const int dots_per_hline = 355; +static const double time_per_hline = (double)1.0/((double)ARM7_CLOCK/dots_per_clock/dots_per_hline); +static const double samples_per_hline = time_per_hline * 44100; +int spu_core_samples = 0; +void SPU_Emulate_core() +{ + samples += samples_per_hline; + spu_core_samples = (int)(samples); + samples -= spu_core_samples; + + //TODO + /*if(driver->AVI_IsRecording() || driver->WAV_IsRecording()) + SPU_MixAudio(SPU_core,spu_core_samples); + else + SPU_MixAudio(SPU_core,spu_core_samples);*/ +} + +extern "C" void SPU_EmulateSamples(int numsamples) +{ + SPU_MixAudio(true,SPU_core,numsamples); + SNDCoreList[0]->UpdateAudio(SPU_core->outbuf,numsamples); +} + +void SPU_Emulate_user(bool mix) +{ + if(!SPU_user) + return; + + u32 audiosize; + + // Check to see how much free space there is + // If there is some, fill up the buffer + audiosize = SNDCore->GetAudioSpace(); + + if (audiosize > 0) + { + //printf("mix %i samples\n", audiosize); + if (audiosize > SPU_user->bufsize) + audiosize = SPU_user->bufsize; + if (mix) SPU_MixAudio(true,SPU_user,audiosize); + SNDCore->UpdateAudio(SPU_user->outbuf, audiosize); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Dummy Sound Interface +////////////////////////////////////////////////////////////////////////////// + +int SNDDummyInit(int buffersize); +void SNDDummyDeInit(); +void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples); +u32 SNDDummyGetAudioSpace(); +void SNDDummyMuteAudio(); +void SNDDummyUnMuteAudio(); +void SNDDummySetVolume(int volume); + +SoundInterface_struct SNDDummy = { + SNDCORE_DUMMY, + "Dummy Sound Interface", + SNDDummyInit, + SNDDummyDeInit, + SNDDummyUpdateAudio, + SNDDummyGetAudioSpace, + SNDDummyMuteAudio, + SNDDummyUnMuteAudio, + SNDDummySetVolume +}; + +////////////////////////////////////////////////////////////////////////////// + +int SNDDummyInit(int buffersize) +{ + return 0; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDummyDeInit() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDummyUpdateAudio(s16 *buffer, u32 num_samples) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +u32 SNDDummyGetAudioSpace() +{ + return 740; +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDummyMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDummyUnMuteAudio() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +void SNDDummySetVolume(int volume) +{ +} + +////////////////////////////////////////////////////////////////////////////// +// +//typedef struct { +// char id[4]; +// u32 size; +//} chunk_struct; +// +//typedef struct { +// chunk_struct riff; +// char rifftype[4]; +//} waveheader_struct; +// +//typedef struct { +// chunk_struct chunk; +// u16 compress; +// u16 numchan; +// u32 rate; +// u32 bytespersec; +// u16 blockalign; +// u16 bitspersample; +//} fmt_struct; +// +//WavWriter::WavWriter() +//: spufp(NULL) +//{ +//} +//bool WavWriter::open(const std::string & fname) +//{ +// waveheader_struct waveheader; +// fmt_struct fmt; +// chunk_struct data; +// size_t elems_written = 0; +// +// if ((spufp = fopen(fname.c_str(), "wb")) == NULL) +// return false; +// +// // Do wave header +// memcpy(waveheader.riff.id, "RIFF", 4); +// waveheader.riff.size = 0; // we'll fix this after the file is closed +// memcpy(waveheader.rifftype, "WAVE", 4); +// elems_written += fwrite((void *)&waveheader, 1, sizeof(waveheader_struct), spufp); +// +// // fmt chunk +// memcpy(fmt.chunk.id, "fmt ", 4); +// fmt.chunk.size = 16; // we'll fix this at the end +// fmt.compress = 1; // PCM +// fmt.numchan = 2; // Stereo +// fmt.rate = 44100; +// fmt.bitspersample = 16; +// fmt.blockalign = fmt.bitspersample / 8 * fmt.numchan; +// fmt.bytespersec = fmt.rate * fmt.blockalign; +// elems_written += fwrite((void *)&fmt, 1, sizeof(fmt_struct), spufp); +// +// // data chunk +// memcpy(data.id, "data", 4); +// data.size = 0; // we'll fix this at the end +// elems_written += fwrite((void *)&data, 1, sizeof(chunk_struct), spufp); +// +// return true; +//} +// +//void WavWriter::close() +//{ +// if(!spufp) return; +// size_t elems_written = 0; +// long length = ftell(spufp); +// +// // Let's fix the riff chunk size and the data chunk size +// fseek(spufp, sizeof(waveheader_struct)-0x8, SEEK_SET); +// length -= 0x8; +// elems_written += fwrite((void *)&length, 1, 4, spufp); +// +// fseek(spufp, sizeof(waveheader_struct)+sizeof(fmt_struct)+0x4, SEEK_SET); +// length -= sizeof(waveheader_struct)+sizeof(fmt_struct); +// elems_written += fwrite((void *)&length, 1, 4, spufp); +// fclose(spufp); +// spufp = NULL; +//} +// +//void WavWriter::update(void* soundData, int numSamples) +//{ +// if(!spufp) return; +// //TODO - big endian for the s16 samples?? +// size_t elems_written = fwrite(soundData, numSamples*2, 2, spufp); +//} +// +//bool WavWriter::isRecording() const +//{ +// return spufp != NULL; +//} +// +// +//static WavWriter wavWriter; +// +//void WAV_End() +//{ +// wavWriter.close(); +//} +// +//bool WAV_Begin(const char* fname) +//{ +// WAV_End(); +// +// if(!wavWriter.open(fname)) +// return false; +// +// driver->USR_InfoMessage("WAV recording started."); +// +// return true; +//} +// +//bool WAV_IsRecording() +//{as +// return wavWriter.isRecording(); +//} +// +//void WAV_WavSoundUpdate(void* soundData, int numSamples) +//{ +// wavWriter.update(soundData, numSamples); +//} +// diff --git a/tools/vio2sf/src/vio2sf/desmume/SPU.h b/tools/vio2sf/src/vio2sf/desmume/SPU.h new file mode 100644 index 000000000..a1618fc8e --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/SPU.h @@ -0,0 +1,150 @@ +/* SPU.h + + Copyright 2006 Theo Berkau + Copyright (C) 2006-2009 DeSmuME team + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef SPU_H +#define SPU_H + +#include +#include "types.h" + +#define FORCEINLINE __forceinline + + + +#define SNDCORE_DEFAULT -1 +#define SNDCORE_DUMMY 0 + +#define CHANSTAT_STOPPED 0 +#define CHANSTAT_PLAY 1 + + +enum SPUInterpolationMode +{ + SPUInterpolation_None = 0, + SPUInterpolation_Linear = 1, + SPUInterpolation_Cosine = 2 +}; + +struct SoundInterface_struct +{ + int id; + const char *Name; + int (*Init)(int buffersize); + void (*DeInit)(); + void (*UpdateAudio)(s16 *buffer, u32 num_samples); + u32 (*GetAudioSpace)(); + void (*MuteAudio)(); + void (*UnMuteAudio)(); + void (*SetVolume)(int volume); +}; + +extern SoundInterface_struct SNDDummy; +extern SoundInterface_struct SNDFile; +extern int SPU_currentCoreNum; + +struct channel_struct +{ + channel_struct() + {} + u32 num; + u8 vol; + u8 datashift; + u8 hold; + u8 pan; + u8 waveduty; + u8 repeat; + u8 format; + u8 status; + u32 addr; + u16 timer; + u16 loopstart; + u32 length; + u32 totlength; + double double_totlength_shifted; + union { + s8 *buf8; + s16 *buf16; + }; + double sampcnt; + double sampinc; + // ADPCM specific + u32 lastsampcnt; + s16 pcm16b, pcm16b_last; + s16 loop_pcm16b; + int index; + int loop_index; + u16 x; + s16 psgnoise_last; +} ; + +class SPU_struct +{ +public: + SPU_struct(int buffersize); + u32 bufpos; + u32 buflength; + s32 *sndbuf; + s16 *outbuf; + u32 bufsize; + channel_struct channels[16]; + + void reset(); + ~SPU_struct(); + void KeyOn(int channel); + void WriteByte(u32 addr, u8 val); + void WriteWord(u32 addr, u16 val); + void WriteLong(u32 addr, u32 val); + + //kills all channels but leaves SPU otherwise running normally + void ShutUp(); +}; + +SoundInterface_struct *SPU_SoundCore(); + +void SPU_Pause(int pause); +void SPU_SetVolume(int volume); +void SPU_KeyOn(int channel); +void SPU_Emulate_core(void); +void SPU_Emulate_user(bool mix = true); + +extern SPU_struct *SPU_core, *SPU_user; +extern int spu_core_samples; + +class WavWriter +{ +public: + WavWriter(); + bool open(const std::string & fname); + void close(); + void update(void* soundData, int numSamples); + bool isRecording() const; +private: + FILE *spufp; +}; + + +void WAV_End(); +bool WAV_Begin(const char* fname); +bool WAV_IsRecording(); +void WAV_WavSoundUpdate(void* soundData, int numSamples); + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/arm_instructions.c b/tools/vio2sf/src/vio2sf/desmume/arm_instructions.c new file mode 100644 index 000000000..40418c733 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/arm_instructions.c @@ -0,0 +1,7928 @@ +/* Copyright (C) 2006 yopyop + Copyright (C) 2006 shash + yopyop156@ifrance.com + yopyop156.ifrance.com + + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "cp15.h" +#include "debug.h" +#include "MMU.h" + + +// Use this macros for reading/writing, so the GDB stub isn't broken +#ifdef GDB_STUB + #define READ32(a,b) cpu->mem_if->read32(a,b) + #define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c) + #define READ16(a,b) cpu->mem_if->read16(a,b) + #define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c) + #define READ8(a,b) cpu->mem_if->read8(a,b) + #define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c) +#else + #define READ32(a,b) MMU_read32(cpu->proc_ID, b) + #define WRITE32(a,b,c) MMU_write32(cpu->proc_ID,b,c) + #define READ16(a,b) MMU_read16(cpu->proc_ID, b) + #define WRITE16(a,b,c) MMU_write16(cpu->proc_ID,b,c) + #define READ8(a,b) MMU_read8(cpu->proc_ID, b) + #define WRITE8(a,b,c) MMU_write8(cpu->proc_ID,b,c) +#endif + + + +#define LSL_IMM shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F); + +#define S_LSL_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\ + shift_op = cpu->R[REG_POS(i,0)]<<((i>>7)&0x1F);\ + } + +#define LSL_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op>=32)\ + shift_op=0;\ + else\ + shift_op=cpu->R[REG_POS(i,0)]<R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], 32-shift_op);\ + shift_op = cpu->R[REG_POS(i,0)]<R[REG_POS(i,0)]);\ + }\ + else\ + {\ + shift_op = 0;\ + c = 0;\ + } + +#define LSR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op!=0)\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\ + } + +#define LSR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op>=32)\ + shift_op = 0;\ + else\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op; + +#define S_LSR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + shift_op = cpu->R[REG_POS(i,0)];\ + }\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = cpu->R[REG_POS(i,0)]>>shift_op;\ + }\ + else\ + if(shift_op==32)\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + shift_op = 0;\ + }\ + else\ + {\ + c = 0;\ + shift_op = 0;\ + } + +#define ASR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op==0)\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + else\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op); + +#define S_ASR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + } + +#define ASR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + else\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF; + +#define S_ASR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + if(shift_op<32)\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = (u32)(((s32)(cpu->R[REG_POS(i,0)]))>>shift_op);\ + }\ + else\ + {\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + shift_op=BIT31(cpu->R[REG_POS(i,0)])*0xFFFFFFFF;\ + } + +#define ROR_IMM shift_op = ((i>>7)&0x1F);\ + if(shift_op==0)\ + {\ + u32 tmp = cpu->CPSR.bits.C;\ + shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\ + }\ + else\ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op); + +#define S_ROR_IMM u32 shift_op = ((i>>7)&0x1F);\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + {\ + u32 tmp = cpu->CPSR.bits.C;\ + shift_op = (tmp<<31)|(cpu->R[REG_POS(i,0)]>>1);\ + c = BIT0(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = ROR(cpu->R[REG_POS(i,0)],shift_op);\ + } + +#define ROR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + if((shift_op==0)||((shift_op&0xF)==0))\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF)); + +#define S_ROR_REG u32 shift_op = (cpu->R[REG_POS(i,8)])&0xFF;\ + u32 c = cpu->CPSR.bits.C;\ + if(shift_op==0)\ + shift_op=cpu->R[REG_POS(i,0)];\ + else\ + {\ + shift_op&=0xF;\ + if(shift_op==0)\ + {\ + shift_op=cpu->R[REG_POS(i,0)];\ + c = BIT31(cpu->R[REG_POS(i,0)]);\ + }\ + else\ + {\ + c = BIT_N(cpu->R[REG_POS(i,0)], shift_op-1);\ + shift_op = ROR(cpu->R[REG_POS(i,0)],(shift_op&0xF));\ + }\ + } + +#define IMM_VALUE u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E); + +#define S_IMM_VALUE u32 shift_op = ROR((i&0xFF), (i>>7)&0x1E);\ + u32 c = cpu->CPSR.bits.C;\ + if((i>>8)&0xF)\ + c = BIT31(shift_op); + +#define IMM_OFF (((i>>4)&0xF0)+(i&0xF)) + +#define IMM_OFF_12 ((i)&0xFFF) + +extern BOOL execute; + +static u32 FASTCALL OP_UND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LOG("Undefined instruction: %08X\n", i); + execute = FALSE; + return 1; +} + +//-----------------------AND------------------------------------ + +#define OP_AND(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_ANDS(a, b)\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR;\ + cpu->R[15] = cpu->R[REG_POS(i,16)] & shift_op;\ + SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_AND_LSL_IMM(register armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_AND(2, 4); +} + +static u32 FASTCALL OP_AND_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_AND(1, 3); +} + +static u32 FASTCALL OP_AND_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_ANDS(2, 4); +} + +static u32 FASTCALL OP_AND_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_ANDS(3, 5); +} + +static u32 FASTCALL OP_AND_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_ANDS(2, 4); +} + +//--------------EOR------------------------------ + +#define OP_EOR(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_EORS(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] ^ shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_EOR_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_EOR(2, 4); +} + +static u32 FASTCALL OP_EOR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_EOR(1, 3); +} + +static u32 FASTCALL OP_EOR_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_EORS(2, 4); +} + +static u32 FASTCALL OP_EOR_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_EORS(3, 5); +} + +static u32 FASTCALL OP_EOR_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_EORS(2, 4); +} + +//-------------SUB------------------------------------- + +#define OP_SUB(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPSUBS(a, b) cpu->R[REG_POS(i,12)] = v - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_SUB_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_SUB(2, 4); +} + +static u32 FASTCALL OP_SUB_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_SUB(1, 3); +} + +static u32 FASTCALL OP_SUB_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OPSUBS(2, 4); +} + +static u32 FASTCALL OP_SUB_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OPSUBS(3, 5); +} + +static u32 FASTCALL OP_SUB_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OPSUBS(2, 4); +} + +//------------------RSB------------------------ + +#define OP_RSB(a, b) cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)];\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OP_RSBS(a, b) cpu->R[REG_POS(i,12)] = shift_op - v;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, v, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_RSB_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_RSB(2, 4); +} + +static u32 FASTCALL OP_RSB_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_RSB(1, 3); +} + +static u32 FASTCALL OP_RSB_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_RSBS(2, 4); +} + +static u32 FASTCALL OP_RSB_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSBS(3, 5); +} + +static u32 FASTCALL OP_RSB_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSBS(2, 4); +} + +//------------------ADD----------------------------------- + +#define OP_ADD(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ADD_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ADD(1, 3); +} + +static u32 FASTCALL OP_ADD_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ADD(2, 4); +} + +static u32 FASTCALL OP_ADD_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ADD(1, 3); +} + +#define OP_ADDS(a, b) cpu->R[REG_POS(i,12)] = v + shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(v, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; + +static u32 FASTCALL OP_ADD_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_ADDS(2, 4); +} + +static u32 FASTCALL OP_ADD_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADDS(3, 5); +} + +static u32 FASTCALL OP_ADD_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADDS(2, 4); +} + +//------------------ADC----------------------------------- + +#define OP_ADC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] + shift_op + cpu->CPSR.bits.C;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ADC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ADC(1, 3); +} + +static u32 FASTCALL OP_ADC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ADC(2, 4); +} + +static u32 FASTCALL OP_ADC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ADC(1, 3); +} + +#define OP_ADCS(a, b) \ + { \ + u32 tmp = shift_op + cpu->CPSR.bits.C;\ + cpu->R[REG_POS(i,12)] = v + tmp;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(shift_op, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(v, tmp, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_ADC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_ADCS(2, 4); +} + +static u32 FASTCALL OP_ADC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_ADCS(3, 5); +} + +static u32 FASTCALL OP_ADC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_ADCS(2, 4); +} + +//-------------SBC------------------------------------- + +#define OP_SBC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] - shift_op - (!cpu->CPSR.bits.C);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_SBC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_SBC(1, 3); +} + +static u32 FASTCALL OP_SBC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_SBC(2, 4); +} + +static u32 FASTCALL OP_SBC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_SBC(1, 3); +} + +#define OP_SBCS(a, b) \ + { \ + u32 tmp = v - (!cpu->CPSR.bits.C);\ + cpu->R[REG_POS(i,12)] = tmp - shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]));\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(v, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, shift_op, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_SBC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_SBCS(2, 4); +} + +static u32 FASTCALL OP_SBC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_SBCS(3, 5); +} + +static u32 FASTCALL OP_SBC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_SBCS(2, 4); +} + +//---------------RSC---------------------------------- + +#define OP_RSC(a, b) cpu->R[REG_POS(i,12)] = shift_op - cpu->R[REG_POS(i,16)] - (!cpu->CPSR.bits.C);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_RSC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_RSC(1, 3); +} + +static u32 FASTCALL OP_RSC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_RSC(2, 4); +} + +static u32 FASTCALL OP_RSC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_RSC(1, 3); +} + +#define OP_RSCS(a,b) \ + { \ + u32 tmp = shift_op - (!cpu->CPSR.bits.C);\ + cpu->R[REG_POS(i,12)] = tmp - v;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp)) & (!UNSIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]));\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(shift_op, (!cpu->CPSR.bits.C), tmp) | SIGNED_UNDERFLOW(tmp, v, cpu->R[REG_POS(i,12)]);\ + return a; \ + } + +static u32 FASTCALL OP_RSC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSL_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSL_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + LSR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + LSR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ASR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ASR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + u32 shift_op; + ROR_IMM; + OP_RSCS(2,4); +} + +static u32 FASTCALL OP_RSC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + ROR_REG; + OP_RSCS(3,5); +} + +static u32 FASTCALL OP_RSC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,16)]; + IMM_VALUE; + OP_RSCS(2,4); +} + +//-------------------TST---------------------------- + +#define OP_TST(a) \ + { \ + unsigned tmp = cpu->R[REG_POS(i,16)] & shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + return a; \ + } + +static u32 FASTCALL OP_TST_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_TST(1); +} + +static u32 FASTCALL OP_TST_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_TST(2); +} + +static u32 FASTCALL OP_TST_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_TST(1); +} + +//-------------------TEQ---------------------------- + +#define OP_TEQ(a) \ + { \ + unsigned tmp = cpu->R[REG_POS(i,16)] ^ shift_op;\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + return a; \ + } + +static u32 FASTCALL OP_TEQ_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_TEQ(1); +} + +static u32 FASTCALL OP_TEQ_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_TEQ(2); +} + +static u32 FASTCALL OP_TEQ_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_TEQ(1); +} + +//-------------CMP------------------------------------- + +#define OP_CMP(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] - shift_op;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + return a; \ + } + +static u32 FASTCALL OP_CMP_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_CMP(1); +} + +static u32 FASTCALL OP_CMP_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_CMP(2); +} + +static u32 FASTCALL OP_CMP_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_CMP(1); +} + +//---------------CMN--------------------------- + +#define OP_CMN(a) \ + { \ + u32 tmp = cpu->R[REG_POS(i,16)] + shift_op;\ + cpu->CPSR.bits.N = BIT31(tmp);\ + cpu->CPSR.bits.Z = (tmp==0);\ + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)], shift_op, tmp);\ + return a; \ + } + +static u32 FASTCALL OP_CMN_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_CMN(1); +} + +static u32 FASTCALL OP_CMN_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_CMN(2); +} + +static u32 FASTCALL OP_CMN_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_CMN(1); +} + +//------------------ORR------------------- + +#define OP_ORR(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +static u32 FASTCALL OP_ORR_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_ORR(2, 4); +} + +static u32 FASTCALL OP_ORR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_ORR(1, 3); +} + +static u32 FASTCALL OP_ORR_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +static u32 FASTCALL OP_ORR_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 5; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 3; +} + +static u32 FASTCALL OP_ORR_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] | shift_op; + if(REG_POS(i,12)==15) + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1)); + cpu->next_instruction = cpu->R[15]; + return 4; + } + cpu->CPSR.bits.C = c; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0); + return 2; +} + +//------------------MOV------------------- + +#define OP_MOV(a, b) cpu->R[REG_POS(i,12)] = shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = shift_op;\ + return b;\ + }\ + return a; + +#define OP_MOV_S(a, b) cpu->R[REG_POS(i,12)] = shift_op;\ + if(BIT20(i) && REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a;\ + +static u32 FASTCALL OP_MOV_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OP_MOV(2,4); +} + +static u32 FASTCALL OP_MOV_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OP_MOV(1,3); +} + +static u32 FASTCALL OP_MOV_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + if (REG_POS(i,0) == 15) shift_op += 4; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OP_MOV_S(2,4); +} + +static u32 FASTCALL OP_MOV_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OP_MOV_S(3,5); +} + +static u32 FASTCALL OP_MOV_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OP_MOV_S(2,4); +} + +//------------------BIC------------------- +#define OPP_BIC(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPP_BIC_S(a, b) cpu->R[REG_POS(i,12)] = cpu->R[REG_POS(i,16)] & (~shift_op);\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_BIC_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OPP_BIC(2,4); +} + +static u32 FASTCALL OP_BIC_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OPP_BIC(1,3); +} + +static u32 FASTCALL OP_BIC_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OPP_BIC_S(2,4); +} + +static u32 FASTCALL OP_BIC_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OPP_BIC_S(3,5); +} + +static u32 FASTCALL OP_BIC_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OPP_BIC_S(2,4); +} + +//------------------MVN------------------- +#define OPP_MVN(a, b) cpu->R[REG_POS(i,12)] = ~shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + return a; + +#define OPP_MVN_S(a, b) cpu->R[REG_POS(i,12)] = ~shift_op;\ + if(REG_POS(i,12)==15)\ + {\ + Status_Reg SPSR = cpu->SPSR;\ + armcpu_switchMode(cpu, SPSR.bits.mode);\ + cpu->CPSR=SPSR;\ + cpu->R[15] &= (0XFFFFFFFC|(((u32)SPSR.bits.T)<<1));\ + cpu->next_instruction = cpu->R[15];\ + return b;\ + }\ + cpu->CPSR.bits.C = c;\ + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,12)]);\ + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,12)]==0);\ + return a; + +static u32 FASTCALL OP_MVN_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSL_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSL_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + LSR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + LSR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ASR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ASR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 shift_op; + ROR_IMM; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + ROR_REG; + OPP_MVN(2,4); +} + +static u32 FASTCALL OP_MVN_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + OPP_MVN(1,3); +} + +static u32 FASTCALL OP_MVN_S_LSL_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSL_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_LSR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_LSR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_ASR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ASR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_ROR_IMM(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_IMM; + OPP_MVN_S(2,4); +} + +static u32 FASTCALL OP_MVN_S_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_ROR_REG; + OPP_MVN_S(3,5); +} + +static u32 FASTCALL OP_MVN_S_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + S_IMM_VALUE; + OPP_MVN_S(2,4); +} + +//-------------MUL------------------------ +#define OPP_M(a,b) v >>= 8;\ + if((v==0)||(v==0xFFFFFF))\ + return b;\ + v >>= 8;\ + if((v==0)||(v==0xFFFF))\ + return b+1;\ + v >>= 8;\ + if((v==0)||(v==0xFF))\ + return b+2;\ + return a;\ + +static u32 FASTCALL OP_MUL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v; + OPP_M(5,2); +} + +static u32 FASTCALL OP_MLA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u32 a = cpu->R[REG_POS(i,8)]; + u32 b = cpu->R[REG_POS(i,12)]; + cpu->R[REG_POS(i,16)] = a * v + b; + + OPP_M(6,3); +} + +static u32 FASTCALL OP_MUL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v; + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + + OPP_M(6,3); +} + +static u32 FASTCALL OP_MLA_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = cpu->R[REG_POS(i,8)] * v + cpu->R[REG_POS(i,12)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0); + OPP_M(7,4); +} + +//----------UMUL-------------------------- + +static u32 FASTCALL OP_UMULL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + OPP_M(6,3); +} + +static u32 FASTCALL OP_UMLAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + OPP_M(7,4); +} + +static u32 FASTCALL OP_UMULL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + OPP_M(7,4); +} + +static u32 FASTCALL OP_UMLAL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_POS(i,0)]; + u64 res = (u64)v * (u64)cpu->R[REG_POS(i,8)] + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + OPP_M(8,5); +} + +//----------SMUL-------------------------- + +static u32 FASTCALL OP_SMULL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b; + + cpu->R[REG_POS(i,12)] = (u32)(res&0xFFFFFFFF); + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + v &= 0xFFFFFFFF; + + OPP_M(6,3); +} + +static u32 FASTCALL OP_SMLAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b + (u64)cpu->R[REG_POS(i,12)]; + + //LOG("%08X * %08X + %08X%08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)]); + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + //LOG("= %08X%08X %08X%08X\r\n", cpu->R[REG_POS(i,16)], cpu->R[REG_POS(i,12)], res); + + v &= 0xFFFFFFFF; + + OPP_M(7,4); +} + +static u32 FASTCALL OP_SMULL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] = (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + v &= 0xFFFFFFFF; + + OPP_M(7,4); +} + +static u32 FASTCALL OP_SMLAL_S(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 v = (s32)cpu->R[REG_POS(i,0)]; + s64 b = (s32)cpu->R[REG_POS(i,8)]; + s64 res = v * b + (u64)cpu->R[REG_POS(i,12)]; + + cpu->R[REG_POS(i,12)] = (u32)res; + cpu->R[REG_POS(i,16)] += (u32)(res>>32); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_POS(i,16)]); + cpu->CPSR.bits.Z = (cpu->R[REG_POS(i,16)]==0) & (cpu->R[REG_POS(i,12)]==0); + + v &= 0xFFFFFFFF; + + OPP_M(8,5); +} + +//---------------SWP------------------------------ + +static u32 FASTCALL OP_SWP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 tmp = ROR(READ32(cpu->mem_if->data, adr), ((cpu->R[REG_POS(i,16)]&3)<<3)); + + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,0)]); + cpu->R[REG_POS(i,12)] = tmp; + + return 4 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]*2; +} + +static u32 FASTCALL OP_SWPB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u8 tmp = READ8(cpu->mem_if->data, adr); + WRITE8(cpu->mem_if->data, adr, (u8)(cpu->R[REG_POS(i,0)]&0xFF)); + cpu->R[REG_POS(i,12)] = tmp; + + return 4 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]*2; +} + +//------------LDRH----------------------------- + +static u32 FASTCALL OP_LDRH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] =(u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (u32)READ16(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------STRH----------------------------- + +static u32 FASTCALL OP_STRH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,16)] = adr; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------LDRSH-------------------------- + +static u32 FASTCALL OP_LDRSH_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------LDRSB---------------------- + +static u32 FASTCALL OP_LDRSB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_PRE_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - cpu->R[REG_POS(i,0)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= IMM_OFF; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_P_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] += cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_POS_INDE_M_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + cpu->R[REG_POS(i,12)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + cpu->R[REG_POS(i,16)] -= cpu->R[REG_POS(i,0)]; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//--------------MRS-------------------------------- + +static u32 FASTCALL OP_MRS_CPSR(armcpu_t *cpu) +{ + cpu->R[REG_POS(cpu->instruction,12)] = cpu->CPSR.val; + + return 1; +} + +static u32 FASTCALL OP_MRS_SPSR(armcpu_t *cpu) +{ + cpu->R[REG_POS(cpu->instruction,12)] = cpu->SPSR.val; + + return 1; +} + +//--------------MSR-------------------------------- + +static u32 FASTCALL OP_MSR_CPSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 operand = cpu->R[REG_POS(i,0)]; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, operand & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (operand & 0xFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (operand & 0xFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (operand & 0xFF0000); + } + if(BIT19(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (operand & 0xFF000000); + + return 1; +} + +static u32 FASTCALL OP_MSR_SPSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 operand = cpu->R[REG_POS(i,0)]; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (operand & 0XFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (operand & 0XFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (operand & 0XFF0000); + } + if(BIT19(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0x00FFFFFF) | (operand & 0XFF000000); + + return 1; +} + +static u32 FASTCALL OP_MSR_CPSR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + armcpu_switchMode(cpu, shift_op & 0x1F); + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFFFF00) | (shift_op & 0XFF); + } + if(BIT17(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00); + if(BIT18(i)) + cpu->CPSR.val = (cpu->CPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000); + } + if(BIT19(i)) + { + //cpu->CPSR.val = (cpu->CPSR.val & 0xFF000000) | (shift_op & 0XFF000000); + cpu->CPSR.val = (cpu->CPSR.val & 0x00FFFFFF) | (shift_op & 0xFF000000); + } + + return 1; +} + +static u32 FASTCALL OP_MSR_SPSR_IMM_VAL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + IMM_VALUE; + + if(cpu->CPSR.bits.mode!=USR) + { + if(BIT16(i)) + { + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFFFF00) | (shift_op & 0XFF); + } + if(BIT17(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFFFF00FF) | (shift_op & 0XFF00); + if(BIT18(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF00FFFF) | (shift_op & 0XFF0000); + } + if(BIT19(i)) + cpu->SPSR.val = (cpu->SPSR.val & 0xFF000000) | (shift_op & 0XFF000000); + + return 1; +} + +//-----------------BRANCH-------------------------- + +static u32 FASTCALL OP_BX(armcpu_t *cpu) +{ + u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)]; + + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & 0xFFFFFFFE; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_BLX_REG(armcpu_t *cpu) +{ + u32 tmp = cpu->R[REG_POS(cpu->instruction, 0)]; + + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = BIT0(tmp); + cpu->R[15] = tmp & 0xFFFFFFFE; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +#define SIGNEXTEND_24(i) (((s32)((i)<<8))>>8) + +static u32 FASTCALL OP_B(armcpu_t *cpu) +{ + u32 off = SIGNEXTEND_24(cpu->instruction); + if(CONDITION(cpu->instruction)==0xF) + { + cpu->R[14] = cpu->next_instruction; + cpu->CPSR.bits.T = 1; + } + cpu->R[15] += (off<<2); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_BL(armcpu_t *cpu) +{ + u32 off = SIGNEXTEND_24(cpu->instruction); + if(CONDITION(cpu->instruction)==0xF) + { + cpu->CPSR.bits.T = 1; + cpu->R[15] += 2; + } + cpu->R[14] = cpu->next_instruction; + cpu->R[15] += (off<<2); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +//----------------CLZ------------------------------- + +u8 CLZ_TAB[16]= +{ + 0, // 0000 + 1, // 0001 + 2, 2, // 001X + 3, 3, 3, 3, // 01XX + 4, 4, 4, 4, 4, 4, 4, 4 // 1XXX +}; + +static u32 FASTCALL OP_CLZ(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rm = cpu->R[REG_POS(i,0)]; + u32 pos; + + if(Rm==0) + { + cpu->R[REG_POS(i,12)]=32; + return 2; + } + + Rm |= (Rm >>1); + Rm |= (Rm >>2); + Rm |= (Rm >>4); + Rm |= (Rm >>8); + Rm |= (Rm >>16); + + pos = + CLZ_TAB[Rm&0xF] + + CLZ_TAB[(Rm>>4)&0xF] + + CLZ_TAB[(Rm>>8)&0xF] + + CLZ_TAB[(Rm>>12)&0xF] + + CLZ_TAB[(Rm>>16)&0xF] + + CLZ_TAB[(Rm>>20)&0xF] + + CLZ_TAB[(Rm>>24)&0xF] + + CLZ_TAB[(Rm>>28)&0xF]; + + cpu->R[REG_POS(i,12)]=32 - pos; + + return 2; +} + +//--------------------QADD--QSUB------------------------------ + +static u32 FASTCALL OP_QADD(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 res = cpu->R[REG_POS(i,16)]+cpu->R[REG_POS(i,0)]; + + LOG("spe add\r\n"); + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,16)],cpu->R[REG_POS(i,0)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QSUB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 res = cpu->R[REG_POS(i,0)]-cpu->R[REG_POS(i,16)]; + + LOG("spe add\r\n"); + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,16)], res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QDADD(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + LOG("spe add\r\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = mul + cpu->R[REG_POS(i,0)]; + if(SIGNED_OVERFLOW(cpu->R[REG_POS(i,0)],mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +static u32 FASTCALL OP_QDSUB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 mul = cpu->R[REG_POS(i,16)]<<1; + u32 res; + + + LOG("spe add\r\n"); + if(BIT31(cpu->R[REG_POS(i,16)])!=BIT31(mul)) + { + cpu->CPSR.bits.Q=1; + mul = 0x80000000-BIT31(mul); + } + + res = cpu->R[REG_POS(i,0)] - mul; + if(SIGNED_UNDERFLOW(cpu->R[REG_POS(i,0)], mul, res)) + { + cpu->CPSR.bits.Q=1; + cpu->R[REG_POS(i,12)]=0x80000000-BIT31(res); + return 2; + } + cpu->R[REG_POS(i,12)]=res; + if(REG_POS(i,12)==15) + { + cpu->R[15] &= 0XFFFFFFFC; + cpu->next_instruction = cpu->R[15]; + return 3; + } + return 2; +} + +//-----------------SMUL------------------------------- + +#define HWORD(i) ((s32)(((s32)(i))>>16)) +#define LWORD(i) (s32)(((s32)((i)<<16))>>16) + +static u32 FASTCALL OP_SMUL_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +static u32 FASTCALL OP_SMUL_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + cpu->R[REG_POS(i,16)] = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + + return 2; +} + +//-----------SMLA---------------------------- + +static u32 FASTCALL OP_SMLA_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLABB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLABT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLATB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLA_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = (u32)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLATT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, tmp + a); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//--------------SMLAL--------------------------------------- + +static u32 FASTCALL OP_SMLAL_B_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALBB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + (res + ((tmp<0)*0xFFFFFFFF))), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += (res + ((tmp<0)*0xFFFFFFFF)); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_B_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(LWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALBT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_T_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* (s64)LWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALTB %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMLAL_T_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)(HWORD(cpu->R[REG_POS(i,0)])* HWORD(cpu->R[REG_POS(i,8)])); + u64 res = (u64)tmp + cpu->R[REG_POS(i,12)]; + + LOG("SMLALTT %08X * %08X + %08X%08X = %08X%08X\r\n", (int)cpu->R[REG_POS(i,0)], (int)cpu->R[REG_POS(i,8)], (int)cpu->R[REG_POS(i,16)], (int)cpu->R[REG_POS(i,12)], (int)(cpu->R[REG_POS(i,16)] + res + ((tmp<0)*0xFFFFFFFF)), (int)(u32) res); + + cpu->R[REG_POS(i,12)] = (u32) res; + cpu->R[REG_POS(i,16)] += res + ((tmp<0)*0xFFFFFFFF); + + return 2; +} + +//--------------SMULW-------------------- + +static u32 FASTCALL OP_SMULW_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //LOG("SMULWB %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +static u32 FASTCALL OP_SMULW_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + + //LOG("SMULWT %08X * %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], ((tmp>>16)&0xFFFFFFFF)); + + cpu->R[REG_POS(i,16)] = ((tmp>>16)&0xFFFFFFFF); + + return 2; +} + +//--------------SMLAW------------------- +static u32 FASTCALL OP_SMLAW_B(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)LWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLAWB %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, (tmp>>16) + a); + + tmp = (tmp>>16); + + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +static u32 FASTCALL OP_SMLAW_T(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + s64 tmp = (s64)HWORD(cpu->R[REG_POS(i,8)]) * (s64)((s32)cpu->R[REG_POS(i,0)]); + u32 a = cpu->R[REG_POS(i,12)]; + + //LOG("SMLAWT %08X * %08X + %08X = %08X\r\n", cpu->R[REG_POS(i,0)], cpu->R[REG_POS(i,8)], a, ((tmp>>16)&0xFFFFFFFF) + a); + + tmp = ((tmp>>16)&0xFFFFFFFF); + cpu->R[REG_POS(i,16)] = tmp + a; + + if(SIGNED_OVERFLOW(tmp, a, cpu->R[REG_POS(i,16)])) + cpu->CPSR.bits.Q = 1; + + return 2; +} + +//------------LDR--------------------------- + +static u32 FASTCALL OP_LDR_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------------------------------------------------------ +static u32 FASTCALL OP_LDR_P_IMM_OFF_POSTIND2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + u32 old; + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + old = armcpu_switchMode(cpu, USR); + cpu->R[REG_POS(i,12)] = val; + armcpu_switchMode(cpu, old); + + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//------------------------------------------------------------ + +static u32 FASTCALL OP_LDR_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr + shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ32(cpu->mem_if->data, adr); + + if(adr&3) + val = ROR(val, 8*(adr&3)); + + if(REG_POS(i,12)==15) + { + cpu->R[15] = val & (0XFFFFFFFC | (((u32)cpu->LDTBit)<<1)); + cpu->CPSR.bits.T = BIT0(val) & cpu->LDTBit; + cpu->next_instruction = cpu->R[15]; + cpu->R[REG_POS(i,16)] = adr - shift_op; + return 5 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + } + + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------LDRB------------------------------------------- + +static u32 FASTCALL OP_LDRB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + u32 val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + u32 val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr + shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 val; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,16)] = adr - shift_op; + cpu->R[REG_POS(i,12)] = val; + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------STR-------------------------------- + +static u32 FASTCALL OP_STR_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + +// execute = false; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------------STRB------------------------------------- + +static u32 FASTCALL OP_STRB_P_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] + IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)] - IMM_OFF_12; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] + shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_PREIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)] - shift_op; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr; + u32 shift_op; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//-----------------------LDRBT------------------------------------- + +static u32 FASTCALL OP_LDRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_IMM_OFF_POSTIND\n"); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_REG_OFF_POSTIND"); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_LSL_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_LSL_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_LSR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_LSR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_ASR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_ASR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_P_ROR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 val; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_LDRBT_M_ROR_IMM_OFF_POSTIND"); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + val = READ8(cpu->mem_if->data, adr); + cpu->R[REG_POS(i,12)] = val; + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//----------------------STRBT---------------------------- + +static u32 FASTCALL OP_STRBT_P_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - IMM_OFF_12; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_REG_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - cpu->R[REG_POS(i,0)]; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_LSL_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSL_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_LSR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + LSR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_ASR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ASR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_P_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr + shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRBT_M_ROR_IMM_OFF_POSTIND(armcpu_t *cpu) +{ + u32 oldmode; + u32 i; + u32 adr; + u32 shift_op; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + oldmode = armcpu_switchMode(cpu, SYS); + + + i = cpu->instruction; + ROR_IMM; + adr = cpu->R[REG_POS(i,16)]; + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_POS(i,12)]); + cpu->R[REG_POS(i,16)] = adr - shift_op; + + armcpu_switchMode(cpu, oldmode); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +//---------------------LDM----------------------------- + +#define OP_L_IA(reg, adr) if(BIT##reg(i))\ + {\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + adr += 4;\ + } + +#define OP_L_IB(reg, adr) if(BIT##reg(i))\ + {\ + adr += 4;\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + } + +#define OP_L_DA(reg, adr) if(BIT##reg(i))\ + {\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + adr -= 4;\ + } + +#define OP_L_DB(reg, adr) if(BIT##reg(i))\ + {\ + adr -= 4;\ + registres[reg] = READ32(cpu->mem_if->data, start);\ + c += waitState[(start>>24)&0xF];\ + } + +static u32 FASTCALL OP_LDMIA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + //start += 4; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + start += 4; + c += waitState[(start>>24)&0xF]; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += 2 + (c==0); + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + u32 start = cpu->R[REG_POS(i,16)]; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + return c + 2; +} + +static u32 FASTCALL OP_LDMIA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start += 4; + cpu->next_instruction = registres[15]; + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + start += 4; + c += waitState[(start>>24)&0xF]; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += 2 + (c==0); + } + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, count; + u32 start = cpu->R[REG_POS(i,16)]; + u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; + u32 * registres = cpu->R; + u32 * waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR.bits.T = BIT0(tmp); + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(i & (1 << REG_POS(i,16))) { + if(i & bitList) + cpu->R[REG_POS(i,16)] = start; + } + else + cpu->R[REG_POS(i,16)] = start; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIA2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 oldmode; + + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 1; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + Status_Reg SPSR; + cpu->R[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + //start += 4; + cpu->next_instruction = cpu->R[15]; + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + else + { + armcpu_switchMode(cpu, oldmode); + } + return c + 2; +} + +static u32 FASTCALL OP_LDMIB2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 oldmode; + u32 c = 0; + + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + //execute = FALSE; + LOG("Untested opcode: OP_LDMIB2"); + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)) + { + u32 tmp; + Status_Reg SPSR; + start += 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + else + { + armcpu_switchMode(cpu, oldmode); + } + return c + 2; +} + +static u32 FASTCALL OP_LDMDA2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 oldmode; + u32 c = 0; + u32 * registres; + u32 * waitState; + + u32 start = cpu->R[REG_POS(i,16)]; + //execute = FALSE; + LOG("Untested opcode: OP_LDMDA2"); + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + } + + return c + 2; +} + +static u32 FASTCALL OP_LDMDB2(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + + u32 oldmode; + u32 c = 0; + u32 * registres; + u32 * waitState; + + u32 start = cpu->R[REG_POS(i,16)]; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + } + else + { + Status_Reg SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + } + + return 2 + c; +} + +static u32 FASTCALL OP_LDMIA2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + u32 tmp; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IA(0, start); + OP_L_IA(1, start); + OP_L_IA(2, start); + OP_L_IA(3, start); + OP_L_IA(4, start); + OP_L_IA(5, start); + OP_L_IA(6, start); + OP_L_IA(7, start); + OP_L_IA(8, start); + OP_L_IA(9, start); + OP_L_IA(10, start); + OP_L_IA(11, start); + OP_L_IA(12, start); + OP_L_IA(13, start); + OP_L_IA(14, start); + + if(BIT15(i)==0) + { + registres[REG_POS(i,16)] = start; + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + cpu->next_instruction = registres[15]; + c += waitState[(start>>24)&0xF]; + + return c + 2; +} + +static u32 FASTCALL OP_LDMIB2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + u32 tmp; + Status_Reg SPSR; + + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + OP_L_IB(0, start); + OP_L_IB(1, start); + OP_L_IB(2, start); + OP_L_IB(3, start); + OP_L_IB(4, start); + OP_L_IB(5, start); + OP_L_IB(6, start); + OP_L_IB(7, start); + OP_L_IB(8, start); + OP_L_IB(9, start); + OP_L_IB(10, start); + OP_L_IB(11, start); + OP_L_IB(12, start); + OP_L_IB(13, start); + OP_L_IB(14, start); + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + registres[REG_POS(i,16)] = start; + + return c + 2; + } + + registres[REG_POS(i,16)] = start + 4; + tmp = READ32(cpu->mem_if->data, start + 4); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + c += waitState[(start>>24)&0xF]; + + return c + 2; +} + +static u32 FASTCALL OP_LDMDA2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp = READ32(cpu->mem_if->data, start); + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + c += waitState[(start>>24)&0xF]; + start -= 4; + cpu->next_instruction = registres[15]; + } + + OP_L_DA(14, start); + OP_L_DA(13, start); + OP_L_DA(12, start); + OP_L_DA(11, start); + OP_L_DA(10, start); + OP_L_DA(9, start); + OP_L_DA(8, start); + OP_L_DA(7, start); + OP_L_DA(6, start); + OP_L_DA(5, start); + OP_L_DA(4, start); + OP_L_DA(3, start); + OP_L_DA(2, start); + OP_L_DA(1, start); + OP_L_DA(0, start); + + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + return c + 2; +} + +static u32 FASTCALL OP_LDMDB2_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 c = 0; + + u32 oldmode; + u32 start = cpu->R[REG_POS(i,16)]; + u32 * registres; + u32 * waitState; + Status_Reg SPSR; +// execute = FALSE; + if(BIT15(i)==0) + { + if(cpu->CPSR.bits.mode==USR) + return 2; + oldmode = armcpu_switchMode(cpu, SYS); + } + + registres = cpu->R; + waitState = MMU.MMU_WAIT32[cpu->proc_ID]; + + if(BIT15(i)) + { + u32 tmp; + start -= 4; + tmp = READ32(cpu->mem_if->data, start); + c += waitState[(start>>24)&0xF]; + registres[15] = tmp & (0XFFFFFFFC | (BIT0(tmp)<<1)); + cpu->CPSR = cpu->SPSR; + cpu->next_instruction = registres[15]; + } + + OP_L_DB(14, start); + OP_L_DB(13, start); + OP_L_DB(12, start); + OP_L_DB(11, start); + OP_L_DB(10, start); + OP_L_DB(9, start); + OP_L_DB(8, start); + OP_L_DB(7, start); + OP_L_DB(6, start); + OP_L_DB(5, start); + OP_L_DB(4, start); + OP_L_DB(3, start); + OP_L_DB(2, start); + OP_L_DB(1, start); + OP_L_DB(0, start); + + registres[REG_POS(i,16)] = start; + + if(BIT15(i)==0) + { + armcpu_switchMode(cpu, oldmode); + return c + 2; + } + + SPSR = cpu->SPSR; + armcpu_switchMode(cpu, SPSR.bits.mode); + cpu->CPSR=SPSR; + return c + 2; +} + +//------------------------------STM---------------------------------- + +static u32 FASTCALL OP_STMIA(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMIB(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMDA(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMDB(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + return c + 1; +} + +static u32 FASTCALL OP_STMIA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMIB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMDA_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMDB_W(armcpu_t *cpu) +{ + u32 i = cpu->instruction, c = 0, b; + u32 start = cpu->R[REG_POS(i,16)]; + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + cpu->R[REG_POS(i,16)] = start; + return c + 1; +} + +static u32 FASTCALL OP_STMIA2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIA2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIB2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIB2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDA2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMDA2"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDB2(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIA2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMIA2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start += 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMIB2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + i = cpu->instruction; + c=0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, b)) + { + start += 4; + WRITE32(cpu->mem_if->data, start, cpu->R[b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + armcpu_switchMode(cpu, oldmode); + cpu->R[REG_POS(i,16)] = start; + + return c + 1; +} + +static u32 FASTCALL OP_STMDA2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + //execute = FALSE; + LOG("Untested opcode: OP_STMDA2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + start -= 4; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +static u32 FASTCALL OP_STMDB2_W(armcpu_t *cpu) +{ + u32 i, c, b; + u32 start; + u32 oldmode; + + if(cpu->CPSR.bits.mode==USR) + return 2; + + i = cpu->instruction; + c = 0; + + start = cpu->R[REG_POS(i,16)]; + oldmode = armcpu_switchMode(cpu, SYS); + + //execute = FALSE; + LOG("Untested opcode: OP_STMDB2_W"); + + for(b=0; b<16; ++b) + { + if(BIT_N(i, 15-b)) + { + start -= 4; + WRITE32(cpu->mem_if->data, start, cpu->R[15-b]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(start>>24)&0xF]; + } + } + + cpu->R[REG_POS(i,16)] = start; + + armcpu_switchMode(cpu, oldmode); + return c + 1; +} + +/* + * + * The Enhanced DSP Extension LDRD and STRD instructions. + * + */ +static u32 FASTCALL +OP_LDRD_STRD_POST_INDEX( armcpu_t *cpu) { + u32 i = cpu->instruction; + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + + /* I bit - immediate or register */ + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + /* U bit - add or subtract */ + if ( BIT23(i)) + cpu->R[REG_POS(i,16)] += index; + else + cpu->R[REG_POS(i,16)] -= index; + + if ( !(Rd_num & 0x1)) { + /* Store/Load */ + if ( BIT5(i)) { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + } + else { + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + } + } + + return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2); +} + +static u32 FASTCALL +OP_LDRD_STRD_OFFSET_PRE_INDEX( armcpu_t *cpu) { + u32 i = cpu->instruction; + u32 Rd_num = REG_POS( i, 12); + u32 addr = cpu->R[REG_POS(i,16)]; + u32 index; + + /* I bit - immediate or register */ + if ( BIT22(i)) + index = IMM_OFF; + else + index = cpu->R[REG_POS(i,0)]; + + /* U bit - add or subtract */ + if ( BIT23(i)) { + addr += index; + + /* W bit - writeback */ + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + } + else { + addr -= index; + + /* W bit - writeback */ + if ( BIT21(i)) + cpu->R[REG_POS(i,16)] = addr; + } + + if ( !(Rd_num & 0x1)) { + /* Store/Load */ + if ( BIT5(i)) { + WRITE32(cpu->mem_if->data, addr, cpu->R[Rd_num]); + WRITE32(cpu->mem_if->data, addr + 4, cpu->R[Rd_num + 1]); + } + else { + cpu->R[Rd_num] = READ32(cpu->mem_if->data, addr); + cpu->R[Rd_num + 1] = READ32(cpu->mem_if->data, addr + 4); + } + } + + return 3 + (MMU.MMU_WAIT32[cpu->proc_ID][(addr>>24)&0xF] * 2); +} + + + +//---------------------STC---------------------------------- + +static u32 FASTCALL OP_STC_P_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_P_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_P_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_M_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_STC_OPTION(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a STC, no feedback is given to the arm */ + return 2; + } +} + +//---------------------LDC---------------------------------- + +static u32 FASTCALL OP_LDC_P_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_IMM_OFF(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_P_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_PREIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_P_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_M_POSTIND(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +static u32 FASTCALL OP_LDC_OPTION(armcpu_t *cpu) +{ + { + /* the NDS has no coproc that responses to a LDC, no feedback is given to the arm */ + return 2; + } +} + +//----------------MCR----------------------- + +static u32 FASTCALL OP_MCR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + execute = FALSE; + return 2; + } + + armcp15_moveARM2CP((armcp15_t*)cpu->coproc[cpnum], cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + //cpu->coproc[cpnum]->moveARM2CP(cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 2; +} + +//----------------MRC----------------------- + +static u32 FASTCALL OP_MRC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 cpnum = REG_POS(i, 8); + + if(!cpu->coproc[cpnum]) + { + execute = FALSE; + return 2; + } + + armcp15_moveCP2ARM((armcp15_t*)cpu->coproc[cpnum], &cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + //cpu->coproc[cpnum]->moveCP2ARM(&cpu->R[REG_POS(i, 12)], REG_POS(i, 16), REG_POS(i, 0), (i>>21)&7, (i>>5)&7); + return 4; +} + +//--------------SWI------------------------------- +static u32 FASTCALL OP_SWI(armcpu_t *cpu) +{ + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + /* TODO (#1#): translocated SWI vectors */ + /* we use an irq thats not in the irq tab, as + it was replaced duie to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */ + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 4; + } + else + { + u32 swinum = (cpu->instruction>>16)&0x1F; + return cpu->swi_tab[swinum](cpu) + 3; + } +} + +//----------------BKPT------------------------- +static u32 FASTCALL OP_BKPT(armcpu_t *cpu) +{ + execute = FALSE; + return 4; +} + +//----------------CDP----------------------- + +static u32 FASTCALL OP_CDP(armcpu_t *cpu) +{ + execute = FALSE; + return 4; +} + +#define TYPE_RETOUR u32 +#define PARAMETRES armcpu_t *cpu +#define CALLTYPE FASTCALL +#define NOM_TAB arm_instructions_set + +#include "instruction_tabdef.inc" diff --git a/tools/vio2sf/src/vio2sf/desmume/arm_instructions.h b/tools/vio2sf/src/vio2sf/desmume/arm_instructions.h new file mode 100644 index 000000000..350680aaf --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/arm_instructions.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ARMINSTRUCTION_H +#define ARMINSTRUCTION_H + +#include "types.h" +#include "armcpu.h" + +extern u32 (FASTCALL* arm_instructions_set[4096])(armcpu_t * cpu); + +#endif + diff --git a/tools/vio2sf/src/vio2sf/desmume/armcpu.c b/tools/vio2sf/src/vio2sf/desmume/armcpu.c new file mode 100644 index 000000000..a3071857e --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/armcpu.c @@ -0,0 +1,579 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "arm_instructions.h" +#include "thumb_instructions.h" +#include "cp15.h" +#include "bios.h" +#include +#include + +const unsigned char arm_cond_table[16*16] = { + /* N=0, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=0, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0x00,0xFF, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=0, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0x00,0xFF,0xFF,0x00, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=0 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=0, V=1 */ + 0x00,0xFF,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=0, C=1, V=0 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0xFF,0x00,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=0, C=1, V=1 */ + 0x00,0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x20, + /* N=1, Z=1, C=0, V=0 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=0, V=1 */ + 0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=0 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0x00,0xFF, + 0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0x20, + /* N=1, Z=1, C=1, V=1 */ + 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, + 0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x20, +}; + +armcpu_t NDS_ARM7; +armcpu_t NDS_ARM9; + +#define SWAP(a, b, c) do \ + { \ + c=a; \ + a=b; \ + b=c; \ + } \ + while(0) + +#ifdef GDB_STUB + +#define STALLED_CYCLE_COUNT 10 + +static void +stall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->stalled = 1; +} + +static void +unstall_cpu( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->stalled = 0; +} + +static void +install_post_exec_fn( void *instance, + void (*ex_fn)( void *, u32 adr, int thumb), + void *fn_data) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = ex_fn; + armcpu->post_ex_fn_data = fn_data; +} + +static void +remove_post_exec_fn( void *instance) { + armcpu_t *armcpu = (armcpu_t *)instance; + + armcpu->post_ex_fn = NULL; +} +#endif + +static u32 +read_cpu_reg( void *instance, u32 reg_num) { + armcpu_t *armcpu = (armcpu_t *)instance; + u32 reg_value = 0; + + if ( reg_num <= 14) { + reg_value = armcpu->R[reg_num]; + } + else if ( reg_num == 15) { + reg_value = armcpu->next_instruction; + } + else if ( reg_num == 16) { + /* CPSR */ + reg_value = armcpu->CPSR.val; + } + + return reg_value; +} + +static void +set_cpu_reg( void *instance, u32 reg_num, u32 value) { + armcpu_t *armcpu = (armcpu_t *)instance; + + if ( reg_num <= 14) { + armcpu->R[reg_num] = value; + } + else if ( reg_num == 15) { + armcpu->next_instruction = value; + } + else if ( reg_num == 16) { + /* FIXME: setting the CPSR */ + } +} + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, + struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret) +#else +int armcpu_new( armcpu_t *armcpu, u32 id) +#endif +{ + armcpu->proc_ID = id; + + if(id==0) + armcpu->swi_tab = ARM9_swi_tab; + else + armcpu->swi_tab = ARM7_swi_tab; + +#ifdef GDB_STUB + armcpu->mem_if = mem_if; + + /* populate the control interface */ + armcpu->ctrl_iface.stall = stall_cpu; + armcpu->ctrl_iface.unstall = unstall_cpu; + armcpu->ctrl_iface.read_reg = read_cpu_reg; + armcpu->ctrl_iface.set_reg = set_cpu_reg; + armcpu->ctrl_iface.install_post_ex_fn = install_post_exec_fn; + armcpu->ctrl_iface.remove_post_ex_fn = remove_post_exec_fn; + armcpu->ctrl_iface.data = armcpu; + + *ctrl_iface_ret = &armcpu->ctrl_iface; + + armcpu->stalled = 0; + armcpu->post_ex_fn = NULL; +#endif + + armcpu_init(armcpu, 0); + + return 0; +} + +void armcpu_init(armcpu_t *armcpu, u32 adr) +{ + u32 i; + + armcpu->LDTBit = (armcpu->proc_ID==0); //Si ARM9 utiliser le syte v5 pour le load + armcpu->intVector = 0xFFFF0000 * (armcpu->proc_ID==0); + armcpu->waitIRQ = FALSE; + armcpu->wirq = FALSE; + +#ifdef GDB_STUB + armcpu->irq_flag = 0; +#endif + + if(armcpu->coproc[15]) free(armcpu->coproc[15]); + + for(i = 0; i < 15; ++i) + { + armcpu->R[i] = 0; + armcpu->coproc[i] = NULL; + } + + armcpu->CPSR.val = armcpu->SPSR.val = SYS; + + armcpu->R13_usr = armcpu->R14_usr = 0; + armcpu->R13_svc = armcpu->R14_svc = 0; + armcpu->R13_abt = armcpu->R14_abt = 0; + armcpu->R13_und = armcpu->R14_und = 0; + armcpu->R13_irq = armcpu->R14_irq = 0; + armcpu->R8_fiq = armcpu->R9_fiq = armcpu->R10_fiq = armcpu->R11_fiq = armcpu->R12_fiq = armcpu->R13_fiq = armcpu->R14_fiq = 0; + + armcpu->SPSR_svc.val = armcpu->SPSR_abt.val = armcpu->SPSR_und.val = armcpu->SPSR_irq.val = armcpu->SPSR_fiq.val = 0; + +#ifdef GDB_STUB + armcpu->instruct_adr = adr; + armcpu->R[15] = adr + 8; +#else + armcpu->R[15] = adr; +#endif + + armcpu->next_instruction = adr; + + armcpu->coproc[15] = (armcp_t*)armcp15_new(armcpu); + +#ifndef GDB_STUB + armcpu_prefetch(armcpu); +#endif +} + +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode) +{ + u32 oldmode = armcpu->CPSR.bits.mode; + + switch(oldmode) + { + case USR : + case SYS : + armcpu->R13_usr = armcpu->R[13]; + armcpu->R14_usr = armcpu->R[14]; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R13_fiq = armcpu->R[13]; + armcpu->R14_fiq = armcpu->R[14]; + armcpu->SPSR_fiq = armcpu->SPSR; + break; + } + case IRQ : + armcpu->R13_irq = armcpu->R[13]; + armcpu->R14_irq = armcpu->R[14]; + armcpu->SPSR_irq = armcpu->SPSR; + break; + + case SVC : + armcpu->R13_svc = armcpu->R[13]; + armcpu->R14_svc = armcpu->R[14]; + armcpu->SPSR_svc = armcpu->SPSR; + break; + + case ABT : + armcpu->R13_abt = armcpu->R[13]; + armcpu->R14_abt = armcpu->R[14]; + armcpu->SPSR_abt = armcpu->SPSR; + break; + + case UND : + armcpu->R13_und = armcpu->R[13]; + armcpu->R14_und = armcpu->R[14]; + armcpu->SPSR_und = armcpu->SPSR; + break; + default : + break; + } + + switch(mode) + { + case USR : + case SYS : + armcpu->R[13] = armcpu->R13_usr; + armcpu->R[14] = armcpu->R14_usr; + //SPSR = CPSR; + break; + + case FIQ : + { + u32 tmp; + SWAP(armcpu->R[8], armcpu->R8_fiq, tmp); + SWAP(armcpu->R[9], armcpu->R9_fiq, tmp); + SWAP(armcpu->R[10], armcpu->R10_fiq, tmp); + SWAP(armcpu->R[11], armcpu->R11_fiq, tmp); + SWAP(armcpu->R[12], armcpu->R12_fiq, tmp); + armcpu->R[13] = armcpu->R13_fiq; + armcpu->R[14] = armcpu->R14_fiq; + armcpu->SPSR = armcpu->SPSR_fiq; + break; + } + + case IRQ : + armcpu->R[13] = armcpu->R13_irq; + armcpu->R[14] = armcpu->R14_irq; + armcpu->SPSR = armcpu->SPSR_irq; + break; + + case SVC : + armcpu->R[13] = armcpu->R13_svc; + armcpu->R[14] = armcpu->R14_svc; + armcpu->SPSR = armcpu->SPSR_svc; + break; + + case ABT : + armcpu->R[13] = armcpu->R13_abt; + armcpu->R[14] = armcpu->R14_abt; + armcpu->SPSR = armcpu->SPSR_abt; + break; + + case UND : + armcpu->R[13] = armcpu->R13_und; + armcpu->R[14] = armcpu->R14_und; + armcpu->SPSR = armcpu->SPSR_und; + break; + + default : + break; + } + + armcpu->CPSR.bits.mode = mode & 0x1F; + return oldmode; +} + +static u32 +armcpu_prefetch(armcpu_t *armcpu) +{ + u32 temp_instruction; + + if(armcpu->CPSR.bits.T == 0) + { +#ifdef GDB_STUB + temp_instruction = + armcpu->mem_if->prefetch32( armcpu->mem_if->data, + armcpu->next_instruction); + + if ( !armcpu->stalled) { + armcpu->instruction = temp_instruction; + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; + } +#else + armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; +#endif + + return MMU.MMU_WAIT32[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF]; + } + +#ifdef GDB_STUB + temp_instruction = + armcpu->mem_if->prefetch16( armcpu->mem_if->data, + armcpu->next_instruction); + + if ( !armcpu->stalled) { + armcpu->instruction = temp_instruction; + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction = armcpu->next_instruction + 2; + armcpu->R[15] = armcpu->next_instruction + 2; + } +#else + armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 2; + armcpu->R[15] = armcpu->next_instruction + 2; +#endif + + return MMU.MMU_WAIT16[armcpu->proc_ID][(armcpu->instruct_adr>>24)&0xF]; +} + + +static BOOL FASTCALL test_EQ(Status_Reg CPSR) { return ( CPSR.bits.Z); } +static BOOL FASTCALL test_NE(Status_Reg CPSR) { return (!CPSR.bits.Z); } +static BOOL FASTCALL test_CS(Status_Reg CPSR) { return ( CPSR.bits.C); } +static BOOL FASTCALL test_CC(Status_Reg CPSR) { return (!CPSR.bits.C); } +static BOOL FASTCALL test_MI(Status_Reg CPSR) { return ( CPSR.bits.N); } +static BOOL FASTCALL test_PL(Status_Reg CPSR) { return (!CPSR.bits.N); } +static BOOL FASTCALL test_VS(Status_Reg CPSR) { return ( CPSR.bits.V); } +static BOOL FASTCALL test_VC(Status_Reg CPSR) { return (!CPSR.bits.V); } +static BOOL FASTCALL test_HI(Status_Reg CPSR) { return (CPSR.bits.C) && (!CPSR.bits.Z); } +static BOOL FASTCALL test_LS(Status_Reg CPSR) { return (CPSR.bits.Z) || (!CPSR.bits.C); } +static BOOL FASTCALL test_GE(Status_Reg CPSR) { return (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LT(Status_Reg CPSR) { return (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_GT(Status_Reg CPSR) { return (!CPSR.bits.Z) && (CPSR.bits.N==CPSR.bits.V); } +static BOOL FASTCALL test_LE(Status_Reg CPSR) { return ( CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V); } +static BOOL FASTCALL test_AL(Status_Reg CPSR) { return 1; } + +static BOOL (FASTCALL* test_conditions[])(Status_Reg CPSR)= { + test_EQ , test_NE , + test_CS , test_CC , + test_MI , test_PL , + test_VS , test_VC , + test_HI , test_LS , + test_GE , test_LT , + test_GT , test_LE , + test_AL +}; +#define TEST_COND2(cond, CPSR) \ + (cond<15&&test_conditions[cond](CPSR)) + + +BOOL armcpu_irqExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + + if(armcpu->CPSR.bits.I) return FALSE; + +#ifdef GDB_STUB + armcpu->irq_flag = 0; +#endif + + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, IRQ); + +#ifdef GDB_STUB + armcpu->R[14] = armcpu->next_instruction + 4; +#else + armcpu->R[14] = armcpu->instruct_adr + 4; +#endif + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0x18; + armcpu->waitIRQ = 0; + +#ifndef GDB_STUB + armcpu->R[15] = armcpu->next_instruction + 8; + armcpu_prefetch(armcpu); +#endif + + return TRUE; +} +/* +static BOOL armcpu_prefetchExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + if(armcpu->CPSR.bits.I) return FALSE; + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, ABT); + armcpu->R[14] = armcpu->next_instruction + 4; + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0xC; + armcpu->R[15] = armcpu->next_instruction + 8; + armcpu->waitIRQ = 0; + return TRUE; +} +*/ + +static BOOL armcpu_prefetchExeption(armcpu_t *armcpu) +{ + Status_Reg tmp; + if(armcpu->CPSR.bits.I) return FALSE; + tmp = armcpu->CPSR; + armcpu_switchMode(armcpu, ABT); + +#ifdef GDB_STUB + armcpu->R[14] = armcpu->next_instruction + 4; +#else + armcpu->R[14] = armcpu->instruct_adr + 4; +#endif + + armcpu->SPSR = tmp; + armcpu->CPSR.bits.T = 0; + armcpu->CPSR.bits.I = 1; + armcpu->next_instruction = armcpu->intVector + 0xC; + armcpu->waitIRQ = 0; + +#ifdef GDB_STUB + armcpu->R[15] = armcpu->next_instruction + 8; +#else + armcpu->R[15] = armcpu->next_instruction; + armcpu_prefetch(armcpu); +#endif + + return TRUE; +} + +BOOL +armcpu_flagIrq( armcpu_t *armcpu) { + if(armcpu->CPSR.bits.I) return FALSE; + + armcpu->waitIRQ = 0; + +#ifdef GDB_STUB + armcpu->irq_flag = 1; +#endif + + return TRUE; +} + + +u32 armcpu_exec(armcpu_t *armcpu) +{ + u32 c = 1; + +#ifdef GDB_STUB + if ( armcpu->stalled) + return STALLED_CYCLE_COUNT; + + /* check for interrupts */ + if ( armcpu->irq_flag) { + armcpu_irqExeption( armcpu); + } + + c = armcpu_prefetch(armcpu); + + if ( armcpu->stalled) { + return c; + } +#endif + + if(armcpu->CPSR.bits.T == 0) + { +/* if((TEST_COND(CONDITION(armcpu->instruction), armcpu->CPSR)) || ((CONDITION(armcpu->instruction)==0xF)&&(CODE(armcpu->instruction)==0x5)))*/ + if((TEST_COND(CONDITION(armcpu->instruction), CODE(armcpu->instruction), armcpu->CPSR))) + { + c += arm_instructions_set[INSTRUCTION_INDEX(armcpu->instruction)](armcpu); + } +#ifdef GDB_STUB + if ( armcpu->post_ex_fn != NULL) { + /* call the external post execute function */ + armcpu->post_ex_fn( armcpu->post_ex_fn_data, + armcpu->instruct_adr, 0); + } +#else + c += armcpu_prefetch(armcpu); +#endif + return c; + } + + c += thumb_instructions_set[armcpu->instruction>>6](armcpu); + +#ifdef GDB_STUB + if ( armcpu->post_ex_fn != NULL) { + /* call the external post execute function */ + armcpu->post_ex_fn( armcpu->post_ex_fn_data, armcpu->instruct_adr, 1); + } +#else + c += armcpu_prefetch(armcpu); +#endif + return c; +} + diff --git a/tools/vio2sf/src/vio2sf/desmume/armcpu.h b/tools/vio2sf/src/vio2sf/desmume/armcpu.h new file mode 100644 index 000000000..733716f64 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/armcpu.h @@ -0,0 +1,288 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef ARM_CPU +#define ARM_CPU + +#include "types.h" +#include "bits.h" +#include "MMU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARMCPU_ARM7 1 +#define ARMCPU_ARM9 0 + +#define CODE(i) (((i)>>25)&0X7) +#define OPCODE(i) (((i)>>21)&0xF) +#define SIGNEBIT(i) BIT_N(i,20) + +#define INSTRUCTION_INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF)) + +#define ROR(i, j) ((((u32)(i))>>(j)) | (((u32)(i))<<(32-(j)))) + +#define UNSIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)) | \ + ((BIT31(a)|BIT31(b))&BIT31(~c))) + +#define UNSIGNED_UNDERFLOW(a,b,c) ((BIT31(~a)&BIT31(b)) | \ + ((BIT31(~a)|BIT31(b))&BIT31(c))) + +#define SIGNED_OVERFLOW(a,b,c) ((BIT31(a)&BIT31(b)&BIT31(~c))|\ + (BIT31(~a)&BIT31(~(b))&BIT31(c))) + +#define SIGNED_UNDERFLOW(a,b,c) ((BIT31(a)&BIT31(~(b))&BIT31(~c))|\ + (BIT31(~a)&BIT31(b)&BIT31(c))) + +#define EQ 0x0 +#define NE 0x1 +#define CS 0x2 +#define CC 0x3 +#define MI 0x4 +#define PL 0x5 +#define VS 0x6 +#define VC 0x7 +#define HI 0x8 +#define LS 0x9 +#define GE 0xA +#define LT 0xB +#define GT 0xC +#define LE 0xD +#define AL 0xE + +/* +#define TEST_COND(cond, CPSR) (((cond)==AL) ||\ + (((cond)==EQ) && ( CPSR.bits.Z))||\ + (((cond)==NE) && (!CPSR.bits.Z))||\ + (((cond)==CS) && ( CPSR.bits.C))||\ + (((cond)==CC) && (!CPSR.bits.C))||\ + (((cond)==MI) && ( CPSR.bits.N))||\ + (((cond)==PL) && (!CPSR.bits.N))||\ + (((cond)==VS) && ( CPSR.bits.V))||\ + (((cond)==VC) && (!CPSR.bits.V))||\ + (((cond)==HI) && (CPSR.bits.C) && (!CPSR.bits.Z))||\ + (((cond)==LS) && ((CPSR.bits.Z) || (!CPSR.bits.C)))||\ + (((cond)==GE) && (CPSR.bits.N==CPSR.bits.V))||\ + (((cond)==LT) && (CPSR.bits.N!=CPSR.bits.V))||\ + (((cond)==GT) && (CPSR.bits.Z==0) && (CPSR.bits.N==CPSR.bits.V))||\ + (((cond)==LE) && ((CPSR.bits.Z) || (CPSR.bits.N!=CPSR.bits.V)))) +*/ + +extern const unsigned char arm_cond_table[16*16]; + +#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)+(cond)] >> (inst)) & 1) + + +enum Mode +{ + USR = 0x10, + FIQ = 0x11, + IRQ = 0x12, + SVC = 0x13, + ABT = 0x17, + UND = 0x1B, + SYS = 0x1F +}; + +#ifdef WORDS_BIGENDIAN +typedef union +{ + struct + { + u32 N : 1, + Z : 1, + C : 1, + V : 1, + Q : 1, + RAZ : 19, + I : 1, + F : 1, + T : 1, + mode : 5; + } bits; + u32 val; +} Status_Reg; +#else +typedef union +{ + struct + { + u32 mode : 5, + T : 1, + F : 1, + I : 1, + RAZ : 19, + Q : 1, + V : 1, + C : 1, + Z : 1, + N : 1; + } bits; + u32 val; +} Status_Reg; +#endif + +/** + * The control interface to a CPU + */ +struct armcpu_ctrl_iface { + /** stall the processor */ + void (*stall)( void *instance); + + /** unstall the processor */ + void (*unstall)( void *instance); + + /** read a register value */ + u32 (*read_reg)( void *instance, u32 reg_num); + + /** set a register value */ + void (*set_reg)( void *instance, u32 reg_num, u32 value); + + /** install the post execute function */ + void (*install_post_ex_fn)( void *instance, + void (*fn)( void *, u32 adr, int thumb), + void *fn_data); + + /** remove the post execute function */ + void (*remove_post_ex_fn)( void *instance); + + /** the private data passed to all interface functions */ + void *data; +}; + + +typedef void* armcp_t; + +typedef struct armcpu_t +{ + u32 proc_ID; + u32 instruction; //4 + u32 instruct_adr; //8 + u32 next_instruction; //12 + + u32 R[16]; //16 + Status_Reg CPSR; //80 + Status_Reg SPSR; + + u32 R13_usr, R14_usr; + u32 R13_svc, R14_svc; + u32 R13_abt, R14_abt; + u32 R13_und, R14_und; + u32 R13_irq, R14_irq; + u32 R8_fiq, R9_fiq, R10_fiq, R11_fiq, R12_fiq, R13_fiq, R14_fiq; + Status_Reg SPSR_svc, SPSR_abt, SPSR_und, SPSR_irq, SPSR_fiq; + + armcp_t *coproc[16]; + + u32 intVector; + u8 LDTBit; //1 : ARMv5 style 0 : non ARMv5 + BOOL waitIRQ; + BOOL wIRQ; + BOOL wirq; + + u32 (* *swi_tab)(struct armcpu_t * cpu); + +#ifdef GDB_STUB + /** there is a pending irq for the cpu */ + int irq_flag; + + /** the post executed function (if installed) */ + void (*post_ex_fn)( void *, u32 adr, int thumb); + + /** data for the post executed function */ + void *post_ex_fn_data; + + + /** flag indicating if the processor is stalled */ + int stalled; + + /** the memory interface */ + struct armcpu_memory_iface *mem_if; + + /** the ctrl interface */ + struct armcpu_ctrl_iface ctrl_iface; +#endif +} armcpu_t; + +#ifdef GDB_STUB +int armcpu_new( armcpu_t *armcpu, u32 id, struct armcpu_memory_iface *mem_if, + struct armcpu_ctrl_iface **ctrl_iface_ret); +#else +int armcpu_new( armcpu_t *armcpu, u32 id); +#endif +void armcpu_init(armcpu_t *armcpu, u32 adr); +u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode); +static u32 armcpu_prefetch(armcpu_t *armcpu); +u32 armcpu_exec(armcpu_t *armcpu); +BOOL armcpu_irqExeption(armcpu_t *armcpu); +//BOOL armcpu_prefetchExeption(armcpu_t *armcpu); +BOOL +armcpu_flagIrq( armcpu_t *armcpu); + +extern armcpu_t NDS_ARM7; +extern armcpu_t NDS_ARM9; + +static INLINE void NDS_makeARM9Int(u32 num) +{ + /* flag the interrupt request source */ + MMU.reg_IF[0] |= (1< +#include "MMU.h" +#include "spu_exports.h" +#include "debug.h" + +extern BOOL execute; + +static u16 getsinetbl[] = { +0x0000, 0x0324, 0x0648, 0x096A, 0x0C8C, 0x0FAB, 0x12C8, 0x15E2, +0x18F9, 0x1C0B, 0x1F1A, 0x2223, 0x2528, 0x2826, 0x2B1F, 0x2E11, +0x30FB, 0x33DF, 0x36BA, 0x398C, 0x3C56, 0x3F17, 0x41CE, 0x447A, +0x471C, 0x49B4, 0x4C3F, 0x4EBF, 0x5133, 0x539B, 0x55F5, 0x5842, +0x5A82, 0x5CB3, 0x5ED7, 0x60EB, 0x62F1, 0x64E8, 0x66CF, 0x68A6, +0x6A6D, 0x6C23, 0x6DC9, 0x6F5E, 0x70E2, 0x7254, 0x73B5, 0x7504, +0x7641, 0x776B, 0x7884, 0x7989, 0x7A7C, 0x7B5C, 0x7C29, 0x7CE3, +0x7D89, 0x7E1D, 0x7E9C, 0x7F09, 0x7F61, 0x7FA6, 0x7FD8, 0x7FF5 +}; + +static u16 getpitchtbl[] = { +0x0000, 0x003B, 0x0076, 0x00B2, 0x00ED, 0x0128, 0x0164, 0x019F, +0x01DB, 0x0217, 0x0252, 0x028E, 0x02CA, 0x0305, 0x0341, 0x037D, +0x03B9, 0x03F5, 0x0431, 0x046E, 0x04AA, 0x04E6, 0x0522, 0x055F, +0x059B, 0x05D8, 0x0614, 0x0651, 0x068D, 0x06CA, 0x0707, 0x0743, +0x0780, 0x07BD, 0x07FA, 0x0837, 0x0874, 0x08B1, 0x08EF, 0x092C, +0x0969, 0x09A7, 0x09E4, 0x0A21, 0x0A5F, 0x0A9C, 0x0ADA, 0x0B18, +0x0B56, 0x0B93, 0x0BD1, 0x0C0F, 0x0C4D, 0x0C8B, 0x0CC9, 0x0D07, +0x0D45, 0x0D84, 0x0DC2, 0x0E00, 0x0E3F, 0x0E7D, 0x0EBC, 0x0EFA, +0x0F39, 0x0F78, 0x0FB6, 0x0FF5, 0x1034, 0x1073, 0x10B2, 0x10F1, +0x1130, 0x116F, 0x11AE, 0x11EE, 0x122D, 0x126C, 0x12AC, 0x12EB, +0x132B, 0x136B, 0x13AA, 0x13EA, 0x142A, 0x146A, 0x14A9, 0x14E9, +0x1529, 0x1569, 0x15AA, 0x15EA, 0x162A, 0x166A, 0x16AB, 0x16EB, +0x172C, 0x176C, 0x17AD, 0x17ED, 0x182E, 0x186F, 0x18B0, 0x18F0, +0x1931, 0x1972, 0x19B3, 0x19F5, 0x1A36, 0x1A77, 0x1AB8, 0x1AFA, +0x1B3B, 0x1B7D, 0x1BBE, 0x1C00, 0x1C41, 0x1C83, 0x1CC5, 0x1D07, +0x1D48, 0x1D8A, 0x1DCC, 0x1E0E, 0x1E51, 0x1E93, 0x1ED5, 0x1F17, +0x1F5A, 0x1F9C, 0x1FDF, 0x2021, 0x2064, 0x20A6, 0x20E9, 0x212C, +0x216F, 0x21B2, 0x21F5, 0x2238, 0x227B, 0x22BE, 0x2301, 0x2344, +0x2388, 0x23CB, 0x240E, 0x2452, 0x2496, 0x24D9, 0x251D, 0x2561, +0x25A4, 0x25E8, 0x262C, 0x2670, 0x26B4, 0x26F8, 0x273D, 0x2781, +0x27C5, 0x280A, 0x284E, 0x2892, 0x28D7, 0x291C, 0x2960, 0x29A5, +0x29EA, 0x2A2F, 0x2A74, 0x2AB9, 0x2AFE, 0x2B43, 0x2B88, 0x2BCD, +0x2C13, 0x2C58, 0x2C9D, 0x2CE3, 0x2D28, 0x2D6E, 0x2DB4, 0x2DF9, +0x2E3F, 0x2E85, 0x2ECB, 0x2F11, 0x2F57, 0x2F9D, 0x2FE3, 0x302A, +0x3070, 0x30B6, 0x30FD, 0x3143, 0x318A, 0x31D0, 0x3217, 0x325E, +0x32A5, 0x32EC, 0x3332, 0x3379, 0x33C1, 0x3408, 0x344F, 0x3496, +0x34DD, 0x3525, 0x356C, 0x35B4, 0x35FB, 0x3643, 0x368B, 0x36D3, +0x371A, 0x3762, 0x37AA, 0x37F2, 0x383A, 0x3883, 0x38CB, 0x3913, +0x395C, 0x39A4, 0x39ED, 0x3A35, 0x3A7E, 0x3AC6, 0x3B0F, 0x3B58, +0x3BA1, 0x3BEA, 0x3C33, 0x3C7C, 0x3CC5, 0x3D0E, 0x3D58, 0x3DA1, +0x3DEA, 0x3E34, 0x3E7D, 0x3EC7, 0x3F11, 0x3F5A, 0x3FA4, 0x3FEE, +0x4038, 0x4082, 0x40CC, 0x4116, 0x4161, 0x41AB, 0x41F5, 0x4240, +0x428A, 0x42D5, 0x431F, 0x436A, 0x43B5, 0x4400, 0x444B, 0x4495, +0x44E1, 0x452C, 0x4577, 0x45C2, 0x460D, 0x4659, 0x46A4, 0x46F0, +0x473B, 0x4787, 0x47D3, 0x481E, 0x486A, 0x48B6, 0x4902, 0x494E, +0x499A, 0x49E6, 0x4A33, 0x4A7F, 0x4ACB, 0x4B18, 0x4B64, 0x4BB1, +0x4BFE, 0x4C4A, 0x4C97, 0x4CE4, 0x4D31, 0x4D7E, 0x4DCB, 0x4E18, +0x4E66, 0x4EB3, 0x4F00, 0x4F4E, 0x4F9B, 0x4FE9, 0x5036, 0x5084, +0x50D2, 0x5120, 0x516E, 0x51BC, 0x520A, 0x5258, 0x52A6, 0x52F4, +0x5343, 0x5391, 0x53E0, 0x542E, 0x547D, 0x54CC, 0x551A, 0x5569, +0x55B8, 0x5607, 0x5656, 0x56A5, 0x56F4, 0x5744, 0x5793, 0x57E2, +0x5832, 0x5882, 0x58D1, 0x5921, 0x5971, 0x59C1, 0x5A10, 0x5A60, +0x5AB0, 0x5B01, 0x5B51, 0x5BA1, 0x5BF1, 0x5C42, 0x5C92, 0x5CE3, +0x5D34, 0x5D84, 0x5DD5, 0x5E26, 0x5E77, 0x5EC8, 0x5F19, 0x5F6A, +0x5FBB, 0x600D, 0x605E, 0x60B0, 0x6101, 0x6153, 0x61A4, 0x61F6, +0x6248, 0x629A, 0x62EC, 0x633E, 0x6390, 0x63E2, 0x6434, 0x6487, +0x64D9, 0x652C, 0x657E, 0x65D1, 0x6624, 0x6676, 0x66C9, 0x671C, +0x676F, 0x67C2, 0x6815, 0x6869, 0x68BC, 0x690F, 0x6963, 0x69B6, +0x6A0A, 0x6A5E, 0x6AB1, 0x6B05, 0x6B59, 0x6BAD, 0x6C01, 0x6C55, +0x6CAA, 0x6CFE, 0x6D52, 0x6DA7, 0x6DFB, 0x6E50, 0x6EA4, 0x6EF9, +0x6F4E, 0x6FA3, 0x6FF8, 0x704D, 0x70A2, 0x70F7, 0x714D, 0x71A2, +0x71F7, 0x724D, 0x72A2, 0x72F8, 0x734E, 0x73A4, 0x73FA, 0x7450, +0x74A6, 0x74FC, 0x7552, 0x75A8, 0x75FF, 0x7655, 0x76AC, 0x7702, +0x7759, 0x77B0, 0x7807, 0x785E, 0x78B4, 0x790C, 0x7963, 0x79BA, +0x7A11, 0x7A69, 0x7AC0, 0x7B18, 0x7B6F, 0x7BC7, 0x7C1F, 0x7C77, +0x7CCF, 0x7D27, 0x7D7F, 0x7DD7, 0x7E2F, 0x7E88, 0x7EE0, 0x7F38, +0x7F91, 0x7FEA, 0x8042, 0x809B, 0x80F4, 0x814D, 0x81A6, 0x81FF, +0x8259, 0x82B2, 0x830B, 0x8365, 0x83BE, 0x8418, 0x8472, 0x84CB, +0x8525, 0x857F, 0x85D9, 0x8633, 0x868E, 0x86E8, 0x8742, 0x879D, +0x87F7, 0x8852, 0x88AC, 0x8907, 0x8962, 0x89BD, 0x8A18, 0x8A73, +0x8ACE, 0x8B2A, 0x8B85, 0x8BE0, 0x8C3C, 0x8C97, 0x8CF3, 0x8D4F, +0x8DAB, 0x8E07, 0x8E63, 0x8EBF, 0x8F1B, 0x8F77, 0x8FD4, 0x9030, +0x908C, 0x90E9, 0x9146, 0x91A2, 0x91FF, 0x925C, 0x92B9, 0x9316, +0x9373, 0x93D1, 0x942E, 0x948C, 0x94E9, 0x9547, 0x95A4, 0x9602, +0x9660, 0x96BE, 0x971C, 0x977A, 0x97D8, 0x9836, 0x9895, 0x98F3, +0x9952, 0x99B0, 0x9A0F, 0x9A6E, 0x9ACD, 0x9B2C, 0x9B8B, 0x9BEA, +0x9C49, 0x9CA8, 0x9D08, 0x9D67, 0x9DC7, 0x9E26, 0x9E86, 0x9EE6, +0x9F46, 0x9FA6, 0xA006, 0xA066, 0xA0C6, 0xA127, 0xA187, 0xA1E8, +0xA248, 0xA2A9, 0xA30A, 0xA36B, 0xA3CC, 0xA42D, 0xA48E, 0xA4EF, +0xA550, 0xA5B2, 0xA613, 0xA675, 0xA6D6, 0xA738, 0xA79A, 0xA7FC, +0xA85E, 0xA8C0, 0xA922, 0xA984, 0xA9E7, 0xAA49, 0xAAAC, 0xAB0E, +0xAB71, 0xABD4, 0xAC37, 0xAC9A, 0xACFD, 0xAD60, 0xADC3, 0xAE27, +0xAE8A, 0xAEED, 0xAF51, 0xAFB5, 0xB019, 0xB07C, 0xB0E0, 0xB145, +0xB1A9, 0xB20D, 0xB271, 0xB2D6, 0xB33A, 0xB39F, 0xB403, 0xB468, +0xB4CD, 0xB532, 0xB597, 0xB5FC, 0xB662, 0xB6C7, 0xB72C, 0xB792, +0xB7F7, 0xB85D, 0xB8C3, 0xB929, 0xB98F, 0xB9F5, 0xBA5B, 0xBAC1, +0xBB28, 0xBB8E, 0xBBF5, 0xBC5B, 0xBCC2, 0xBD29, 0xBD90, 0xBDF7, +0xBE5E, 0xBEC5, 0xBF2C, 0xBF94, 0xBFFB, 0xC063, 0xC0CA, 0xC132, +0xC19A, 0xC202, 0xC26A, 0xC2D2, 0xC33A, 0xC3A2, 0xC40B, 0xC473, +0xC4DC, 0xC544, 0xC5AD, 0xC616, 0xC67F, 0xC6E8, 0xC751, 0xC7BB, +0xC824, 0xC88D, 0xC8F7, 0xC960, 0xC9CA, 0xCA34, 0xCA9E, 0xCB08, +0xCB72, 0xCBDC, 0xCC47, 0xCCB1, 0xCD1B, 0xCD86, 0xCDF1, 0xCE5B, +0xCEC6, 0xCF31, 0xCF9C, 0xD008, 0xD073, 0xD0DE, 0xD14A, 0xD1B5, +0xD221, 0xD28D, 0xD2F8, 0xD364, 0xD3D0, 0xD43D, 0xD4A9, 0xD515, +0xD582, 0xD5EE, 0xD65B, 0xD6C7, 0xD734, 0xD7A1, 0xD80E, 0xD87B, +0xD8E9, 0xD956, 0xD9C3, 0xDA31, 0xDA9E, 0xDB0C, 0xDB7A, 0xDBE8, +0xDC56, 0xDCC4, 0xDD32, 0xDDA0, 0xDE0F, 0xDE7D, 0xDEEC, 0xDF5B, +0xDFC9, 0xE038, 0xE0A7, 0xE116, 0xE186, 0xE1F5, 0xE264, 0xE2D4, +0xE343, 0xE3B3, 0xE423, 0xE493, 0xE503, 0xE573, 0xE5E3, 0xE654, +0xE6C4, 0xE735, 0xE7A5, 0xE816, 0xE887, 0xE8F8, 0xE969, 0xE9DA, +0xEA4B, 0xEABC, 0xEB2E, 0xEB9F, 0xEC11, 0xEC83, 0xECF5, 0xED66, +0xEDD9, 0xEE4B, 0xEEBD, 0xEF2F, 0xEFA2, 0xF014, 0xF087, 0xF0FA, +0xF16D, 0xF1E0, 0xF253, 0xF2C6, 0xF339, 0xF3AD, 0xF420, 0xF494, +0xF507, 0xF57B, 0xF5EF, 0xF663, 0xF6D7, 0xF74C, 0xF7C0, 0xF834, +0xF8A9, 0xF91E, 0xF992, 0xFA07, 0xFA7C, 0xFAF1, 0xFB66, 0xFBDC, +0xFC51, 0xFCC7, 0xFD3C, 0xFDB2, 0xFE28, 0xFE9E, 0xFF14, 0xFF8A +}; + +static u8 getvoltbl[] = { +0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, +0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, +0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, +0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, +0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, +0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, +0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, +0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, +0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, +0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, +0x22, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x29, +0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x31, +0x32, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, +0x3C, 0x3C, 0x3D, 0x3E, 0x3F, 0x3F, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45, 0x46, 0x47, +0x48, 0x49, 0x4A, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, +0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, 0x7B, +0x7D, 0x7E, 0x7F, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, +0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, +0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x36, +0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3B, 0x3C, 0x3D, 0x3E, 0x3E, 0x3F, 0x40, 0x40, +0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4D, +0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, +0x5E, 0x5F, 0x60, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x70, +0x71, 0x73, 0x74, 0x75, 0x77, 0x78, 0x79, 0x7B, 0x7C, 0x7E, 0x7E, 0x40, 0x41, 0x42, 0x43, 0x43, +0x44, 0x45, 0x46, 0x47, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, +0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, +0x62, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6E, 0x70, 0x71, 0x72, 0x74, 0x75, +0x76, 0x78, 0x79, 0x7B, 0x7C, 0x7D, 0x7E, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, +0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, +0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x65, 0x66, +0x67, 0x68, 0x69, 0x6A, 0x6C, 0x6D, 0x6E, 0x6F, 0x71, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, +0x7C, 0x7D, 0x7E, 0x7F +}; + +u32 bios_nop(armcpu_t * cpu) +{ + if (cpu->proc_ID == ARMCPU_ARM9) + { + LOG("Unimplemented bios function %02X(ARM9) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]); + } + else + { + LOG("Unimplemented bios function %02X(ARM7) was used. R0:%08X\n", (cpu->instruction)&0x1F, cpu->R[0]); + } + return 3; +} + +u32 delayLoop(armcpu_t * cpu) +{ + return cpu->R[0] * 4; +} + +//u32 oldmode[2]; + +u32 intrWaitARM(armcpu_t * cpu) +{ + u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + u32 intr; + u32 intrFlag = 0; + + //execute = FALSE; + if(cpu->proc_ID) + { + intrFlagAdr = 0x380FFF8; + } else { + intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + } + intr = MMU_read32(cpu->proc_ID, intrFlagAdr); + intrFlag = cpu->R[1] & intr; + + if(intrFlag) + { + // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s) + // on efface son(les) occurence(s). + intr ^= intrFlag; + MMU_write32(cpu->proc_ID, intrFlagAdr, intr); + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + cpu->waitIRQ = 1; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + + return 1; +} + +u32 waitVBlankARM(armcpu_t * cpu) +{ + u32 intrFlagAdr;// = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + u32 intr; + u32 intrFlag = 0; + + //execute = FALSE; + if(cpu->proc_ID) + { + intrFlagAdr = 0x380FFF8; + } else { + intrFlagAdr = (((armcp15_t *)(cpu->coproc[15]))->DTCMRegion&0xFFFFF000)+0x3FF8; + } + intr = MMU_read32(cpu->proc_ID, intrFlagAdr); + intrFlag = 1 & intr; + + if(intrFlag) + { + // si une(ou plusieurs) des interruptions que l'on attend s'est(se sont) produite(s) + // on efface son(les) occurence(s). + intr ^= intrFlag; + MMU_write32(cpu->proc_ID, intrFlagAdr, intr); + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + cpu->waitIRQ = 1; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + + return 1; +} + +u32 wait4IRQ(armcpu_t* cpu) +{ + //execute= FALSE; + if(cpu->wirq) + { + if(!cpu->waitIRQ) + { + cpu->waitIRQ = 0; + cpu->wirq = 0; + //cpu->switchMode(oldmode[cpu->proc_ID]); + return 1; + } + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + return 1; + } + cpu->waitIRQ = 1; + cpu->wirq = 1; + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + //oldmode[cpu->proc_ID] = cpu->switchMode(SVC); + return 1; +} + +u32 devide(armcpu_t* cpu) +{ + s32 num = (s32)cpu->R[0]; + s32 dnum = (s32)cpu->R[1]; + + if(dnum==0) return 0; + + cpu->R[0] = (u32)(num / dnum); + cpu->R[1] = (u32)(num % dnum); + cpu->R[3] = (u32) (((s32)cpu->R[0])<0 ? -cpu->R[0] : cpu->R[0]); + + return 6; +} + +u32 copy(armcpu_t* cpu) +{ + u32 src = cpu->R[0]; + u32 dst = cpu->R[1]; + u32 cnt = cpu->R[2]; + + switch(BIT26(cnt)) + { + case 0: + src &= 0xFFFFFFFE; + dst &= 0xFFFFFFFE; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write16(cpu->proc_ID, dst, MMU_read16(cpu->proc_ID, src)); + cnt--; + dst+=2; + src+=2; + } + break; + case 1: + { + u32 val = MMU_read16(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write16(cpu->proc_ID, dst, val); + cnt--; + dst+=2; + } + } + break; + } + break; + case 1: + src &= 0xFFFFFFFC; + dst &= 0xFFFFFFFC; + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = MMU_read32(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, val); + cnt--; + dst+=4; + } + } + break; + } + break; + } + return 1; +} + +u32 fastCopy(armcpu_t* cpu) +{ + u32 src = cpu->R[0] & 0xFFFFFFFC; + u32 dst = cpu->R[1] & 0xFFFFFFFC; + u32 cnt = cpu->R[2]; + + switch(BIT24(cnt)) + { + case 0: + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, MMU_read32(cpu->proc_ID, src)); + cnt--; + dst+=4; + src+=4; + } + break; + case 1: + { + u32 val = MMU_read32(cpu->proc_ID, src); + cnt &= 0x1FFFFF; + while(cnt) + { + MMU_write32(cpu->proc_ID, dst, val); + cnt--; + dst+=4; + } + } + break; + } + return 1; +} + +u32 LZ77UnCompVram(armcpu_t* cpu) +{ + int i1, i2; + int byteCount; + int byteShift; + u32 writeValue; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + byteCount = 0; + byteShift = 0; + writeValue = 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = MMU_read8(cpu->proc_ID, source++) << 8; + data |= MMU_read8(cpu->proc_ID, source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest + byteCount - offset - 1; + for(i2 = 0; i2 < length; i2++) { + writeValue |= (MMU_read8(cpu->proc_ID, windowOffset++) << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteShift = 0; + byteCount = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 LZ77UnCompWram(armcpu_t* cpu) +{ + int i1, i2; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + + if(d) { + for(i1 = 0; i1 < 8; i1++) { + if(d & 0x80) { + int length; + int offset; + u32 windowOffset; + u16 data = MMU_read8(cpu->proc_ID, source++) << 8; + data |= MMU_read8(cpu->proc_ID, source++); + length = (data >> 12) + 3; + offset = (data & 0x0FFF); + windowOffset = dest - offset - 1; + for(i2 = 0; i2 < length; i2++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, windowOffset++)); + len--; + if(len == 0) + return 0; + } + } else { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + d <<= 1; + } + } else { + for(i1 = 0; i1 < 8; i1++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 RLUnCompVram(armcpu_t* cpu) +{ + int i; + int len; + int byteCount; + int byteShift; + u32 writeValue; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + byteCount = 0; + byteShift = 0; + writeValue = 0; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = MMU_read8(cpu->proc_ID, source++); + l += 3; + for(i = 0;i < l; i++) { + writeValue |= (data << byteShift); + byteShift += 8; + byteCount++; + + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + writeValue |= (MMU_read8(cpu->proc_ID, source++) << byteShift); + byteShift += 8; + byteCount++; + if(byteCount == 2) { + MMU_write16(cpu->proc_ID, dest, writeValue); + dest += 2; + byteCount = 0; + byteShift = 0; + writeValue = 0; + } + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 RLUnCompWram(armcpu_t* cpu) +{ + int i; + int len; + u32 source = cpu->R[0]; + u32 dest = cpu->R[1]; + + u32 header = MMU_read32(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + while(len > 0) { + u8 d = MMU_read8(cpu->proc_ID, source++); + int l = d & 0x7F; + if(d & 0x80) { + u8 data = MMU_read8(cpu->proc_ID, source++); + l += 3; + for(i = 0;i < l; i++) { + MMU_write8(cpu->proc_ID, dest++, data); + len--; + if(len == 0) + return 0; + } + } else { + l++; + for(i = 0; i < l; i++) { + MMU_write8(cpu->proc_ID, dest++, MMU_read8(cpu->proc_ID, source++)); + len--; + if(len == 0) + return 0; + } + } + } + return 1; +} + +u32 UnCompHuffman(armcpu_t* cpu) +{ + u32 source, dest, writeValue, header, treeStart, mask; + u32 data; + u8 treeSize, currentNode, rootNode; + int byteCount, byteShift, len, pos; + int writeData; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + treeSize = MMU_read8(cpu->proc_ID, source++); + + treeStart = source; + + source += ((treeSize+1)<<1)-1; // minus because we already skipped one byte + + len = header >> 8; + + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + + pos = 0; + rootNode = MMU_read8(cpu->proc_ID, treeStart); + currentNode = rootNode; + writeData = 0; + byteShift = 0; + byteCount = 0; + writeValue = 0; + + if((header & 0x0F) == 8) { + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if(data & mask) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos); + } + + if(writeData) { + writeValue |= (currentNode << byteShift); + byteCount++; + byteShift += 8; + + pos = 0; + currentNode = rootNode; + writeData = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + MMU_write8(cpu->proc_ID, dest, writeValue); + writeValue = 0; + dest += 4; + len -= 4; + } + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + } + } + } else { + int halfLen = 0; + int value = 0; + while(len > 0) { + // take left + if(pos == 0) + pos++; + else + pos += (((currentNode & 0x3F)+1)<<1); + + if((data & mask)) { + // right + if(currentNode & 0x40) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos+1); + } else { + // left + if(currentNode & 0x80) + writeData = 1; + currentNode = MMU_read8(cpu->proc_ID, treeStart+pos); + } + + if(writeData) { + if(halfLen == 0) + value |= currentNode; + else + value |= (currentNode<<4); + + halfLen += 4; + if(halfLen == 8) { + writeValue |= (value << byteShift); + byteCount++; + byteShift += 8; + + halfLen = 0; + value = 0; + + if(byteCount == 4) { + byteCount = 0; + byteShift = 0; + MMU_write8(cpu->proc_ID, dest, writeValue); + dest += 4; + writeValue = 0; + len -= 4; + } + } + pos = 0; + currentNode = rootNode; + writeData = 0; + } + mask >>= 1; + if(mask == 0) { + mask = 0x80000000; + data = MMU_read8(cpu->proc_ID, source); + source += 4; + } + } + } + return 1; +} + +u32 BitUnPack(armcpu_t* cpu) +{ + u32 source,dest,header,base,d,temp; + int len,bits,revbits,dataSize,data,bitwritecount,mask,bitcount,addBase; + u8 b; + + source = cpu->R[0]; + dest = cpu->R[1]; + header = cpu->R[2]; + + len = MMU_read16(cpu->proc_ID, header); + // check address + bits = MMU_read8(cpu->proc_ID, header+2); + revbits = 8 - bits; + // u32 value = 0; + base = MMU_read8(cpu->proc_ID, header+4); + addBase = (base & 0x80000000) ? 1 : 0; + base &= 0x7fffffff; + dataSize = MMU_read8(cpu->proc_ID, header+3); + + data = 0; + bitwritecount = 0; + while(1) { + len -= 1; + if(len < 0) + break; + mask = 0xff >> revbits; + b = MMU_read8(cpu->proc_ID, source); + source++; + bitcount = 0; + while(1) { + if(bitcount >= 8) + break; + d = b & mask; + temp = d >> bitcount; + if(!temp && addBase) { + temp += base; + } + data |= temp << bitwritecount; + bitwritecount += dataSize; + if(bitwritecount >= 32) { + MMU_write8(cpu->proc_ID, dest, data); + dest += 4; + data = 0; + bitwritecount = 0; + } + mask <<= bits; + bitcount += bits; + } + } + return 1; +} + +u32 Diff8bitUnFilterWram(armcpu_t* cpu) +{ + u32 source,dest,header; + u8 data,diff; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + (( (source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0)) + return 0; + + len = header >> 8; + + data = MMU_read8(cpu->proc_ID, source++); + MMU_write8(cpu->proc_ID, dest++, data); + len--; + + while(len > 0) { + diff = MMU_read8(cpu->proc_ID, source++); + data += diff; + MMU_write8(cpu->proc_ID, dest++, data); + len--; + } + return 1; +} + +u32 Diff16bitUnFilter(armcpu_t* cpu) +{ + u32 source,dest,header; + u16 data; + int len; + + source = cpu->R[0]; + dest = cpu->R[1]; + + header = MMU_read8(cpu->proc_ID, source); + source += 4; + + if(((source & 0xe000000) == 0) || + ((source + ((header >> 8) & 0x1fffff)) & 0xe000000) == 0) + return 0; + + len = header >> 8; + + data = MMU_read16(cpu->proc_ID, source); + source += 2; + MMU_write16(cpu->proc_ID, dest, data); + dest += 2; + len -= 2; + + while(len >= 2) { + u16 diff = MMU_read16(cpu->proc_ID, source); + source += 2; + data += diff; + MMU_write16(cpu->proc_ID, dest, data); + dest += 2; + len -= 2; + } + return 1; +} + +u32 bios_sqrt(armcpu_t* cpu) +{ + cpu->R[0] = (u32)sqrt((double)(cpu->R[0])); + return 1; +} + +u32 setHaltCR(armcpu_t* cpu) +{ + MMU_write8(cpu->proc_ID, 0x4000300+cpu->proc_ID, cpu->R[0]); + return 1; +} + +u32 getSineTab(armcpu_t* cpu) +{ + cpu->R[0] = getsinetbl[cpu->R[0]]; + return 1; +} + +u32 getPitchTab(armcpu_t* cpu) +{ + cpu->R[0] = getpitchtbl[cpu->R[0]]; + return 1; +} + +u32 getVolumeTab(armcpu_t* cpu) +{ + cpu->R[0] = getvoltbl[cpu->R[0]]; + return 1; +} + +u32 getCRC16(armcpu_t* cpu) +{ + unsigned int i,j; + + u32 crc = cpu->R[0]; + u32 datap = cpu->R[1]; + u32 size = cpu->R[2]; + + static u16 val[] = { 0xC0C1,0xC181,0xC301,0xC601,0xCC01,0xD801,0xF001,0xA001 }; + for(i = 0; i < size; i++) + { + crc = crc ^ MMU_read8( cpu->proc_ID, datap + i); + + for(j = 0; j < 8; j++) { + int do_bit = 0; + + if ( crc & 0x1) + do_bit = 1; + + crc = crc >> 1; + + if ( do_bit) { + crc = crc ^ (val[j] << (7-j)); + } + } + } + cpu->R[0] = crc; + return 1; +} + +u32 SoundBias(armcpu_t* cpu) +{ + // u32 current = SPU_ReadLong(0x4000504); + // if (cpu->R[0] > current) + //SPU_WriteLong(0x4000504, current + 0x1); + // else + //SPU_WriteLong(0x4000504, current - 0x1); + // return cpu->R[1]; + + u32 curBias = MMU_read32(ARMCPU_ARM7,0x04000504); + u32 newBias = (curBias == 0) ? 0x000:0x200; + u32 delay = (newBias > curBias) ? (newBias-curBias) : (curBias-newBias); + + MMU_write32(ARMCPU_ARM7,0x04000504, newBias); + return cpu->R[1] * delay; +} + +u32 (* ARM9_swi_tab[32])(armcpu_t* cpu)={ + bios_nop, // 0x00 + bios_nop, // 0x01 + bios_nop, // 0x02 + delayLoop, // 0x03 + intrWaitARM, // 0x04 + waitVBlankARM, // 0x05 + wait4IRQ, // 0x06 + bios_nop, // 0x07 + bios_nop, // 0x08 + devide, // 0x09 + bios_nop, // 0x0A + copy, // 0x0B + fastCopy, // 0x0C + bios_sqrt, // 0x0D + getCRC16, // 0x0E + bios_nop, // 0x0F + BitUnPack, // 0x10 + LZ77UnCompWram, // 0x11 + LZ77UnCompVram, // 0x12 + UnCompHuffman, // 0x13 + RLUnCompWram, // 0x14 + RLUnCompVram, // 0x15 + Diff8bitUnFilterWram, // 0x16 + bios_nop, // 0x17 + Diff16bitUnFilter, // 0x18 + bios_nop, // 0x19 + bios_nop, // 0x1A + bios_nop, // 0x1B + bios_nop, // 0x1C + bios_nop, // 0x1D + bios_nop, // 0x1E + setHaltCR, // 0x1F +}; + +u32 (* ARM7_swi_tab[32])(armcpu_t* cpu)={ + bios_nop, // 0x00 + bios_nop, // 0x01 + bios_nop, // 0x02 + delayLoop, // 0x03 + intrWaitARM, // 0x04 + waitVBlankARM, // 0x05 + wait4IRQ, // 0x06 + wait4IRQ, // 0x07 + SoundBias, // 0x08 + devide, // 0x09 + bios_nop, // 0x0A + copy, // 0x0B + fastCopy, // 0x0C + bios_sqrt, // 0x0D + getCRC16, // 0x0E + bios_nop, // 0x0F + BitUnPack, // 0x10 + LZ77UnCompWram, // 0x11 + LZ77UnCompVram, // 0x12 + UnCompHuffman, // 0x13 + RLUnCompWram, // 0x14 + RLUnCompVram, // 0x15 + Diff8bitUnFilterWram, // 0x16 + bios_nop, // 0x17 + bios_nop, // 0x18 + bios_nop, // 0x19 + getSineTab, // 0x1A + getPitchTab, // 0x1B + getVolumeTab, // 0x1C + bios_nop, // 0x1D + bios_nop, // 0x1E + setHaltCR, // 0x1F +}; diff --git a/tools/vio2sf/src/vio2sf/desmume/bios.h b/tools/vio2sf/src/vio2sf/desmume/bios.h new file mode 100644 index 000000000..7f717cb8c --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/bios.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef BIOS_H +#define BIOS_H + +#include "armcpu.h" + +extern u32 (* ARM9_swi_tab[32])(armcpu_t * cpu); +extern u32 (* ARM7_swi_tab[32])(armcpu_t * cpu); +extern u32 wait4IRQ(armcpu_t * cpu); + +#endif + diff --git a/tools/vio2sf/src/vio2sf/desmume/bits.h b/tools/vio2sf/src/vio2sf/desmume/bits.h new file mode 100644 index 000000000..be64f65d7 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/bits.h @@ -0,0 +1,44 @@ +#ifndef BITS_H +#define BITS_H + +#define BIT(n) (1<<(n)) + +#define BIT_N(i,n) (((i)>>(n))&1) +#define BIT0(i) ((i)&1) +#define BIT1(i) BIT_N(i,1) +#define BIT2(i) BIT_N(i,2) +#define BIT3(i) BIT_N(i,3) +#define BIT4(i) BIT_N(i,4) +#define BIT5(i) BIT_N(i,5) +#define BIT6(i) BIT_N(i,6) +#define BIT7(i) BIT_N(i,7) +#define BIT8(i) BIT_N(i,8) +#define BIT9(i) BIT_N(i,9) +#define BIT10(i) BIT_N(i,10) +#define BIT11(i) BIT_N(i,11) +#define BIT12(i) BIT_N(i,12) +#define BIT13(i) BIT_N(i,13) +#define BIT14(i) BIT_N(i,14) +#define BIT15(i) BIT_N(i,15) +#define BIT16(i) BIT_N(i,16) +#define BIT17(i) BIT_N(i,17) +#define BIT18(i) BIT_N(i,18) +#define BIT19(i) BIT_N(i,19) +#define BIT20(i) BIT_N(i,20) +#define BIT21(i) BIT_N(i,21) +#define BIT22(i) BIT_N(i,22) +#define BIT23(i) BIT_N(i,23) +#define BIT24(i) BIT_N(i,24) +#define BIT25(i) BIT_N(i,25) +#define BIT26(i) BIT_N(i,26) +#define BIT27(i) BIT_N(i,27) +#define BIT28(i) BIT_N(i,28) +#define BIT29(i) BIT_N(i,29) +#define BIT30(i) BIT_N(i,30) +#define BIT31(i) ((i)>>31) + +#define CONDITION(i) (i)>>28 + +#define REG_POS(i,n) (((i)>>n)&0xF) + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/config.h b/tools/vio2sf/src/vio2sf/desmume/config.h new file mode 100644 index 000000000..2f2f707ee --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/config.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 thoduv + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include + +#include "debug.h" + +#endif /*__CONFIG_H__*/ + diff --git a/tools/vio2sf/src/vio2sf/desmume/cp15.c b/tools/vio2sf/src/vio2sf/desmume/cp15.c new file mode 100644 index 000000000..d8ff7b071 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/cp15.c @@ -0,0 +1,590 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include "cp15.h" +#include "debug.h" +#include "MMU.h" + +armcp15_t *armcp15_new(armcpu_t * c) +{ + int i; + armcp15_t *armcp15 = (armcp15_t*)malloc(sizeof(armcp15_t)); + if(!armcp15) return NULL; + + armcp15->cpu = c; + armcp15->IDCode = 0x41049460; + armcp15->cacheType = 0x0F0D2112; + armcp15->TCMSize = 0x00140140; + armcp15->ctrl = 0x00000000; + armcp15->DCConfig = 0x0; + armcp15->ICConfig = 0x0; + armcp15->writeBuffCtrl = 0x0; + armcp15->und = 0x0; + armcp15->DaccessPerm = 0x22222222; + armcp15->IaccessPerm = 0x22222222; + armcp15->protectBaseSize0 = 0x0; + armcp15->protectBaseSize1 = 0x0; + armcp15->protectBaseSize2 = 0x0; + armcp15->protectBaseSize3 = 0x0; + armcp15->protectBaseSize4 = 0x0; + armcp15->protectBaseSize5 = 0x0; + armcp15->protectBaseSize6 = 0x0; + armcp15->protectBaseSize7 = 0x0; + armcp15->cacheOp = 0x0; + armcp15->DcacheLock = 0x0; + armcp15->IcacheLock = 0x0; + armcp15->ITCMRegion = 0x0C; + armcp15->DTCMRegion = 0x0080000A; + armcp15->processID = 0; + + /* preset calculated regionmasks */ + for (i=0;i<8;i++) { + armcp15->regionWriteMask_USR[i] = 0 ; + armcp15->regionWriteMask_SYS[i] = 0 ; + armcp15->regionReadMask_USR[i] = 0 ; + armcp15->regionReadMask_SYS[i] = 0 ; + armcp15->regionExecuteMask_USR[i] = 0 ; + armcp15->regionExecuteMask_SYS[i] = 0 ; + armcp15->regionWriteSet_USR[i] = 0 ; + armcp15->regionWriteSet_SYS[i] = 0 ; + armcp15->regionReadSet_USR[i] = 0 ; + armcp15->regionReadSet_SYS[i] = 0 ; + armcp15->regionExecuteSet_USR[i] = 0 ; + armcp15->regionExecuteSet_SYS[i] = 0 ; + } ; + + return armcp15; +} + +#define ACCESSTYPE(val,n) (((val) >> (4*n)) & 0x0F) +#define SIZEIDENTIFIER(val) ((((val) >> 1) & 0x1F)) +#define SIZEBINARY(val) (1 << (SIZEIDENTIFIER(val)+1)) +#define MASKFROMREG(val) (~((SIZEBINARY(val)-1) | 0x3F)) +#define SETFROMREG(val) ((val) & MASKFROMREG(val)) +/* sets the precalculated regions to mask,set for the affected accesstypes */ +void armcp15_setSingleRegionAccess(armcp15_t *armcp15,unsigned long dAccess,unsigned long iAccess,unsigned char num, unsigned long mask,unsigned long set) { + + switch (ACCESSTYPE(dAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = 0 ; + armcp15->regionReadSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: /* no access at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 2: /* read at USR, all to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 3: /* all to USR, all to sys */ + armcp15->regionWriteMask_USR[num] = mask ; + armcp15->regionWriteSet_USR[num] = set ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = mask ; + armcp15->regionWriteSet_SYS[num] = set ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 5: /* no access at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = 0 ; + armcp15->regionReadSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + case 6: /* read at USR, read to sys */ + armcp15->regionWriteMask_USR[num] = 0 ; + armcp15->regionWriteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_USR[num] = mask ; + armcp15->regionReadSet_USR[num] = set ; + armcp15->regionWriteMask_SYS[num] = 0 ; + armcp15->regionWriteSet_SYS[num] = 0xFFFFFFFF ; + armcp15->regionReadMask_SYS[num] = mask ; + armcp15->regionReadSet_SYS[num] = set ; + break ; + } + switch (ACCESSTYPE(iAccess,num)) { + case 4: /* UNP */ + case 7: /* UNP */ + case 8: /* UNP */ + case 9: /* UNP */ + case 10: /* UNP */ + case 11: /* UNP */ + case 12: /* UNP */ + case 13: /* UNP */ + case 14: /* UNP */ + case 15: /* UNP */ + case 0: /* no access at all */ + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = 0 ; + armcp15->regionExecuteSet_SYS[num] = 0xFFFFFFFF ; + break ; + case 1: + armcp15->regionExecuteMask_USR[num] = 0 ; + armcp15->regionExecuteSet_USR[num] = 0xFFFFFFFF ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + case 2: + case 3: + case 6: + armcp15->regionExecuteMask_USR[num] = mask ; + armcp15->regionExecuteSet_USR[num] = set ; + armcp15->regionExecuteMask_SYS[num] = mask ; + armcp15->regionExecuteSet_SYS[num] = set ; + break ; + } +} ; + +/* precalculate region masks/sets from cp15 register */ +void armcp15_maskPrecalc(armcp15_t *armcp15) +{ + #define precalc(num) { \ + u32 mask = 0, set = 0xFFFFFFFF ; /* (x & 0) == 0xFF..FF is allways false (disabled) */ \ + if (BIT_N(armcp15->protectBaseSize##num,0)) /* if region is enabled */ \ + { /* reason for this define: naming includes var */ \ + mask = MASKFROMREG(armcp15->protectBaseSize##num) ; \ + set = SETFROMREG(armcp15->protectBaseSize##num) ; \ + if (SIZEIDENTIFIER(armcp15->protectBaseSize##num)==0x1F) \ + { /* for the 4GB region, u32 suffers wraparound */ \ + mask = 0 ; set = 0 ; /* (x & 0) == 0 is allways true (enabled) */ \ + } \ + } \ + armcp15_setSingleRegionAccess(armcp15,armcp15->DaccessPerm,armcp15->IaccessPerm,num,mask,set) ; \ + } + precalc(0) ; + precalc(1) ; + precalc(2) ; + precalc(3) ; + precalc(4) ; + precalc(5) ; + precalc(6) ; + precalc(7) ; +} + +INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) +{ + int i ; + if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */ + for (i=0;i<8;i++) { + switch (access) { + case CP15_ACCESS_WRITEUSR: + if ((address & armcp15->regionWriteMask_USR[i]) == armcp15->regionWriteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_WRITESYS: + if ((address & armcp15->regionWriteMask_SYS[i]) == armcp15->regionWriteSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_READUSR: + if ((address & armcp15->regionReadMask_USR[i]) == armcp15->regionReadSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_READSYS: + if ((address & armcp15->regionReadMask_SYS[i]) == armcp15->regionReadSet_SYS[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECUSR: + if ((address & armcp15->regionExecuteMask_USR[i]) == armcp15->regionExecuteSet_USR[i]) return TRUE ; + break ; + case CP15_ACCESS_EXECSYS: + if ((address & armcp15->regionExecuteMask_SYS[i]) == armcp15->regionExecuteSet_SYS[i]) return TRUE ; + break ; + } + } + /* when protections are enabled, but no region allows access, deny access */ + return FALSE ; +} + +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + return FALSE; +} + +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + return FALSE; +} + +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr) +{ + return FALSE; +} + +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 0 : + if((opcode1 == 0)&&(CRm==0)) + { + switch(opcode2) + { + case 1 : + *R = armcp15->cacheType; + return TRUE; + case 2 : + *R = armcp15->TCMSize; + return TRUE; + default : + *R = armcp15->IDCode; + return TRUE; + } + } + return FALSE; + case 1 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->ctrl; + return TRUE; + } + return FALSE; + + case 2 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0 : + *R = armcp15->DCConfig; + return TRUE; + case 1 : + *R = armcp15->ICConfig; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 3 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + *R = armcp15->writeBuffCtrl; + return TRUE; + } + return FALSE; + case 5 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2 : + *R = armcp15->DaccessPerm; + return TRUE; + case 3 : + *R = armcp15->IaccessPerm; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 6 : + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0 : + *R = armcp15->protectBaseSize0; + return TRUE; + case 1 : + *R = armcp15->protectBaseSize1; + return TRUE; + case 2 : + *R = armcp15->protectBaseSize2; + return TRUE; + case 3 : + *R = armcp15->protectBaseSize3; + return TRUE; + case 4 : + *R = armcp15->protectBaseSize4; + return TRUE; + case 5 : + *R = armcp15->protectBaseSize5; + return TRUE; + case 6 : + *R = armcp15->protectBaseSize6; + return TRUE; + case 7 : + *R = armcp15->protectBaseSize7; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 9 : + if((opcode1==0)) + { + switch(CRm) + { + case 0 : + switch(opcode2) + { + case 0 : + *R = armcp15->DcacheLock; + return TRUE; + case 1 : + *R = armcp15->IcacheLock; + return TRUE; + default : + return FALSE; + } + case 1 : + switch(opcode2) + { + case 0 : + *R = armcp15->DTCMRegion; + return TRUE; + case 1 : + *R = armcp15->ITCMRegion; + return TRUE; + default : + return FALSE; + } + } + } + return FALSE; + default : + return FALSE; + } +} + + +u32 CP15wait4IRQ(armcpu_t *cpu) +{ + /* on the first call, wirq is not set */ + if(cpu->wirq) + { + /* check wether an irq was issued */ + if(!cpu->waitIRQ) + { + cpu->waitIRQ = 0; + cpu->wirq = 0; + return 1; /* return execution */ + } + /* otherwise, repeat this instruction */ + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + return 1; + } + /* first run, set us into waiting state */ + cpu->waitIRQ = 1; + cpu->wirq = 1; + /* and set next instruction to repeat this */ + cpu->R[15] = cpu->instruct_adr; + cpu->next_instruction = cpu->R[15]; + /* CHECKME: IME shouldn't be modified (?) */ + MMU.reg_IME[0] = 1; + return 1; +} + +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2) +{ + if(armcp15->cpu->CPSR.bits.mode == USR) return FALSE; + + switch(CRn) + { + case 1 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + armcp15->ctrl = val; + MMU.ARM9_RW_MODE = BIT7(val); + armcp15->cpu->intVector = 0x0FFF0000 * (BIT13(val)); + armcp15->cpu->LDTBit = !BIT15(val); //TBit + /*if(BIT17(val)) + { + log::ajouter("outch !!!!!!!"); + } + if(BIT19(val)) + { + log::ajouter("outch !!!!!!!"); + }*/ + return TRUE; + } + return FALSE; + case 2 : + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 0 : + armcp15->DCConfig = val; + return TRUE; + case 1 : + armcp15->ICConfig = val; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 3 : + if((opcode1==0) && (opcode2==0) && (CRm==0)) + { + armcp15->writeBuffCtrl = val; + return TRUE; + } + return FALSE; + if((opcode1==0) && (CRm==0)) + { + switch(opcode2) + { + case 2 : + armcp15->DaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + case 3 : + armcp15->IaccessPerm = val; + armcp15_maskPrecalc(armcp15); + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 6 : + if((opcode1==0) && (opcode2==0)) + { + switch(CRm) + { + case 0 : + armcp15->protectBaseSize0 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 1 : + armcp15->protectBaseSize1 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 2 : + armcp15->protectBaseSize2 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 3 : + armcp15->protectBaseSize3 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 4 : + armcp15->protectBaseSize4 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 5 : + armcp15->protectBaseSize5 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 6 : + armcp15->protectBaseSize6 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + case 7 : + armcp15->protectBaseSize7 = val; + armcp15_maskPrecalc(armcp15) ; + return TRUE; + default : + return FALSE; + } + } + return FALSE; + case 7 : + if((CRm==0)&&(opcode1==0)&&((opcode2==4))) + { + CP15wait4IRQ(armcp15->cpu); + return TRUE; + } + return FALSE; + case 9 : + if((opcode1==0)) + { + switch(CRm) + { + case 0 : + switch(opcode2) + { + case 0 : + armcp15->DcacheLock = val; + return TRUE; + case 1 : + armcp15->IcacheLock = val; + return TRUE; + default : + return FALSE; + } + case 1 : + switch(opcode2) + { + case 0 : + armcp15->DTCMRegion = val; + MMU.DTCMRegion = val & 0x0FFFFFFC0; + /*sprintf(logbuf, "%08X", val); + log::ajouter(logbuf);*/ + return TRUE; + case 1 : + armcp15->ITCMRegion = val; + /* ITCM base is not writeable! */ + MMU.ITCMRegion = 0; + return TRUE; + default : + return FALSE; + } + } + } + return FALSE; + default : + return FALSE; + } +} + + + diff --git a/tools/vio2sf/src/vio2sf/desmume/cp15.h b/tools/vio2sf/src/vio2sf/desmume/cp15.h new file mode 100644 index 000000000..49496f3e5 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/cp15.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CP15_H__ +#define __CP15_H__ + +#include "armcpu.h" + +typedef struct +{ + u32 IDCode; + u32 cacheType; + u32 TCMSize; + u32 ctrl; + u32 DCConfig; + u32 ICConfig; + u32 writeBuffCtrl; + u32 und; + u32 DaccessPerm; + u32 IaccessPerm; + u32 protectBaseSize0; + u32 protectBaseSize1; + u32 protectBaseSize2; + u32 protectBaseSize3; + u32 protectBaseSize4; + u32 protectBaseSize5; + u32 protectBaseSize6; + u32 protectBaseSize7; + u32 cacheOp; + u32 DcacheLock; + u32 IcacheLock; + u32 ITCMRegion; + u32 DTCMRegion; + u32 processID; + u32 RAM_TAG; + u32 testState; + u32 cacheDbg; + /* calculated bitmasks for the regions to decide rights uppon */ + /* calculation is done in the MCR instead of on mem access for performance */ + u32 regionWriteMask_USR[8] ; + u32 regionWriteMask_SYS[8] ; + u32 regionReadMask_USR[8] ; + u32 regionReadMask_SYS[8] ; + u32 regionExecuteMask_USR[8] ; + u32 regionExecuteMask_SYS[8] ; + u32 regionWriteSet_USR[8] ; + u32 regionWriteSet_SYS[8] ; + u32 regionReadSet_USR[8] ; + u32 regionReadSet_SYS[8] ; + u32 regionExecuteSet_USR[8] ; + u32 regionExecuteSet_SYS[8] ; + + armcpu_t * cpu; + +} armcp15_t; + +armcp15_t *armcp15_new(armcpu_t *c); +BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr); +BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); +INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) ; + + +#define CP15_ACCESS_WRITE 0 +#define CP15_ACCESS_READ 2 +#define CP15_ACCESS_EXECUTE 4 +#define CP15_ACCESS_WRITEUSR CP15_ACCESS_WRITE +#define CP15_ACCESS_WRITESYS 1 +#define CP15_ACCESS_READUSR CP15_ACCESS_READ +#define CP15_ACCESS_READSYS 3 +#define CP15_ACCESS_EXECUSR CP15_ACCESS_EXECUTE +#define CP15_ACCESS_EXECSYS 5 + +#endif /* __CP15_H__*/ diff --git a/tools/vio2sf/src/vio2sf/desmume/debug.h b/tools/vio2sf/src/vio2sf/desmume/debug.h new file mode 100644 index 000000000..647eaaacb --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/debug.h @@ -0,0 +1,11 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#define LOG(x) +#define GPULOG(x) +#define DIVLOG(x) +#define SQRTLOG(x) +#define CARDLOG(x) +#define DMALOG(x) + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/dscard.h b/tools/vio2sf/src/vio2sf/desmume/dscard.h new file mode 100644 index 000000000..9b002e347 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/dscard.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 thoduv + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __DSCARD_H__ +#define __DSCARD_H__ + +typedef struct +{ + + u32 adress; + u32 transfer_count; + +} nds_dscard; + +#endif /*__DSCARD_H__*/ + + + diff --git a/tools/vio2sf/src/vio2sf/desmume/instruction_tabdef.inc b/tools/vio2sf/src/vio2sf/desmume/instruction_tabdef.inc new file mode 100644 index 000000000..f63763a73 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/instruction_tabdef.inc @@ -0,0 +1,4400 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +TYPE_RETOUR (*CALLTYPE NOM_TAB[4096])(PARAMETRES)={ + OP_AND_LSL_IMM, // 000 0000 0 0000 + OP_AND_LSL_REG, // 000 0000 0 0001 + OP_AND_LSR_IMM, // 000 0000 0 0010 + OP_AND_LSR_REG, // 000 0000 0 0011 + OP_AND_ASR_IMM, // 000 0000 0 0100 + OP_AND_ASR_REG, // 000 0000 0 0101 + OP_AND_ROR_IMM, // 000 0000 0 0110 + OP_AND_ROR_REG, // 000 0000 0 0111 + + OP_AND_LSL_IMM, // 000 0000 0 1000 + OP_MUL, // 000 0000 0 1001 + OP_AND_LSR_IMM, // OOO OOOO O 1010 + OP_STRH_POS_INDE_M_REG_OFF, // 000 0000 0 1011 + OP_AND_ASR_IMM, // 000 0000 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0000 0 1101 + OP_AND_ROR_IMM, // 000 0000 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0000 0 1111 + + OP_AND_S_LSL_IMM, // 000 0000 1 0000 + OP_AND_S_LSL_REG, // 000 0000 1 0001 + OP_AND_S_LSR_IMM, // 000 0000 1 0010 + OP_AND_S_LSR_REG, // 000 0000 1 0011 + OP_AND_S_ASR_IMM, // 000 0000 1 0100 + OP_AND_S_ASR_REG, // 000 0000 1 0101 + OP_AND_S_ROR_IMM, // 000 0000 1 0110 + OP_AND_S_ROR_REG, // 000 0000 1 0111 + + OP_AND_S_LSL_IMM, // 000 0000 1 1000 + OP_MUL_S, // 000 0000 1 1001 + OP_AND_S_LSR_IMM, // 000 0000 1 1010 + OP_LDRH_POS_INDE_M_REG_OFF, // 000 0000 1 1011 + OP_AND_S_ASR_IMM, // 000 0000 1 1100 + OP_LDRSB_POS_INDE_M_REG_OFF,// 000 0000 1 1101 + OP_AND_S_ROR_IMM, // 000 0000 1 1110 + OP_LDRSH_POS_INDE_M_REG_OFF,// 000 0000 1 1111 + + OP_EOR_LSL_IMM, // 000 0001 0 0000 + OP_EOR_LSL_REG, // 000 0001 0 0001 + OP_EOR_LSR_IMM, // 000 0001 0 0010 + OP_EOR_LSR_REG, // 000 0001 0 0011 + OP_EOR_ASR_IMM, // 000 0001 0 0100 + OP_EOR_ASR_REG, // 000 0001 0 0101 + OP_EOR_ROR_IMM, // 000 0001 0 0110 + OP_EOR_ROR_REG, // 000 0001 0 0111 + + OP_EOR_LSL_IMM, // 000 0001 0 1000 + OP_MLA, // 000 0001 0 1001 + OP_EOR_LSR_IMM, // OOO OOO1 O 1010 + OP_UND, // 000 0001 0 1011 + OP_EOR_ASR_IMM, // 000 0001 0 1100 + OP_UND, // 000 0001 0 1101 + OP_EOR_ROR_IMM, // 000 0001 0 1110 + OP_UND, // 000 0001 0 1111 + + OP_EOR_S_LSL_IMM, // 000 0001 1 0000 + OP_EOR_S_LSL_REG, // 000 0001 1 0001 + OP_EOR_S_LSR_IMM, // 000 0001 1 0010 + OP_EOR_S_LSR_REG, // 000 0001 1 0011 + OP_EOR_S_ASR_IMM, // 000 0001 1 0100 + OP_EOR_S_ASR_REG, // 000 0001 1 0101 + OP_EOR_S_ROR_IMM, // 000 0001 1 0110 + OP_EOR_S_ROR_REG, // 000 0001 1 0111 + + OP_EOR_S_LSL_IMM, // 000 0001 1 1000 + OP_MLA_S, // 000 0001 1 1001 + OP_EOR_S_LSR_IMM, // 000 0001 1 1010 + OP_UND, // 000 0001 1 1011 + OP_EOR_S_ASR_IMM, // 000 0001 1 1100 + OP_UND, // 000 0001 1 1101 + OP_EOR_S_ROR_IMM, // 000 0001 1 1110 + OP_UND, // 000 0001 1 1111 + + OP_SUB_LSL_IMM, // 000 0010 0 0000 + OP_SUB_LSL_REG, // 000 0010 0 0001 + OP_SUB_LSR_IMM, // 000 0010 0 0010 + OP_SUB_LSR_REG, // 000 0010 0 0011 + OP_SUB_ASR_IMM, // 000 0010 0 0100 + OP_SUB_ASR_REG, // 000 0010 0 0101 + OP_SUB_ROR_IMM, // 000 0010 0 0110 + OP_SUB_ROR_REG, // 000 0010 0 0111 + + OP_SUB_LSL_IMM, // 000 0010 0 1000 + OP_UND, // 000 0010 0 1001 + OP_SUB_LSR_IMM, // OOO OO1O O 1010 + OP_STRH_POS_INDE_M_IMM_OFF, // 000 0010 0 1011 + OP_SUB_ASR_IMM, // 000 0010 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0010 0 1101 + OP_SUB_ROR_IMM, // 000 0010 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0010 0 1111 + + OP_SUB_S_LSL_IMM, // 000 0010 1 0000 + OP_SUB_S_LSL_REG, // 000 0010 1 0001 + OP_SUB_S_LSR_IMM, // 000 0010 1 0010 + OP_SUB_S_LSR_REG, // 000 0010 1 0011 + OP_SUB_S_ASR_IMM, // 000 0010 1 0100 + OP_SUB_S_ASR_REG, // 000 0010 1 0101 + OP_SUB_S_ROR_IMM, // 000 0010 1 0110 + OP_SUB_S_ROR_REG, // 000 0010 1 0111 + + OP_SUB_S_LSL_IMM, // 000 0010 1 1000 + OP_UND, // 000 0010 1 1001 + OP_SUB_S_LSR_IMM, // 000 0010 1 1010 + OP_LDRH_POS_INDE_M_IMM_OFF, // 000 0010 1 1011 + OP_SUB_S_ASR_IMM, // 000 0010 1 1100 + OP_LDRSB_POS_INDE_M_IMM_OFF,// 000 0010 1 1101 + OP_SUB_S_ROR_IMM, // 000 0010 1 1110 + OP_LDRSH_POS_INDE_M_IMM_OFF,// 000 0010 1 1111 +//-------------------- + OP_RSB_LSL_IMM, // 000 0011 0 0000 + OP_RSB_LSL_REG, // 000 0011 0 0001 + OP_RSB_LSR_IMM, // 000 0011 0 0010 + OP_RSB_LSR_REG, // 000 0011 0 0011 + OP_RSB_ASR_IMM, // 000 0011 0 0100 + OP_RSB_ASR_REG, // 000 0011 0 0101 + OP_RSB_ROR_IMM, // 000 0011 0 0110 + OP_RSB_ROR_REG, // 000 0011 0 0111 + + OP_RSB_LSL_IMM, // 000 0011 0 1000 + OP_UND, // 000 0011 0 1001 + OP_RSB_LSR_IMM, // OOO OO11 O 1010 + OP_UND, // 000 0011 0 1011 + OP_RSB_ASR_IMM, // 000 0011 0 1100 + OP_UND, // 000 0011 0 1101 + OP_RSB_ROR_IMM, // 000 0011 0 1110 + OP_UND, // 000 0011 0 1111 + + OP_RSB_S_LSL_IMM, // 000 0011 1 0000 + OP_RSB_S_LSL_REG, // 000 0011 1 0001 + OP_RSB_S_LSR_IMM, // 000 0011 1 0010 + OP_RSB_S_LSR_REG, // 000 0011 1 0011 + OP_RSB_S_ASR_IMM, // 000 0011 1 0100 + OP_RSB_S_ASR_REG, // 000 0011 1 0101 + OP_RSB_S_ROR_IMM, // 000 0011 1 0110 + OP_RSB_S_ROR_REG, // 000 0011 1 0111 + + OP_RSB_S_LSL_IMM, // 000 0011 1 1000 + OP_UND, // 000 0011 1 1001 + OP_RSB_S_LSR_IMM, // 000 0011 1 1010 + OP_UND, // 000 0011 1 1011 + OP_RSB_S_ASR_IMM, // 000 0011 1 1100 + OP_UND, // 000 0011 1 1101 + OP_RSB_S_ROR_IMM, // 000 0011 1 1110 + OP_UND, // 000 0011 1 1111 +//-------------------------- + OP_ADD_LSL_IMM, // 000 0100 0 0000 + OP_ADD_LSL_REG, // 000 0100 0 0001 + OP_ADD_LSR_IMM, // 000 0100 0 0010 + OP_ADD_LSR_REG, // 000 0100 0 0011 + OP_ADD_ASR_IMM, // 000 0100 0 0100 + OP_ADD_ASR_REG, // 000 0100 0 0101 + OP_ADD_ROR_IMM, // 000 0100 0 0110 + OP_ADD_ROR_REG, // 000 0100 0 0111 + + OP_ADD_LSL_IMM, // 000 0100 0 1000 + OP_UMULL, // 000 0100 0 1001 + OP_ADD_LSR_IMM, // OOO O10O O 1010 + OP_STRH_POS_INDE_P_REG_OFF, // 000 0100 0 1011 + OP_ADD_ASR_IMM, // 000 0100 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0100 0 1101 + OP_ADD_ROR_IMM, // 000 0100 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0100 0 1111 + + OP_ADD_S_LSL_IMM, // 000 0100 1 0000 + OP_ADD_S_LSL_REG, // 000 0100 1 0001 + OP_ADD_S_LSR_IMM, // 000 0100 1 0010 + OP_ADD_S_LSR_REG, // 000 0100 1 0011 + OP_ADD_S_ASR_IMM, // 000 0100 1 0100 + OP_ADD_S_ASR_REG, // 000 0100 1 0101 + OP_ADD_S_ROR_IMM, // 000 0100 1 0110 + OP_ADD_S_ROR_REG, // 000 0100 1 0111 + + OP_ADD_S_LSL_IMM, // 000 0100 1 1000 + OP_UMULL_S, // 000 0100 1 1001 + OP_ADD_S_LSR_IMM, // 000 0100 1 1010 + OP_LDRH_POS_INDE_P_REG_OFF, // 000 0100 1 1011 + OP_ADD_S_ASR_IMM, // 000 0100 1 1100 + OP_LDRSB_POS_INDE_P_REG_OFF,// 000 0100 1 1101 + OP_ADD_S_ROR_IMM, // 000 0100 1 1110 + OP_LDRSH_POS_INDE_P_REG_OFF,// 000 0100 1 1111 +//----------------------------------------- + OP_ADC_LSL_IMM, // 000 0101 0 0000 + OP_ADC_LSL_REG, // 000 0101 0 0001 + OP_ADC_LSR_IMM, // 000 0101 0 0010 + OP_ADC_LSR_REG, // 000 0101 0 0011 + OP_ADC_ASR_IMM, // 000 0101 0 0100 + OP_ADC_ASR_REG, // 000 0101 0 0101 + OP_ADC_ROR_IMM, // 000 0101 0 0110 + OP_ADC_ROR_REG, // 000 0101 0 0111 + + OP_ADC_LSL_IMM, // 000 0101 0 1000 + OP_UMLAL, // 000 0101 0 1001 + OP_ADC_LSR_IMM, // OOO O101 O 1010 + OP_UND, // 000 0101 0 1011 + OP_ADC_ASR_IMM, // 000 0101 0 1100 + OP_UND, // 000 0101 0 1101 + OP_ADC_ROR_IMM, // 000 0101 0 1110 + OP_UND, // 000 0101 0 1111 + + OP_ADC_S_LSL_IMM, // 000 0101 1 0000 + OP_ADC_S_LSL_REG, // 000 0101 1 0001 + OP_ADC_S_LSR_IMM, // 000 0101 1 0010 + OP_ADC_S_LSR_REG, // 000 0101 1 0011 + OP_ADC_S_ASR_IMM, // 000 0101 1 0100 + OP_ADC_S_ASR_REG, // 000 0101 1 0101 + OP_ADC_S_ROR_IMM, // 000 0101 1 0110 + OP_ADC_S_ROR_REG, // 000 0101 1 0111 + + OP_ADC_S_LSL_IMM, // 000 0101 1 1000 + OP_UMLAL_S, // 000 0101 1 1001 + OP_ADC_S_LSR_IMM, // 000 0101 1 1010 + OP_UND, // 000 0101 1 1011 + OP_ADC_S_ASR_IMM, // 000 0101 1 1100 + OP_UND, // 000 0101 1 1101 + OP_ADC_S_ROR_IMM, // 000 0101 1 1110 + OP_UND, // 000 0101 1 1111 +//------------------------------------------ + OP_SBC_LSL_IMM, // 000 0110 0 0000 + OP_SBC_LSL_REG, // 000 0110 0 0001 + OP_SBC_LSR_IMM, // 000 0110 0 0010 + OP_SBC_LSR_REG, // 000 0110 0 0011 + OP_SBC_ASR_IMM, // 000 0110 0 0100 + OP_SBC_ASR_REG, // 000 0110 0 0101 + OP_SBC_ROR_IMM, // 000 0110 0 0110 + OP_SBC_ROR_REG, // 000 0110 0 0111 + + OP_SBC_LSL_IMM, // 000 0110 0 1000 + OP_SMULL, // 000 0110 0 1001 + OP_SBC_LSR_IMM, // OOO O11O O 1010 + OP_STRH_POS_INDE_P_IMM_OFF, // 000 0110 0 1011 + OP_SBC_ASR_IMM, // 000 0110 0 1100 + OP_LDRD_STRD_POST_INDEX, + // 000 0110 0 1101 + OP_SBC_ROR_IMM, // 000 0110 0 1110 + OP_LDRD_STRD_POST_INDEX, + // 000 0110 0 1111 + + OP_SBC_S_LSL_IMM, // 000 0110 1 0000 + OP_SBC_S_LSL_REG, // 000 0110 1 0001 + OP_SBC_S_LSR_IMM, // 000 0110 1 0010 + OP_SBC_S_LSR_REG, // 000 0110 1 0011 + OP_SBC_S_ASR_IMM, // 000 0110 1 0100 + OP_SBC_S_ASR_REG, // 000 0110 1 0101 + OP_SBC_S_ROR_IMM, // 000 0110 1 0110 + OP_SBC_S_ROR_REG, // 000 0110 1 0111 + + OP_SBC_S_LSL_IMM, // 000 0110 1 1000 + OP_SMULL_S, // 000 0110 1 1001 + OP_SBC_S_LSR_IMM, // 000 0110 1 1010 + OP_LDRH_POS_INDE_P_IMM_OFF, // 000 0110 1 1011 + OP_SBC_S_ASR_IMM, // 000 0110 1 1100 + OP_LDRSB_POS_INDE_P_IMM_OFF,// 000 0110 1 1101 + OP_SBC_S_ROR_IMM, // 000 0110 1 1110 + OP_LDRSH_POS_INDE_P_IMM_OFF,// 000 0110 1 1111 +//------------------------------------------ + OP_RSC_LSL_IMM, // 000 0111 0 0000 + OP_RSC_LSL_REG, // 000 0111 0 0001 + OP_RSC_LSR_IMM, // 000 0111 0 0010 + OP_RSC_LSR_REG, // 000 0111 0 0011 + OP_RSC_ASR_IMM, // 000 0111 0 0100 + OP_RSC_ASR_REG, // 000 0111 0 0101 + OP_RSC_ROR_IMM, // 000 0111 0 0110 + OP_RSC_ROR_REG, // 000 0111 0 0111 + + OP_RSC_LSL_IMM, // 000 0111 0 1000 + OP_SMLAL, // 000 0111 0 1001 + OP_RSC_LSR_IMM, // OOO O111 O 1010 + OP_UND, // 000 0111 0 1011 + OP_RSC_ASR_IMM, // 000 0111 0 1100 + OP_UND, // 000 0111 0 1101 + OP_RSC_ROR_IMM, // 000 0111 0 1110 + OP_UND, // 000 0111 0 1111 + + OP_RSC_S_LSL_IMM, // 000 0111 1 0000 + OP_RSC_S_LSL_REG, // 000 0111 1 0001 + OP_RSC_S_LSR_IMM, // 000 0111 1 0010 + OP_RSC_S_LSR_REG, // 000 0111 1 0011 + OP_RSC_S_ASR_IMM, // 000 0111 1 0100 + OP_RSC_S_ASR_REG, // 000 0111 1 0101 + OP_RSC_S_ROR_IMM, // 000 0111 1 0110 + OP_RSC_S_ROR_REG, // 000 0111 1 0111 + + OP_RSC_S_LSL_IMM, // 000 0111 1 1000 + OP_SMLAL_S, // 000 0111 1 1001 + OP_RSC_S_LSR_IMM, // 000 0111 1 1010 + OP_UND, // 000 0111 1 1011 + OP_RSC_S_ASR_IMM, // 000 0111 1 1100 + OP_UND, // 000 0111 1 1101 + OP_RSC_S_ROR_IMM, // 000 0111 1 1110 + OP_UND, // 000 0111 1 1111 +//------------------------------------------ + OP_MRS_CPSR, // 000 1000 0 0000 + OP_UND, // 000 1000 0 0001 + OP_UND, // 000 1000 0 0010 + OP_UND, // 000 1000 0 0011 + OP_UND, // 000 1000 0 0100 + OP_QADD, // 000 1000 0 0101 + OP_UND, // 000 1000 0 0110 + OP_UND, // 000 1000 0 0111 + + OP_SMLA_B_B, // 000 1000 0 1000 + OP_SWP, // 000 1000 0 1001 + OP_SMLA_T_B, // 000 1000 0 1010 + OP_STRH_M_REG_OFF, // 000 1000 0 1011 + OP_SMLA_B_T, // 000 1000 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1000 0 1101 + OP_SMLA_T_T, // 000 1000 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1000 0 1111 + + OP_TST_LSL_IMM, // 000 1000 1 0000 + OP_TST_LSL_REG, // 000 1000 1 0001 + OP_TST_LSR_IMM, // 000 1000 1 0010 + OP_TST_LSR_REG, // 000 1000 1 0011 + OP_TST_ASR_IMM, // 000 1000 1 0100 + OP_TST_ASR_REG, // 000 1000 1 0101 + OP_TST_ROR_IMM, // 000 1000 1 0110 + OP_TST_ROR_REG, // 000 1000 1 0111 + + OP_TST_LSL_IMM, // 000 1000 1 1000 + OP_UND, // 000 1000 1 1001 + OP_TST_LSR_IMM, // OOO 100O 1 1010 + OP_LDRH_M_REG_OFF, // 000 1000 1 1011 + OP_TST_ASR_IMM, // 000 1000 1 1100 + OP_LDRSB_M_REG_OFF,// 000 1000 1 1101 + OP_TST_ROR_IMM, // 000 1000 1 1110 + OP_LDRSH_M_REG_OFF,// 000 1000 1 1111 +//------------------------------------------ + OP_MSR_CPSR, // 000 1001 0 0000 + OP_BX, // 000 1001 0 0001 + OP_UND, // 000 1001 0 0010 + OP_BLX_REG, // 000 1001 0 0011 + OP_UND, // 000 1001 0 0100 + OP_QSUB, // 000 1001 0 0101 + OP_UND, // 000 1001 0 0110 + OP_BKPT, // 000 1001 0 0111 + + OP_SMLAW_B, // 000 1001 0 1000 + OP_UND, // 000 1001 0 1001 + OP_SMULW_B, // 000 1001 0 1010 + OP_STRH_PRE_INDE_M_REG_OFF, // 000 1001 0 1011 + OP_SMLAW_T, // 000 1001 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1001 0 1101 + OP_SMULW_T, // 000 1001 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1001 0 1111 + + OP_TEQ_LSL_IMM, // 000 1001 1 0000 + OP_TEQ_LSL_REG, // 000 1001 1 0001 + OP_TEQ_LSR_IMM, // 000 1001 1 0010 + OP_TEQ_LSR_REG, // 000 1001 1 0011 + OP_TEQ_ASR_IMM, // 000 1001 1 0100 + OP_TEQ_ASR_REG, // 000 1001 1 0101 + OP_TEQ_ROR_IMM, // 000 1001 1 0110 + OP_TEQ_ROR_REG, // 000 1001 1 0111 + + OP_TEQ_LSL_IMM, // 000 1001 1 1000 + OP_UND, // 000 1001 1 1001 + OP_TEQ_LSR_IMM, // OOO 1001 1 1010 + OP_LDRH_PRE_INDE_M_REG_OFF, // 000 1001 1 1011 + OP_TEQ_ASR_IMM, // 000 1001 1 1100 + OP_LDRSB_PRE_INDE_M_REG_OFF, // 000 1001 1 1101 + OP_TEQ_ROR_IMM, // 000 1001 1 1110 + OP_LDRSH_PRE_INDE_M_REG_OFF, // 000 1001 1 1111 +//------------------------------------------ + OP_MRS_SPSR, // 000 1010 0 0000 + OP_UND, // 000 1010 0 0001 + OP_UND, // 000 1010 0 0010 + OP_UND, // 000 1010 0 0011 + OP_UND, // 000 1010 0 0100 + OP_QDADD, // 000 1010 0 0101 + OP_UND, // 000 1010 0 0110 + OP_UND, // 000 1010 0 0111 + + OP_SMLAL_B_B, // 000 1010 0 1000 + OP_SWPB, // 000 1010 0 1001 + OP_SMLAL_T_B, // 000 1010 0 1010 + OP_STRH_M_IMM_OFF, // 000 1010 0 1011 + OP_SMLAL_B_T, // 000 1010 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1010 0 1101 + OP_SMLAL_T_T, // 000 1010 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1010 0 1111 + + OP_CMP_LSL_IMM, // 000 1010 1 0000 + OP_CMP_LSL_REG, // 000 1010 1 0001 + OP_CMP_LSR_IMM, // 000 1010 1 0010 + OP_CMP_LSR_REG, // 000 1010 1 0011 + OP_CMP_ASR_IMM, // 000 1010 1 0100 + OP_CMP_ASR_REG, // 000 1010 1 0101 + OP_CMP_ROR_IMM, // 000 1010 1 0110 + OP_CMP_ROR_REG, // 000 1010 1 0111 + + OP_CMP_LSL_IMM, // 000 1010 1 1000 + OP_UND, // 000 1010 1 1001 + OP_CMP_LSR_IMM, // OOO 1O1O 1 1010 + OP_LDRH_M_IMM_OFF, // 000 1010 1 1011 + OP_CMP_ASR_IMM, // 000 1010 1 1100 + OP_LDRSB_M_IMM_OFF,// 000 1010 1 1101 + OP_CMP_ROR_IMM, // 000 1010 1 1110 + OP_LDRSH_M_IMM_OFF,// 000 1010 1 1111 +//------------------------------------------ + OP_MSR_SPSR, // 000 1011 0 0000 + OP_CLZ, // 000 1011 0 0001 + OP_UND, // 000 1011 0 0010 + OP_UND, // 000 1011 0 0011 + OP_UND, // 000 1011 0 0100 + OP_QDSUB, // 000 1011 0 0101 + OP_UND, // 000 1011 0 0110 + OP_UND, // 000 1011 0 0111 + + OP_SMUL_B_B, // 000 1011 0 1000 + OP_UND, // 000 1011 0 1001 + OP_SMUL_T_B, // 000 1011 0 1010 + OP_STRH_PRE_INDE_M_IMM_OFF, // 000 1011 0 1011 + OP_SMUL_B_T, // 000 1011 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1011 0 1101 + OP_SMUL_T_T, // 000 1011 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1011 0 1111 + + OP_CMN_LSL_IMM, // 000 1011 1 0000 + OP_CMN_LSL_REG, // 000 1011 1 0001 + OP_CMN_LSR_IMM, // 000 1011 1 0010 + OP_CMN_LSR_REG, // 000 1011 1 0011 + OP_CMN_ASR_IMM, // 000 1011 1 0100 + OP_CMN_ASR_REG, // 000 1011 1 0101 + OP_CMN_ROR_IMM, // 000 1011 1 0110 + OP_CMN_ROR_REG, // 000 1011 1 0111 + + OP_CMN_LSL_IMM, // 000 1011 1 1000 + OP_UND, // 000 1011 1 1001 + OP_CMN_LSR_IMM, // OOO 1O11 1 1010 + OP_LDRH_PRE_INDE_M_IMM_OFF, // 000 1011 1 1011 + OP_CMN_ASR_IMM, // 000 1011 1 1100 + OP_LDRSB_PRE_INDE_M_IMM_OFF, // 000 1011 1 1101 + OP_CMN_ROR_IMM, // 000 1011 1 1110 + OP_LDRSH_PRE_INDE_M_IMM_OFF, // 000 1011 1 1111 +//------------------------------------------ + OP_ORR_LSL_IMM, // 000 1100 0 0000 + OP_ORR_LSL_REG, // 000 1100 0 0001 + OP_ORR_LSR_IMM, // 000 1100 0 0010 + OP_ORR_LSR_REG, // 000 1100 0 0011 + OP_ORR_ASR_IMM, // 000 1100 0 0100 + OP_ORR_ASR_REG, // 000 1100 0 0101 + OP_ORR_ROR_IMM, // 000 1100 0 0110 + OP_ORR_ROR_REG, // 000 1100 0 0111 + + OP_ORR_LSL_IMM, // 000 1100 0 1000 + OP_UND, // 000 1100 0 1001 + OP_ORR_LSR_IMM, // OOO 110O O 1010 + OP_STRH_P_REG_OFF, // 000 1100 0 1011 + OP_ORR_ASR_IMM, // 000 1100 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1100 0 1101 + OP_ORR_ROR_IMM, // 000 1100 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1100 0 1111 + + OP_ORR_S_LSL_IMM, // 000 1100 1 0000 + OP_ORR_S_LSL_REG, // 000 1100 1 0001 + OP_ORR_S_LSR_IMM, // 000 1100 1 0010 + OP_ORR_S_LSR_REG, // 000 1100 1 0011 + OP_ORR_S_ASR_IMM, // 000 1100 1 0100 + OP_ORR_S_ASR_REG, // 000 1100 1 0101 + OP_ORR_S_ROR_IMM, // 000 1100 1 0110 + OP_ORR_S_ROR_REG, // 000 1100 1 0111 + + OP_ORR_S_LSL_IMM, // 000 1100 1 1000 + OP_UND, // 000 1100 1 1001 + OP_ORR_S_LSR_IMM, // 000 1100 1 1010 + OP_LDRH_P_REG_OFF, // 000 1100 1 1011 + OP_ORR_S_ASR_IMM, // 000 1100 1 1100 + OP_LDRSB_P_REG_OFF,// 000 1100 1 1101 + OP_ORR_S_ROR_IMM, // 000 1100 1 1110 + OP_LDRSH_P_REG_OFF,// 000 1100 1 1111 +//------------------------------------------ + OP_MOV_LSL_IMM, // 000 1101 0 0000 + OP_MOV_LSL_REG, // 000 1101 0 0001 + OP_MOV_LSR_IMM, // 000 1101 0 0010 + OP_MOV_LSR_REG, // 000 1101 0 0011 + OP_MOV_ASR_IMM, // 000 1101 0 0100 + OP_MOV_ASR_REG, // 000 1101 0 0101 + OP_MOV_ROR_IMM, // 000 1101 0 0110 + OP_MOV_ROR_REG, // 000 1101 0 0111 + + OP_MOV_LSL_IMM, // 000 1101 0 1000 + OP_UND, // 000 1101 0 1001 + OP_MOV_LSR_IMM, // OOO 1101 O 1010 + OP_STRH_PRE_INDE_P_REG_OFF, // 000 1101 0 1011 + OP_MOV_ASR_IMM, // 000 1101 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1101 0 1101 + OP_MOV_ROR_IMM, // 000 1101 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1101 0 1111 + + OP_MOV_S_LSL_IMM, // 000 1101 1 0000 + OP_MOV_S_LSL_REG, // 000 1101 1 0001 + OP_MOV_S_LSR_IMM, // 000 1101 1 0010 + OP_MOV_S_LSR_REG, // 000 1101 1 0011 + OP_MOV_S_ASR_IMM, // 000 1101 1 0100 + OP_MOV_S_ASR_REG, // 000 1101 1 0101 + OP_MOV_S_ROR_IMM, // 000 1101 1 0110 + OP_MOV_S_ROR_REG, // 000 1101 1 0111 + + OP_MOV_S_LSL_IMM, // 000 1101 1 1000 + OP_UND, // 000 1101 1 1001 + OP_MOV_S_LSR_IMM, // 000 1101 1 1010 + OP_LDRH_PRE_INDE_P_REG_OFF, // 000 1101 1 1011 + OP_MOV_S_ASR_IMM, // 000 1101 1 1100 + OP_LDRSB_PRE_INDE_P_REG_OFF,// 000 1101 1 1101 + OP_MOV_S_ROR_IMM, // 000 1101 1 1110 + OP_LDRSH_PRE_INDE_P_REG_OFF,// 000 1101 1 1111 +//------------------------------------------ + OP_BIC_LSL_IMM, // 000 1110 0 0000 + OP_BIC_LSL_REG, // 000 1110 0 0001 + OP_BIC_LSR_IMM, // 000 1110 0 0010 + OP_BIC_LSR_REG, // 000 1110 0 0011 + OP_BIC_ASR_IMM, // 000 1110 0 0100 + OP_BIC_ASR_REG, // 000 1110 0 0101 + OP_BIC_ROR_IMM, // 000 1110 0 0110 + OP_BIC_ROR_REG, // 000 1110 0 0111 + + OP_BIC_LSL_IMM, // 000 1110 0 1000 + OP_UND, // 000 1110 0 1001 + OP_BIC_LSR_IMM, // OOO 111O O 1010 + OP_STRH_P_IMM_OFF, // 000 1110 0 1011 + OP_BIC_ASR_IMM, // 000 1110 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1110 0 1101 + OP_BIC_ROR_IMM, // 000 1110 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1110 0 1111 + + OP_BIC_S_LSL_IMM, // 000 1110 1 0000 + OP_BIC_S_LSL_REG, // 000 1110 1 0001 + OP_BIC_S_LSR_IMM, // 000 1110 1 0010 + OP_BIC_S_LSR_REG, // 000 1110 1 0011 + OP_BIC_S_ASR_IMM, // 000 1110 1 0100 + OP_BIC_S_ASR_REG, // 000 1110 1 0101 + OP_BIC_S_ROR_IMM, // 000 1110 1 0110 + OP_BIC_S_ROR_REG, // 000 1110 1 0111 + + OP_BIC_S_LSL_IMM, // 000 1110 1 1000 + OP_UND, // 000 1110 1 1001 + OP_BIC_S_LSR_IMM, // 000 1110 1 1010 + OP_LDRH_P_IMM_OFF, // 000 1110 1 1011 + OP_BIC_S_ASR_IMM, // 000 1110 1 1100 + OP_LDRSB_P_IMM_OFF,// 000 1110 1 1101 + OP_BIC_S_ROR_IMM, // 000 1110 1 1110 + OP_LDRSH_P_IMM_OFF,// 000 1110 1 1111 +//------------------------------------------- + OP_MVN_LSL_IMM, // 000 1111 0 0000 + OP_MVN_LSL_REG, // 000 1111 0 0001 + OP_MVN_LSR_IMM, // 000 1111 0 0010 + OP_MVN_LSR_REG, // 000 1111 0 0011 + OP_MVN_ASR_IMM, // 000 1111 0 0100 + OP_MVN_ASR_REG, // 000 1111 0 0101 + OP_MVN_ROR_IMM, // 000 1111 0 0110 + OP_MVN_ROR_REG, // 000 1111 0 0111 + + OP_MVN_LSL_IMM, // 000 1111 0 1000 + OP_UND, // 000 1111 0 1001 + OP_MVN_LSR_IMM, // OOO 1111 O 1010 + OP_STRH_PRE_INDE_P_IMM_OFF, // 000 1111 0 1011 + OP_MVN_ASR_IMM, // 000 1111 0 1100 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1111 0 1101 + OP_MVN_ROR_IMM, // 000 1111 0 1110 + OP_LDRD_STRD_OFFSET_PRE_INDEX, + // 000 1111 0 1111 + + OP_MVN_S_LSL_IMM, // 000 1111 1 0000 + OP_MVN_S_LSL_REG, // 000 1111 1 0001 + OP_MVN_S_LSR_IMM, // 000 1111 1 0010 + OP_MVN_S_LSR_REG, // 000 1111 1 0011 + OP_MVN_S_ASR_IMM, // 000 1111 1 0100 + OP_MVN_S_ASR_REG, // 000 1111 1 0101 + OP_MVN_S_ROR_IMM, // 000 1111 1 0110 + OP_MVN_S_ROR_REG, // 000 1111 1 0111 + + OP_MVN_S_LSL_IMM, // 000 1111 1 1000 + OP_UND, // 000 1111 1 1001 + OP_MVN_S_LSR_IMM, // 000 1111 1 1010 + OP_LDRH_PRE_INDE_P_IMM_OFF, // 000 1111 1 1011 + OP_MVN_S_ASR_IMM, // 000 1111 1 1100 + OP_LDRSB_PRE_INDE_P_IMM_OFF,// 000 1111 1 1101 + OP_MVN_S_ROR_IMM, // 000 1111 1 1110 + OP_LDRSH_PRE_INDE_P_IMM_OFF,// 000 1111 1 1111 +//------------------------------------------- + OP_AND_IMM_VAL, // 001 0000 0 0000 + OP_AND_IMM_VAL, // 001 0000 0 0001 + OP_AND_IMM_VAL, // 001 0000 0 0010 + OP_AND_IMM_VAL, // 001 0000 0 0011 + OP_AND_IMM_VAL, // 001 0000 0 0100 + OP_AND_IMM_VAL, // 001 0000 0 0101 + OP_AND_IMM_VAL, // 001 0000 0 0110 + OP_AND_IMM_VAL, // 001 0000 0 0111 + OP_AND_IMM_VAL, // 001 0000 0 1000 + OP_AND_IMM_VAL, // 001 0000 0 1001 + OP_AND_IMM_VAL, // 001 0000 0 1010 + OP_AND_IMM_VAL, // 001 0000 0 1011 + OP_AND_IMM_VAL, // 001 0000 0 1100 + OP_AND_IMM_VAL, // 001 0000 0 1101 + OP_AND_IMM_VAL, // 001 0000 0 1110 + OP_AND_IMM_VAL, // 001 0000 0 1111 + + OP_AND_S_IMM_VAL, // 001 0000 1 0000 + OP_AND_S_IMM_VAL, // 001 0000 1 0001 + OP_AND_S_IMM_VAL, // 001 0000 1 0010 + OP_AND_S_IMM_VAL, // 001 0000 1 0011 + OP_AND_S_IMM_VAL, // 001 0000 1 0100 + OP_AND_S_IMM_VAL, // 001 0000 1 0101 + OP_AND_S_IMM_VAL, // 001 0000 1 0110 + OP_AND_S_IMM_VAL, // 001 0000 1 0111 + OP_AND_S_IMM_VAL, // 001 0000 1 1000 + OP_AND_S_IMM_VAL, // 001 0000 1 1001 + OP_AND_S_IMM_VAL, // 001 0000 1 1010 + OP_AND_S_IMM_VAL, // 001 0000 1 1011 + OP_AND_S_IMM_VAL, // 001 0000 1 1100 + OP_AND_S_IMM_VAL, // 001 0000 1 1101 + OP_AND_S_IMM_VAL, // 001 0000 1 1110 + OP_AND_S_IMM_VAL, // 001 0000 1 1111 +//------------------------------------------ + OP_EOR_IMM_VAL, // 001 0001 0 0000 + OP_EOR_IMM_VAL, // 001 0001 0 0001 + OP_EOR_IMM_VAL, // 001 0001 0 0010 + OP_EOR_IMM_VAL, // 001 0001 0 0011 + OP_EOR_IMM_VAL, // 001 0001 0 0100 + OP_EOR_IMM_VAL, // 001 0001 0 0101 + OP_EOR_IMM_VAL, // 001 0001 0 0110 + OP_EOR_IMM_VAL, // 001 0001 0 0111 + OP_EOR_IMM_VAL, // 001 0001 0 1000 + OP_EOR_IMM_VAL, // 001 0001 0 1001 + OP_EOR_IMM_VAL, // 001 0001 0 1010 + OP_EOR_IMM_VAL, // 001 0001 0 1011 + OP_EOR_IMM_VAL, // 001 0001 0 1100 + OP_EOR_IMM_VAL, // 001 0001 0 1101 + OP_EOR_IMM_VAL, // 001 0001 0 1110 + OP_EOR_IMM_VAL, // 001 0001 0 1111 + + OP_EOR_S_IMM_VAL, // 001 0001 1 0000 + OP_EOR_S_IMM_VAL, // 001 0001 1 0001 + OP_EOR_S_IMM_VAL, // 001 0001 1 0010 + OP_EOR_S_IMM_VAL, // 001 0001 1 0011 + OP_EOR_S_IMM_VAL, // 001 0001 1 0100 + OP_EOR_S_IMM_VAL, // 001 0001 1 0101 + OP_EOR_S_IMM_VAL, // 001 0001 1 0110 + OP_EOR_S_IMM_VAL, // 001 0001 1 0111 + OP_EOR_S_IMM_VAL, // 001 0001 1 1000 + OP_EOR_S_IMM_VAL, // 001 0001 1 1001 + OP_EOR_S_IMM_VAL, // 001 0001 1 1010 + OP_EOR_S_IMM_VAL, // 001 0001 1 1011 + OP_EOR_S_IMM_VAL, // 001 0001 1 1100 + OP_EOR_S_IMM_VAL, // 001 0001 1 1101 + OP_EOR_S_IMM_VAL, // 001 0001 1 1110 + OP_EOR_S_IMM_VAL, // 001 0001 1 1111 +//------------------------------------------ + OP_SUB_IMM_VAL, // 001 0010 0 0000 + OP_SUB_IMM_VAL, // 001 0010 0 0001 + OP_SUB_IMM_VAL, // 001 0010 0 0010 + OP_SUB_IMM_VAL, // 001 0010 0 0011 + OP_SUB_IMM_VAL, // 001 0010 0 0100 + OP_SUB_IMM_VAL, // 001 0010 0 0101 + OP_SUB_IMM_VAL, // 001 0010 0 0110 + OP_SUB_IMM_VAL, // 001 0010 0 0111 + OP_SUB_IMM_VAL, // 001 0010 0 1000 + OP_SUB_IMM_VAL, // 001 0010 0 1001 + OP_SUB_IMM_VAL, // 001 0010 0 1010 + OP_SUB_IMM_VAL, // 001 0010 0 1011 + OP_SUB_IMM_VAL, // 001 0010 0 1100 + OP_SUB_IMM_VAL, // 001 0010 0 1101 + OP_SUB_IMM_VAL, // 001 0010 0 1110 + OP_SUB_IMM_VAL, // 001 0010 0 1111 + + OP_SUB_S_IMM_VAL, // 001 0010 1 0000 + OP_SUB_S_IMM_VAL, // 001 0010 1 0001 + OP_SUB_S_IMM_VAL, // 001 0010 1 0010 + OP_SUB_S_IMM_VAL, // 001 0010 1 0011 + OP_SUB_S_IMM_VAL, // 001 0010 1 0100 + OP_SUB_S_IMM_VAL, // 001 0010 1 0101 + OP_SUB_S_IMM_VAL, // 001 0010 1 0110 + OP_SUB_S_IMM_VAL, // 001 0010 1 0111 + OP_SUB_S_IMM_VAL, // 001 0010 1 1000 + OP_SUB_S_IMM_VAL, // 001 0010 1 1001 + OP_SUB_S_IMM_VAL, // 001 0010 1 1010 + OP_SUB_S_IMM_VAL, // 001 0010 1 1011 + OP_SUB_S_IMM_VAL, // 001 0010 1 1100 + OP_SUB_S_IMM_VAL, // 001 0010 1 1101 + OP_SUB_S_IMM_VAL, // 001 0010 1 1110 + OP_SUB_S_IMM_VAL, // 001 0010 1 1111 +//------------------------------------------ + OP_RSB_IMM_VAL, // 001 0011 0 0000 + OP_RSB_IMM_VAL, // 001 0011 0 0001 + OP_RSB_IMM_VAL, // 001 0011 0 0010 + OP_RSB_IMM_VAL, // 001 0011 0 0011 + OP_RSB_IMM_VAL, // 001 0011 0 0100 + OP_RSB_IMM_VAL, // 001 0011 0 0101 + OP_RSB_IMM_VAL, // 001 0011 0 0110 + OP_RSB_IMM_VAL, // 001 0011 0 0111 + OP_RSB_IMM_VAL, // 001 0011 0 1000 + OP_RSB_IMM_VAL, // 001 0011 0 1001 + OP_RSB_IMM_VAL, // 001 0011 0 1010 + OP_RSB_IMM_VAL, // 001 0011 0 1011 + OP_RSB_IMM_VAL, // 001 0011 0 1100 + OP_RSB_IMM_VAL, // 001 0011 0 1101 + OP_RSB_IMM_VAL, // 001 0011 0 1110 + OP_RSB_IMM_VAL, // 001 0011 0 1111 + + OP_RSB_S_IMM_VAL, // 001 0011 1 0000 + OP_RSB_S_IMM_VAL, // 001 0011 1 0001 + OP_RSB_S_IMM_VAL, // 001 0011 1 0010 + OP_RSB_S_IMM_VAL, // 001 0011 1 0011 + OP_RSB_S_IMM_VAL, // 001 0011 1 0100 + OP_RSB_S_IMM_VAL, // 001 0011 1 0101 + OP_RSB_S_IMM_VAL, // 001 0011 1 0110 + OP_RSB_S_IMM_VAL, // 001 0011 1 0111 + OP_RSB_S_IMM_VAL, // 001 0011 1 1000 + OP_RSB_S_IMM_VAL, // 001 0011 1 1001 + OP_RSB_S_IMM_VAL, // 001 0011 1 1010 + OP_RSB_S_IMM_VAL, // 001 0011 1 1011 + OP_RSB_S_IMM_VAL, // 001 0011 1 1100 + OP_RSB_S_IMM_VAL, // 001 0011 1 1101 + OP_RSB_S_IMM_VAL, // 001 0011 1 1110 + OP_RSB_S_IMM_VAL, // 001 0011 1 1111 +//------------------------------------------ + OP_ADD_IMM_VAL, // 001 0100 0 0000 + OP_ADD_IMM_VAL, // 001 0100 0 0001 + OP_ADD_IMM_VAL, // 001 0100 0 0010 + OP_ADD_IMM_VAL, // 001 0100 0 0011 + OP_ADD_IMM_VAL, // 001 0100 0 0100 + OP_ADD_IMM_VAL, // 001 0100 0 0101 + OP_ADD_IMM_VAL, // 001 0100 0 0110 + OP_ADD_IMM_VAL, // 001 0100 0 0111 + OP_ADD_IMM_VAL, // 001 0100 0 1000 + OP_ADD_IMM_VAL, // 001 0100 0 1001 + OP_ADD_IMM_VAL, // 001 0100 0 1010 + OP_ADD_IMM_VAL, // 001 0100 0 1011 + OP_ADD_IMM_VAL, // 001 0100 0 1100 + OP_ADD_IMM_VAL, // 001 0100 0 1101 + OP_ADD_IMM_VAL, // 001 0100 0 1110 + OP_ADD_IMM_VAL, // 001 0100 0 1111 + + OP_ADD_S_IMM_VAL, // 001 0100 1 0000 + OP_ADD_S_IMM_VAL, // 001 0100 1 0001 + OP_ADD_S_IMM_VAL, // 001 0100 1 0010 + OP_ADD_S_IMM_VAL, // 001 0100 1 0011 + OP_ADD_S_IMM_VAL, // 001 0100 1 0100 + OP_ADD_S_IMM_VAL, // 001 0100 1 0101 + OP_ADD_S_IMM_VAL, // 001 0100 1 0110 + OP_ADD_S_IMM_VAL, // 001 0100 1 0111 + OP_ADD_S_IMM_VAL, // 001 0100 1 1000 + OP_ADD_S_IMM_VAL, // 001 0100 1 1001 + OP_ADD_S_IMM_VAL, // 001 0100 1 1010 + OP_ADD_S_IMM_VAL, // 001 0100 1 1011 + OP_ADD_S_IMM_VAL, // 001 0100 1 1100 + OP_ADD_S_IMM_VAL, // 001 0100 1 1101 + OP_ADD_S_IMM_VAL, // 001 0100 1 1110 + OP_ADD_S_IMM_VAL, // 001 0100 1 1111 +//------------------------------------------ + OP_ADC_IMM_VAL, // 001 0101 0 0000 + OP_ADC_IMM_VAL, // 001 0101 0 0001 + OP_ADC_IMM_VAL, // 001 0101 0 0010 + OP_ADC_IMM_VAL, // 001 0101 0 0011 + OP_ADC_IMM_VAL, // 001 0101 0 0100 + OP_ADC_IMM_VAL, // 001 0101 0 0101 + OP_ADC_IMM_VAL, // 001 0101 0 0110 + OP_ADC_IMM_VAL, // 001 0101 0 0111 + OP_ADC_IMM_VAL, // 001 0101 0 1000 + OP_ADC_IMM_VAL, // 001 0101 0 1001 + OP_ADC_IMM_VAL, // 001 0101 0 1010 + OP_ADC_IMM_VAL, // 001 0101 0 1011 + OP_ADC_IMM_VAL, // 001 0101 0 1100 + OP_ADC_IMM_VAL, // 001 0101 0 1101 + OP_ADC_IMM_VAL, // 001 0101 0 1110 + OP_ADC_IMM_VAL, // 001 0101 0 1111 + + OP_ADC_S_IMM_VAL, // 001 0101 1 0000 + OP_ADC_S_IMM_VAL, // 001 0101 1 0001 + OP_ADC_S_IMM_VAL, // 001 0101 1 0010 + OP_ADC_S_IMM_VAL, // 001 0101 1 0011 + OP_ADC_S_IMM_VAL, // 001 0101 1 0100 + OP_ADC_S_IMM_VAL, // 001 0101 1 0101 + OP_ADC_S_IMM_VAL, // 001 0101 1 0110 + OP_ADC_S_IMM_VAL, // 001 0101 1 0111 + OP_ADC_S_IMM_VAL, // 001 0101 1 1000 + OP_ADC_S_IMM_VAL, // 001 0101 1 1001 + OP_ADC_S_IMM_VAL, // 001 0101 1 1010 + OP_ADC_S_IMM_VAL, // 001 0101 1 1011 + OP_ADC_S_IMM_VAL, // 001 0101 1 1100 + OP_ADC_S_IMM_VAL, // 001 0101 1 1101 + OP_ADC_S_IMM_VAL, // 001 0101 1 1110 + OP_ADC_S_IMM_VAL, // 001 0101 1 1111 +//------------------------------------------ + OP_SBC_IMM_VAL, // 001 0110 0 0000 + OP_SBC_IMM_VAL, // 001 0110 0 0001 + OP_SBC_IMM_VAL, // 001 0110 0 0010 + OP_SBC_IMM_VAL, // 001 0110 0 0011 + OP_SBC_IMM_VAL, // 001 0110 0 0100 + OP_SBC_IMM_VAL, // 001 0110 0 0101 + OP_SBC_IMM_VAL, // 001 0110 0 0110 + OP_SBC_IMM_VAL, // 001 0110 0 0111 + OP_SBC_IMM_VAL, // 001 0110 0 1000 + OP_SBC_IMM_VAL, // 001 0110 0 1001 + OP_SBC_IMM_VAL, // 001 0110 0 1010 + OP_SBC_IMM_VAL, // 001 0110 0 1011 + OP_SBC_IMM_VAL, // 001 0110 0 1100 + OP_SBC_IMM_VAL, // 001 0110 0 1101 + OP_SBC_IMM_VAL, // 001 0110 0 1110 + OP_SBC_IMM_VAL, // 001 0110 0 1111 + + OP_SBC_S_IMM_VAL, // 001 0110 1 0000 + OP_SBC_S_IMM_VAL, // 001 0110 1 0001 + OP_SBC_S_IMM_VAL, // 001 0110 1 0010 + OP_SBC_S_IMM_VAL, // 001 0110 1 0011 + OP_SBC_S_IMM_VAL, // 001 0110 1 0100 + OP_SBC_S_IMM_VAL, // 001 0110 1 0101 + OP_SBC_S_IMM_VAL, // 001 0110 1 0110 + OP_SBC_S_IMM_VAL, // 001 0110 1 0111 + OP_SBC_S_IMM_VAL, // 001 0110 1 1000 + OP_SBC_S_IMM_VAL, // 001 0110 1 1001 + OP_SBC_S_IMM_VAL, // 001 0110 1 1010 + OP_SBC_S_IMM_VAL, // 001 0110 1 1011 + OP_SBC_S_IMM_VAL, // 001 0110 1 1100 + OP_SBC_S_IMM_VAL, // 001 0110 1 1101 + OP_SBC_S_IMM_VAL, // 001 0110 1 1110 + OP_SBC_S_IMM_VAL, // 001 0110 1 1111 +//------------------------------------------ + OP_RSC_IMM_VAL, // 001 0111 0 0000 + OP_RSC_IMM_VAL, // 001 0111 0 0001 + OP_RSC_IMM_VAL, // 001 0111 0 0010 + OP_RSC_IMM_VAL, // 001 0111 0 0011 + OP_RSC_IMM_VAL, // 001 0111 0 0100 + OP_RSC_IMM_VAL, // 001 0111 0 0101 + OP_RSC_IMM_VAL, // 001 0111 0 0110 + OP_RSC_IMM_VAL, // 001 0111 0 0111 + OP_RSC_IMM_VAL, // 001 0111 0 1000 + OP_RSC_IMM_VAL, // 001 0111 0 1001 + OP_RSC_IMM_VAL, // 001 0111 0 1010 + OP_RSC_IMM_VAL, // 001 0111 0 1011 + OP_RSC_IMM_VAL, // 001 0111 0 1100 + OP_RSC_IMM_VAL, // 001 0111 0 1101 + OP_RSC_IMM_VAL, // 001 0111 0 1110 + OP_RSC_IMM_VAL, // 001 0111 0 1111 + + OP_RSC_S_IMM_VAL, // 001 0111 1 0000 + OP_RSC_S_IMM_VAL, // 001 0111 1 0001 + OP_RSC_S_IMM_VAL, // 001 0111 1 0010 + OP_RSC_S_IMM_VAL, // 001 0111 1 0011 + OP_RSC_S_IMM_VAL, // 001 0111 1 0100 + OP_RSC_S_IMM_VAL, // 001 0111 1 0101 + OP_RSC_S_IMM_VAL, // 001 0111 1 0110 + OP_RSC_S_IMM_VAL, // 001 0111 1 0111 + OP_RSC_S_IMM_VAL, // 001 0111 1 1000 + OP_RSC_S_IMM_VAL, // 001 0111 1 1001 + OP_RSC_S_IMM_VAL, // 001 0111 1 1010 + OP_RSC_S_IMM_VAL, // 001 0111 1 1011 + OP_RSC_S_IMM_VAL, // 001 0111 1 1100 + OP_RSC_S_IMM_VAL, // 001 0111 1 1101 + OP_RSC_S_IMM_VAL, // 001 0111 1 1110 + OP_RSC_S_IMM_VAL, // 001 0111 1 1111 +//------------------------------------------ + OP_UND, // 001 1000 0 0000 + OP_UND, // 001 1000 0 0001 + OP_UND, // 001 1000 0 0010 + OP_UND, // 001 1000 0 0011 + OP_UND, // 001 1000 0 0100 + OP_UND, // 001 1000 0 0101 + OP_UND, // 001 1000 0 0110 + OP_UND, // 001 1000 0 0111 + OP_UND, // 001 1000 0 1000 + OP_UND, // 001 1000 0 1001 + OP_UND, // 001 1000 0 1010 + OP_UND, // 001 1000 0 1011 + OP_UND, // 001 1000 0 1100 + OP_UND, // 001 1000 0 1101 + OP_UND, // 001 1000 0 1110 + OP_UND, // 001 1000 0 1111 + + OP_TST_IMM_VAL, // 001 1000 1 0000 + OP_TST_IMM_VAL, // 001 1000 1 0001 + OP_TST_IMM_VAL, // 001 1000 1 0010 + OP_TST_IMM_VAL, // 001 1000 1 0011 + OP_TST_IMM_VAL, // 001 1000 1 0100 + OP_TST_IMM_VAL, // 001 1000 1 0101 + OP_TST_IMM_VAL, // 001 1000 1 0110 + OP_TST_IMM_VAL, // 001 1000 1 0111 + OP_TST_IMM_VAL, // 001 1000 1 1000 + OP_TST_IMM_VAL, // 001 1000 1 1001 + OP_TST_IMM_VAL, // 001 1000 1 1010 + OP_TST_IMM_VAL, // 001 1000 1 1011 + OP_TST_IMM_VAL, // 001 1000 1 1100 + OP_TST_IMM_VAL, // 001 1000 1 1101 + OP_TST_IMM_VAL, // 001 1000 1 1110 + OP_TST_IMM_VAL, // 001 1000 1 1111 +//------------------------------------------ + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0000 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0001 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0010 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0011 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0100 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0101 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0110 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 0111 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1000 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1001 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1010 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1011 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1100 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1101 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1110 + OP_MSR_CPSR_IMM_VAL, // 001 1001 0 1111 + + OP_TEQ_IMM_VAL, // 001 1001 1 0000 + OP_TEQ_IMM_VAL, // 001 1001 1 0001 + OP_TEQ_IMM_VAL, // 001 1001 1 0010 + OP_TEQ_IMM_VAL, // 001 1001 1 0011 + OP_TEQ_IMM_VAL, // 001 1001 1 0100 + OP_TEQ_IMM_VAL, // 001 1001 1 0101 + OP_TEQ_IMM_VAL, // 001 1001 1 0110 + OP_TEQ_IMM_VAL, // 001 1001 1 0111 + OP_TEQ_IMM_VAL, // 001 1001 1 1000 + OP_TEQ_IMM_VAL, // 001 1001 1 1001 + OP_TEQ_IMM_VAL, // 001 1001 1 1010 + OP_TEQ_IMM_VAL, // 001 1001 1 1011 + OP_TEQ_IMM_VAL, // 001 1001 1 1100 + OP_TEQ_IMM_VAL, // 001 1001 1 1101 + OP_TEQ_IMM_VAL, // 001 1001 1 1110 + OP_TEQ_IMM_VAL, // 001 1001 1 1111 +//------------------------------------------ + OP_UND, // 001 1010 0 0000 + OP_UND, // 001 1010 0 0001 + OP_UND, // 001 1010 0 0010 + OP_UND, // 001 1010 0 0011 + OP_UND, // 001 1010 0 0100 + OP_UND, // 001 1010 0 0101 + OP_UND, // 001 1010 0 0110 + OP_UND, // 001 1010 0 0111 + OP_UND, // 001 1010 0 1000 + OP_UND, // 001 1010 0 1001 + OP_UND, // 001 1010 0 1010 + OP_UND, // 001 1010 0 1011 + OP_UND, // 001 1010 0 1100 + OP_UND, // 001 1010 0 1101 + OP_UND, // 001 1010 0 1110 + OP_UND, // 001 1010 0 1111 + + OP_CMP_IMM_VAL, // 001 1010 1 0000 + OP_CMP_IMM_VAL, // 001 1010 1 0001 + OP_CMP_IMM_VAL, // 001 1010 1 0010 + OP_CMP_IMM_VAL, // 001 1010 1 0011 + OP_CMP_IMM_VAL, // 001 1010 1 0100 + OP_CMP_IMM_VAL, // 001 1010 1 0101 + OP_CMP_IMM_VAL, // 001 1010 1 0110 + OP_CMP_IMM_VAL, // 001 1010 1 0111 + OP_CMP_IMM_VAL, // 001 1010 1 1000 + OP_CMP_IMM_VAL, // 001 1010 1 1001 + OP_CMP_IMM_VAL, // 001 1010 1 1010 + OP_CMP_IMM_VAL, // 001 1010 1 1011 + OP_CMP_IMM_VAL, // 001 1010 1 1100 + OP_CMP_IMM_VAL, // 001 1010 1 1101 + OP_CMP_IMM_VAL, // 001 1010 1 1110 + OP_CMP_IMM_VAL, // 001 1010 1 1111 +//------------------------------------------ + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0000 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0001 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0010 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0011 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0100 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0101 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0110 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 0111 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1000 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1001 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1010 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1011 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1100 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1101 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1110 + OP_MSR_SPSR_IMM_VAL, // 001 1011 0 1111 + + OP_CMN_IMM_VAL, // 001 1011 1 0000 + OP_CMN_IMM_VAL, // 001 1011 1 0001 + OP_CMN_IMM_VAL, // 001 1011 1 0010 + OP_CMN_IMM_VAL, // 001 1011 1 0011 + OP_CMN_IMM_VAL, // 001 1011 1 0100 + OP_CMN_IMM_VAL, // 001 1011 1 0101 + OP_CMN_IMM_VAL, // 001 1011 1 0110 + OP_CMN_IMM_VAL, // 001 1011 1 0111 + OP_CMN_IMM_VAL, // 001 1011 1 1000 + OP_CMN_IMM_VAL, // 001 1011 1 1001 + OP_CMN_IMM_VAL, // 001 1011 1 1010 + OP_CMN_IMM_VAL, // 001 1011 1 1011 + OP_CMN_IMM_VAL, // 001 1011 1 1100 + OP_CMN_IMM_VAL, // 001 1011 1 1101 + OP_CMN_IMM_VAL, // 001 1011 1 1110 + OP_CMN_IMM_VAL, // 001 1011 1 1111 +//------------------------------------------ + OP_ORR_IMM_VAL, // 001 1100 0 0000 + OP_ORR_IMM_VAL, // 001 1100 0 0001 + OP_ORR_IMM_VAL, // 001 1100 0 0010 + OP_ORR_IMM_VAL, // 001 1100 0 0011 + OP_ORR_IMM_VAL, // 001 1100 0 0100 + OP_ORR_IMM_VAL, // 001 1100 0 0101 + OP_ORR_IMM_VAL, // 001 1100 0 0110 + OP_ORR_IMM_VAL, // 001 1100 0 0111 + OP_ORR_IMM_VAL, // 001 1100 0 1000 + OP_ORR_IMM_VAL, // 001 1100 0 1001 + OP_ORR_IMM_VAL, // 001 1100 0 1010 + OP_ORR_IMM_VAL, // 001 1100 0 1011 + OP_ORR_IMM_VAL, // 001 1100 0 1100 + OP_ORR_IMM_VAL, // 001 1100 0 1101 + OP_ORR_IMM_VAL, // 001 1100 0 1110 + OP_ORR_IMM_VAL, // 001 1100 0 1111 + + OP_ORR_S_IMM_VAL, // 001 1100 1 0000 + OP_ORR_S_IMM_VAL, // 001 1100 1 0001 + OP_ORR_S_IMM_VAL, // 001 1100 1 0010 + OP_ORR_S_IMM_VAL, // 001 1100 1 0011 + OP_ORR_S_IMM_VAL, // 001 1100 1 0100 + OP_ORR_S_IMM_VAL, // 001 1100 1 0101 + OP_ORR_S_IMM_VAL, // 001 1100 1 0110 + OP_ORR_S_IMM_VAL, // 001 1100 1 0111 + OP_ORR_S_IMM_VAL, // 001 1100 1 1000 + OP_ORR_S_IMM_VAL, // 001 1100 1 1001 + OP_ORR_S_IMM_VAL, // 001 1100 1 1010 + OP_ORR_S_IMM_VAL, // 001 1100 1 1011 + OP_ORR_S_IMM_VAL, // 001 1100 1 1100 + OP_ORR_S_IMM_VAL, // 001 1100 1 1101 + OP_ORR_S_IMM_VAL, // 001 1100 1 1110 + OP_ORR_S_IMM_VAL, // 001 1100 1 1111 +//------------------------------------------ + OP_MOV_IMM_VAL, // 001 1101 0 0000 + OP_MOV_IMM_VAL, // 001 1101 0 0001 + OP_MOV_IMM_VAL, // 001 1101 0 0010 + OP_MOV_IMM_VAL, // 001 1101 0 0011 + OP_MOV_IMM_VAL, // 001 1101 0 0100 + OP_MOV_IMM_VAL, // 001 1101 0 0101 + OP_MOV_IMM_VAL, // 001 1101 0 0110 + OP_MOV_IMM_VAL, // 001 1101 0 0111 + OP_MOV_IMM_VAL, // 001 1101 0 1000 + OP_MOV_IMM_VAL, // 001 1101 0 1001 + OP_MOV_IMM_VAL, // 001 1101 0 1010 + OP_MOV_IMM_VAL, // 001 1101 0 1011 + OP_MOV_IMM_VAL, // 001 1101 0 1100 + OP_MOV_IMM_VAL, // 001 1101 0 1101 + OP_MOV_IMM_VAL, // 001 1101 0 1110 + OP_MOV_IMM_VAL, // 001 1101 0 1111 + + OP_MOV_S_IMM_VAL, // 001 1101 1 0000 + OP_MOV_S_IMM_VAL, // 001 1101 1 0001 + OP_MOV_S_IMM_VAL, // 001 1101 1 0010 + OP_MOV_S_IMM_VAL, // 001 1101 1 0011 + OP_MOV_S_IMM_VAL, // 001 1101 1 0100 + OP_MOV_S_IMM_VAL, // 001 1101 1 0101 + OP_MOV_S_IMM_VAL, // 001 1101 1 0110 + OP_MOV_S_IMM_VAL, // 001 1101 1 0111 + OP_MOV_S_IMM_VAL, // 001 1101 1 1000 + OP_MOV_S_IMM_VAL, // 001 1101 1 1001 + OP_MOV_S_IMM_VAL, // 001 1101 1 1010 + OP_MOV_S_IMM_VAL, // 001 1101 1 1011 + OP_MOV_S_IMM_VAL, // 001 1101 1 1100 + OP_MOV_S_IMM_VAL, // 001 1101 1 1101 + OP_MOV_S_IMM_VAL, // 001 1101 1 1110 + OP_MOV_S_IMM_VAL, // 001 1101 1 1111 +//------------------------------------------ + OP_BIC_IMM_VAL, // 001 1110 0 0000 + OP_BIC_IMM_VAL, // 001 1110 0 0001 + OP_BIC_IMM_VAL, // 001 1110 0 0010 + OP_BIC_IMM_VAL, // 001 1110 0 0011 + OP_BIC_IMM_VAL, // 001 1110 0 0100 + OP_BIC_IMM_VAL, // 001 1110 0 0101 + OP_BIC_IMM_VAL, // 001 1110 0 0110 + OP_BIC_IMM_VAL, // 001 1110 0 0111 + OP_BIC_IMM_VAL, // 001 1110 0 1000 + OP_BIC_IMM_VAL, // 001 1110 0 1001 + OP_BIC_IMM_VAL, // 001 1110 0 1010 + OP_BIC_IMM_VAL, // 001 1110 0 1011 + OP_BIC_IMM_VAL, // 001 1110 0 1100 + OP_BIC_IMM_VAL, // 001 1110 0 1101 + OP_BIC_IMM_VAL, // 001 1110 0 1110 + OP_BIC_IMM_VAL, // 001 1110 0 1111 + + OP_BIC_S_IMM_VAL, // 001 1110 1 0000 + OP_BIC_S_IMM_VAL, // 001 1110 1 0001 + OP_BIC_S_IMM_VAL, // 001 1110 1 0010 + OP_BIC_S_IMM_VAL, // 001 1110 1 0011 + OP_BIC_S_IMM_VAL, // 001 1110 1 0100 + OP_BIC_S_IMM_VAL, // 001 1110 1 0101 + OP_BIC_S_IMM_VAL, // 001 1110 1 0110 + OP_BIC_S_IMM_VAL, // 001 1110 1 0111 + OP_BIC_S_IMM_VAL, // 001 1110 1 1000 + OP_BIC_S_IMM_VAL, // 001 1110 1 1001 + OP_BIC_S_IMM_VAL, // 001 1110 1 1010 + OP_BIC_S_IMM_VAL, // 001 1110 1 1011 + OP_BIC_S_IMM_VAL, // 001 1110 1 1100 + OP_BIC_S_IMM_VAL, // 001 1110 1 1101 + OP_BIC_S_IMM_VAL, // 001 1110 1 1110 + OP_BIC_S_IMM_VAL, // 001 1110 1 1111 +//------------------------------------------ + OP_MVN_IMM_VAL, // 001 1111 0 0000 + OP_MVN_IMM_VAL, // 001 1111 0 0001 + OP_MVN_IMM_VAL, // 001 1111 0 0010 + OP_MVN_IMM_VAL, // 001 1111 0 0011 + OP_MVN_IMM_VAL, // 001 1111 0 0100 + OP_MVN_IMM_VAL, // 001 1111 0 0101 + OP_MVN_IMM_VAL, // 001 1111 0 0110 + OP_MVN_IMM_VAL, // 001 1111 0 0111 + OP_MVN_IMM_VAL, // 001 1111 0 1000 + OP_MVN_IMM_VAL, // 001 1111 0 1001 + OP_MVN_IMM_VAL, // 001 1111 0 1010 + OP_MVN_IMM_VAL, // 001 1111 0 1011 + OP_MVN_IMM_VAL, // 001 1111 0 1100 + OP_MVN_IMM_VAL, // 001 1111 0 1101 + OP_MVN_IMM_VAL, // 001 1111 0 1110 + OP_MVN_IMM_VAL, // 001 1111 0 1111 + + OP_MVN_S_IMM_VAL, // 001 1111 1 0000 + OP_MVN_S_IMM_VAL, // 001 1111 1 0001 + OP_MVN_S_IMM_VAL, // 001 1111 1 0010 + OP_MVN_S_IMM_VAL, // 001 1111 1 0011 + OP_MVN_S_IMM_VAL, // 001 1111 1 0100 + OP_MVN_S_IMM_VAL, // 001 1111 1 0101 + OP_MVN_S_IMM_VAL, // 001 1111 1 0110 + OP_MVN_S_IMM_VAL, // 001 1111 1 0111 + OP_MVN_S_IMM_VAL, // 001 1111 1 1000 + OP_MVN_S_IMM_VAL, // 001 1111 1 1001 + OP_MVN_S_IMM_VAL, // 001 1111 1 1010 + OP_MVN_S_IMM_VAL, // 001 1111 1 1011 + OP_MVN_S_IMM_VAL, // 001 1111 1 1100 + OP_MVN_S_IMM_VAL, // 001 1111 1 1101 + OP_MVN_S_IMM_VAL, // 001 1111 1 1110 + OP_MVN_S_IMM_VAL, // 001 1111 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0000 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0001 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0010 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0011 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0100 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0101 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0110 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 0111 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1000 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1001 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1010 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1011 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1100 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1101 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1110 + OP_STR_M_IMM_OFF_POSTIND, //010 0000 0 1111 + + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0000 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0001 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0010 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0011 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0100 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0101 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0110 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 0111 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1000 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1001 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1010 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1011 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1100 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1101 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1110 + OP_LDR_M_IMM_OFF_POSTIND, //010 0000 1 1111 +//------------------------------------------ + OP_UND, //010 0001 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, +//------------------------------------------ + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0000 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0001 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0010 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0011 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0100 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0101 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0110 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 0111 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1000 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1001 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1010 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1011 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1100 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1101 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1110 + OP_STRB_M_IMM_OFF_POSTIND, //010 0010 0 1111 + + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0000 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0001 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0010 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0011 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0100 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0101 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0110 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 0111 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1000 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1001 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1010 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1011 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1100 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1101 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1110 + OP_LDRB_M_IMM_OFF_POSTIND, //010 0010 1 1111 +//------------------------------------------ + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_STRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 + OP_LDRBT_M_IMM_OFF_POSTIND, //010 0011 0 0000 +//------------------------------------------ + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND, //010 0100 0 0000 +//------------------------------------------ + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STR_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 + OP_LDR_P_IMM_OFF_POSTIND2, //010 0100 0 0000 +//------------------------------------------ + OP_STRB_P_IMM_OFF_POSTIND, //010 0110 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRB_P_IMM_OFF_POSTIND, //010 0110 1 1111 +//------------------------------------------ + OP_STRBT_P_IMM_OFF_POSTIND, //010 0111 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_STRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0100 0 0000 + OP_LDRBT_P_IMM_OFF_POSTIND, //010 0111 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF, //010 1000 0 0000 + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + OP_STR_M_IMM_OFF, + + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, + OP_LDR_M_IMM_OFF, //010 1000 1 1111 +//------------------------------------------ + OP_STR_M_IMM_OFF_PREIND, //010 1001 0 0000 + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + OP_STR_M_IMM_OFF_PREIND, + + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, + OP_LDR_M_IMM_OFF_PREIND, //010 1001 1 1111 +//------------------------------------------ + OP_STRB_M_IMM_OFF, //010 1010 0 0000 + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + OP_STRB_M_IMM_OFF, + + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, + OP_LDRB_M_IMM_OFF, //010 1010 1 1111 +//------------------------------------------ + OP_STRB_M_IMM_OFF_PREIND, //010 1011 0 0000 + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + OP_STRB_M_IMM_OFF_PREIND, + + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, + OP_LDRB_M_IMM_OFF_PREIND, //010 1011 1 1111 +//------------------------------------------ + OP_STR_P_IMM_OFF, //010 1100 0 0000 + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + OP_STR_P_IMM_OFF, + + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, + OP_LDR_P_IMM_OFF, //010 1100 1 1111 +//------------------------------------------ + OP_STR_P_IMM_OFF_PREIND, //010 1101 0 0000 + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + OP_STR_P_IMM_OFF_PREIND, + + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, + OP_LDR_P_IMM_OFF_PREIND, //010 1101 1 1111 +//------------------------------------------ + OP_STRB_P_IMM_OFF, //010 1110 0 0000 + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + OP_STRB_P_IMM_OFF, + + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, + OP_LDRB_P_IMM_OFF, //010 1110 1 1111 +//------------------------------------------ + OP_STRB_P_IMM_OFF_PREIND, //010 1111 0 0000 + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + OP_STRB_P_IMM_OFF_PREIND, + + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, + OP_LDRB_P_IMM_OFF_PREIND, //010 1111 1 1111 +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF_POSTIND, //011 0000 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0000 1 1111 +//------------------------------------------ + OP_UND, //011 0001 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, //011 0001 1 1111 +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF_POSTIND, //011 0010 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0010 1 1111 +//------------------------------------------ + OP_STRBT_M_LSL_IMM_OFF_POSTIND, //011 0011 0 0000 + OP_UND, + OP_STRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_M_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0011 1 1111 +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF_POSTIND, //011 0100 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_POSTIND, + OP_UND, //011 0100 1 1111 +//------------------------------------------ + OP_UND, //011 0101 0 0000 + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, + OP_UND, //011 0101 1 1111 +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF_POSTIND, //011 0110 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_POSTIND, + OP_UND, +//------------------------------------------ + OP_STRBT_P_LSL_IMM_OFF_POSTIND, //011 0111 0 0000 + OP_UND, + OP_STRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_STRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + + OP_LDRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSL_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_LSR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ASR_IMM_OFF_POSTIND, + OP_UND, + OP_LDRBT_P_ROR_IMM_OFF_POSTIND, + OP_UND, +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF, //011 1000 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF, + OP_UND, + OP_STR_M_ASR_IMM_OFF, + OP_UND, + OP_STR_M_ROR_IMM_OFF, + OP_UND, + OP_STR_M_LSL_IMM_OFF, + OP_UND, + OP_STR_M_LSR_IMM_OFF, + OP_UND, + OP_STR_M_ASR_IMM_OFF, + OP_UND, + OP_STR_M_ROR_IMM_OFF, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF, + OP_UND, + OP_LDR_M_LSR_IMM_OFF, + OP_UND, + OP_LDR_M_ASR_IMM_OFF, + OP_UND, + OP_LDR_M_ROR_IMM_OFF, + OP_UND, + OP_LDR_M_LSL_IMM_OFF, + OP_UND, + OP_LDR_M_LSR_IMM_OFF, + OP_UND, + OP_LDR_M_ASR_IMM_OFF, + OP_UND, + OP_LDR_M_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STR_M_LSL_IMM_OFF_PREIND, //011 1001 0 0000 + OP_UND, + OP_STR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_M_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_M_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF, //011 1010 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF, + OP_UND, + OP_STRB_M_ASR_IMM_OFF, + OP_UND, + OP_STRB_M_ROR_IMM_OFF, + OP_UND, + OP_STRB_M_LSL_IMM_OFF, + OP_UND, + OP_STRB_M_LSR_IMM_OFF, + OP_UND, + OP_STRB_M_ASR_IMM_OFF, + OP_UND, + OP_STRB_M_ROR_IMM_OFF, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STRB_M_LSL_IMM_OFF_PREIND, //011 1011 0 0000 + OP_UND, + OP_STRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_M_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF, //011 1100 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF, + OP_UND, + OP_STR_P_ASR_IMM_OFF, + OP_UND, + OP_STR_P_ROR_IMM_OFF, + OP_UND, + OP_STR_P_LSL_IMM_OFF, + OP_UND, + OP_STR_P_LSR_IMM_OFF, + OP_UND, + OP_STR_P_ASR_IMM_OFF, + OP_UND, + OP_STR_P_ROR_IMM_OFF, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF, + OP_UND, + OP_LDR_P_LSR_IMM_OFF, + OP_UND, + OP_LDR_P_ASR_IMM_OFF, + OP_UND, + OP_LDR_P_ROR_IMM_OFF, + OP_UND, + OP_LDR_P_LSL_IMM_OFF, + OP_UND, + OP_LDR_P_LSR_IMM_OFF, + OP_UND, + OP_LDR_P_ASR_IMM_OFF, + OP_UND, + OP_LDR_P_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STR_P_LSL_IMM_OFF_PREIND, //011 1101 0 0000 + OP_UND, + OP_STR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STR_P_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDR_P_ROR_IMM_OFF_PREIND, + OP_UND, +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF, //011 1110 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF, + OP_UND, + OP_STRB_P_ASR_IMM_OFF, + OP_UND, + OP_STRB_P_ROR_IMM_OFF, + OP_UND, + OP_STRB_P_LSL_IMM_OFF, + OP_UND, + OP_STRB_P_LSR_IMM_OFF, + OP_UND, + OP_STRB_P_ASR_IMM_OFF, + OP_UND, + OP_STRB_P_ROR_IMM_OFF, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF, + OP_UND, +//------------------------------------------ + OP_STRB_P_LSL_IMM_OFF_PREIND, //011 1111 0 0000 + OP_UND, + OP_STRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_STRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + + OP_LDRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSL_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_LSR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ASR_IMM_OFF_PREIND, + OP_UND, + OP_LDRB_P_ROR_IMM_OFF_PREIND, + OP_UND, //011 1111 1 1111 +//------------------------------------------ + OP_STMDA, //100 0000 0 0000 + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + OP_STMDA, + + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, + OP_LDMDA, +//------------------------------------------ + OP_STMDA_W, //100 0001 0 0000 + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + OP_STMDA_W, + + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, + OP_LDMDA_W, +//------------------------------------------ + OP_STMDA2, //100 0010 0 0000 + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + OP_STMDA2, + + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, + OP_LDMDA2, +//------------------------------------------ + OP_STMDA2_W, //100 0011 0 0000 + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + OP_STMDA2_W, + + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, + OP_LDMDA2_W, +//------------------------------------------ + OP_STMIA, //100 0100 0 0000 + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + OP_STMIA, + + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, + OP_LDMIA, +//------------------------------------------ + OP_STMIA_W, //100 0101 0 0000 + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + OP_STMIA_W, + + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, + OP_LDMIA_W, +//------------------------------------------ + OP_STMIA2, //100 0110 0 0000 + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + OP_STMIA2, + + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, + OP_LDMIA2, +//------------------------------------------ + OP_STMIA2_W, //100 0111 0 0000 + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + OP_STMIA2_W, + + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, + OP_LDMIA2_W, +//------------------------------------------ + OP_STMDB, //100 1000 0 0000 + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + OP_STMDB, + + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, + OP_LDMDB, +//------------------------------------------ + OP_STMDB_W, //100 1001 0 0000 + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + OP_STMDB_W, + + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, + OP_LDMDB_W, +//------------------------------------------ + OP_STMDB2, //100 1010 0 0000 + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + OP_STMDB2, + + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, + OP_LDMDB2, +//------------------------------------------ + OP_STMDB2_W, //100 1011 0 0000 + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + OP_STMDB2_W, + + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, + OP_LDMDB2_W, +//------------------------------------------ + + + OP_STMIB, //100 1100 0 0000 + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + OP_STMIB, + + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, + OP_LDMIB, +//------------------------------------------ + OP_STMIB_W, //100 1101 0 0000 + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + OP_STMIB_W, + + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, + OP_LDMIB_W, +//------------------------------------------ + OP_STMIB2, //100 1110 0 0000 + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + OP_STMIB2, + + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, + OP_LDMIB2, +//------------------------------------------ + OP_STMIB2_W, //100 1111 0 0000 + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + OP_STMIB2_W, + + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, + OP_LDMIB2_W, +//------------------------------------------ + OP_B, //101 0000 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0001 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0010 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0011 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0100 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0101 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0110 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_B, //101 0111 0 0000 + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, + OP_B, +//------------------------------------------ + OP_BL, //101 1000 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1001 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1010 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1011 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1100 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1101 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1110 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_BL, //101 1111 0 0000 + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, + OP_BL, +//------------------------------------------ + OP_STC_OPTION, //110 0000 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_M_POSTIND, //110 0001 0 0000 + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0010 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_M_POSTIND, //110 0011 0 0000 + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + OP_STC_M_POSTIND, + + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, + OP_LDC_M_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0100 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_P_POSTIND, //110 0101 0 0000 + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, +//------------------------------------------ + OP_STC_OPTION, //110 0110 0 0000 + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + OP_STC_OPTION, + + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, + OP_LDC_OPTION, +//------------------------------------------ + OP_STC_P_POSTIND, //110 0111 0 0000 + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + OP_STC_P_POSTIND, + + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, + OP_LDC_P_POSTIND, +//------------------------------------------ + OP_STC_M_IMM_OFF, //110 1000 0 0000 + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, +//------------------------------------------ + OP_STC_M_PREIND, //110 1001 0 0000 + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, +//------------------------------------------ + OP_STC_M_IMM_OFF, //110 1010 0 0000 + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + OP_STC_M_IMM_OFF, + + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, + OP_LDC_M_IMM_OFF, +//------------------------------------------ + OP_STC_M_PREIND, //110 1011 0 0000 + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + OP_STC_M_PREIND, + + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, + OP_LDC_M_PREIND, +//------------------------------------------ + OP_STC_P_IMM_OFF, //110 1100 0 0000 + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, +//------------------------------------------ + OP_STC_P_PREIND, //110 1101 0 0000 + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, +//------------------------------------------ + OP_STC_P_IMM_OFF, //110 1110 0 0000 + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + OP_STC_P_IMM_OFF, + + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, + OP_LDC_P_IMM_OFF, +//------------------------------------------ + OP_STC_P_PREIND, //110 1111 0 0000 + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + OP_STC_P_PREIND, + + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, + OP_LDC_P_PREIND, +//------------------------------------------ + OP_CDP, //111 0000 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0001 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0010 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0011 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0100 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0101 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0110 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_CDP, //111 0111 0 0000 + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + OP_CDP, + OP_MCR, + + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, + OP_CDP, + OP_MRC, +//--------------------------------------------- + OP_SWI, //111 1000 0 0000 + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, + OP_SWI, +}; + diff --git a/tools/vio2sf/src/vio2sf/desmume/matrix.c b/tools/vio2sf/src/vio2sf/desmume/matrix.c new file mode 100644 index 000000000..555d62b15 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/matrix.c @@ -0,0 +1,257 @@ +/* + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "matrix.h" + +void MatrixInit (float *matrix) +{ + memset (matrix, 0, sizeof(float)*16); + + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f; +} + +void MatrixMultVec4x4 (float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8] + matrix[12]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9] + matrix[13]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14]; +} + +void MatrixMultVec3x3 (float *matrix, float *vecPtr) +{ + float x = vecPtr[0]; + float y = vecPtr[1]; + float z = vecPtr[2]; + + vecPtr[0] = x * matrix[0] + y * matrix[4] + z * matrix[ 8]; + vecPtr[1] = x * matrix[1] + y * matrix[5] + z * matrix[ 9]; + vecPtr[2] = x * matrix[2] + y * matrix[6] + z * matrix[10]; +} + +void MatrixIdentity (float *matrix) +{ + memset (matrix, 0, sizeof(float)*16); + + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f; +} + +void MatrixMultiply (float *matrix, float *rightMatrix) +{ + float tmpMatrix[16]; + + tmpMatrix[0] = (matrix[0]*rightMatrix[0])+(matrix[4]*rightMatrix[1])+(matrix[8]*rightMatrix[2])+(matrix[12]*rightMatrix[3]); + tmpMatrix[1] = (matrix[1]*rightMatrix[0])+(matrix[5]*rightMatrix[1])+(matrix[9]*rightMatrix[2])+(matrix[13]*rightMatrix[3]); + tmpMatrix[2] = (matrix[2]*rightMatrix[0])+(matrix[6]*rightMatrix[1])+(matrix[10]*rightMatrix[2])+(matrix[14]*rightMatrix[3]); + tmpMatrix[3] = (matrix[3]*rightMatrix[0])+(matrix[7]*rightMatrix[1])+(matrix[11]*rightMatrix[2])+(matrix[15]*rightMatrix[3]); + + tmpMatrix[4] = (matrix[0]*rightMatrix[4])+(matrix[4]*rightMatrix[5])+(matrix[8]*rightMatrix[6])+(matrix[12]*rightMatrix[7]); + tmpMatrix[5] = (matrix[1]*rightMatrix[4])+(matrix[5]*rightMatrix[5])+(matrix[9]*rightMatrix[6])+(matrix[13]*rightMatrix[7]); + tmpMatrix[6] = (matrix[2]*rightMatrix[4])+(matrix[6]*rightMatrix[5])+(matrix[10]*rightMatrix[6])+(matrix[14]*rightMatrix[7]); + tmpMatrix[7] = (matrix[3]*rightMatrix[4])+(matrix[7]*rightMatrix[5])+(matrix[11]*rightMatrix[6])+(matrix[15]*rightMatrix[7]); + + tmpMatrix[8] = (matrix[0]*rightMatrix[8])+(matrix[4]*rightMatrix[9])+(matrix[8]*rightMatrix[10])+(matrix[12]*rightMatrix[11]); + tmpMatrix[9] = (matrix[1]*rightMatrix[8])+(matrix[5]*rightMatrix[9])+(matrix[9]*rightMatrix[10])+(matrix[13]*rightMatrix[11]); + tmpMatrix[10] = (matrix[2]*rightMatrix[8])+(matrix[6]*rightMatrix[9])+(matrix[10]*rightMatrix[10])+(matrix[14]*rightMatrix[11]); + tmpMatrix[11] = (matrix[3]*rightMatrix[8])+(matrix[7]*rightMatrix[9])+(matrix[11]*rightMatrix[10])+(matrix[15]*rightMatrix[11]); + + tmpMatrix[12] = (matrix[0]*rightMatrix[12])+(matrix[4]*rightMatrix[13])+(matrix[8]*rightMatrix[14])+(matrix[12]*rightMatrix[15]); + tmpMatrix[13] = (matrix[1]*rightMatrix[12])+(matrix[5]*rightMatrix[13])+(matrix[9]*rightMatrix[14])+(matrix[13]*rightMatrix[15]); + tmpMatrix[14] = (matrix[2]*rightMatrix[12])+(matrix[6]*rightMatrix[13])+(matrix[10]*rightMatrix[14])+(matrix[14]*rightMatrix[15]); + tmpMatrix[15] = (matrix[3]*rightMatrix[12])+(matrix[7]*rightMatrix[13])+(matrix[11]*rightMatrix[14])+(matrix[15]*rightMatrix[15]); + + memcpy (matrix, tmpMatrix, sizeof(float)*16); +} +/* +void MatrixMulti (float* right) +{ + float tmpMatrix[16]; + + tmpMatrix[0] = (matrix[0]*right[0])+(matrix[4]*right[1])+(matrix[8]*right[2])+(matrix[12]*right[3]); + tmpMatrix[1] = (matrix[1]*right[0])+(matrix[5]*right[1])+(matrix[9]*right[2])+(matrix[13]*right[3]); + tmpMatrix[2] = (matrix[2]*right[0])+(matrix[6]*right[1])+(matrix[10]*right[2])+(matrix[14]*right[3]); + tmpMatrix[3] = (matrix[3]*right[0])+(matrix[7]*right[1])+(matrix[11]*right[2])+(matrix[15]*right[3]); + + tmpMatrix[4] = (matrix[0]*right[4])+(matrix[4]*right[5])+(matrix[8]*right[6])+(matrix[12]*right[7]); + tmpMatrix[5] = (matrix[1]*right[4])+(matrix[5]*right[5])+(matrix[9]*right[6])+(matrix[13]*right[7]); + tmpMatrix[6] = (matrix[2]*right[4])+(matrix[6]*right[5])+(matrix[10]*right[6])+(matrix[14]*right[7]); + tmpMatrix[7] = (matrix[3]*right[4])+(matrix[7]*right[5])+(matrix[11]*right[6])+(matrix[15]*right[7]); + + tmpMatrix[8] = (matrix[0]*right[8])+(matrix[4]*right[9])+(matrix[8]*right[10])+(matrix[12]*right[11]); + tmpMatrix[9] = (matrix[1]*right[8])+(matrix[5]*right[9])+(matrix[9]*right[10])+(matrix[13]*right[11]); + tmpMatrix[10] = (matrix[2]*right[8])+(matrix[6]*right[9])+(matrix[10]*right[10])+(matrix[14]*right[11]); + tmpMatrix[11] = (matrix[3]*right[8])+(matrix[7]*right[9])+(matrix[11]*right[10])+(matrix[15]*right[11]); + + tmpMatrix[12] = (matrix[0]*right[12])+(matrix[4]*right[13])+(matrix[8]*right[14])+(matrix[12]*right[15]); + tmpMatrix[13] = (matrix[1]*right[12])+(matrix[5]*right[13])+(matrix[9]*right[14])+(matrix[13]*right[15]); + tmpMatrix[14] = (matrix[2]*right[12])+(matrix[6]*right[13])+(matrix[10]*right[14])+(matrix[14]*right[15]); + tmpMatrix[15] = (matrix[3]*right[12])+(matrix[7]*right[13])+(matrix[11]*right[14])+(matrix[15]*right[15]); + + memcpy (matrix, tmpMatrix, sizeof(float)*16); +} + + +float* Matrix::Get (void) +{ + return matrix; +} + +float MatrixGet (float *matrix, int index) +{ + return matrix[index]; +} +*/ + +float MatrixGetMultipliedIndex (int index, float *matrix, float *rightMatrix) +{ + int iMod = index%4, iDiv = (index>>2)<<2; + + return (matrix[iMod ]*rightMatrix[iDiv ])+(matrix[iMod+ 4]*rightMatrix[iDiv+1])+ + (matrix[iMod+8]*rightMatrix[iDiv+2])+(matrix[iMod+12]*rightMatrix[iDiv+3]); +} + +void MatrixSet (float *matrix, int x, int y, float value) +{ + matrix [x+(y<<2)] = value; +} +/* +void Matrix::Set (int pos, float value) +{ + matrix [pos] = value; +} +*/ +void MatrixCopy (float *matrixDST, float *matrixSRC) +{ + memcpy (matrixDST, matrixSRC, sizeof(float)*16); +} + +void MatrixTranslate (float *matrix, float *ptr) +{ + matrix[12] += (matrix[0]*ptr[0])+(matrix[4]*ptr[1])+(matrix[ 8]*ptr[2]); + matrix[13] += (matrix[1]*ptr[0])+(matrix[5]*ptr[1])+(matrix[ 9]*ptr[2]); + matrix[14] += (matrix[2]*ptr[0])+(matrix[6]*ptr[1])+(matrix[10]*ptr[2]); + matrix[15] += (matrix[3]*ptr[0])+(matrix[7]*ptr[1])+(matrix[11]*ptr[2]); +} + +void MatrixScale (float *matrix, float *ptr) +{ + matrix[0] *= ptr[0]; + matrix[1] *= ptr[0]; + matrix[2] *= ptr[0]; + matrix[3] *= ptr[0]; + + matrix[4] *= ptr[1]; + matrix[5] *= ptr[1]; + matrix[6] *= ptr[1]; + matrix[7] *= ptr[1]; + + matrix[8] *= ptr[2]; + matrix[9] *= ptr[2]; + matrix[10] *= ptr[2]; + matrix[11] *= ptr[2]; +} +/* +void Matrix::Set (float a11, float a21, float a31, float a41, + float a12, float a22, float a32, float a42, + float a13, float a23, float a33, float a43, + float a14, float a24, float a34, float a44) +{ +} +*/ + + +//----------------------------------------- + +void MatrixStackInit (MatrixStack *stack) +{ + stack->matrix = NULL; + stack->position = 0; + stack->size = 0; +} + +void MatrixStackSetMaxSize (MatrixStack *stack, int size) +{ + int i = 0; + + stack->size = size; + + if (stack->matrix == NULL) + { + stack->matrix = (float*) malloc (stack->size*16*sizeof(float)); + } + else + { + free (stack->matrix); + stack->matrix = (float*) malloc (stack->size*16*sizeof(float)); + } + + for (i = 0; i < stack->size; i++) + { + MatrixInit (&stack->matrix[i*16]); + } + + stack->size--; +} + + +void MatrixStackSetStackPosition (MatrixStack *stack, int pos) +{ + stack->position += pos; + + if (stack->position < 0) + stack->position = 0; + else if (stack->position > stack->size) + stack->position = stack->size; +} + +void MatrixStackPushMatrix (MatrixStack *stack, float *ptr) +{ + MatrixCopy (&stack->matrix[stack->position*16], ptr); + + MatrixStackSetStackPosition (stack, 1); +} + +float * MatrixStackPopMatrix (MatrixStack *stack, int size) +{ + MatrixStackSetStackPosition(stack, -size); + + return &stack->matrix[stack->position*16]; +} + +float * MatrixStackGetPos (MatrixStack *stack, int pos) +{ + return &stack->matrix[pos*16]; +} + +float * MatrixStackGet (MatrixStack *stack) +{ + return &stack->matrix[stack->position*16]; +} + +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr) +{ + MatrixCopy (&stack->matrix[pos*16], ptr); +} diff --git a/tools/vio2sf/src/vio2sf/desmume/matrix.h b/tools/vio2sf/src/vio2sf/desmume/matrix.h new file mode 100644 index 000000000..05c0786e2 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/matrix.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2006-2007 shash + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MATRIX_H +#define MATRIX_H + +typedef struct MatrixStack +{ + float *matrix; + int position; + int size; +} MatrixStack; + +void MatrixInit (float *matrix); +void MatrixMultVec3x3 (float *matrix, float *vecPtr); +void MatrixMultVec4x4 (float *matrix, float *vecPtr); +void MatrixIdentity (float *matrix); +void MatrixMultiply (float *matrix, float *rightMatrix); +float MatrixGetMultipliedIndex(int index, float *matrix, float *rightMatrix); +void MatrixSet (float *matrix, int x, int y, float value); +void MatrixCopy (float *matrixDST, float *matrixSRC); +void MatrixTranslate (float *matrix, float *ptr); +void MatrixScale (float *matrix, float *ptr); + +void MatrixStackInit (MatrixStack *stack); +void MatrixStackSetMaxSize (MatrixStack *stack, int size); +void MatrixStackSetStackPosition (MatrixStack *stack, int pos); +void MatrixStackPushMatrix (MatrixStack *stack, float *ptr); +float* MatrixStackPopMatrix (MatrixStack *stack, int size); +float* MatrixStackGetPos (MatrixStack *stack, int pos); +float* MatrixStackGet (MatrixStack *stack); +void MatrixStackLoadMatrix (MatrixStack *stack, int pos, float *ptr); + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/mc.c b/tools/vio2sf/src/vio2sf/desmume/mc.c new file mode 100644 index 000000000..756a92c8d --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/mc.c @@ -0,0 +1,121 @@ +/* Copyright (C) 2006 thoduv + Copyright (C) 2006-2007 Theo Berkau + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include "debug.h" +#include "types.h" +#include "mc.h" + +#define FW_CMD_READ 0x3 +#define FW_CMD_WRITEDISABLE 0x4 +#define FW_CMD_READSTATUS 0x5 +#define FW_CMD_WRITEENABLE 0x6 +#define FW_CMD_PAGEWRITE 0xA + +#define BM_CMD_AUTODETECT 0xFF +#define BM_CMD_WRITESTATUS 0x1 +#define BM_CMD_WRITELOW 0x2 +#define BM_CMD_READLOW 0x3 +#define BM_CMD_WRITEDISABLE 0x4 +#define BM_CMD_READSTATUS 0x5 +#define BM_CMD_WRITEENABLE 0x6 +#define BM_CMD_WRITEHIGH 0xA +#define BM_CMD_READHIGH 0xB + +/* FLASH*/ +#define COMM_PAGE_WRITE 0x0A +#define COMM_PAGE_ERASE 0xDB +#define COMM_SECTOR_ERASE 0xD8 +#define COMM_CHIP_ERASE 0xC7 +#define CARDFLASH_READ_BYTES_FAST 0x0B /* Not used*/ +#define CARDFLASH_DEEP_POWDOWN 0xB9 /* Not used*/ +#define CARDFLASH_WAKEUP 0xAB /* Not used*/ + +void mc_init(memory_chip_t *mc, int type) +{ + mc->com = 0; + mc->addr = 0; + mc->addr_shift = 0; + mc->data = NULL; + mc->size = 0; + mc->write_enable = FALSE; + mc->writeable_buffer = FALSE; + mc->type = type; + mc->autodetectsize = 0; + + switch(mc->type) + { + case MC_TYPE_EEPROM1: + mc->addr_size = 1; + break; + case MC_TYPE_EEPROM2: + case MC_TYPE_FRAM: + mc->addr_size = 2; + break; + case MC_TYPE_FLASH: + mc->addr_size = 3; + break; + default: break; + } +} + +u8 *mc_alloc(memory_chip_t *mc, u32 size) +{ + u8 *buffer; + buffer = malloc(size); + + mc->data = buffer; + if(!buffer) { return NULL; } + mc->size = size; + mc->writeable_buffer = TRUE; + + return buffer; +} + +void mc_free(memory_chip_t *mc) +{ + if(mc->data) + { + free(mc->data); + mc->data = 0; + } + mc_init(mc, 0); +} + +void mc_realloc(memory_chip_t *mc, int type, u32 size) +{ + mc_free(mc); + mc_init(mc, type); + mc_alloc(mc, size); +} + + +void mc_reset_com(memory_chip_t *mc) +{ +} +u8 fw_transfer(memory_chip_t *mc, u8 data) +{ + return 0; +} +u8 bm_transfer(memory_chip_t *mc, u8 data) +{ + return 0; +} + diff --git a/tools/vio2sf/src/vio2sf/desmume/mc.h b/tools/vio2sf/src/vio2sf/desmume/mc.h new file mode 100644 index 000000000..f78b7c39f --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/mc.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2006 thoduv + Copyright (C) 2006 Theo Berkau + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __FW_H__ +#define __FW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "types.h" + +#define MC_TYPE_AUTODETECT 0x0 +#define MC_TYPE_EEPROM1 0x1 +#define MC_TYPE_EEPROM2 0x2 +#define MC_TYPE_FLASH 0x3 +#define MC_TYPE_FRAM 0x4 + +#define MC_SIZE_4KBITS 0x000200 +#define MC_SIZE_64KBITS 0x002000 +#define MC_SIZE_256KBITS 0x008000 +#define MC_SIZE_512KBITS 0x010000 +#define MC_SIZE_1MBITS 0x020000 +#define MC_SIZE_2MBITS 0x040000 +#define MC_SIZE_4MBITS 0x080000 +#define MC_SIZE_8MBITS 0x100000 +#define MC_SIZE_16MBITS 0x200000 +#define MC_SIZE_64MBITS 0x800000 + +static int save_types[6][2] = { + {MC_TYPE_AUTODETECT,1}, + {MC_TYPE_EEPROM1,MC_SIZE_4KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_64KBITS}, + {MC_TYPE_EEPROM2,MC_SIZE_512KBITS}, + {MC_TYPE_FLASH,MC_SIZE_256KBITS}, + {MC_TYPE_FRAM,MC_SIZE_2MBITS} +}; + +typedef struct +{ + u8 com; /* persistent command actually handled */ + u32 addr; /* current address for reading/writing */ + u8 addr_shift; /* shift for address (since addresses are transfered by 3 bytes units) */ + u8 addr_size; /* size of addr when writing/reading */ + + BOOL write_enable; /* is write enabled ? */ + + u8 *data; /* memory data */ + u32 size; /* memory size */ + BOOL writeable_buffer; /* is "data" writeable ? */ + int type; /* type of Memory */ + char *filename; + FILE *fp; + u8 autodetectbuf[32768]; + int autodetectsize; +} memory_chip_t; + +#define NDS_FW_SIZE_V1 (256 * 1024) /* size of fw memory on nds v1 */ +#define NDS_FW_SIZE_V2 (512 * 1024) /* size of fw memory on nds v2 */ + +void mc_init(memory_chip_t *mc, int type); /* reset and init values for memory struct */ +u8 *mc_alloc(memory_chip_t *mc, u32 size); /* alloc mc memory */ +void mc_realloc(memory_chip_t *mc, int type, u32 size); /* realloc mc memory */ +void mc_load_file(memory_chip_t *mc, const char* filename); /* load save file and setup fp */ +int mc_load_duc(memory_chip_t *mc, const char* filename); /* load Action Replay DS save file */ +void mc_free(memory_chip_t *mc); /* delete mc memory */ +void mc_reset_com(memory_chip_t *mc); /* reset communication with mc */ +u8 fw_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from firmware */ +u8 bm_transfer(memory_chip_t *mc, u8 data); /* transfer to, then receive data from backup memory */ + +#ifdef __cplusplus +} +#endif + +#endif /*__FW_H__*/ + diff --git a/tools/vio2sf/src/vio2sf/desmume/mem.h b/tools/vio2sf/src/vio2sf/desmume/mem.h new file mode 100644 index 000000000..72060f1f5 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/mem.h @@ -0,0 +1,141 @@ +/* Copyright 2005-2006 Guillaume Duhamel + Copyright 2005 Theo Berkau + + This file is part of Yabause. + + Yabause is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Yabause is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Yabause; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MEM_H +#define MEM_H + +#include +#include "types.h" + +/* Type 1 Memory, faster for byte (8 bits) accesses */ + +static INLINE u8 T1ReadByte(u8 * mem, u32 addr) +{ + return mem[addr]; +} + +static INLINE u16 T1ReadWord(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 1] << 8) | mem[addr]; +#else + return *((u16 *) (mem + addr)); +#endif +} + +static INLINE u32 T1ReadLong(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *((u32 *)mem + (addr>>2)); +#endif +} + +static INLINE u64 T1ReadQuad(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return (mem[addr + 7] << 56 | mem[addr + 6] << 48 | + mem[addr + 5] << 40 | mem[addr + 4] << 32 | + mem[addr + 3] << 24 | mem[addr + 2] << 16 | + mem[addr + 1] << 8 | mem[addr]); +#else + return *((u64 *) (mem + addr)); +#endif +} + +static INLINE void T1WriteByte(u8 * mem, u32 addr, u8 val) +{ + mem[addr] = val; +} + +static INLINE void T1WriteWord(u8 * mem, u32 addr, u16 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 1] = val >> 8; + mem[addr] = val & 0xFF; +#else + *((u16 *) (mem + addr)) = val; +#endif +} + +static INLINE void T1WriteLong(u8 * mem, u32 addr, u32 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr + 3] = val >> 24; + mem[addr + 2] = (val >> 16) & 0xFF; + mem[addr + 1] = (val >> 8) & 0xFF; + mem[addr] = val & 0xFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +/* Type 2 Memory, faster for word (16 bits) accesses */ + +static INLINE u8 T2ReadByte(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return mem[addr ^ 1]; +#else + return mem[addr]; +#endif +} + +static INLINE u16 T2ReadWord(u8 * mem, u32 addr) +{ + return *((u16 *) (mem + addr)); +} + +static INLINE u32 T2ReadLong(u8 * mem, u32 addr) +{ +#ifdef WORDS_BIGENDIAN + return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr)); +#else + return *((u32 *) (mem + addr)); +#endif +} + +static INLINE void T2WriteByte(u8 * mem, u32 addr, u8 val) +{ +#ifdef WORDS_BIGENDIAN + mem[addr ^ 1] = val; +#else + mem[addr] = val; +#endif +} + +static INLINE void T2WriteWord(u8 * mem, u32 addr, u16 val) +{ + *((u16 *) (mem + addr)) = val; +} + +static INLINE void T2WriteLong(u8 * mem, u32 addr, u32 val) +{ +#ifdef WORDS_BIGENDIAN + *((u16 *) (mem + addr + 2)) = val >> 16; + *((u16 *) (mem + addr)) = val & 0xFFFF; +#else + *((u32 *) (mem + addr)) = val; +#endif +} + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/registers.h b/tools/vio2sf/src/vio2sf/desmume/registers.h new file mode 100644 index 000000000..f9060214d --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/registers.h @@ -0,0 +1,333 @@ +/* Copyright (C) 2006 Theo Berkau + + Ideas borrowed from Stephane Dallongeville's SCSP core + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef REGISTERS_H +#define REGISTERS_H + +#define REG_REGION_MASK 0x0FFFEF80 +#define REG_BASE_DISPx 0x04000000 +#define REG_BASE_DISPA 0x04000000 +#define REG_BASE_DISPB 0x04001000 +#define REG_BASE_DMA 0x04000080 +#define REG_BASE_SIORTCTIMERS 0x04000100 +#define REG_BASE_ROMIPC 0x04000180 +#define REG_BASE_MEMIRQ 0x04000200 +#define REG_BASE_MATH 0x04000280 +#define REG_BASE_OTHER 0x04000300 +#define REG_BASE_RCVPORTS 0x04100000 + +// Display Engine A +#define REG_DISPA_DISPCNT 0x04000000 +#define REG_DISPA_VCOUNT 0x04000006 +#define REG_DISPA_BG0CNT 0x04000008 +#define REG_DISPA_BG1CNT 0x0400000A +#define REG_DISPA_BG2CNT 0x0400000C +#define REG_DISPA_BG3CNT 0x0400000E +#define REG_DISPA_BG0HOFS 0x04000010 +#define REG_DISPA_BG0VOFS 0x04000012 +#define REG_DISPA_BG1HOFS 0x04000014 +#define REG_DISPA_BG1VOFS 0x04000016 +#define REG_DISPA_BG2HOFS 0x04000018 +#define REG_DISPA_BG2VOFS 0x0400001A +#define REG_DISPA_BG3HOFS 0x0400001C +#define REG_DISPA_BG3VOFS 0x0400001E +#define REG_DISPA_BG2PA 0x04000020 +#define REG_DISPA_BG2PB 0x04000022 +#define REG_DISPA_BG2PC 0x04000024 +#define REG_DISPA_BG2PD 0x04000026 +#define REG_DISPA_BG2XL 0x04000028 +#define REG_DISPA_BG2XH 0x0400002A +#define REG_DISPA_BG2YL 0x0400002C +#define REG_DISPA_BG2YH 0x0400002E +#define REG_DISPA_BG3PA 0x04000030 +#define REG_DISPA_BG3PB 0x04000032 +#define REG_DISPA_BG3PC 0x04000034 +#define REG_DISPA_BG3PD 0x04000036 +#define REG_DISPA_BG3XL 0x04000038 +#define REG_DISPA_BG3XH 0x0400003A +#define REG_DISPA_BG3YL 0x0400003C +#define REG_DISPA_BG3YH 0x0400003E +#define REG_DISPA_WIN0H 0x04000040 +#define REG_DISPA_WIN1H 0x04000042 +#define REG_DISPA_WIN0V 0x04000044 +#define REG_DISPA_WIN1V 0x04000046 +#define REG_DISPA_WININ 0x04000048 +#define REG_DISPA_WINOUT 0x0400004A +#define REG_DISPA_MOSAIC 0x0400004C +#define REG_DISPA_BLDCNT 0x04000050 +#define REG_DISPA_BLDALPHA 0x04000052 +#define REG_DISPA_BLDY 0x04000054 +#define REG_DISPA_MASTERBRIGHT 0x0400006C + +// DMA +#define REG_DMA0SAD 0x040000B0 +#define REG_DMA0DAD 0x040000B4 +#define REG_DMA0CNTL 0x040000B8 +#define REG_DMA0CNTH 0x040000BA +#define REG_DMA1SAD 0x040000BC +#define REG_DMA1DAD 0x040000C0 +#define REG_DMA1CNTL 0x040000C4 +#define REG_DMA1CNTH 0x040000C6 +#define REG_DMA2SAD 0x040000C8 +#define REG_DMA2DAD 0x040000CC +#define REG_DMA2CNTL 0x040000D0 +#define REG_DMA2CNTH 0x040000D2 +#define REG_DMA3SAD 0x040000D4 +#define REG_DMA3DAD 0x040000D8 +#define REG_DMA3CNTL 0x040000DC +#define REG_DMA3CNTH 0x040000DE +#define REG_DMA0FILL 0x040000E0 +#define REG_DMA1FILL 0x040000E4 +#define REG_DMA2FILL 0x040000E8 +#define REG_DMA3FILL 0x040000EC + +// Timers +#define REG_TM0CNTL 0x04000100 +#define REG_TM0CNTH 0x04000102 +#define REG_TM1CNTL 0x04000104 +#define REG_TM1CNTH 0x04000106 +#define REG_TM2CNTL 0x04000108 +#define REG_TM2CNTH 0x0400010A +#define REG_TM3CNTL 0x0400010C +#define REG_TM3CNTH 0x0400010E + +// SIO/Keypad Input/RTC +#define REG_SIODATA32 0x04000120 +#define REG_SIOCNT 0x04000128 +#define REG_KEYINPUT 0x04000130 +#define REG_KEYCNT 0x04000132 +#define REG_RCNT 0x04000134 +#define REG_EXTKEYIN 0x04000136 +#define REG_RTC 0x04000138 + +// IPC +#define REG_IPCSYNC 0x04000180 +#define REG_IPCFIFOCNT 0x04000184 +#define REG_IPCFIFOSEND 0x04000188 + +// ROM +#define REG_AUXSPICNT 0x040001A0 +#define REG_AUXSPIDATA 0x040001A2 +#define REG_GCROMCTRL 0x040001A4 +#define REG_GCCMDOUT 0x040001A8 +#define REG_ENCSEED0L 0x040001B0 +#define REG_ENCSEED1L 0x040001B4 +#define REG_ENCSEED0H 0x040001B8 +#define REG_ENCSEED1H 0x040001BC +#define REG_SPICNT 0x040001C0 +#define REG_SPIDATA 0x040001C2 + +// Memory/IRQ +#define REG_EXMEMCNT 0x04000204 +#define REG_WIFIWAITCNT 0x04000206 +#define REG_IME 0x04000208 +#define REG_IE 0x04000210 +#define REG_IF 0x04000214 +#define REG_VRAMCNTA 0x04000240 +#define REG_VRAMSTAT 0x04000240 +#define REG_VRAMCNTB 0x04000241 +#define REG_WRAMSTAT 0x04000241 +#define REG_VRAMCNTC 0x04000242 +#define REG_VRAMCNTD 0x04000243 +#define REG_VRAMCNTE 0x04000244 +#define REG_VRAMCNTF 0x04000245 +#define REG_VRAMCNTG 0x04000246 +#define REG_WRAMCNT 0x04000247 +#define REG_VRAMCNTH 0x04000248 +#define REG_VRAMCNTI 0x04000249 + +// Math +#define REG_DIVCNT 0x04000280 +#define REG_DIVNUMER 0x04000290 +#define REG_DIVDENOM 0x04000298 +#define REG_DIVRESULT 0x040002A0 +#define REG_DIVREMRESULT 0x040002A8 +#define REG_SQRTCNT 0x040002B0 +#define REG_SQRTRESULT 0x040002B4 +#define REG_SQRTPARAM 0x040002B8 + +// Other +#define REG_POSTFLG 0x04000300 +#define REG_HALTCNT 0x04000301 +#define REG_POWCNT1 0x04000304 +#define REG_POWCNT2 0x04000304 +#define REG_BIOSPROT 0x04000308 + +#define REG_DISPB_DISPCNT 0x04001000 +#define REG_DISPB_BG0CNT 0x04001008 +#define REG_DISPB_BG1CNT 0x0400100A +#define REG_DISPB_BG2CNT 0x0400100C +#define REG_DISPB_BG3CNT 0x0400100E +#define REG_DISPB_BG0HOFS 0x04001010 +#define REG_DISPB_BG0VOFS 0x04001012 +#define REG_DISPB_BG1HOFS 0x04001014 +#define REG_DISPB_BG1VOFS 0x04001016 +#define REG_DISPB_BG2HOFS 0x04001018 +#define REG_DISPB_BG2VOFS 0x0400101A +#define REG_DISPB_BG3HOFS 0x0400101C +#define REG_DISPB_BG3VOFS 0x0400101E +#define REG_DISPB_BG2PA 0x04001020 +#define REG_DISPB_BG2PB 0x04001022 +#define REG_DISPB_BG2PC 0x04001024 +#define REG_DISPB_BG2PD 0x04001026 +#define REG_DISPB_BG2XL 0x04001028 +#define REG_DISPB_BG2XH 0x0400102A +#define REG_DISPB_BG2YL 0x0400102C +#define REG_DISPB_BG2YH 0x0400102E +#define REG_DISPB_BG3PA 0x04001030 +#define REG_DISPB_BG3PB 0x04001032 +#define REG_DISPB_BG3PC 0x04001034 +#define REG_DISPB_BG3PD 0x04001036 +#define REG_DISPB_BG3XL 0x04001038 +#define REG_DISPB_BG3XH 0x0400103A +#define REG_DISPB_BG3YL 0x0400103C +#define REG_DISPB_BG3YH 0x0400103E +#define REG_DISPB_WIN0H 0x04001040 +#define REG_DISPB_WIN1H 0x04001042 +#define REG_DISPB_WIN0V 0x04001044 +#define REG_DISPB_WIN1V 0x04001046 +#define REG_DISPB_WININ 0x04001048 +#define REG_DISPB_WINOUT 0x0400104A +#define REG_DISPB_MOSAIC 0x0400104C +#define REG_DISPB_BLDCNT 0x04001050 +#define REG_DISPB_BLDALPHA 0x04001052 +#define REG_DISPB_BLDY 0x04001054 +#define REG_DISPB_MASTERBRIGHT 0x0400106C + +// Receive ports +#define REG_IPCFIFORECV 0x04100000 +#define REG_GCDATAIN 0x04100010 + + + + + +#define REG_DISPB 0x00001000 +// core A and B specific +#define REG_DISPx_DISPCNT 0x04000000 +#define REG_DISPx_VCOUNT 0x04000006 +#define REG_DISPx_BG0CNT 0x04000008 +#define REG_DISPx_BG1CNT 0x0400000A +#define REG_DISPx_BG2CNT 0x0400000C +#define REG_DISPx_BG3CNT 0x0400000E +#define REG_DISPx_BG0HOFS 0x04000010 +#define REG_DISPx_BG0VOFS 0x04000012 +#define REG_DISPx_BG1HOFS 0x04000014 +#define REG_DISPx_BG1VOFS 0x04000016 +#define REG_DISPx_BG2HOFS 0x04000018 +#define REG_DISPx_BG2VOFS 0x0400001A +#define REG_DISPx_BG3HOFS 0x0400001C +#define REG_DISPx_BG3VOFS 0x0400001E +#define REG_DISPx_BG2PA 0x04000020 +#define REG_DISPx_BG2PB 0x04000022 +#define REG_DISPx_BG2PC 0x04000024 +#define REG_DISPx_BG2PD 0x04000026 +#define REG_DISPx_BG2XL 0x04000028 +#define REG_DISPx_BG2XH 0x0400002A +#define REG_DISPx_BG2YL 0x0400002C +#define REG_DISPx_BG2YH 0x0400002E +#define REG_DISPx_BG3PA 0x04000030 +#define REG_DISPx_BG3PB 0x04000032 +#define REG_DISPx_BG3PC 0x04000034 +#define REG_DISPx_BG3PD 0x04000036 +#define REG_DISPx_BG3XL 0x04000038 +#define REG_DISPx_BG3XH 0x0400003A +#define REG_DISPx_BG3YL 0x0400003C +#define REG_DISPx_BG3YH 0x0400003E +#define REG_DISPx_WIN0H 0x04000040 +#define REG_DISPx_WIN1H 0x04000042 +#define REG_DISPx_WIN0V 0x04000044 +#define REG_DISPx_WIN1V 0x04000046 +#define REG_DISPx_WININ 0x04000048 +#define REG_DISPx_WINOUT 0x0400004A +#define REG_DISPx_MOSAIC 0x0400004C +#define REG_DISPx_BLDCNT 0x04000050 +#define REG_DISPx_BLDALPHA 0x04000052 +#define REG_DISPx_BLDY 0x04000054 +#define REG_DISPx_MASTERBRIGHT 0x0400006C +// core A specific +#define REG_DISPA_DISPSTAT 0x04000004 +#define REG_DISPA_DISP3DCNT 0x04000060 +#define REG_DISPA_DISPCAPCNT 0x04000064 +#define REG_DISPA_DISPMMEMFIFO 0x04000068 + + +#define eng_3D_RDLINES_COUNT 0x04000320 +#define eng_3D_EDGE_COLOR 0x04000330 +#define eng_3D_ALPHA_TEST_REF 0x04000340 +#define eng_3D_CLEAR_COLOR 0x04000350 +#define eng_3D_CLEAR_DEPTH 0x04000354 +#define eng_3D_CLRIMAGE_OFFSET 0x04000356 +#define eng_3D_FOG_COLOR 0x04000358 +#define eng_3D_FOG_OFFSET 0x0400035C +#define eng_3D_FOG_TABLE 0x04000360 +#define eng_3D_TOON_TABLE 0x04000380 +#define eng_3D_GXFIFO 0x04000400 + +// 3d commands +#define cmd_3D_MTX_MODE 0x04000440 +#define cmd_3D_MTX_PUSH 0x04000444 +#define cmd_3D_MTX_POP 0x04000448 +#define cmd_3D_MTX_STORE 0x0400044C +#define cmd_3D_MTX_RESTORE 0x04000450 +#define cmd_3D_MTX_IDENTITY 0x04000454 +#define cmd_3D_MTX_LOAD_4x4 0x04000458 +#define cmd_3D_MTX_LOAD_4x3 0x0400045C +#define cmd_3D_MTX_MULT_4x4 0x04000460 +#define cmd_3D_MTX_MULT_4x3 0x04000464 +#define cmd_3D_MTX_MULT_3x3 0x04000468 +#define cmd_3D_MTX_SCALE 0x0400046C +#define cmd_3D_MTX_TRANS 0x04000470 +#define cmd_3D_COLOR 0x04000480 +#define cmd_3D_NORMA 0x04000484 +#define cmd_3D_TEXCOORD 0x04000488 +#define cmd_3D_VTX_16 0x0400048C +#define cmd_3D_VTX_10 0x04000490 +#define cmd_3D_VTX_XY 0x04000494 +#define cmd_3D_VTX_XZ 0x04000498 +#define cmd_3D_VTX_YZ 0x0400049C +#define cmd_3D_VTX_DIFF 0x040004A0 +#define cmd_3D_POLYGON_ATTR 0x040004A4 +#define cmd_3D_TEXIMAGE_PARAM 0x040004A8 +#define cmd_3D_PLTT_BASE 0x040004AC +#define cmd_3D_DIF_AMB 0x040004C0 +#define cmd_3D_SPE_EMI 0x040004C4 +#define cmd_3D_LIGHT_VECTOR 0x040004C8 +#define cmd_3D_LIGHT_COLOR 0x040004CC +#define cmd_3D_SHININESS 0x040004D0 +#define cmd_3D_BEGIN_VTXS 0x04000500 +#define cmd_3D_END_VTXS 0x04000504 +#define cmd_3D_SWAP_BUFFERS 0x04000540 +#define cmd_3D_VIEWPORT 0x04000580 +#define cmd_3D_BOX_TEST 0x040005C0 +#define cmd_3D_POS_TEST 0x040005C4 +#define cmd_3D_VEC_TEST 0x040005C8 + +#define eng_3D_GXSTAT 0x04000600 +#define eng_3D_RAM_COUNT 0x04000604 +#define eng_3D_DISP_1DOT_DEPTH 0x04000610 +#define eng_3D_POS_RESULT 0x04000620 +#define eng_3D_VEC_RESULT 0x04000630 +#define eng_3D_CLIPMTX_RESULT 0x04000640 +#define eng_3D_VECMTX_RESULT 0x04000680 + + +#endif diff --git a/tools/vio2sf/src/vio2sf/desmume/spu_exports.h b/tools/vio2sf/src/vio2sf/desmume/spu_exports.h new file mode 100644 index 000000000..d1b186e8c --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/spu_exports.h @@ -0,0 +1,30 @@ +#ifndef _SPU_EXPORTS_H +#define _SPU_EXPORTS_H + + +#ifndef _SPU_CPP_ + +void SPU_WriteLong(u32 addr, u32 val); +void SPU_WriteByte(u32 addr, u8 val); +void SPU_WriteWord(u32 addr, u16 val); +void SPU_EmulateSamples(int numsamples); +int SPU_ChangeSoundCore(int coreid, int buffersize); +void SPU_Reset(void); +void SPU_DeInit(void); + +typedef struct +{ + int id; + const char *Name; + int (*Init)(int buffersize); + void (*DeInit)(); + void (*UpdateAudio)(s16 *buffer, u32 num_samples); + u32 (*GetAudioSpace)(); + void (*MuteAudio)(); + void (*UnMuteAudio)(); + void (*SetVolume)(int volume); +} SoundInterface_struct; + +#endif _SPU_CPP_ + +#endif //_SPU_EXPORTS_H diff --git a/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.c b/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.c new file mode 100644 index 000000000..fbe5e31c8 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.c @@ -0,0 +1,944 @@ +/* + Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + Code added on 18/08/2006 by shash + - Missing missaligned addresses correction + (reference in http://nocash.emubase.de/gbatek.htm#cpumemoryalignments) + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bios.h" +#include "debug.h" +#include "MMU.h" + +#define REG_NUM(i, n) (((i)>>n)&0x7) + +extern BOOL execute; + +// Use this macros for reading/writing, so the GDB stub isn't broken +#ifdef GDB_STUB + #define READ32(a,b) cpu->mem_if->read32(a,b) + #define WRITE32(a,b,c) cpu->mem_if->write32(a,b,c) + #define READ16(a,b) cpu->mem_if->read16(a,b) + #define WRITE16(a,b,c) cpu->mem_if->write16(a,b,c) + #define READ8(a,b) cpu->mem_if->read8(a,b) + #define WRITE8(a,b,c) cpu->mem_if->write8(a,b,c) +#else + #define READ32(a,b) MMU_read32(cpu->proc_ID, b) + #define WRITE32(a,b,c) MMU_write32(cpu->proc_ID,b,c) + #define READ16(a,b) MMU_read16(cpu->proc_ID, b) + #define WRITE16(a,b,c) MMU_write16(cpu->proc_ID,b,c) + #define READ8(a,b) MMU_read8(cpu->proc_ID, b) + #define WRITE8(a,b,c) MMU_write8(cpu->proc_ID,b,c) +#endif + +static u32 FASTCALL OP_UND_THUMB(armcpu_t *cpu) +{ + execute = FALSE; + return 1; +} + +static u32 FASTCALL OP_LSL_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] = cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_LSL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], 32-v); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] << v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_LSR_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + // cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 2; +} + +static u32 FASTCALL OP_LSR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = (cpu->R[REG_NUM(i, 3)] >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ASR_0(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 3)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 3)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ASR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = (i>>6) & 0x1F; + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 3)], v-1); + cpu->R[REG_NUM(i, 0)] = (((s32)cpu->R[REG_NUM(i, 3)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 2; +} + +static u32 FASTCALL OP_ADD_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + u32 b = cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = a + b; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_SUB_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + u32 b = cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = a - b; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, b, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_ADD_IMM3(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = a + REG_NUM(i, 6); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + + return 2; +} + +static u32 FASTCALL OP_SUB_IMM3(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = a - REG_NUM(i, 6); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, REG_NUM(i, 6), cpu->R[REG_NUM(i, 0)]); + + return 2; +} + +static u32 FASTCALL OP_MOV_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = i & 0xFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 8)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 8)] == 0; + + return 2; +} + +static u32 FASTCALL OP_CMP_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + + return 2; +} + +static u32 FASTCALL OP_ADD_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] + (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->R[REG_NUM(i, 8)] = tmp; + + return 2; +} + +static u32 FASTCALL OP_SUB_IMM8(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 8)] - (i & 0xFF); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 8)], (i & 0xFF), tmp); + cpu->R[REG_NUM(i, 8)] = tmp; + + return 2; +} + +static u32 FASTCALL OP_AND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] &= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_EOR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] ^= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_LSL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], 32-v); + cpu->R[REG_NUM(i, 0)] <<= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v==32) + cpu->CPSR.bits.C = BIT0(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 3; +} + +static u32 FASTCALL OP_LSR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] >>= v; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v==32) + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + else + cpu->CPSR.bits.C = 0; + cpu->R[REG_NUM(i, 0)] = 0; + cpu->CPSR.bits.N = 0; + cpu->CPSR.bits.Z = 1; + + return 3; +} + +static u32 FASTCALL OP_ASR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(!v) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + if(v<32) + { + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = (u32)(((s32)cpu->R[REG_NUM(i, 0)]) >> v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->R[REG_NUM(i, 0)] = BIT31(cpu->R[REG_NUM(i, 0)])*0xFFFFFFFF; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_ADC_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 0)]; + u32 b = cpu->R[REG_NUM(i, 3)]; + u32 tmp = b + cpu->CPSR.bits.C; + u32 res = a + tmp; + + cpu->R[REG_NUM(i, 0)] = res; + + cpu->CPSR.bits.N = BIT31(res); + cpu->CPSR.bits.Z = res == 0; + + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | UNSIGNED_OVERFLOW(tmp, a, res); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(b, cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, a, res); + + return 3; +} + +static u32 FASTCALL OP_SBC_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 0)]; + u32 b = cpu->R[REG_NUM(i, 3)]; + u32 tmp = a - (!cpu->CPSR.bits.C); + u32 res = tmp - b; + cpu->R[REG_NUM(i, 0)] = res; + + cpu->CPSR.bits.N = BIT31(res); + cpu->CPSR.bits.Z = res == 0; + + cpu->CPSR.bits.C = (!UNSIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp)) & (!UNSIGNED_OVERFLOW(tmp, b, res)); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(a, !cpu->CPSR.bits.C, tmp) | SIGNED_OVERFLOW(tmp, b, res); + + return 3; +} + +static u32 FASTCALL OP_ROR_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 v = cpu->R[REG_NUM(i, 3)]&0xFF; + + if(v == 0) + { + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + v &= 0xF; + if(v == 0) + { + cpu->CPSR.bits.C = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + return 3; + } + cpu->CPSR.bits.C = BIT_N(cpu->R[REG_NUM(i, 0)], v-1); + cpu->R[REG_NUM(i, 0)] = ROR(cpu->R[REG_NUM(i, 0)], v); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_TST(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] & cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + + return 3; +} + +static u32 FASTCALL OP_NEG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 a = cpu->R[REG_NUM(i, 3)]; + cpu->R[REG_NUM(i, 0)] = -((signed int)a); + + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(0, a, cpu->R[REG_NUM(i, 0)]); + + return 3; +} + +static u32 FASTCALL OP_CMP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] -cpu->R[REG_NUM(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_CMN(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 tmp = cpu->R[REG_NUM(i, 0)] + cpu->R[REG_NUM(i, 3)]; + + //execute = FALSE; + //log::ajouter("OP_CMN THUMB"); + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = UNSIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_OVERFLOW(cpu->R[REG_NUM(i, 0)], cpu->R[REG_NUM(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_ORR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] |= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_MUL_REG(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] *= cpu->R[REG_NUM(i, 3)]; + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_BIC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] &= (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_MVN(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 0)] = (~cpu->R[REG_NUM(i, 3)]); + cpu->CPSR.bits.N = BIT31(cpu->R[REG_NUM(i, 0)]); + cpu->CPSR.bits.Z = cpu->R[REG_NUM(i, 0)] == 0; + + return 3; +} + +static u32 FASTCALL OP_ADD_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rd = (i&7) | ((i>>4)&8); + cpu->R[Rd] += cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + cpu->next_instruction = cpu->R[15]; + + return 2; +} + +static u32 FASTCALL OP_CMP_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rn = (i&7) | ((i>>4)&8); + u32 tmp = cpu->R[Rn] -cpu->R[REG_POS(i, 3)]; + + cpu->CPSR.bits.N = BIT31(tmp); + cpu->CPSR.bits.Z = tmp == 0; + cpu->CPSR.bits.C = !UNSIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); + cpu->CPSR.bits.V = SIGNED_UNDERFLOW(cpu->R[Rn], cpu->R[REG_POS(i, 3)], tmp); + + return 3; +} + +static u32 FASTCALL OP_MOV_SPE(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 Rd = (i&7) | ((i>>4)&8); + cpu->R[Rd] = cpu->R[REG_POS(i, 3)]; + + if(Rd==15) + cpu->next_instruction = cpu->R[15]; + + return 2; +} + +static u32 FASTCALL OP_BX_THUMB(armcpu_t *cpu) +{ + u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[15] = (Rm & 0xFFFFFFFE); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_BLX_THUMB(armcpu_t *cpu) +{ + u32 Rm = cpu->R[REG_POS(cpu->instruction, 3)]; + + cpu->CPSR.bits.T = BIT0(Rm); + cpu->R[14] = cpu->next_instruction | 1; + cpu->R[15] = (Rm & 0xFFFFFFFE); + cpu->next_instruction = cpu->R[15]; + + return 3; +} + +static u32 FASTCALL OP_LDR_PCREL(armcpu_t *cpu) +{ + u32 adr = (cpu->R[15]&0xFFFFFFFC) + ((cpu->instruction&0xFF)<<2); + + cpu->R[REG_NUM(cpu->instruction, 8)] = READ32(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 6)] + cpu->R[REG_NUM(i, 3)]; + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE16(cpu->mem_if->data, adr, ((u16)cpu->R[REG_NUM(i, 0)])); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + WRITE8(cpu->mem_if->data, adr, ((u8)cpu->R[REG_NUM(i, 0)])); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (s32)((s8)READ8(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = (cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]); + u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC); + + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (u32)READ8(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRSH_REG_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + cpu->R[REG_NUM(i, 6)]; + cpu->R[REG_NUM(i, 0)] = (s32)((s16)READ16(cpu->mem_if->data, adr)); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>4)&0x7C); + u32 tempValue = READ32(cpu->mem_if->data, adr&0xFFFFFFFC); + adr = (adr&3)*8; + tempValue = (tempValue>>adr) | (tempValue<<(32-adr)); + cpu->R[REG_NUM(i, 0)] = tempValue; + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRB_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + WRITE8(cpu->mem_if->data, adr, (u8)cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRB_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>6)&0x1F); + cpu->R[REG_NUM(i, 0)] = READ8(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STRH_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + WRITE16(cpu->mem_if->data, adr, (u16)cpu->R[REG_NUM(i, 0)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDRH_IMM_OFF(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 3)] + ((i>>5)&0x3E); + cpu->R[REG_NUM(i, 0)] = READ16(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_STR_SPREL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + WRITE32(cpu->mem_if->data, adr, cpu->R[REG_NUM(i, 8)]); + + return 2 + MMU.MMU_WAIT16[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_LDR_SPREL(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] + ((i&0xFF)<<2); + cpu->R[REG_NUM(i, 8)] = READ32(cpu->mem_if->data, adr); + + return 3 + MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; +} + +static u32 FASTCALL OP_ADD_2PC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = (cpu->R[15]&0xFFFFFFFC) + ((i&0xFF)<<2); + + return 5; +} + +static u32 FASTCALL OP_ADD_2SP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[REG_NUM(i, 8)] = cpu->R[13] + ((i&0xFF)<<2); + + return 2; +} + +static u32 FASTCALL OP_ADJUST_P_SP(armcpu_t *cpu) +{ + cpu->R[13] += ((cpu->instruction&0x7F)<<2); + + return 1; +} + +static u32 FASTCALL OP_ADJUST_M_SP(armcpu_t *cpu) +{ + cpu->R[13] -= ((cpu->instruction&0x7F)<<2); + + return 1; +} + +static u32 FASTCALL OP_PUSH(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + } + cpu->R[13] = adr + 4; + + return c + 3; +} + +static u32 FASTCALL OP_PUSH_LR(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13] - 4; + u32 c = 0, j; + + WRITE32(cpu->mem_if->data, adr, cpu->R[14]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + + for(j = 0; j<8; ++j) + if(BIT_N(i, 7-j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[7-j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr -= 4; + } + cpu->R[13] = adr + 4; + + return c + 4; +} + +static u32 FASTCALL OP_POP(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[13] = adr; + + return c + 2; +} + +static u32 FASTCALL OP_POP_PC(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[13]; + u32 c = 0, j; + u32 v; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + + v = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + cpu->R[15] = v & 0xFFFFFFFE; + cpu->next_instruction = v & 0xFFFFFFFE; + if(cpu->proc_ID==0) + cpu->CPSR.bits.T = BIT0(v); + adr += 4; + + cpu->R[13] = adr; + return c + 5; +} + +static u32 FASTCALL OP_BKPT_THUMB(armcpu_t *cpu) +{ + return 1; +} + +static u32 FASTCALL OP_STMIA_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 8)]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + WRITE32(cpu->mem_if->data, adr, cpu->R[j]); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[REG_NUM(i, 8)] = adr; + return c + 2; +} + +static u32 FASTCALL OP_LDMIA_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + u32 adr = cpu->R[REG_NUM(i, 8)]; + u32 c = 0, j; + + for(j = 0; j<8; ++j) + if(BIT_N(i, j)) + { + cpu->R[j] = READ32(cpu->mem_if->data, adr); + c += MMU.MMU_WAIT32[cpu->proc_ID][(adr>>24)&0xF]; + adr += 4; + } + cpu->R[REG_NUM(i, 8)] = adr; + return c + 3; +} + +static u32 FASTCALL OP_B_COND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR)) + return 1; + + cpu->R[15] += ((s32)((s8)(i&0xFF)))<<1; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_SWI_THUMB(armcpu_t *cpu) +{ + if (((cpu->intVector != 0) ^ (cpu->proc_ID == ARMCPU_ARM9))) + { + /* we use an irq thats not in the irq tab, as + it was replaced duie to a changed intVector */ + Status_Reg tmp = cpu->CPSR; + armcpu_switchMode(cpu, SVC); /* enter svc mode */ + cpu->R[14] = cpu->R[15] - 4; /* jump to swi Vector */ + cpu->SPSR = tmp; /* save old CPSR as new SPSR */ + cpu->CPSR.bits.T = 0; /* handle as ARM32 code */ + cpu->CPSR.bits.I = cpu->SPSR.bits.I; /* keep int disable flag */ + cpu->R[15] = cpu->intVector + 0x08; + cpu->next_instruction = cpu->R[15]; + return 3; + } + else + { + u32 swinum = cpu->instruction & 0xFF; + return cpu->swi_tab[swinum](cpu) + 3; + } + //return 3; +} + +#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) + +static u32 FASTCALL OP_B_UNCOND(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] += (SIGNEEXT_IMM11(i)<<1); + cpu->next_instruction = cpu->R[15]; + return 3; +} + +static u32 FASTCALL OP_BLX(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1))&0xFFFFFFFC; + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + cpu->CPSR.bits.T = 0; + return 3; +} + +static u32 FASTCALL OP_BL_10(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[14] = cpu->R[15] + (SIGNEEXT_IMM11(i)<<12); + return 1; +} + +static u32 FASTCALL OP_BL_THUMB(armcpu_t *cpu) +{ + u32 i = cpu->instruction; + cpu->R[15] = (cpu->R[14] + ((i&0x7FF)<<1)); + cpu->R[14] = cpu->next_instruction | 1; + cpu->next_instruction = cpu->R[15]; + return 3; +} + +#define TYPE_RETOUR u32 +#define CALLTYPE FASTCALL +#define PARAMETRES armcpu_t *cpu +#define NOM_THUMB_TAB thumb_instructions_set + +#include "thumb_tabdef.inc" diff --git a/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.h b/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.h new file mode 100644 index 000000000..27088a6e3 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/thumb_instructions.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef THUMB_INSTRUCTIONS_H +#define THUMB_INSTRUCTIONS_H + +#include "armcpu.h" + +extern u32 (FASTCALL* thumb_instructions_set[1024])(armcpu_t * cpu); + +#endif + diff --git a/tools/vio2sf/src/vio2sf/desmume/thumb_tabdef.inc b/tools/vio2sf/src/vio2sf/desmume/thumb_tabdef.inc new file mode 100644 index 000000000..1a9c53b03 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/thumb_tabdef.inc @@ -0,0 +1,1111 @@ +/* Copyright (C) 2006 yopyop + yopyop156@ifrance.com + yopyop156.ifrance.com + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +TYPE_RETOUR (* CALLTYPE NOM_THUMB_TAB[1024])(PARAMETRES)={ + OP_LSL_0, //00 0000 0000 + OP_LSL, //00 0000 0001 + OP_LSL, //00 0000 0010 + OP_LSL, //00 0000 0011 + OP_LSL, //00 0000 0100 + OP_LSL, //00 0000 0101 + OP_LSL, //00 0000 0110 + OP_LSL, //00 0000 0111 + OP_LSL, //00 0000 1000 + OP_LSL, //00 0000 1001 + OP_LSL, //00 0000 1010 + OP_LSL, //00 0000 1011 + OP_LSL, //00 0000 1100 + OP_LSL, //00 0000 1101 + OP_LSL, //00 0000 1110 + OP_LSL, //00 0000 1111 + + OP_LSL, //00 0001 0000 + OP_LSL, //00 0001 0001 + OP_LSL, //00 0001 0010 + OP_LSL, //00 0001 0011 + OP_LSL, //00 0001 0100 + OP_LSL, //00 0001 0101 + OP_LSL, //00 0001 0110 + OP_LSL, //00 0001 0111 + OP_LSL, //00 0001 1000 + OP_LSL, //00 0001 1001 + OP_LSL, //00 0001 1010 + OP_LSL, //00 0001 1011 + OP_LSL, //00 0001 1100 + OP_LSL, //00 0001 1101 + OP_LSL, //00 0001 1110 + OP_LSL, //00 0001 1111 + + OP_LSR_0, //00 0010 0000 + OP_LSR, //00 0010 0001 + OP_LSR, //00 0010 0010 + OP_LSR, //00 0010 0011 + OP_LSR, //00 0010 0100 + OP_LSR, //00 0010 0101 + OP_LSR, //00 0010 0110 + OP_LSR, //00 0010 0111 + OP_LSR, //00 0010 1000 + OP_LSR, //00 0010 1001 + OP_LSR, //00 0010 1010 + OP_LSR, //00 0010 1011 + OP_LSR, //00 0010 1100 + OP_LSR, //00 0010 1101 + OP_LSR, //00 0010 1110 + OP_LSR, //00 0010 1111 + + OP_LSR, //00 0011 0000 + OP_LSR, //00 0011 0001 + OP_LSR, //00 0011 0010 + OP_LSR, //00 0011 0011 + OP_LSR, //00 0011 0100 + OP_LSR, //00 0011 0101 + OP_LSR, //00 0011 0110 + OP_LSR, //00 0011 0111 + OP_LSR, //00 0011 1000 + OP_LSR, //00 0011 1001 + OP_LSR, //00 0011 1010 + OP_LSR, //00 0011 1011 + OP_LSR, //00 0011 1100 + OP_LSR, //00 0011 1101 + OP_LSR, //00 0011 1110 + OP_LSR, //00 0011 1111 + + OP_ASR_0, //00 0100 0000 + OP_ASR, //00 0100 0001 + OP_ASR, //00 0100 0010 + OP_ASR, //00 0100 0011 + OP_ASR, //00 0100 0100 + OP_ASR, //00 0100 0101 + OP_ASR, //00 0100 0110 + OP_ASR, //00 0100 0111 + OP_ASR, //00 0100 1000 + OP_ASR, //00 0100 1001 + OP_ASR, //00 0100 1010 + OP_ASR, //00 0100 1011 + OP_ASR, //00 0100 1100 + OP_ASR, //00 0100 1101 + OP_ASR, //00 0100 1110 + OP_ASR, //00 0100 1111 + + OP_ASR, //00 0101 0000 + OP_ASR, //00 0101 0001 + OP_ASR, //00 0101 0010 + OP_ASR, //00 0101 0011 + OP_ASR, //00 0101 0100 + OP_ASR, //00 0101 0101 + OP_ASR, //00 0101 0110 + OP_ASR, //00 0101 0111 + OP_ASR, //00 0101 1000 + OP_ASR, //00 0101 1001 + OP_ASR, //00 0101 1010 + OP_ASR, //00 0101 1011 + OP_ASR, //00 0101 1100 + OP_ASR, //00 0101 1101 + OP_ASR, //00 0101 1110 + OP_ASR, //00 0101 1111 + + OP_ADD_REG, //00 0110 0000 + OP_ADD_REG, //00 0110 0001 + OP_ADD_REG, //00 0110 0010 + OP_ADD_REG, //00 0110 0011 + OP_ADD_REG, //00 0110 0100 + OP_ADD_REG, //00 0110 0101 + OP_ADD_REG, //00 0110 0110 + OP_ADD_REG, //00 0110 0111 + OP_SUB_REG, //00 0110 1000 + OP_SUB_REG, //00 0110 1001 + OP_SUB_REG, //00 0110 1010 + OP_SUB_REG, //00 0110 1011 + OP_SUB_REG, //00 0110 1100 + OP_SUB_REG, //00 0110 1101 + OP_SUB_REG, //00 0110 1110 + OP_SUB_REG, //00 0110 1111 + + OP_ADD_IMM3, //00 0111 0000 + OP_ADD_IMM3, //00 0111 0001 + OP_ADD_IMM3, //00 0111 0010 + OP_ADD_IMM3, //00 0111 0011 + OP_ADD_IMM3, //00 0111 0100 + OP_ADD_IMM3, //00 0111 0101 + OP_ADD_IMM3, //00 0111 0110 + OP_ADD_IMM3, //00 0111 0111 + OP_SUB_IMM3, //00 0111 1000 + OP_SUB_IMM3, //00 0111 1001 + OP_SUB_IMM3, //00 0111 1010 + OP_SUB_IMM3, //00 0111 1011 + OP_SUB_IMM3, //00 0111 1100 + OP_SUB_IMM3, //00 0111 1101 + OP_SUB_IMM3, //00 0111 1110 + OP_SUB_IMM3, //00 0111 1111 + + OP_MOV_IMM8, //00 1000 0000 + OP_MOV_IMM8, //00 1000 0001 + OP_MOV_IMM8, //00 1000 0010 + OP_MOV_IMM8, //00 1000 0011 + OP_MOV_IMM8, //00 1000 0100 + OP_MOV_IMM8, //00 1000 0101 + OP_MOV_IMM8, //00 1000 0110 + OP_MOV_IMM8, //00 1000 0111 + OP_MOV_IMM8, //00 1000 1000 + OP_MOV_IMM8, //00 1000 1001 + OP_MOV_IMM8, //00 1000 1010 + OP_MOV_IMM8, //00 1000 1011 + OP_MOV_IMM8, //00 1000 1100 + OP_MOV_IMM8, //00 1000 1101 + OP_MOV_IMM8, //00 1000 1110 + OP_MOV_IMM8, //00 1000 1111 + + OP_MOV_IMM8, //00 1001 0000 + OP_MOV_IMM8, //00 1001 0001 + OP_MOV_IMM8, //00 1001 0010 + OP_MOV_IMM8, //00 1001 0011 + OP_MOV_IMM8, //00 1001 0100 + OP_MOV_IMM8, //00 1001 0101 + OP_MOV_IMM8, //00 1001 0110 + OP_MOV_IMM8, //00 1001 0111 + OP_MOV_IMM8, //00 1001 1000 + OP_MOV_IMM8, //00 1001 1001 + OP_MOV_IMM8, //00 1001 1010 + OP_MOV_IMM8, //00 1001 1011 + OP_MOV_IMM8, //00 1001 1100 + OP_MOV_IMM8, //00 1001 1101 + OP_MOV_IMM8, //00 1001 1110 + OP_MOV_IMM8, //00 1001 1111 + + OP_CMP_IMM8, //00 1010 0000 + OP_CMP_IMM8, //00 1010 0001 + OP_CMP_IMM8, //00 1010 0010 + OP_CMP_IMM8, //00 1010 0011 + OP_CMP_IMM8, //00 1010 0100 + OP_CMP_IMM8, //00 1010 0101 + OP_CMP_IMM8, //00 1010 0110 + OP_CMP_IMM8, //00 1010 0111 + OP_CMP_IMM8, //00 1010 1000 + OP_CMP_IMM8, //00 1010 1001 + OP_CMP_IMM8, //00 1010 1010 + OP_CMP_IMM8, //00 1010 1011 + OP_CMP_IMM8, //00 1010 1100 + OP_CMP_IMM8, //00 1010 1101 + OP_CMP_IMM8, //00 1010 1110 + OP_CMP_IMM8, //00 1010 1111 + + OP_CMP_IMM8, //00 1011 0000 + OP_CMP_IMM8, //00 1011 0001 + OP_CMP_IMM8, //00 1011 0010 + OP_CMP_IMM8, //00 1011 0011 + OP_CMP_IMM8, //00 1011 0100 + OP_CMP_IMM8, //00 1011 0101 + OP_CMP_IMM8, //00 1011 0110 + OP_CMP_IMM8, //00 1011 0111 + OP_CMP_IMM8, //00 1011 1000 + OP_CMP_IMM8, //00 1011 1001 + OP_CMP_IMM8, //00 1011 1010 + OP_CMP_IMM8, //00 1011 1011 + OP_CMP_IMM8, //00 1011 1100 + OP_CMP_IMM8, //00 1011 1101 + OP_CMP_IMM8, //00 1011 1110 + OP_CMP_IMM8, //00 1011 1111 + + OP_ADD_IMM8, //00 1100 0000 + OP_ADD_IMM8, //00 1100 0001 + OP_ADD_IMM8, //00 1100 0010 + OP_ADD_IMM8, //00 1100 0011 + OP_ADD_IMM8, //00 1100 0100 + OP_ADD_IMM8, //00 1100 0101 + OP_ADD_IMM8, //00 1100 0110 + OP_ADD_IMM8, //00 1100 0111 + OP_ADD_IMM8, //00 1100 1000 + OP_ADD_IMM8, //00 1100 1001 + OP_ADD_IMM8, //00 1100 1010 + OP_ADD_IMM8, //00 1100 1011 + OP_ADD_IMM8, //00 1100 1100 + OP_ADD_IMM8, //00 1100 1101 + OP_ADD_IMM8, //00 1100 1110 + OP_ADD_IMM8, //00 1100 1111 + + OP_ADD_IMM8, //00 1101 0000 + OP_ADD_IMM8, //00 1101 0001 + OP_ADD_IMM8, //00 1101 0010 + OP_ADD_IMM8, //00 1101 0011 + OP_ADD_IMM8, //00 1101 0100 + OP_ADD_IMM8, //00 1101 0101 + OP_ADD_IMM8, //00 1101 0110 + OP_ADD_IMM8, //00 1101 0111 + OP_ADD_IMM8, //00 1101 1000 + OP_ADD_IMM8, //00 1101 1001 + OP_ADD_IMM8, //00 1101 1010 + OP_ADD_IMM8, //00 1101 1011 + OP_ADD_IMM8, //00 1101 1100 + OP_ADD_IMM8, //00 1101 1101 + OP_ADD_IMM8, //00 1101 1110 + OP_ADD_IMM8, //00 1101 1111 + + OP_SUB_IMM8, //00 1110 0000 + OP_SUB_IMM8, //00 1110 0001 + OP_SUB_IMM8, //00 1110 0010 + OP_SUB_IMM8, //00 1110 0011 + OP_SUB_IMM8, //00 1110 0100 + OP_SUB_IMM8, //00 1110 0101 + OP_SUB_IMM8, //00 1110 0110 + OP_SUB_IMM8, //00 1110 0111 + OP_SUB_IMM8, //00 1110 1000 + OP_SUB_IMM8, //00 1110 1001 + OP_SUB_IMM8, //00 1110 1010 + OP_SUB_IMM8, //00 1110 1011 + OP_SUB_IMM8, //00 1110 1100 + OP_SUB_IMM8, //00 1110 1101 + OP_SUB_IMM8, //00 1110 1110 + OP_SUB_IMM8, //00 1110 1111 + + OP_SUB_IMM8, //00 1111 0000 + OP_SUB_IMM8, //00 1111 0001 + OP_SUB_IMM8, //00 1111 0010 + OP_SUB_IMM8, //00 1111 0011 + OP_SUB_IMM8, //00 1111 0100 + OP_SUB_IMM8, //00 1111 0101 + OP_SUB_IMM8, //00 1111 0110 + OP_SUB_IMM8, //00 1111 0111 + OP_SUB_IMM8, //00 1111 1000 + OP_SUB_IMM8, //00 1111 1001 + OP_SUB_IMM8, //00 1111 1010 + OP_SUB_IMM8, //00 1111 1011 + OP_SUB_IMM8, //00 1111 1100 + OP_SUB_IMM8, //00 1111 1101 + OP_SUB_IMM8, //00 1111 1110 + OP_SUB_IMM8, //00 1111 1111 + + OP_AND, //01 0000 0000 + OP_EOR, //01 0000 0001 + OP_LSL_REG, //01 0000 0010 + OP_LSR_REG, //01 0000 0011 + OP_ASR_REG, //01 0000 0100 + OP_ADC_REG, //01 0000 0101 + OP_SBC_REG, //01 0000 0110 + OP_ROR_REG, //01 0000 0111 + OP_TST, //01 0000 1000 + OP_NEG, //01 0000 1001 + OP_CMP, //01 0000 1010 + OP_CMN, //01 0000 1011 + OP_ORR, //01 0000 1100 + OP_MUL_REG, //01 0000 1101 + OP_BIC, //01 0000 1110 + OP_MVN, //01 0000 1111 + + OP_ADD_SPE, //01 0001 0000 + OP_ADD_SPE, //01 0001 0001 + OP_ADD_SPE, //01 0001 0010 + OP_ADD_SPE, //01 0001 0011 + OP_CMP_SPE, //01 0001 0100 + OP_CMP_SPE, //01 0001 0101 + OP_CMP_SPE, //01 0001 0110 + OP_CMP_SPE, //01 0001 0111 + OP_MOV_SPE, //01 0001 1000 + OP_MOV_SPE, //01 0001 1001 + OP_MOV_SPE, //01 0001 1010 + OP_MOV_SPE, //01 0001 1011 + OP_BX_THUMB, //01 0001 1100 + OP_BX_THUMB, //01 0001 1101 + OP_BLX_THUMB, //01 0001 1110 + OP_BLX_THUMB, //01 0001 1111 + + OP_LDR_PCREL, //01 0010 0000 + OP_LDR_PCREL, //01 0010 0001 + OP_LDR_PCREL, //01 0010 0010 + OP_LDR_PCREL, //01 0010 0011 + OP_LDR_PCREL, //01 0010 0100 + OP_LDR_PCREL, //01 0010 0101 + OP_LDR_PCREL, //01 0010 0110 + OP_LDR_PCREL, //01 0010 0111 + OP_LDR_PCREL, //01 0010 1000 + OP_LDR_PCREL, //01 0010 1001 + OP_LDR_PCREL, //01 0010 1010 + OP_LDR_PCREL, //01 0010 1011 + OP_LDR_PCREL, //01 0010 1100 + OP_LDR_PCREL, //01 0010 1101 + OP_LDR_PCREL, //01 0010 1110 + OP_LDR_PCREL, //01 0010 1111 + + OP_LDR_PCREL, //01 0011 0000 + OP_LDR_PCREL, //01 0011 0001 + OP_LDR_PCREL, //01 0011 0010 + OP_LDR_PCREL, //01 0011 0011 + OP_LDR_PCREL, //01 0011 0100 + OP_LDR_PCREL, //01 0011 0101 + OP_LDR_PCREL, //01 0011 0110 + OP_LDR_PCREL, //01 0011 0111 + OP_LDR_PCREL, //01 0011 1000 + OP_LDR_PCREL, //01 0011 1001 + OP_LDR_PCREL, //01 0011 1010 + OP_LDR_PCREL, //01 0011 1011 + OP_LDR_PCREL, //01 0011 1100 + OP_LDR_PCREL, //01 0011 1101 + OP_LDR_PCREL, //01 0011 1110 + OP_LDR_PCREL, //01 0011 1111 + + OP_STR_REG_OFF, //01 0100 0000 + OP_STR_REG_OFF, //01 0100 0001 + OP_STR_REG_OFF, //01 0100 0010 + OP_STR_REG_OFF, //01 0100 0011 + OP_STR_REG_OFF, //01 0100 0100 + OP_STR_REG_OFF, //01 0100 0101 + OP_STR_REG_OFF, //01 0100 0110 + OP_STR_REG_OFF, //01 0100 0111 + OP_STRH_REG_OFF, //01 0100 1000 + OP_STRH_REG_OFF, //01 0100 1001 + OP_STRH_REG_OFF, //01 0100 1010 + OP_STRH_REG_OFF, //01 0100 1011 + OP_STRH_REG_OFF, //01 0100 1100 + OP_STRH_REG_OFF, //01 0100 1101 + OP_STRH_REG_OFF, //01 0100 1110 + OP_STRH_REG_OFF, //01 0100 1111 + + OP_STRB_REG_OFF, //01 0101 0000 + OP_STRB_REG_OFF, //01 0101 0001 + OP_STRB_REG_OFF, //01 0101 0010 + OP_STRB_REG_OFF, //01 0101 0011 + OP_STRB_REG_OFF, //01 0101 0100 + OP_STRB_REG_OFF, //01 0101 0101 + OP_STRB_REG_OFF, //01 0101 0110 + OP_STRB_REG_OFF, //01 0101 0111 + OP_LDRSB_REG_OFF, //01 0101 1000 + OP_LDRSB_REG_OFF, //01 0101 1001 + OP_LDRSB_REG_OFF, //01 0101 1010 + OP_LDRSB_REG_OFF, //01 0101 1011 + OP_LDRSB_REG_OFF, //01 0101 1100 + OP_LDRSB_REG_OFF, //01 0101 1101 + OP_LDRSB_REG_OFF, //01 0101 1110 + OP_LDRSB_REG_OFF, //01 0101 1111 + + OP_LDR_REG_OFF, //01 0110 0000 + OP_LDR_REG_OFF, //01 0110 0001 + OP_LDR_REG_OFF, //01 0110 0010 + OP_LDR_REG_OFF, //01 0110 0011 + OP_LDR_REG_OFF, //01 0110 0100 + OP_LDR_REG_OFF, //01 0110 0101 + OP_LDR_REG_OFF, //01 0110 0110 + OP_LDR_REG_OFF, //01 0110 0111 + OP_LDRH_REG_OFF, //01 0110 1000 + OP_LDRH_REG_OFF, //01 0110 1001 + OP_LDRH_REG_OFF, //01 0110 1010 + OP_LDRH_REG_OFF, //01 0110 1011 + OP_LDRH_REG_OFF, //01 0110 1100 + OP_LDRH_REG_OFF, //01 0110 1101 + OP_LDRH_REG_OFF, //01 0110 1110 + OP_LDRH_REG_OFF, //01 0110 1111 + + OP_LDRB_REG_OFF, //01 0111 0000 + OP_LDRB_REG_OFF, //01 0111 0001 + OP_LDRB_REG_OFF, //01 0111 0010 + OP_LDRB_REG_OFF, //01 0111 0011 + OP_LDRB_REG_OFF, //01 0111 0100 + OP_LDRB_REG_OFF, //01 0111 0101 + OP_LDRB_REG_OFF, //01 0111 0110 + OP_LDRB_REG_OFF, //01 0111 0111 + OP_LDRSH_REG_OFF, //01 0111 1000 + OP_LDRSH_REG_OFF, //01 0111 1001 + OP_LDRSH_REG_OFF, //01 0111 1010 + OP_LDRSH_REG_OFF, //01 0111 1011 + OP_LDRSH_REG_OFF, //01 0111 1100 + OP_LDRSH_REG_OFF, //01 0111 1101 + OP_LDRSH_REG_OFF, //01 0111 1110 + OP_LDRSH_REG_OFF, //01 0111 1111 + + OP_STR_IMM_OFF, //01 1000 0000 + OP_STR_IMM_OFF, //01 1000 0001 + OP_STR_IMM_OFF, //01 1000 0010 + OP_STR_IMM_OFF, //01 1000 0011 + OP_STR_IMM_OFF, //01 1000 0100 + OP_STR_IMM_OFF, //01 1000 0101 + OP_STR_IMM_OFF, //01 1000 0110 + OP_STR_IMM_OFF, //01 1000 0111 + OP_STR_IMM_OFF, //01 1000 1000 + OP_STR_IMM_OFF, //01 1000 1001 + OP_STR_IMM_OFF, //01 1000 1010 + OP_STR_IMM_OFF, //01 1000 1011 + OP_STR_IMM_OFF, //01 1000 1100 + OP_STR_IMM_OFF, //01 1000 1101 + OP_STR_IMM_OFF, //01 1000 1110 + OP_STR_IMM_OFF, //01 1000 1111 + + OP_STR_IMM_OFF, //01 1001 0000 + OP_STR_IMM_OFF, //01 1001 0001 + OP_STR_IMM_OFF, //01 1001 0010 + OP_STR_IMM_OFF, //01 1001 0011 + OP_STR_IMM_OFF, //01 1001 0100 + OP_STR_IMM_OFF, //01 1001 0101 + OP_STR_IMM_OFF, //01 1001 0110 + OP_STR_IMM_OFF, //01 1001 0111 + OP_STR_IMM_OFF, //01 1001 1000 + OP_STR_IMM_OFF, //01 1001 1001 + OP_STR_IMM_OFF, //01 1001 1010 + OP_STR_IMM_OFF, //01 1001 1011 + OP_STR_IMM_OFF, //01 1001 1100 + OP_STR_IMM_OFF, //01 1001 1101 + OP_STR_IMM_OFF, //01 1001 1110 + OP_STR_IMM_OFF, //01 1001 1111 + + OP_LDR_IMM_OFF, //01 1010 0000 + OP_LDR_IMM_OFF, //01 1010 0001 + OP_LDR_IMM_OFF, //01 1010 0010 + OP_LDR_IMM_OFF, //01 1010 0011 + OP_LDR_IMM_OFF, //01 1010 0100 + OP_LDR_IMM_OFF, //01 1010 0101 + OP_LDR_IMM_OFF, //01 1010 0110 + OP_LDR_IMM_OFF, //01 1010 0111 + OP_LDR_IMM_OFF, //01 1010 1000 + OP_LDR_IMM_OFF, //01 1010 1001 + OP_LDR_IMM_OFF, //01 1010 1010 + OP_LDR_IMM_OFF, //01 1010 1011 + OP_LDR_IMM_OFF, //01 1010 1100 + OP_LDR_IMM_OFF, //01 1010 1101 + OP_LDR_IMM_OFF, //01 1010 1110 + OP_LDR_IMM_OFF, //01 1010 1111 + + OP_LDR_IMM_OFF, //01 1011 0000 + OP_LDR_IMM_OFF, //01 1011 0001 + OP_LDR_IMM_OFF, //01 1011 0010 + OP_LDR_IMM_OFF, //01 1011 0011 + OP_LDR_IMM_OFF, //01 1011 0100 + OP_LDR_IMM_OFF, //01 1011 0101 + OP_LDR_IMM_OFF, //01 1011 0110 + OP_LDR_IMM_OFF, //01 1011 0111 + OP_LDR_IMM_OFF, //01 1011 1000 + OP_LDR_IMM_OFF, //01 1011 1001 + OP_LDR_IMM_OFF, //01 1011 1010 + OP_LDR_IMM_OFF, //01 1011 1011 + OP_LDR_IMM_OFF, //01 1011 1100 + OP_LDR_IMM_OFF, //01 1011 1101 + OP_LDR_IMM_OFF, //01 1011 1110 + OP_LDR_IMM_OFF, //01 1011 1111 + + OP_STRB_IMM_OFF, //01 1100 0000 + OP_STRB_IMM_OFF, //01 1100 0001 + OP_STRB_IMM_OFF, //01 1100 0010 + OP_STRB_IMM_OFF, //01 1100 0011 + OP_STRB_IMM_OFF, //01 1100 0100 + OP_STRB_IMM_OFF, //01 1100 0101 + OP_STRB_IMM_OFF, //01 1100 0110 + OP_STRB_IMM_OFF, //01 1100 0111 + OP_STRB_IMM_OFF, //01 1100 1000 + OP_STRB_IMM_OFF, //01 1100 1001 + OP_STRB_IMM_OFF, //01 1100 1010 + OP_STRB_IMM_OFF, //01 1100 1011 + OP_STRB_IMM_OFF, //01 1100 1100 + OP_STRB_IMM_OFF, //01 1100 1101 + OP_STRB_IMM_OFF, //01 1100 1110 + OP_STRB_IMM_OFF, //01 1100 1111 + + OP_STRB_IMM_OFF, //01 1101 0000 + OP_STRB_IMM_OFF, //01 1101 0001 + OP_STRB_IMM_OFF, //01 1101 0010 + OP_STRB_IMM_OFF, //01 1101 0011 + OP_STRB_IMM_OFF, //01 1101 0100 + OP_STRB_IMM_OFF, //01 1101 0101 + OP_STRB_IMM_OFF, //01 1101 0110 + OP_STRB_IMM_OFF, //01 1101 0111 + OP_STRB_IMM_OFF, //01 1101 1000 + OP_STRB_IMM_OFF, //01 1101 1001 + OP_STRB_IMM_OFF, //01 1101 1010 + OP_STRB_IMM_OFF, //01 1101 1011 + OP_STRB_IMM_OFF, //01 1101 1100 + OP_STRB_IMM_OFF, //01 1101 1101 + OP_STRB_IMM_OFF, //01 1101 1110 + OP_STRB_IMM_OFF, //01 1101 1111 + + OP_LDRB_IMM_OFF, //01 1110 0000 + OP_LDRB_IMM_OFF, //01 1110 0001 + OP_LDRB_IMM_OFF, //01 1110 0010 + OP_LDRB_IMM_OFF, //01 1110 0011 + OP_LDRB_IMM_OFF, //01 1110 0100 + OP_LDRB_IMM_OFF, //01 1110 0101 + OP_LDRB_IMM_OFF, //01 1110 0110 + OP_LDRB_IMM_OFF, //01 1110 0111 + OP_LDRB_IMM_OFF, //01 1110 1000 + OP_LDRB_IMM_OFF, //01 1110 1001 + OP_LDRB_IMM_OFF, //01 1110 1010 + OP_LDRB_IMM_OFF, //01 1110 1011 + OP_LDRB_IMM_OFF, //01 1110 1100 + OP_LDRB_IMM_OFF, //01 1110 1101 + OP_LDRB_IMM_OFF, //01 1110 1110 + OP_LDRB_IMM_OFF, //01 1110 1111 + + OP_LDRB_IMM_OFF, //01 1111 0000 + OP_LDRB_IMM_OFF, //01 1111 0001 + OP_LDRB_IMM_OFF, //01 1111 0010 + OP_LDRB_IMM_OFF, //01 1111 0011 + OP_LDRB_IMM_OFF, //01 1111 0100 + OP_LDRB_IMM_OFF, //01 1111 0101 + OP_LDRB_IMM_OFF, //01 1111 0110 + OP_LDRB_IMM_OFF, //01 1111 0111 + OP_LDRB_IMM_OFF, //01 1111 1000 + OP_LDRB_IMM_OFF, //01 1111 1001 + OP_LDRB_IMM_OFF, //01 1111 1010 + OP_LDRB_IMM_OFF, //01 1111 1011 + OP_LDRB_IMM_OFF, //01 1111 1100 + OP_LDRB_IMM_OFF, //01 1111 1101 + OP_LDRB_IMM_OFF, //01 1111 1110 + OP_LDRB_IMM_OFF, //01 1111 1111 + + OP_STRH_IMM_OFF, //10 0000 0000 + OP_STRH_IMM_OFF, //10 0000 0001 + OP_STRH_IMM_OFF, //10 0000 0010 + OP_STRH_IMM_OFF, //10 0000 0011 + OP_STRH_IMM_OFF, //10 0000 0100 + OP_STRH_IMM_OFF, //10 0000 0101 + OP_STRH_IMM_OFF, //10 0000 0110 + OP_STRH_IMM_OFF, //10 0000 0111 + OP_STRH_IMM_OFF, //10 0000 1000 + OP_STRH_IMM_OFF, //10 0000 1001 + OP_STRH_IMM_OFF, //10 0000 1010 + OP_STRH_IMM_OFF, //10 0000 1011 + OP_STRH_IMM_OFF, //10 0000 1100 + OP_STRH_IMM_OFF, //10 0000 1101 + OP_STRH_IMM_OFF, //10 0000 1110 + OP_STRH_IMM_OFF, //10 0000 1111 + + OP_STRH_IMM_OFF, //10 0001 0000 + OP_STRH_IMM_OFF, //10 0001 0001 + OP_STRH_IMM_OFF, //10 0001 0010 + OP_STRH_IMM_OFF, //10 0001 0011 + OP_STRH_IMM_OFF, //10 0001 0100 + OP_STRH_IMM_OFF, //10 0001 0101 + OP_STRH_IMM_OFF, //10 0001 0110 + OP_STRH_IMM_OFF, //10 0001 0111 + OP_STRH_IMM_OFF, //10 0001 1000 + OP_STRH_IMM_OFF, //10 0001 1001 + OP_STRH_IMM_OFF, //10 0001 1010 + OP_STRH_IMM_OFF, //10 0001 1011 + OP_STRH_IMM_OFF, //10 0001 1100 + OP_STRH_IMM_OFF, //10 0001 1101 + OP_STRH_IMM_OFF, //10 0001 1110 + OP_STRH_IMM_OFF, //10 0001 1111 + + OP_LDRH_IMM_OFF, //10 0010 0000 + OP_LDRH_IMM_OFF, //10 0010 0001 + OP_LDRH_IMM_OFF, //10 0010 0010 + OP_LDRH_IMM_OFF, //10 0010 0011 + OP_LDRH_IMM_OFF, //10 0010 0100 + OP_LDRH_IMM_OFF, //10 0010 0101 + OP_LDRH_IMM_OFF, //10 0010 0110 + OP_LDRH_IMM_OFF, //10 0010 0111 + OP_LDRH_IMM_OFF, //10 0010 1000 + OP_LDRH_IMM_OFF, //10 0010 1001 + OP_LDRH_IMM_OFF, //10 0010 1010 + OP_LDRH_IMM_OFF, //10 0010 1011 + OP_LDRH_IMM_OFF, //10 0010 1100 + OP_LDRH_IMM_OFF, //10 0010 1101 + OP_LDRH_IMM_OFF, //10 0010 1110 + OP_LDRH_IMM_OFF, //10 0010 1111 + + OP_LDRH_IMM_OFF, //10 0011 0000 + OP_LDRH_IMM_OFF, //10 0011 0001 + OP_LDRH_IMM_OFF, //10 0011 0010 + OP_LDRH_IMM_OFF, //10 0011 0011 + OP_LDRH_IMM_OFF, //10 0011 0100 + OP_LDRH_IMM_OFF, //10 0011 0101 + OP_LDRH_IMM_OFF, //10 0011 0110 + OP_LDRH_IMM_OFF, //10 0011 0111 + OP_LDRH_IMM_OFF, //10 0011 1000 + OP_LDRH_IMM_OFF, //10 0011 1001 + OP_LDRH_IMM_OFF, //10 0011 1010 + OP_LDRH_IMM_OFF, //10 0011 1011 + OP_LDRH_IMM_OFF, //10 0011 1100 + OP_LDRH_IMM_OFF, //10 0011 1101 + OP_LDRH_IMM_OFF, //10 0011 1110 + OP_LDRH_IMM_OFF, //10 0011 1111 + + OP_STR_SPREL, //10 0100 0000 + OP_STR_SPREL, //10 0100 0001 + OP_STR_SPREL, //10 0100 0010 + OP_STR_SPREL, //10 0100 0011 + OP_STR_SPREL, //10 0100 0100 + OP_STR_SPREL, //10 0100 0101 + OP_STR_SPREL, //10 0100 0110 + OP_STR_SPREL, //10 0100 0111 + OP_STR_SPREL, //10 0100 1000 + OP_STR_SPREL, //10 0100 1001 + OP_STR_SPREL, //10 0100 1010 + OP_STR_SPREL, //10 0100 1011 + OP_STR_SPREL, //10 0100 1100 + OP_STR_SPREL, //10 0100 1101 + OP_STR_SPREL, //10 0100 1110 + OP_STR_SPREL, //10 0100 1111 + + OP_STR_SPREL, //10 0101 0000 + OP_STR_SPREL, //10 0101 0001 + OP_STR_SPREL, //10 0101 0010 + OP_STR_SPREL, //10 0101 0011 + OP_STR_SPREL, //10 0101 0100 + OP_STR_SPREL, //10 0101 0101 + OP_STR_SPREL, //10 0101 0110 + OP_STR_SPREL, //10 0101 0111 + OP_STR_SPREL, //10 0101 1000 + OP_STR_SPREL, //10 0101 1001 + OP_STR_SPREL, //10 0101 1010 + OP_STR_SPREL, //10 0101 1011 + OP_STR_SPREL, //10 0101 1100 + OP_STR_SPREL, //10 0101 1101 + OP_STR_SPREL, //10 0101 1110 + OP_STR_SPREL, //10 0101 1111 + + OP_LDR_SPREL, //10 0110 0000 + OP_LDR_SPREL, //10 0110 0001 + OP_LDR_SPREL, //10 0110 0010 + OP_LDR_SPREL, //10 0110 0011 + OP_LDR_SPREL, //10 0110 0100 + OP_LDR_SPREL, //10 0110 0101 + OP_LDR_SPREL, //10 0110 0110 + OP_LDR_SPREL, //10 0110 0111 + OP_LDR_SPREL, //10 0110 1000 + OP_LDR_SPREL, //10 0110 1001 + OP_LDR_SPREL, //10 0110 1010 + OP_LDR_SPREL, //10 0110 1011 + OP_LDR_SPREL, //10 0110 1100 + OP_LDR_SPREL, //10 0110 1101 + OP_LDR_SPREL, //10 0110 1110 + OP_LDR_SPREL, //10 0110 1111 + + OP_LDR_SPREL, //10 0111 0000 + OP_LDR_SPREL, //10 0111 0001 + OP_LDR_SPREL, //10 0111 0010 + OP_LDR_SPREL, //10 0111 0011 + OP_LDR_SPREL, //10 0111 0100 + OP_LDR_SPREL, //10 0111 0101 + OP_LDR_SPREL, //10 0111 0110 + OP_LDR_SPREL, //10 0111 0111 + OP_LDR_SPREL, //10 0111 1000 + OP_LDR_SPREL, //10 0111 1001 + OP_LDR_SPREL, //10 0111 1010 + OP_LDR_SPREL, //10 0111 1011 + OP_LDR_SPREL, //10 0111 1100 + OP_LDR_SPREL, //10 0111 1101 + OP_LDR_SPREL, //10 0111 1110 + OP_LDR_SPREL, //10 0111 1111 + + OP_ADD_2PC, //10 1000 0000 + OP_ADD_2PC, //10 1000 0001 + OP_ADD_2PC, //10 1000 0010 + OP_ADD_2PC, //10 1000 0011 + OP_ADD_2PC, //10 1000 0100 + OP_ADD_2PC, //10 1000 0101 + OP_ADD_2PC, //10 1000 0110 + OP_ADD_2PC, //10 1000 0111 + OP_ADD_2PC, //10 1000 1000 + OP_ADD_2PC, //10 1000 1001 + OP_ADD_2PC, //10 1000 1010 + OP_ADD_2PC, //10 1000 1011 + OP_ADD_2PC, //10 1000 1100 + OP_ADD_2PC, //10 1000 1101 + OP_ADD_2PC, //10 1000 1110 + OP_ADD_2PC, //10 1000 1111 + + OP_ADD_2PC, //10 1001 0000 + OP_ADD_2PC, //10 1001 0001 + OP_ADD_2PC, //10 1001 0010 + OP_ADD_2PC, //10 1001 0011 + OP_ADD_2PC, //10 1001 0100 + OP_ADD_2PC, //10 1001 0101 + OP_ADD_2PC, //10 1001 0110 + OP_ADD_2PC, //10 1001 0111 + OP_ADD_2PC, //10 1001 1000 + OP_ADD_2PC, //10 1001 1001 + OP_ADD_2PC, //10 1001 1010 + OP_ADD_2PC, //10 1001 1011 + OP_ADD_2PC, //10 1001 1100 + OP_ADD_2PC, //10 1001 1101 + OP_ADD_2PC, //10 1001 1110 + OP_ADD_2PC, //10 1001 1111 + + OP_ADD_2SP, //10 1010 0000 + OP_ADD_2SP, //10 1010 0001 + OP_ADD_2SP, //10 1010 0010 + OP_ADD_2SP, //10 1010 0011 + OP_ADD_2SP, //10 1010 0100 + OP_ADD_2SP, //10 1010 0101 + OP_ADD_2SP, //10 1010 0110 + OP_ADD_2SP, //10 1010 0111 + OP_ADD_2SP, //10 1010 1000 + OP_ADD_2SP, //10 1010 1001 + OP_ADD_2SP, //10 1010 1010 + OP_ADD_2SP, //10 1010 1011 + OP_ADD_2SP, //10 1010 1100 + OP_ADD_2SP, //10 1010 1101 + OP_ADD_2SP, //10 1010 1110 + OP_ADD_2SP, //10 1010 1111 + + OP_ADD_2SP, //10 1011 0000 + OP_ADD_2SP, //10 1011 0001 + OP_ADD_2SP, //10 1011 0010 + OP_ADD_2SP, //10 1011 0011 + OP_ADD_2SP, //10 1011 0100 + OP_ADD_2SP, //10 1011 0101 + OP_ADD_2SP, //10 1011 0110 + OP_ADD_2SP, //10 1011 0111 + OP_ADD_2SP, //10 1011 1000 + OP_ADD_2SP, //10 1011 1001 + OP_ADD_2SP, //10 1011 1010 + OP_ADD_2SP, //10 1011 1011 + OP_ADD_2SP, //10 1011 1100 + OP_ADD_2SP, //10 1011 1101 + OP_ADD_2SP, //10 1011 1110 + OP_ADD_2SP, //10 1011 1111 + + OP_ADJUST_P_SP, //10 1100 0000 + OP_ADJUST_P_SP, //10 1100 0001 + OP_ADJUST_M_SP, //10 1100 0010 + OP_ADJUST_M_SP, //10 1100 0011 + OP_UND_THUMB, //10 1100 0100 + OP_UND_THUMB, //10 1100 0101 + OP_UND_THUMB, //10 1100 0110 + OP_UND_THUMB, //10 1100 0111 + OP_UND_THUMB, //10 1100 1000 + OP_UND_THUMB, //10 1100 1001 + OP_UND_THUMB, //10 1100 1010 + OP_UND_THUMB, //10 1100 1011 + OP_UND_THUMB, //10 1100 1100 + OP_UND_THUMB, //10 1100 1101 + OP_UND_THUMB, //10 1100 1110 + OP_UND_THUMB, //10 1100 1111 + + OP_PUSH, //10 1101 0000 + OP_PUSH, //10 1101 0001 + OP_PUSH, //10 1101 0010 + OP_PUSH, //10 1101 0011 + OP_PUSH_LR, //10 1101 0100 + OP_PUSH_LR, //10 1101 0101 + OP_PUSH_LR, //10 1101 0110 + OP_PUSH_LR, //10 1101 0111 + OP_UND_THUMB, //10 1101 1000 + OP_UND_THUMB, //10 1101 1001 + OP_UND_THUMB, //10 1101 1010 + OP_UND_THUMB, //10 1101 1011 + OP_UND_THUMB, //10 1101 1100 + OP_UND_THUMB, //10 1101 1101 + OP_UND_THUMB, //10 1101 1110 + OP_UND_THUMB, //10 1101 1111 + + OP_UND_THUMB, //10 1110 0000 + OP_UND_THUMB, //10 1110 0001 + OP_UND_THUMB, //10 1110 0010 + OP_UND_THUMB, //10 1110 0011 + OP_UND_THUMB, //10 1110 0100 + OP_UND_THUMB, //10 1110 0101 + OP_UND_THUMB, //10 1110 0110 + OP_UND_THUMB, //10 1110 0111 + OP_UND_THUMB, //10 1110 1000 + OP_UND_THUMB, //10 1110 1001 + OP_UND_THUMB, //10 1110 1010 + OP_UND_THUMB, //10 1110 1011 + OP_UND_THUMB, //10 1110 1100 + OP_UND_THUMB, //10 1110 1101 + OP_UND_THUMB, //10 1110 1110 + OP_UND_THUMB, //10 1110 1111 + + OP_POP, //10 1111 0000 + OP_POP, //10 1111 0001 + OP_POP, //10 1111 0010 + OP_POP, //10 1111 0011 + OP_POP_PC, //10 1111 0100 + OP_POP_PC, //10 1111 0101 + OP_POP_PC, //10 1111 0110 + OP_POP_PC, //10 1111 0111 + OP_BKPT_THUMB, //10 1111 1000 + OP_BKPT_THUMB, //10 1111 1001 + OP_BKPT_THUMB, //10 1111 1010 + OP_BKPT_THUMB, //10 1111 1011 + OP_UND_THUMB, //10 1111 1100 + OP_UND_THUMB, //10 1111 1101 + OP_UND_THUMB, //10 1111 1110 + OP_UND_THUMB, //10 1111 1111 + + OP_STMIA_THUMB, //11 0000 0000 + OP_STMIA_THUMB, //11 0000 0001 + OP_STMIA_THUMB, //11 0000 0010 + OP_STMIA_THUMB, //11 0000 0011 + OP_STMIA_THUMB, //11 0000 0100 + OP_STMIA_THUMB, //11 0000 0101 + OP_STMIA_THUMB, //11 0000 0110 + OP_STMIA_THUMB, //11 0000 0111 + OP_STMIA_THUMB, //11 0000 1000 + OP_STMIA_THUMB, //11 0000 1001 + OP_STMIA_THUMB, //11 0000 1010 + OP_STMIA_THUMB, //11 0000 1011 + OP_STMIA_THUMB, //11 0000 1100 + OP_STMIA_THUMB, //11 0000 1101 + OP_STMIA_THUMB, //11 0000 1110 + OP_STMIA_THUMB, //11 0000 1111 + + OP_STMIA_THUMB, //11 0001 0000 + OP_STMIA_THUMB, //11 0001 0001 + OP_STMIA_THUMB, //11 0001 0010 + OP_STMIA_THUMB, //11 0001 0011 + OP_STMIA_THUMB, //11 0001 0100 + OP_STMIA_THUMB, //11 0001 0101 + OP_STMIA_THUMB, //11 0001 0110 + OP_STMIA_THUMB, //11 0001 0111 + OP_STMIA_THUMB, //11 0001 1000 + OP_STMIA_THUMB, //11 0001 1001 + OP_STMIA_THUMB, //11 0001 1010 + OP_STMIA_THUMB, //11 0001 1011 + OP_STMIA_THUMB, //11 0001 1100 + OP_STMIA_THUMB, //11 0001 1101 + OP_STMIA_THUMB, //11 0001 1110 + OP_STMIA_THUMB, //11 0001 1111 + + OP_LDMIA_THUMB, //11 0010 0000 + OP_LDMIA_THUMB, //11 0010 0001 + OP_LDMIA_THUMB, //11 0010 0010 + OP_LDMIA_THUMB, //11 0010 0011 + OP_LDMIA_THUMB, //11 0010 0100 + OP_LDMIA_THUMB, //11 0010 0101 + OP_LDMIA_THUMB, //11 0010 0110 + OP_LDMIA_THUMB, //11 0010 0111 + OP_LDMIA_THUMB, //11 0010 1000 + OP_LDMIA_THUMB, //11 0010 1001 + OP_LDMIA_THUMB, //11 0010 1010 + OP_LDMIA_THUMB, //11 0010 1011 + OP_LDMIA_THUMB, //11 0010 1100 + OP_LDMIA_THUMB, //11 0010 1101 + OP_LDMIA_THUMB, //11 0010 1110 + OP_LDMIA_THUMB, //11 0010 1111 + + OP_LDMIA_THUMB, //11 0011 0000 + OP_LDMIA_THUMB, //11 0011 0001 + OP_LDMIA_THUMB, //11 0011 0010 + OP_LDMIA_THUMB, //11 0011 0011 + OP_LDMIA_THUMB, //11 0011 0100 + OP_LDMIA_THUMB, //11 0011 0101 + OP_LDMIA_THUMB, //11 0011 0110 + OP_LDMIA_THUMB, //11 0011 0111 + OP_LDMIA_THUMB, //11 0011 1000 + OP_LDMIA_THUMB, //11 0011 1001 + OP_LDMIA_THUMB, //11 0011 1010 + OP_LDMIA_THUMB, //11 0011 1011 + OP_LDMIA_THUMB, //11 0011 1100 + OP_LDMIA_THUMB, //11 0011 1101 + OP_LDMIA_THUMB, //11 0011 1110 + OP_LDMIA_THUMB, //11 0011 1111 + + OP_B_COND, //11 0100 0000 + OP_B_COND, //11 0100 0001 + OP_B_COND, //11 0100 0010 + OP_B_COND, //11 0100 0011 + OP_B_COND, //11 0100 0100 + OP_B_COND, //11 0100 0101 + OP_B_COND, //11 0100 0110 + OP_B_COND, //11 0100 0111 + OP_B_COND, //11 0100 1000 + OP_B_COND, //11 0100 1001 + OP_B_COND, //11 0100 1010 + OP_B_COND, //11 0100 1011 + OP_B_COND, //11 0100 1100 + OP_B_COND, //11 0100 1101 + OP_B_COND, //11 0100 1110 + OP_B_COND, //11 0100 1111 + + OP_B_COND, //11 0101 0000 + OP_B_COND, //11 0101 0001 + OP_B_COND, //11 0101 0010 + OP_B_COND, //11 0101 0011 + OP_B_COND, //11 0101 0100 + OP_B_COND, //11 0101 0101 + OP_B_COND, //11 0101 0110 + OP_B_COND, //11 0101 0111 + OP_B_COND, //11 0101 1000 + OP_B_COND, //11 0101 1001 + OP_B_COND, //11 0101 1010 + OP_B_COND, //11 0101 1011 + OP_B_COND, //11 0101 1100 + OP_B_COND, //11 0101 1101 + OP_B_COND, //11 0101 1110 + OP_B_COND, //11 0101 1111 + + OP_B_COND, //11 0110 0000 + OP_B_COND, //11 0110 0001 + OP_B_COND, //11 0110 0010 + OP_B_COND, //11 0110 0011 + OP_B_COND, //11 0110 0100 + OP_B_COND, //11 0110 0101 + OP_B_COND, //11 0110 0110 + OP_B_COND, //11 0110 0111 + OP_B_COND, //11 0110 1000 + OP_B_COND, //11 0110 1001 + OP_B_COND, //11 0110 1010 + OP_B_COND, //11 0110 1011 + OP_B_COND, //11 0110 1100 + OP_B_COND, //11 0110 1101 + OP_B_COND, //11 0110 1110 + OP_B_COND, //11 0110 1111 + + OP_B_COND, //11 0111 0000 + OP_B_COND, //11 0111 0001 + OP_B_COND, //11 0111 0010 + OP_B_COND, //11 0111 0011 + OP_B_COND, //11 0111 0100 + OP_B_COND, //11 0111 0101 + OP_B_COND, //11 0111 0110 + OP_B_COND, //11 0111 0111 + OP_B_COND, //11 0111 1000 + OP_B_COND, //11 0111 1001 + OP_B_COND, //11 0111 1010 + OP_B_COND, //11 0111 1011 + OP_SWI_THUMB, //11 0111 1100 + OP_SWI_THUMB, //11 0111 1101 + OP_SWI_THUMB, //11 0111 1110 + OP_SWI_THUMB, //11 0111 1111 + + OP_B_UNCOND, //11 1000 0000 + OP_B_UNCOND, //11 1000 0001 + OP_B_UNCOND, //11 1000 0010 + OP_B_UNCOND, //11 1000 0011 + OP_B_UNCOND, //11 1000 0100 + OP_B_UNCOND, //11 1000 0101 + OP_B_UNCOND, //11 1000 0110 + OP_B_UNCOND, //11 1000 0111 + OP_B_UNCOND, //11 1000 1000 + OP_B_UNCOND, //11 1000 1001 + OP_B_UNCOND, //11 1000 1010 + OP_B_UNCOND, //11 1000 1011 + OP_B_UNCOND, //11 1000 1100 + OP_B_UNCOND, //11 1000 1101 + OP_B_UNCOND, //11 1000 1110 + OP_B_UNCOND, //11 1000 1111 + + OP_B_UNCOND, //11 1001 0000 + OP_B_UNCOND, //11 1001 0001 + OP_B_UNCOND, //11 1001 0010 + OP_B_UNCOND, //11 1001 0011 + OP_B_UNCOND, //11 1001 0100 + OP_B_UNCOND, //11 1001 0101 + OP_B_UNCOND, //11 1001 0110 + OP_B_UNCOND, //11 1001 0111 + OP_B_UNCOND, //11 1001 1000 + OP_B_UNCOND, //11 1001 1001 + OP_B_UNCOND, //11 1001 1010 + OP_B_UNCOND, //11 1001 1011 + OP_B_UNCOND, //11 1001 1100 + OP_B_UNCOND, //11 1001 1101 + OP_B_UNCOND, //11 1001 1110 + OP_B_UNCOND, //11 1001 1111 + + OP_BLX, //11 1010 0000 + OP_BLX, //11 1010 0001 + OP_BLX, //11 1010 0010 + OP_BLX, //11 1010 0011 + OP_BLX, //11 1010 0100 + OP_BLX, //11 1010 0101 + OP_BLX, //11 1010 0110 + OP_BLX, //11 1010 0111 + OP_BLX, //11 1010 1000 + OP_BLX, //11 1010 1001 + OP_BLX, //11 1010 1010 + OP_BLX, //11 1010 1011 + OP_BLX, //11 1010 1100 + OP_BLX, //11 1010 1101 + OP_BLX, //11 1010 1110 + OP_BLX, //11 1010 1111 + + OP_BLX, //11 1011 0000 + OP_BLX, //11 1011 0001 + OP_BLX, //11 1011 0010 + OP_BLX, //11 1011 0011 + OP_BLX, //11 1011 0100 + OP_BLX, //11 1011 0101 + OP_BLX, //11 1011 0110 + OP_BLX, //11 1011 0111 + OP_BLX, //11 1011 1000 + OP_BLX, //11 1011 1001 + OP_BLX, //11 1011 1010 + OP_BLX, //11 1011 1011 + OP_BLX, //11 1011 1100 + OP_BLX, //11 1011 1101 + OP_BLX, //11 1011 1110 + OP_BLX, //11 1011 1111 + + OP_BL_10, //11 1100 0000 + OP_BL_10, //11 1100 0001 + OP_BL_10, //11 1100 0010 + OP_BL_10, //11 1100 0011 + OP_BL_10, //11 1100 0100 + OP_BL_10, //11 1100 0101 + OP_BL_10, //11 1100 0110 + OP_BL_10, //11 1100 0111 + OP_BL_10, //11 1100 1000 + OP_BL_10, //11 1100 1001 + OP_BL_10, //11 1100 1010 + OP_BL_10, //11 1100 1011 + OP_BL_10, //11 1100 1100 + OP_BL_10, //11 1100 1101 + OP_BL_10, //11 1100 1110 + OP_BL_10, //11 1100 1111 + + OP_BL_10, //11 1101 0000 + OP_BL_10, //11 1101 0001 + OP_BL_10, //11 1101 0010 + OP_BL_10, //11 1101 0011 + OP_BL_10, //11 1101 0100 + OP_BL_10, //11 1101 0101 + OP_BL_10, //11 1101 0110 + OP_BL_10, //11 1101 0111 + OP_BL_10, //11 1101 1000 + OP_BL_10, //11 1101 1001 + OP_BL_10, //11 1101 1010 + OP_BL_10, //11 1101 1011 + OP_BL_10, //11 1101 1100 + OP_BL_10, //11 1101 1101 + OP_BL_10, //11 1101 1110 + OP_BL_10, //11 1101 1111 + + OP_BL_THUMB, //11 1110 0000 + OP_BL_THUMB, //11 1110 0001 + OP_BL_THUMB, //11 1110 0010 + OP_BL_THUMB, //11 1110 0011 + OP_BL_THUMB, //11 1110 0100 + OP_BL_THUMB, //11 1110 0101 + OP_BL_THUMB, //11 1110 0110 + OP_BL_THUMB, //11 1110 0111 + OP_BL_THUMB, //11 1110 1000 + OP_BL_THUMB, //11 1110 1001 + OP_BL_THUMB, //11 1110 1010 + OP_BL_THUMB, //11 1110 1011 + OP_BL_THUMB, //11 1110 1100 + OP_BL_THUMB, //11 1110 1101 + OP_BL_THUMB, //11 1110 1110 + OP_BL_THUMB, //11 1110 1111 + + OP_BL_THUMB, //11 1111 0000 + OP_BL_THUMB, //11 1111 0001 + OP_BL_THUMB, //11 1111 0010 + OP_BL_THUMB, //11 1111 0011 + OP_BL_THUMB, //11 1111 0100 + OP_BL_THUMB, //11 1111 0101 + OP_BL_THUMB, //11 1111 0110 + OP_BL_THUMB, //11 1111 0111 + OP_BL_THUMB, //11 1111 1000 + OP_BL_THUMB, //11 1111 1001 + OP_BL_THUMB, //11 1111 1010 + OP_BL_THUMB, //11 1111 1011 + OP_BL_THUMB, //11 1111 1100 + OP_BL_THUMB, //11 1111 1101 + OP_BL_THUMB, //11 1111 1110 + OP_BL_THUMB, //11 1111 1111 +}; //1089 + diff --git a/tools/vio2sf/src/vio2sf/desmume/types.h b/tools/vio2sf/src/vio2sf/desmume/types.h new file mode 100644 index 000000000..ed4f21076 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/desmume/types.h @@ -0,0 +1,171 @@ +/* Copyright (C) 2005 Guillaume Duhamel + + This file is part of DeSmuME + + DeSmuME is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DeSmuME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DeSmuME; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TYPES_HPP +#define TYPES_HPP + +#ifndef FASTCALL +#ifdef __MINGW32__ +#define FASTCALL __attribute__((fastcall)) +#elif defined (__i386__) +#define FASTCALL __attribute__((regparm(3))) +#else +#define FASTCALL +#endif +#endif + +#ifndef INLINE +#ifdef _MSC_VER +#define INLINE _inline +#else +#define INLINE inline +#endif +#endif + +#ifdef DESMUME_COCOA +#ifdef __BIG_ENDIAN__ +#define WORDS_BIGENDIAN +#endif +#endif + +#if defined(__LP64__) +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long u64; +typedef unsigned long pointer; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long s64; +#else +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +#ifdef _MSC_VER +typedef unsigned __int64 u64; +#else +typedef unsigned long long u64; +#endif +typedef unsigned long pointer; + +typedef signed char s8; +typedef signed short s16; +typedef signed long s32; +#ifdef _MSC_VER +typedef __int64 s64; +#else +typedef signed long long s64; +#endif +#endif + +typedef u8 uint8; +typedef u16 uint16; + +#ifndef OBJ_C +typedef u32 uint32; +#else +#define uint32 u32 //uint32 is defined in Leopard somewhere, avoid conflicts +#endif + +/*---------- GPU3D fixed-points types -----------*/ + +typedef s32 f32; +#define inttof32(n) ((n) << 12) +#define f32toint(n) ((n) >> 12) +#define floattof32(n) ((int32)((n) * (1 << 12))) +#define f32tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 t16; +#define f32tot16(n) ((t16)(n >> 8)) +#define inttot16(n) ((n) << 4) +#define t16toint(n) ((n) >> 4) +#define floattot16(n) ((t16)((n) * (1 << 4))) +#define t16ofloat(n) (((float)(n)) / (float)(1<<4)) + +typedef s16 v16; +#define inttov16(n) ((n) << 12) +#define f32tov16(n) (n) +#define floattov16(n) ((v16)((n) * (1 << 12))) +#define v16toint(n) ((n) >> 12) +#define v16tofloat(n) (((float)(n)) / (float)(1<<12)) + +typedef s16 v10; +#define inttov10(n) ((n) << 9) +#define f32tov10(n) ((v10)(n >> 3)) +#define v10toint(n) ((n) >> 9) +#define floattov10(n) ((v10)((n) * (1 << 9))) +#define v10tofloat(n) (((float)(n)) / (float)(1<<9)) + +/*----------------------*/ + +#ifndef OBJ_C +typedef int BOOL; +#else +//apple also defines BOOL +typedef int desmume_BOOL; +#define BOOL desmume_BOOL +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __GNUC__ +#define PACKED __attribute__((packed)) +#endif + +#ifdef WORDS_BIGENDIAN +# define LOCAL_BE +#else +# define LOCAL_LE +#endif + +/* little endian (ds' endianess) to local endianess convert macros */ +#ifdef LOCAL_BE /* local arch is big endian */ +# define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) +# define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +#else /* local arch is little endian */ +# define LE_TO_LOCAL_16(x) (x) +# define LE_TO_LOCAL_32(x) (x) +# define LOCAL_TO_LE_16(x) (x) +# define LOCAL_TO_LE_32(x) (x) +#endif + +/* kilobytes and megabytes macro */ +#define MB(x) ((x)*1024*1024) +#define KB(x) ((x)*1024) + +#define CPU_STR(c) ((c==ARM9)?"ARM9":"ARM7") +typedef enum +{ + ARM9 = 0, + ARM7 = 1 +} cpu_id_t; + +#define __PACKED __attribute__((__packed__)) + +#endif diff --git a/tools/vio2sf/src/vio2sf/drvimpl.c b/tools/vio2sf/src/vio2sf/drvimpl.c new file mode 100644 index 000000000..e54f26543 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/drvimpl.c @@ -0,0 +1,856 @@ +#include +#include +#include + +#include "desmume/MMU.h" +#include "desmume/armcpu.h" +#include "desmume/ndssystem.h" +#include "desmume/spu_exports.h" +#include "desmume/cp15.h" + +#include "zlib/zlib.h" +#include "../xsfc/tagget.h" +#include "../xsfc/drvimpl.h" + +volatile BOOL execute = FALSE; + +static struct +{ + unsigned char *rom; + unsigned char *state; + unsigned romsize; + unsigned statesize; + unsigned stateptr; +} loaderwork = { 0, 0, 0, 0, 0 }; + +static void load_term(void) +{ + if (loaderwork.rom) + { + free(loaderwork.rom); + loaderwork.rom = 0; + } + loaderwork.romsize = 0; + if (loaderwork.state) + { + free(loaderwork.state); + loaderwork.state = 0; + } + loaderwork.statesize = 0; +} + +static int load_map(int issave, unsigned char *udata, unsigned usize) +{ + unsigned char *iptr; + unsigned isize; + unsigned char *xptr; + unsigned xsize = getdwordle(udata + 4); + unsigned xofs = getdwordle(udata + 0); + if (issave) + { + iptr = loaderwork.state; + isize = loaderwork.statesize; + loaderwork.state = 0; + loaderwork.statesize = 0; + } + else + { + iptr = loaderwork.rom; + isize = loaderwork.romsize; + loaderwork.rom = 0; + loaderwork.romsize = 0; + } + if (!iptr) + { + unsigned rsize = xofs + xsize; + if (!issave) + { + rsize -= 1; + rsize |= rsize >> 1; + rsize |= rsize >> 2; + rsize |= rsize >> 4; + rsize |= rsize >> 8; + rsize |= rsize >> 16; + rsize += 1; + } + iptr = malloc(rsize + 10); + if (!iptr) + return XSF_FALSE; + memset(iptr, 0, rsize + 10); + isize = rsize; + } + else if (isize < xofs + xsize) + { + unsigned rsize = xofs + xsize; + if (!issave) + { + rsize -= 1; + rsize |= rsize >> 1; + rsize |= rsize >> 2; + rsize |= rsize >> 4; + rsize |= rsize >> 8; + rsize |= rsize >> 16; + rsize += 1; + } + xptr = realloc(iptr, xofs + rsize + 10); + if (!xptr) + { + free(iptr); + return XSF_FALSE; + } + iptr = xptr; + isize = rsize; + } + memcpy(iptr + xofs, udata + 8, xsize); + if (issave) + { + loaderwork.state = iptr; + loaderwork.statesize = isize; + } + else + { + loaderwork.rom = iptr; + loaderwork.romsize = isize; + } + return XSF_TRUE; +} + +static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc) +{ + int ret; + int zerr; + uLongf usize = 8; + uLongf rsize = usize; + unsigned char *udata; + unsigned char *rdata; + + udata = malloc(usize); + if (!udata) + return XSF_FALSE; + + while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize))) + { + if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr) + { + free(udata); + return XSF_FALSE; + } + if (usize >= 8) + { + usize = getdwordle(udata + 4) + 8; + if (usize < rsize) + { + rsize += rsize; + usize = rsize; + } + else + rsize = usize; + } + else + { + rsize += rsize; + usize = rsize; + } + free(udata); + udata = malloc(usize); + if (!udata) + return XSF_FALSE; + } + + rdata = realloc(udata, usize); + if (!rdata) + { + free(udata); + return XSF_FALSE; + } + + if (0) + { + unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize); + if (ccrc != zcrc) + return XSF_FALSE; + } + + ret = load_map(issave, rdata, usize); + free(rdata); + return ret; +} + +static int load_psf_one(unsigned char *pfile, unsigned bytes) +{ + unsigned char *ptr = pfile; + unsigned code_size; + unsigned resv_size; + unsigned code_crc; + if (bytes < 16 || getdwordle(ptr) != 0x24465350) + return XSF_FALSE; + + resv_size = getdwordle(ptr + 4); + code_size = getdwordle(ptr + 8); + code_crc = getdwordle(ptr + 12); + + if (resv_size) + { + unsigned resv_pos = 0; + ptr = pfile + 16; + if (16+ resv_size > bytes) + return XSF_FALSE; + while (resv_pos + 12 < resv_size) + { + unsigned save_size = getdwordle(ptr + resv_pos + 4); + unsigned save_crc = getdwordle(ptr + resv_pos + 8); + if (getdwordle(ptr + resv_pos + 0) == 0x45564153) + { + if (resv_pos + 12 + save_size > resv_size) + return XSF_FALSE; + if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc)) + return XSF_FALSE; + } + resv_pos += 12 + save_size; + } + } + + if (code_size) + { + ptr = pfile + 16 + resv_size; + if (16 + resv_size + code_size > bytes) + return XSF_FALSE; + if (!load_mapz(0, ptr, code_size, code_crc)) + return XSF_FALSE; + } + + return XSF_TRUE; +} + +typedef struct +{ + const char *tag; + int taglen; + int level; + int found; +} loadlibwork_t; + +static int load_psf_and_libs(int level, void *pfile, unsigned bytes); + +static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) +{ + loadlibwork_t *pwork = (loadlibwork_t *)pWork; + int ret = xsf_tagenum_callback_returnvaluecontinue; + if (pNameEnd - pNameTop == pwork->taglen && !_strnicmp(pNameTop, pwork->tag , pwork->taglen)) + { + unsigned l = pValueEnd - pValueTop; + char *lib = malloc(l + 1); + if (!lib) + { + ret = xsf_tagenum_callback_returnvaluebreak; + } + else + { + void *libbuf; + unsigned libsize; + memcpy(lib, pValueTop, l); + lib[l] = '\0'; + if (!xsf_get_lib(lib, &libbuf, &libsize)) + { + ret = xsf_tagenum_callback_returnvaluebreak; + } + else + { + if (!load_psf_and_libs(pwork->level + 1, libbuf, libsize)) + ret = xsf_tagenum_callback_returnvaluebreak; + else + pwork->found++; + free(libbuf); + } + free(lib); + } + } + return ret; +} + +static int load_psf_and_libs(int level, void *pfile, unsigned bytes) +{ + int haslib = 0; + loadlibwork_t work; + + work.level = level; + work.tag = "_lib"; + work.taglen = strlen(work.tag); + work.found = 0; + + if (level <= 10 && xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0) + return XSF_FALSE; + + haslib = work.found; + + if (!load_psf_one(pfile, bytes)) + return XSF_FALSE; + +/* if (haslib) */ + { + int n = 2; + do + { + char tbuf[16]; +#ifdef HAVE_SPRINTF_S + sprintf_s(tbuf, sizeof(tbuf), "_lib%d", n++); +#else + sprintf(tbuf, "_lib%d", n++); +#endif + work.tag = tbuf; + work.taglen = strlen(work.tag); + work.found = 0; + if (xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0) + return XSF_FALSE; + } + while (work.found); + } + return XSF_TRUE; +} + +static int load_psf(void *pfile, unsigned bytes) +{ + load_term(); + + return load_psf_and_libs(1, pfile, bytes); +} + +static void load_getstateinit(unsigned ptr) +{ + loaderwork.stateptr = ptr; +} + +static u16 getwordle(const unsigned char *pData) +{ + return pData[0] | (((u16)pData[1]) << 8); +} + +static void load_getsta(Status_Reg *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + { + u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + ptr[i].bits.N = (st >> 31) & 1; + ptr[i].bits.Z = (st >> 30) & 1; + ptr[i].bits.C = (st >> 29) & 1; + ptr[i].bits.V = (st >> 28) & 1; + ptr[i].bits.Q = (st >> 27) & 1; + ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1); + ptr[i].bits.I = (st >> 7) & 1; + ptr[i].bits.F = (st >> 6) & 1; + ptr[i].bits.T = (st >> 5) & 1; + ptr[i].bits.mode = (st >> 0) & 0x1f; + } + loaderwork.stateptr += s; +} + +static void load_getbool(BOOL *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + loaderwork.stateptr += s; +} + +#if defined(SIGNED_IS_NOT_2S_COMPLEMENT) +/* 2's complement */ +#define u32tos32(v) ((s32)((((s64)(v)) ^ 0x80000000) - 0x80000000)) +#else +/* 2's complement */ +#define u32tos32(v) ((s32)v) +#endif + +static void load_gets32(s32 *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2))); + loaderwork.stateptr += s; +} + +static void load_getu32(u32 *ptr, unsigned l) +{ + unsigned s = l << 2; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); + loaderwork.stateptr += s; +} + +static void load_getu16(u16 *ptr, unsigned l) +{ + unsigned s = l << 1; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1)); + loaderwork.stateptr += s; +} + +static void load_getu8(u8 *ptr, unsigned l) +{ + unsigned s = l; + unsigned i; + if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) + return; + for (i = 0; i < l; i++) + ptr[i] = loaderwork.state[loaderwork.stateptr + i]; + loaderwork.stateptr += s; +} + +void gdb_stub_fix(armcpu_t *armcpu) +{ + /* armcpu->R[15] = armcpu->instruct_adr; */ + armcpu->next_instruction = armcpu->instruct_adr; + if(armcpu->CPSR.bits.T == 0) + { + armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 4; + armcpu->R[15] = armcpu->next_instruction + 4; + } + else + { + armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); + armcpu->instruct_adr = armcpu->next_instruction; + armcpu->next_instruction += 2; + armcpu->R[15] = armcpu->next_instruction + 2; + } +} + +static void load_setstate(void) +{ + if (!loaderwork.statesize) + return; + + /* Skip over "Desmume Save File" crap */ + load_getstateinit(0x17); + + /* Read ARM7 cpu registers */ + load_getu32(&NDS_ARM7.proc_ID, 1); + load_getu32(&NDS_ARM7.instruction, 1); + load_getu32(&NDS_ARM7.instruct_adr, 1); + load_getu32(&NDS_ARM7.next_instruction, 1); + load_getu32(NDS_ARM7.R, 16); + load_getsta(&NDS_ARM7.CPSR, 1); + load_getsta(&NDS_ARM7.SPSR, 1); + load_getu32(&NDS_ARM7.R13_usr, 1); + load_getu32(&NDS_ARM7.R14_usr, 1); + load_getu32(&NDS_ARM7.R13_svc, 1); + load_getu32(&NDS_ARM7.R14_svc, 1); + load_getu32(&NDS_ARM7.R13_abt, 1); + load_getu32(&NDS_ARM7.R14_abt, 1); + load_getu32(&NDS_ARM7.R13_und, 1); + load_getu32(&NDS_ARM7.R14_und, 1); + load_getu32(&NDS_ARM7.R13_irq, 1); + load_getu32(&NDS_ARM7.R14_irq, 1); + load_getu32(&NDS_ARM7.R8_fiq, 1); + load_getu32(&NDS_ARM7.R9_fiq, 1); + load_getu32(&NDS_ARM7.R10_fiq, 1); + load_getu32(&NDS_ARM7.R11_fiq, 1); + load_getu32(&NDS_ARM7.R12_fiq, 1); + load_getu32(&NDS_ARM7.R13_fiq, 1); + load_getu32(&NDS_ARM7.R14_fiq, 1); + load_getsta(&NDS_ARM7.SPSR_svc, 1); + load_getsta(&NDS_ARM7.SPSR_abt, 1); + load_getsta(&NDS_ARM7.SPSR_und, 1); + load_getsta(&NDS_ARM7.SPSR_irq, 1); + load_getsta(&NDS_ARM7.SPSR_fiq, 1); + load_getu32(&NDS_ARM7.intVector, 1); + load_getu8(&NDS_ARM7.LDTBit, 1); + load_getbool(&NDS_ARM7.waitIRQ, 1); + load_getbool(&NDS_ARM7.wIRQ, 1); + load_getbool(&NDS_ARM7.wirq, 1); + + /* Read ARM9 cpu registers */ + load_getu32(&NDS_ARM9.proc_ID, 1); + load_getu32(&NDS_ARM9.instruction, 1); + load_getu32(&NDS_ARM9.instruct_adr, 1); + load_getu32(&NDS_ARM9.next_instruction, 1); + load_getu32(NDS_ARM9.R, 16); + load_getsta(&NDS_ARM9.CPSR, 1); + load_getsta(&NDS_ARM9.SPSR, 1); + load_getu32(&NDS_ARM9.R13_usr, 1); + load_getu32(&NDS_ARM9.R14_usr, 1); + load_getu32(&NDS_ARM9.R13_svc, 1); + load_getu32(&NDS_ARM9.R14_svc, 1); + load_getu32(&NDS_ARM9.R13_abt, 1); + load_getu32(&NDS_ARM9.R14_abt, 1); + load_getu32(&NDS_ARM9.R13_und, 1); + load_getu32(&NDS_ARM9.R14_und, 1); + load_getu32(&NDS_ARM9.R13_irq, 1); + load_getu32(&NDS_ARM9.R14_irq, 1); + load_getu32(&NDS_ARM9.R8_fiq, 1); + load_getu32(&NDS_ARM9.R9_fiq, 1); + load_getu32(&NDS_ARM9.R10_fiq, 1); + load_getu32(&NDS_ARM9.R11_fiq, 1); + load_getu32(&NDS_ARM9.R12_fiq, 1); + load_getu32(&NDS_ARM9.R13_fiq, 1); + load_getu32(&NDS_ARM9.R14_fiq, 1); + load_getsta(&NDS_ARM9.SPSR_svc, 1); + load_getsta(&NDS_ARM9.SPSR_abt, 1); + load_getsta(&NDS_ARM9.SPSR_und, 1); + load_getsta(&NDS_ARM9.SPSR_irq, 1); + load_getsta(&NDS_ARM9.SPSR_fiq, 1); + load_getu32(&NDS_ARM9.intVector, 1); + load_getu8(&NDS_ARM9.LDTBit, 1); + load_getbool(&NDS_ARM9.waitIRQ, 1); + load_getbool(&NDS_ARM9.wIRQ, 1); + load_getbool(&NDS_ARM9.wirq, 1); + + /* Read in other internal variables that are important */ + load_gets32(&nds.ARM9Cycle, 1); + load_gets32(&nds.ARM7Cycle, 1); + load_gets32(&nds.cycles, 1); + load_gets32(nds.timerCycle[0], 4); + load_gets32(nds.timerCycle[1], 4); + load_getbool(nds.timerOver[0], 4); + load_getbool(nds.timerOver[1], 4); + load_gets32(&nds.nextHBlank, 1); + load_getu32(&nds.VCount, 1); + load_getu32(&nds.old, 1); + load_gets32(&nds.diff, 1); + load_getbool(&nds.lignerendu, 1); + load_getu16(&nds.touchX, 1); + load_getu16(&nds.touchY, 1); + + /* Read in memory/registers specific to the ARM9 */ + load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000); + load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000); + load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000); + load_getu8 (ARM9Mem.MAIN_MEM, 0x400000); + load_getu8 (ARM9Mem.ARM9_REG, 0x10000); + load_getu8 (ARM9Mem.ARM9_VMEM, 0x800); + load_getu8 (ARM9Mem.ARM9_OAM, 0x800); + load_getu8 (ARM9Mem.ARM9_ABG, 0x80000); + load_getu8 (ARM9Mem.ARM9_BBG, 0x20000); + load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000); + load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000); + load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000); + + /* Read in memory/registers specific to the ARM7 */ + load_getu8 (MMU.ARM7_ERAM, 0x10000); + load_getu8 (MMU.ARM7_REG, 0x10000); + load_getu8 (MMU.ARM7_WIRAM, 0x10000); + + /* Read in shared memory */ + load_getu8 (MMU.SWIRAM, 0x8000); + +#ifdef GDB_STUB +#else + gdb_stub_fix(&NDS_ARM9); + gdb_stub_fix(&NDS_ARM7); +#endif +} + +static struct +{ + unsigned char *pcmbufalloc; + unsigned char *pcmbuftop; + unsigned filled; + unsigned used; + u32 bufferbytes; + u32 cycles; + int xfs_load; + int sync_type; + int arm7_clockdown_level; + int arm9_clockdown_level; +} sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +static void SNDIFDeInit(void) +{ + if (sndifwork.pcmbufalloc) + { + free(sndifwork.pcmbufalloc); + sndifwork.pcmbufalloc = 0; + sndifwork.pcmbuftop = 0; + sndifwork.bufferbytes = 0; + } +} +static int SNDIFInit(int buffersize) +{ + u32 bufferbytes = buffersize * sizeof(s16); + SNDIFDeInit(); + sndifwork.pcmbufalloc = malloc(bufferbytes + 3); + if (!sndifwork.pcmbufalloc) + return -1; + sndifwork.pcmbuftop = sndifwork.pcmbufalloc + ((4 - (((int)sndifwork.pcmbufalloc) & 3)) & 3); + sndifwork.bufferbytes = bufferbytes; + sndifwork.filled = 0; + sndifwork.used = 0; + sndifwork.cycles = 0; + return 0; +} +static void SNDIFMuteAudio(void) +{ +} +static void SNDIFUnMuteAudio(void) +{ +} +static void SNDIFSetVolume(int volume) +{ +} +static int SNDIFGetAudioSpace(void) +{ + return sndifwork.bufferbytes >> 2; // bytes to samples +} +static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples) +{ + u32 num_bytes = num_samples << 2; + if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes; + memcpy(sndifwork.pcmbuftop, buffer, num_bytes); + sndifwork.filled = num_bytes; + sndifwork.used = 0; +} +#define VIO2SFSNDIFID 0 +static SoundInterface_struct VIO2SFSNDIF = +{ + VIO2SFSNDIFID, + "vio2sf Sound Interface", + SNDIFInit, + SNDIFDeInit, + SNDIFUpdateAudio, + SNDIFGetAudioSpace, + SNDIFMuteAudio, + SNDIFUnMuteAudio, + SNDIFSetVolume +}; + +SoundInterface_struct *SNDCoreList[] = { + &VIO2SFSNDIF, + NULL +}; + +static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0; +static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0; + +int xsf_start(void *pfile, unsigned bytes) +{ + int frames = xsf_tagget_int("_frames", pfile, bytes, -1); + int clockdown = xsf_tagget_int("_clockdown", pfile, bytes, 0); + sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", pfile, bytes, 0); + sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", pfile, bytes, clockdown); + sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", pfile, bytes, clockdown); + + sndifwork.xfs_load = 0; + if (!load_psf(pfile, bytes)) + return XSF_FALSE; + +#ifdef GDB_STUB + if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface)) +#else + if (NDS_Init()) +#endif + return XSF_FALSE; + + SPU_ChangeSoundCore(0, 737); + + execute = FALSE; + + MMU_unsetRom(); + if (loaderwork.rom) + { + NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1); + } + + NDS_Reset(); + + execute = TRUE; + + if (loaderwork.state) + { + armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15]; + int proc; + if (frames == -1) + { + + /* set initial ARM9 coprocessor state */ + + armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0); + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); + armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4); + armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0); + armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0); + armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0); + armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0); + armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0); + armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0); + armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0); + armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1); + + armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0); + + armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1); + armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3); + armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2); + armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0); + armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0); + + armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); + armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1); + armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1); + + /* set initial timer state */ + + MMU_write16(0, REG_TM0CNTL, 0x0000); + MMU_write16(0, REG_TM0CNTH, 0x00C1); + MMU_write16(1, REG_TM0CNTL, 0x0000); + MMU_write16(1, REG_TM0CNTH, 0x00C1); + MMU_write16(1, REG_TM1CNTL, 0xf7e7); + MMU_write16(1, REG_TM1CNTH, 0x00C1); + + /* set initial interrupt state */ + + MMU.reg_IME[0] = 0x00000001; + MMU.reg_IE[0] = 0x00042001; + MMU.reg_IME[1] = 0x00000001; + MMU.reg_IE[1] = 0x0104009d; + } + else if (frames > 0) + { + /* execute boot code */ + int i; + for (i=0; i 0) + { + /* skip 1 sec */ + int i; + for (i=0; i 0) + { + if (remainbytes > bytes) + { + memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes); + sndifwork.used += bytes; + ptr += bytes; + remainbytes -= bytes; /**/ + bytes = 0; /**/ + break; + } + else + { + memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes); + sndifwork.used += remainbytes; + ptr += remainbytes; + bytes -= remainbytes; + remainbytes = 0; + } + } + if (remainbytes == 0) + { + +/* +#define HBASE_CYCLES (16756000*2) +#define HBASE_CYCLES (33512000*1) +#define HBASE_CYCLES (33509300.322234) +*/ +#define HBASE_CYCLES (33509300.322234) +#define HLINE_CYCLES (6 * (99 + 256)) +#define HSAMPLES ((u32)((44100.0 * HLINE_CYCLES) / HBASE_CYCLES)) +#define VDIVISION 100 +#define VLINES 263 +#define VBASE_CYCLES (((double)HBASE_CYCLES) / VDIVISION) +#define VSAMPLES ((u32)((44100.0 * HLINE_CYCLES * VLINES) / HBASE_CYCLES)) + + int numsamples; + if (sndifwork.sync_type == 1) + { + /* vsync */ + sndifwork.cycles += ((44100 / VDIVISION) * HLINE_CYCLES * VLINES); + if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1))) + { + numsamples = (VSAMPLES + 1); + sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1)); + } + else + { + numsamples = (VSAMPLES + 0); + sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0)); + } + NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); + } + else + { + /* hsync */ + sndifwork.cycles += (44100 * HLINE_CYCLES); + if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1))) + { + numsamples = (HSAMPLES + 1); + sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1)); + } + else + { + numsamples = (HSAMPLES + 0); + sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0)); + } + NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); + } + SPU_EmulateSamples(numsamples); + } + } + return ptr - (unsigned char *)pbuffer; +} + +void xsf_term(void) +{ + MMU_unsetRom(); + NDS_DeInit(); + load_term(); +} diff --git a/tools/vio2sf/src/vio2sf/zlib/adler32.c b/tools/vio2sf/src/vio2sf/zlib/adler32.c new file mode 100644 index 000000000..f201d6701 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/adler32.c @@ -0,0 +1,149 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 > BASE) sum1 -= BASE; + if (sum1 > BASE) sum1 -= BASE; + if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 > BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/README.contrib b/tools/vio2sf/src/vio2sf/zlib/contrib/README.contrib new file mode 100644 index 000000000..1e05c4f18 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/README.contrib @@ -0,0 +1,17 @@ +All files under this contrib directory are UNSUPPORTED. There were +provided by users of zlib and were not tested by the authors of zlib. +Use at your own risk. Please contact the authors of the contributions +for help about these, not the zlib authors. Thanks. + + +inflate86/ by Chris Anderson + Tuned x86 gcc asm code to replace inflate_fast() + +masmx64/ by Gilles Vollant + x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to + replace longest_match() and inflate_fast() + +masmx86/ by Gilles Vollant + x86 asm code to replace longest_match() and inflate_fast(), + for Visual C++ and MASM + diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffas86.c b/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffas86.c new file mode 100644 index 000000000..6da76358c --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffas86.c @@ -0,0 +1,1157 @@ +/* inffas86.c is a hand tuned assembler version of + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } ar; + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->write; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) + __asm__ __volatile__ ( +" leaq %0, %%rax\n" +" movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ +" movq %%rsp, (%%rax)\n" +" movq %%rax, %%rsp\n" /* make rsp point to &ar */ +" movq 16(%%rsp), %%rsi\n" /* rsi = in */ +" movq 32(%%rsp), %%rdi\n" /* rdi = out */ +" movq 24(%%rsp), %%r9\n" /* r9 = last */ +" movq 48(%%rsp), %%r10\n" /* r10 = end */ +" movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ +" movq 72(%%rsp), %%r11\n" /* r11 = dcode */ +" movq 80(%%rsp), %%rdx\n" /* rdx = hold */ +" movl 88(%%rsp), %%ebx\n" /* ebx = bits */ +" movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ +" movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ + /* r14d = len */ + /* r15d = dist */ +" cld\n" +" cmpq %%rdi, %%r10\n" +" je .L_one_time\n" /* if only one decode left */ +" cmpq %%rsi, %%r9\n" +" je .L_one_time\n" +" jmp .L_do_loop\n" + +".L_one_time:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code_one_time\n" + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ +" jmp .L_get_length_code_one_time\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpq %%rdi, %%r10\n" +" jbe .L_break_loop\n" +" cmpq %%rsi, %%r9\n" +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_length_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" movq %%r12, %%r8\n" /* r8 = lmask */ +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" + +".L_get_length_code_one_time:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%r14d\n" /* len = this */ +" shrl $16, %%r14d\n" /* len = this.val */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r14d\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" movq %%r13, %%r8\n" /* r8 = dmask */ +" cmpb $32, %%bl\n" +" ja .L_get_distance_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_distance_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%r15d\n" /* dist = this */ +" shrl $16, %%r15d\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movq %%rsi, %%r8\n" /* save in so from can use it's reg */ +" movq %%rdi, %%rax\n" +" subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ + +" cmpl %%r15d, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%rsi), %%al\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%r15d\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ +" je .L_check_window\n" + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movb -1(%%rdi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +".L_set_two:\n" +" rep stosw\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r14d, %%eax\n" /* eax += len */ +" movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r15d, %%eax\n" /* eax += dist */ +" movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" /* ecx = nbytes */ +" movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ +" negl %%ecx\n" /* nbytes = -nbytes */ + +" cmpl %%r15d, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 96(%%rsp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" addq %%rax, %%rsi\n" /* from += wsize - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%r14d\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 96(%%rsp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" movl 92(%%rsp), %%esi\n" /* from = wsize */ +" addq 56(%%rsp), %%rsi\n" /* from += window */ +" addq %%rax, %%rsi\n" /* from += write */ +" subq %%rcx, %%rsi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" movl 96(%%rsp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" movq 56(%%rsp), %%rsi\n" /* rsi = window */ +" addq %%rax, %%rsi\n" +" subq %%rcx, %%rsi\n" /* from += write - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" /* ecx = len */ +" rep movsb\n" + +" movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl $4, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 116(%%rsp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movq %%rsi, 16(%%rsp)\n" /* in */ +" movq %%rdi, 32(%%rsp)\n" /* out */ +" movl %%ebx, 88(%%rsp)\n" /* bits */ +" movq %%rdx, 80(%%rsp)\n" /* hold */ +" movq (%%rsp), %%rax\n" /* restore rbp and rsp */ +" movq 8(%%rsp), %%rbp\n" +" movq %%rax, %%rsp\n" + : + : "m" (ar) + : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" + ); +#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) + __asm__ __volatile__ ( +" leal %0, %%eax\n" +" movl %%esp, (%%eax)\n" /* save esp, ebp */ +" movl %%ebp, 4(%%eax)\n" +" movl %%eax, %%esp\n" +" movl 8(%%esp), %%esi\n" /* esi = in */ +" movl 16(%%esp), %%edi\n" /* edi = out */ +" movl 40(%%esp), %%edx\n" /* edx = hold */ +" movl 44(%%esp), %%ebx\n" /* ebx = bits */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ + +" cld\n" +" jmp .L_do_loop\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpl %%edi, 24(%%esp)\n" /* out < end */ +" jbe .L_break_loop\n" +" cmpl %%esi, 12(%%esp)\n" /* in < last */ +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" cmpb $15, %%bl\n" +" ja .L_get_length_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_length_code:\n" +" movl 56(%%esp), %%eax\n" /* eax = lmask */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%ecx\n" /* len = this */ +" shrl $16, %%ecx\n" /* len = this.val */ +" movl %%ecx, 64(%%esp)\n" /* save len */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_len\n" /* if (op <= bits) */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" cmpb $15, %%bl\n" +" ja .L_get_distance_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_distance_code:\n" +" movl 60(%%esp), %%eax\n" /* eax = dmask */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%ebp\n" /* dist = this */ +" shrl $16, %%ebp\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ +" movl %%edi, %%eax\n" +" subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ + +" cmpl %%ebp, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%esi), %%al\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%ebp\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpl %%edi, 20(%%esp)\n" +" je .L_check_window\n" /* out == beg, if outside window */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movb -1(%%edi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +".L_set_two:\n" +" rep stosw\n" +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl 64(%%esp), %%eax\n" /* eax += len */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%ebp, %%eax\n" /* eax += dist */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" +" movl 48(%%esp), %%eax\n" /* eax = wsize */ +" negl %%ecx\n" /* nbytes = -nbytes */ +" movl 28(%%esp), %%esi\n" /* from = window */ + +" cmpl %%ebp, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 52(%%esp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" subl %%ecx, %%eax\n" +" addl %%eax, %%esi\n" /* from += wsize - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 52(%%esp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" addl 48(%%esp), %%esi\n" /* from += wsize */ +" addl %%eax, %%esi\n" /* from += write */ +" subl %%ecx, %%esi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl 28(%%esp), %%esi\n" /* from = window */ +" movl 52(%%esp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" addl %%eax, %%esi\n" +" subl %%ecx, %%esi\n" /* from += write - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" +" rep movsb\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl 8(%%esp), %%esi\n" +" movl $4, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 72(%%esp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movl %%esi, 8(%%esp)\n" /* save in */ +" movl %%edi, 16(%%esp)\n" /* save out */ +" movl %%ebx, 44(%%esp)\n" /* save bits */ +" movl %%edx, 40(%%esp)\n" /* save hold */ +" movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ +" movl (%%esp), %%esp\n" + : + : "m" (ar) + : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" + ); +#elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) + __asm { + lea eax, ar + mov [eax], esp /* save esp, ebp */ + mov [eax+4], ebp + mov esp, eax + mov esi, [esp+8] /* esi = in */ + mov edi, [esp+16] /* edi = out */ + mov edx, [esp+40] /* edx = hold */ + mov ebx, [esp+44] /* ebx = bits */ + mov ebp, [esp+32] /* ebp = lcode */ + + cld + jmp L_do_loop + +ALIGN 4 +L_while_test: + cmp [esp+24], edi + jbe L_break_loop + cmp [esp+12], esi + jbe L_break_loop + +L_do_loop: + cmp bl, 15 + ja L_get_length_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_length_code: + mov eax, [esp+56] /* eax = lmask */ + and eax, edx /* eax &= hold */ + mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah /* cl = this.bits */ + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base /* if (op != 0) 45.7% */ + + shr eax, 16 /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov ecx, eax /* len = this */ + shr ecx, 16 /* len = this.val */ + mov [esp+64], ecx /* save len */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + and cl, 15 /* op &= 15 */ + jz L_decode_distance /* if (!op) */ + cmp bl, cl + jae L_add_bits_to_len /* if (op <= bits) */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + shr edx, cl + add [esp+64], eax /* len += hold & mask[op] */ + +L_decode_distance: + cmp bl, 15 + ja L_get_distance_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_distance_code: + mov eax, [esp+60] /* eax = dmask */ + mov ecx, [esp+36] /* ecx = dcode */ + and eax, edx /* eax &= hold */ + mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ + +L_dodist: + mov ebp, eax /* dist = this */ + shr ebp, 16 /* dist = this.val */ + mov cl, ah + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + mov cl, al /* cl = this.op */ + + test al, 16 /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 /* op &= 15 */ + jz L_check_dist_one + cmp bl, cl + jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax /* (1 << op) - 1 */ + and eax, edx /* eax &= hold */ + shr edx, cl + add ebp, eax /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov [esp+8], esi /* save in so from can use it's reg */ + mov eax, edi + sub eax, [esp+20] /* nbytes = out - beg */ + + cmp eax, ebp + jb L_clip_window /* if (dist > nbytes) 4.2% */ + + mov ecx, [esp+64] /* ecx = len */ + mov esi, edi + sub esi, ebp /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two + + rep movsw + mov al, [esi] + mov [edi], al + inc edi + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_copy_two: + rep movsw + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp ebp, 1 /* if dist 1, is a memset */ + jne L_check_window + cmp [esp+20], edi + je L_check_window /* out == beg, if outside window */ + + mov ecx, [esp+64] /* ecx = len */ + mov al, [edi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [edi], al /* memset out with from[-1] */ + inc edi + +L_set_two: + rep stosw + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, [esp+64] /* eax += len */ + mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, ebp /* eax += dist */ + mov ecx, [esp+36] /* ecx = dcode */ + mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax + mov eax, [esp+48] /* eax = wsize */ + neg ecx /* nbytes = -nbytes */ + mov esi, [esp+28] /* from = window */ + + cmp eax, ebp + jb L_invalid_distance_too_far /* if (dist > wsize) */ + + add ecx, ebp /* nbytes = dist - nbytes */ + cmp dword ptr [esp+52], 0 + jne L_wrap_around_window /* if (write != 0) */ + + sub eax, ecx + add esi, eax /* from += wsize - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [esp+52] /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window /* if (write >= nbytes) */ + + add esi, [esp+48] /* from += wsize */ + add esi, eax /* from += write */ + sub esi, ecx /* from -= nbytes */ + sub ecx, eax /* nbytes -= write */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, [esp+28] /* from = window */ + mov ecx, [esp+52] /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + add esi, eax + sub esi, ecx /* from += write - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_do_copy: + mov ecx, eax + rep movsb + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [esp+72], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [esp+72], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [esp+72], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov esi, [esp+4] + mov dword ptr [esp+72], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [esp+72], 0 + +L_break_loop_with_status: +/* put in, out, bits, and hold back into ar and pop esp */ + mov [esp+8], esi /* save in */ + mov [esp+16], edi /* save out */ + mov [esp+44], ebx /* save bits */ + mov [esp+40], edx /* save hold */ + mov ebp, [esp+4] /* restore esp, ebp */ + mov esp, [esp] + } +#else +#error "x86 architecture not defined" +#endif + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = ar.hold; + state->bits = ar.bits; + return; +} + diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffast.S b/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffast.S new file mode 100644 index 000000000..2245a2905 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/inflate86/inffast.S @@ -0,0 +1,1368 @@ +/* + * inffast.S is a hand tuned assembler version of: + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * This version (Jan-23-2003) of inflate_fast was coded and tested under + * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that + * machine, I found that gzip style archives decompressed about 20% faster than + * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will + * depend on how large of a buffer is used for z_stream.next_in & next_out + * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in + * stream processing I/O and crc32/addler32. In my case, this routine used + * 70% of the cpu time and crc32 used 20%. + * + * I am confident that this version will work in the general case, but I have + * not tested a wide variety of datasets or a wide variety of platforms. + * + * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. + * It should be a runtime flag instead of compile time flag... + * + * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. + * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code + * is compiled. Without either option, runtime detection is enabled. Runtime + * detection should work on all modern cpus and the recomended algorithm (flip + * ID bit on eflags and then use the cpuid instruction) is used in many + * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 + * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o + * inffast.obj generates a COFF object which can then be linked with MSVC++ + * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. + * + * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and + * slower than compiler generated code). Adjusted cpuid check to use the MMX + * code only for Pentiums < P4 until I have more data on the P4. Speed + * improvment is only about 15% on the Athlon when compared with code generated + * with MSVC++. Not sure yet, but I think the P4 will also be slower using the + * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and + * have less latency than MMX ops. Added code to buffer the last 11 bytes of + * the input stream since the MMX code grabs bits in chunks of 32, which + * differs from the inffast.c algorithm. I don't think there would have been + * read overruns where a page boundary was crossed (a segfault), but there + * could have been overruns when next_in ends on unaligned memory (unintialized + * memory read). + * + * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C + * version of the non-MMX code so that it doesn't depend on zstrm and zstate + * structure offsets which are hard coded in this file. This was last tested + * with zlib-1.2.0 which is currently in beta testing, newer versions of this + * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and + * http://www.charm.net/~christop/zlib/ + */ + + +/* + * if you have underscore linking problems (_inflate_fast undefined), try + * using -DGAS_COFF + */ +#if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) + +#if defined( WIN32 ) || defined( __CYGWIN__ ) +#define GAS_COFF /* windows object format */ +#else +#define GAS_ELF +#endif + +#endif /* ! GAS_COFF && ! GAS_ELF */ + + +#if defined( GAS_COFF ) + +/* coff externals have underscores */ +#define inflate_fast _inflate_fast +#define inflate_fast_use_mmx _inflate_fast_use_mmx + +#endif /* GAS_COFF */ + + +.file "inffast.S" + +.globl inflate_fast + +.text +.align 4,0 +.L_invalid_literal_length_code_msg: +.string "invalid literal/length code" + +.align 4,0 +.L_invalid_distance_code_msg: +.string "invalid distance code" + +.align 4,0 +.L_invalid_distance_too_far_msg: +.string "invalid distance too far back" + +#if ! defined( NO_MMX ) +.align 4,0 +.L_mask: /* mask[N] = ( 1 << N ) - 1 */ +.long 0 +.long 1 +.long 3 +.long 7 +.long 15 +.long 31 +.long 63 +.long 127 +.long 255 +.long 511 +.long 1023 +.long 2047 +.long 4095 +.long 8191 +.long 16383 +.long 32767 +.long 65535 +.long 131071 +.long 262143 +.long 524287 +.long 1048575 +.long 2097151 +.long 4194303 +.long 8388607 +.long 16777215 +.long 33554431 +.long 67108863 +.long 134217727 +.long 268435455 +.long 536870911 +.long 1073741823 +.long 2147483647 +.long 4294967295 +#endif /* NO_MMX */ + +.text + +/* + * struct z_stream offsets, in zlib.h + */ +#define next_in_strm 0 /* strm->next_in */ +#define avail_in_strm 4 /* strm->avail_in */ +#define next_out_strm 12 /* strm->next_out */ +#define avail_out_strm 16 /* strm->avail_out */ +#define msg_strm 24 /* strm->msg */ +#define state_strm 28 /* strm->state */ + +/* + * struct inflate_state offsets, in inflate.h + */ +#define mode_state 0 /* state->mode */ +#define wsize_state 32 /* state->wsize */ +#define write_state 40 /* state->write */ +#define window_state 44 /* state->window */ +#define hold_state 48 /* state->hold */ +#define bits_state 52 /* state->bits */ +#define lencode_state 68 /* state->lencode */ +#define distcode_state 72 /* state->distcode */ +#define lenbits_state 76 /* state->lenbits */ +#define distbits_state 80 /* state->distbits */ + +/* + * inflate_fast's activation record + */ +#define local_var_size 64 /* how much local space for vars */ +#define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ +#define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ + +/* + * offsets for local vars on stack + */ +#define out 60 /* unsigned char* */ +#define window 56 /* unsigned char* */ +#define wsize 52 /* unsigned int */ +#define write 48 /* unsigned int */ +#define in 44 /* unsigned char* */ +#define beg 40 /* unsigned char* */ +#define buf 28 /* char[ 12 ] */ +#define len 24 /* unsigned int */ +#define last 20 /* unsigned char* */ +#define end 16 /* unsigned char* */ +#define dcode 12 /* code* */ +#define lcode 8 /* code* */ +#define dmask 4 /* unsigned int */ +#define lmask 0 /* unsigned int */ + +/* + * typedef enum inflate_mode consts, in inflate.h + */ +#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ +#define INFLATE_MODE_BAD 26 + + +#if ! defined( USE_MMX ) && ! defined( NO_MMX ) + +#define RUN_TIME_MMX + +#define CHECK_MMX 1 +#define DO_USE_MMX 2 +#define DONT_USE_MMX 3 + +.globl inflate_fast_use_mmx + +.data + +.align 4,0 +inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ +.long CHECK_MMX + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast_use_mmx,@object +.size inflate_fast_use_mmx,4 +#endif + +#endif /* RUN_TIME_MMX */ + +#if defined( GAS_COFF ) +/* coff info: scl 2 = extern, type 32 = function */ +.def inflate_fast; .scl 2; .type 32; .endef +#endif + +.text + +.align 32,0x90 +inflate_fast: + pushl %edi + pushl %esi + pushl %ebp + pushl %ebx + pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ + subl $local_var_size, %esp + cld + +#define strm_r %esi +#define state_r %edi + + movl strm_sp(%esp), strm_r + movl state_strm(strm_r), state_r + + /* in = strm->next_in; + * out = strm->next_out; + * last = in + strm->avail_in - 11; + * beg = out - (start - strm->avail_out); + * end = out + (strm->avail_out - 257); + */ + movl avail_in_strm(strm_r), %edx + movl next_in_strm(strm_r), %eax + + addl %eax, %edx /* avail_in += next_in */ + subl $11, %edx /* avail_in -= 11 */ + + movl %eax, in(%esp) + movl %edx, last(%esp) + + movl start_sp(%esp), %ebp + movl avail_out_strm(strm_r), %ecx + movl next_out_strm(strm_r), %ebx + + subl %ecx, %ebp /* start -= avail_out */ + negl %ebp /* start = -start */ + addl %ebx, %ebp /* start += next_out */ + + subl $257, %ecx /* avail_out -= 257 */ + addl %ebx, %ecx /* avail_out += out */ + + movl %ebx, out(%esp) + movl %ebp, beg(%esp) + movl %ecx, end(%esp) + + /* wsize = state->wsize; + * write = state->write; + * window = state->window; + * hold = state->hold; + * bits = state->bits; + * lcode = state->lencode; + * dcode = state->distcode; + * lmask = ( 1 << state->lenbits ) - 1; + * dmask = ( 1 << state->distbits ) - 1; + */ + + movl lencode_state(state_r), %eax + movl distcode_state(state_r), %ecx + + movl %eax, lcode(%esp) + movl %ecx, dcode(%esp) + + movl $1, %eax + movl lenbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, lmask(%esp) + + movl $1, %eax + movl distbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, dmask(%esp) + + movl wsize_state(state_r), %eax + movl write_state(state_r), %ecx + movl window_state(state_r), %edx + + movl %eax, wsize(%esp) + movl %ecx, write(%esp) + movl %edx, window(%esp) + + movl hold_state(state_r), %ebp + movl bits_state(state_r), %ebx + +#undef strm_r +#undef state_r + +#define in_r %esi +#define from_r %esi +#define out_r %edi + + movl in(%esp), in_r + movl last(%esp), %ecx + cmpl in_r, %ecx + ja .L_align_long /* if in < last */ + + addl $11, %ecx /* ecx = &in[ avail_in ] */ + subl in_r, %ecx /* ecx = avail_in */ + movl $12, %eax + subl %ecx, %eax /* eax = 12 - avail_in */ + leal buf(%esp), %edi + rep movsb /* memcpy( buf, in, avail_in ) */ + movl %eax, %ecx + xorl %eax, %eax + rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ + leal buf(%esp), in_r /* in = buf */ + movl in_r, last(%esp) /* last = in, do just one iteration */ + jmp .L_is_aligned + + /* align in_r on long boundary */ +.L_align_long: + testl $3, in_r + jz .L_is_aligned + xorl %eax, %eax + movb (in_r), %al + incl in_r + movl %ebx, %ecx + addl $8, %ebx + shll %cl, %eax + orl %eax, %ebp + jmp .L_align_long + +.L_is_aligned: + movl out(%esp), out_r + +#if defined( NO_MMX ) + jmp .L_do_loop +#endif + +#if defined( USE_MMX ) + jmp .L_init_mmx +#endif + +/*** Runtime MMX check ***/ + +#if defined( RUN_TIME_MMX ) +.L_check_mmx: + cmpl $DO_USE_MMX, inflate_fast_use_mmx + je .L_init_mmx + ja .L_do_loop /* > 2 */ + + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushf + movl (%esp), %eax /* copy eflags to eax */ + xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) + * to see if cpu supports cpuid... + * ID bit method not supported by NexGen but + * bios may load a cpuid instruction and + * cpuid may be disabled on Cyrix 5-6x86 */ + popf + pushf + popl %edx /* copy new eflags to edx */ + xorl %eax, %edx /* test if ID bit is flipped */ + jz .L_dont_use_mmx /* not flipped if zero */ + xorl %eax, %eax + cpuid + cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ + jne .L_dont_use_mmx + cmpl $0x6c65746e, %ecx + jne .L_dont_use_mmx + cmpl $0x49656e69, %edx + jne .L_dont_use_mmx + movl $1, %eax + cpuid /* get cpu features */ + shrl $8, %eax + andl $15, %eax + cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ + jne .L_dont_use_mmx + testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ + jnz .L_use_mmx + jmp .L_dont_use_mmx +.L_use_mmx: + movl $DO_USE_MMX, inflate_fast_use_mmx + jmp .L_check_mmx_pop +.L_dont_use_mmx: + movl $DONT_USE_MMX, inflate_fast_use_mmx +.L_check_mmx_pop: + popl %edx + popl %ecx + popl %ebx + popl %eax + jmp .L_check_mmx +#endif + + +/*** Non-MMX code ***/ + +#if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) + +#define hold_r %ebp +#define bits_r %bl +#define bitslong_r %ebx + +.align 32,0x90 +.L_while_test: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * do { + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = lcode[hold & lmask] + */ + cmpb $15, bits_r + ja .L_get_length_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_length_code: + movl lmask(%esp), %edx /* edx = lmask */ + movl lcode(%esp), %ecx /* ecx = lcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * dolen: + * bits -= this.bits; + * hold >>= this.bits + */ + movb %ah, %cl /* cl = this.bits */ + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* check if op is a literal + * if (op == 0) { + * PUP(out) = this.val; + * } + */ + testb %al, %al + jnz .L_test_for_length_base /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test + +.L_test_for_length_base: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len + * + * else if (op & 16) { + * len = this.val + * op &= 15 + * if (op) { + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * len += hold & mask[op]; + * bits -= op; + * hold >>= op; + * } + */ +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + movb %al, %cl + + testb $16, %al + jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + andb $15, %cl /* op &= 15 */ + jz .L_save_len /* if (!op) */ + cmpb %cl, bits_r + jae .L_add_bits_to_len /* if (op <= bits) */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_len: + movl $1, %eax + shll %cl, %eax + decl %eax + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, len_r /* len += hold & mask[op] */ + +.L_save_len: + movl len_r, len(%esp) /* save len */ +#undef len_r + +.L_decode_distance: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = dcode[hold & dmask]; + * dodist: + * bits -= this.bits; + * hold >>= this.bits; + * op = this.op; + */ + + cmpb $15, bits_r + ja .L_get_distance_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_distance_code: + movl dmask(%esp), %edx /* edx = dmask */ + movl dcode(%esp), %ecx /* ecx = dcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ + +#define dist_r %edx +.L_dodist: + movl %eax, dist_r /* dist = this */ + shrl $16, dist_r /* dist = this.val */ + movb %ah, %cl + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* if (op & 16) { + * dist = this.val + * op &= 15 + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * dist += hold & mask[op]; + * bits -= op; + * hold >>= op; + */ + movb %al, %cl /* cl = this.op */ + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist + andb $15, %cl /* op &= 15 */ + jz .L_check_dist_one + cmpb %cl, bits_r + jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_dist: + movl $1, %eax + shll %cl, %eax + decl %eax /* (1 << op) - 1 */ + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ + jmp .L_check_window + +.L_check_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * nbytes = out - beg; + * if (dist <= nbytes) { + * from = out - dist; + * do { + * PUP(out) = PUP(from); + * } while (--len > 0) { + * } + */ + + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window /* if (dist > nbytes) 4.2% */ + + movl len(%esp), %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +.align 16,0x90 +.L_check_dist_one: + cmpl $1, dist_r + jne .L_check_window + cmpl out_r, beg(%esp) + je .L_check_window + + decl out_r + movl len(%esp), %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + jmp .L_while_test + +.align 16,0x90 +.L_test_for_second_level_length: + /* else if ((op & 64) == 0) { + * this = lcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl lcode(%esp), %edx /* edx = lcode */ + movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ + jmp .L_dolen + +.align 16,0x90 +.L_test_for_second_level_dist: + /* else if ((op & 64) == 0) { + * this = dcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl dcode(%esp), %edx /* edx = dcode */ + movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ + jmp .L_dodist + +.align 16,0x90 +.L_clip_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * else { + * if (dist > wsize) { + * invalid distance + * } + * from = window; + * nbytes = dist - nbytes; + * if (write == 0) { + * from += wsize - nbytes; + */ +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = len + * + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define len_r %eax + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_wrap_around_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else if (write < nbytes) { + * from += wsize + write - nbytes; + * nbytes -= write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = window; + * nbytes = write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while(--nbytes); + * from = out - dist; + * } + * } + * } + */ +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_contiguous_in_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else { + * from += write - nbytes; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1: + /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out + * %eax = len + * + * while (len > 0) { + * PUP(out) = PUP(from); + * len--; + * } + * } + * } while (in < last && out < end); + */ +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +#undef len_r +#undef dist_r + +#endif /* NO_MMX || RUN_TIME_MMX */ + + +/*** MMX code ***/ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +.align 32,0x90 +.L_init_mmx: + emms + +#undef bits_r +#undef bitslong_r +#define bitslong_r %ebp +#define hold_mm %mm0 + movd %ebp, hold_mm + movl %ebx, bitslong_r + +#define used_mm %mm1 +#define dmask2_mm %mm2 +#define lmask2_mm %mm3 +#define lmask_mm %mm4 +#define dmask_mm %mm5 +#define tmp_mm %mm6 + + movd lmask(%esp), lmask_mm + movq lmask_mm, lmask2_mm + movd dmask(%esp), dmask_mm + movq dmask_mm, dmask2_mm + pxor used_mm, used_mm + movl lcode(%esp), %ebx /* ebx = lcode */ + jmp .L_do_loop_mmx + +.align 32,0x90 +.L_while_test_mmx: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_length_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_length_code_mmx: + pand hold_mm, lmask_mm + movd lmask_mm, %eax + movq lmask2_mm, lmask_mm + movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen_mmx: + movzbl %ah, %ecx /* ecx = this.bits */ + movd %ecx, used_mm + subl %ecx, bitslong_r /* bits -= this.bits */ + + testb %al, %al + jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test_mmx + +.L_test_for_length_base_mmx: +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + + testb $16, %al + jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ + andl $15, %eax /* op &= 15 */ + jz .L_decode_distance_mmx /* if (!op) */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm + movd hold_mm, %ecx + subl %eax, bitslong_r + andl .L_mask(,%eax,4), %ecx + addl %ecx, len_r /* len += hold & mask[op] */ + +.L_decode_distance_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_dist_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_dist_code_mmx: + movl dcode(%esp), %ebx /* ebx = dcode */ + pand hold_mm, dmask_mm + movd dmask_mm, %eax + movq dmask2_mm, dmask_mm + movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ + +.L_dodist_mmx: +#define dist_r %ebx + movzbl %ah, %ecx /* ecx = this.bits */ + movl %eax, dist_r + shrl $16, dist_r /* dist = this.val */ + subl %ecx, bitslong_r /* bits -= this.bits */ + movd %ecx, used_mm + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist_mmx + andl $15, %eax /* op &= 15 */ + jz .L_check_dist_one_mmx + +.L_add_bits_to_dist_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm /* save bit length of current op */ + movd hold_mm, %ecx /* get the next bits on input stream */ + subl %eax, bitslong_r /* bits -= op bits */ + andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ + addl %ecx, dist_r /* dist += hold & mask[op] */ + +.L_check_window_mmx: + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ + + movl len_r, %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_check_dist_one_mmx: + cmpl $1, dist_r + jne .L_check_window_mmx + cmpl out_r, beg(%esp) + je .L_check_window_mmx + + decl out_r + movl len_r, %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_test_for_second_level_length_mmx: + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + addl len_r, %ecx + movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dolen_mmx + +.align 16,0x90 +.L_test_for_second_level_dist_mmx: + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + movl dcode(%esp), %eax /* ecx = dcode */ + addl dist_r, %ecx + movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dodist_mmx + +.align 16,0x90 +.L_clip_window_mmx: +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window_mmx /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_wrap_around_window_mmx: +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_contiguous_in_window_mmx: +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1_mmx: +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +#undef hold_r +#undef bitslong_r + +#endif /* USE_MMX || RUN_TIME_MMX */ + + +/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ + +.L_invalid_distance_code: + /* else { + * strm->msg = "invalid distance code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_distance_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_test_for_end_of_block: + /* else if (op & 32) { + * state->mode = TYPE; + * break; + * } + */ + testb $32, %al + jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ + + movl $0, %ecx + movl $INFLATE_MODE_TYPE, %edx + jmp .L_update_stream_state + +.L_invalid_literal_length_code: + /* else { + * strm->msg = "invalid literal/length code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_literal_length_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_invalid_distance_too_far: + /* strm->msg = "invalid distance too far back"; + * state->mode = BAD; + */ + movl in(%esp), in_r /* from_r has in's reg, put in back */ + movl $.L_invalid_distance_too_far_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_update_stream_state: + /* set strm->msg = %ecx, strm->state->mode = %edx */ + movl strm_sp(%esp), %eax + testl %ecx, %ecx /* if (msg != NULL) */ + jz .L_skip_msg + movl %ecx, msg_strm(%eax) /* strm->msg = msg */ +.L_skip_msg: + movl state_strm(%eax), %eax /* state = strm->state */ + movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ + jmp .L_break_loop + +.align 32,0x90 +.L_break_loop: + +/* + * Regs: + * + * bits = %ebp when mmx, and in %ebx when non-mmx + * hold = %hold_mm when mmx, and in %ebp when non-mmx + * in = %esi + * out = %edi + */ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_next_in + +#endif /* RUN_TIME_MMX */ + + movl %ebp, %ebx + +.L_update_next_in: + +#endif + +#define strm_r %eax +#define state_r %edx + + /* len = bits >> 3; + * in -= len; + * bits -= len << 3; + * hold &= (1U << bits) - 1; + * state->hold = hold; + * state->bits = bits; + * strm->next_in = in; + * strm->next_out = out; + */ + movl strm_sp(%esp), strm_r + movl %ebx, %ecx + movl state_strm(strm_r), state_r + shrl $3, %ecx + subl %ecx, in_r + shll $3, %ecx + subl %ecx, %ebx + movl out_r, next_out_strm(strm_r) + movl %ebx, bits_state(state_r) + movl %ebx, %ecx + + leal buf(%esp), %ebx + cmpl %ebx, last(%esp) + jne .L_buf_not_used /* if buf != last */ + + subl %ebx, in_r /* in -= buf */ + movl next_in_strm(strm_r), %ebx + movl %ebx, last(%esp) /* last = strm->next_in */ + addl %ebx, in_r /* in += strm->next_in */ + movl avail_in_strm(strm_r), %ebx + subl $11, %ebx + addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ + +.L_buf_not_used: + movl in_r, next_in_strm(strm_r) + + movl $1, %ebx + shll %cl, %ebx + decl %ebx + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_hold + +#endif /* RUN_TIME_MMX */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ebp + + emms + +.L_update_hold: + +#endif /* USE_MMX || RUN_TIME_MMX */ + + andl %ebx, %ebp + movl %ebp, hold_state(state_r) + +#define last_r %ebx + + /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ + movl last(%esp), last_r + cmpl in_r, last_r + jbe .L_last_is_smaller /* if (in >= last) */ + + subl in_r, last_r /* last -= in */ + addl $11, last_r /* last += 11 */ + movl last_r, avail_in_strm(strm_r) + jmp .L_fixup_out +.L_last_is_smaller: + subl last_r, in_r /* in -= last */ + negl in_r /* in = -in */ + addl $11, in_r /* in += 11 */ + movl in_r, avail_in_strm(strm_r) + +#undef last_r +#define end_r %ebx + +.L_fixup_out: + /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ + movl end(%esp), end_r + cmpl out_r, end_r + jbe .L_end_is_smaller /* if (out >= end) */ + + subl out_r, end_r /* end -= out */ + addl $257, end_r /* end += 257 */ + movl end_r, avail_out_strm(strm_r) + jmp .L_done +.L_end_is_smaller: + subl end_r, out_r /* out -= end */ + negl out_r /* out = -out */ + addl $257, out_r /* out += 257 */ + movl out_r, avail_out_strm(strm_r) + +#undef end_r +#undef strm_r +#undef state_r + +.L_done: + addl $local_var_size, %esp + popf + popl %ebx + popl %ebp + popl %esi + popl %edi + ret + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast,@function +.size inflate_fast,.-inflate_fast +#endif diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/bld_ml64.bat b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/bld_ml64.bat new file mode 100644 index 000000000..8f9343d0a --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/bld_ml64.bat @@ -0,0 +1,2 @@ +ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +ml64.exe /Flgvmat64 /c /Zi gvmat64.asm diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.asm b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.asm new file mode 100644 index 000000000..790d65554 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.asm @@ -0,0 +1,513 @@ +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); /* current match */ + +; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for infozip Zip, I use option: +; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm +; +; to compile this file for zLib, I use option: +; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm +; Be carrefull to adapt zlib1222add below to your version of zLib +; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change +; value of zlib1222add later) +; +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005 and Windows 2003 server DDK +; +; (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from +; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) +; + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ +.code +longest_match PROC + + +;LocalVarsSize equ 88 + LocalVarsSize equ 72 + +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp + + chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len + ; low word: s->wmask +;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 +;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 +;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w +;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx +;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 +;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d +;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 +IFDEF INFOZIP +ELSE + nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size +ENDIF + +save_rdi equ rsp + 24 - LocalVarsSize +save_rsi equ rsp + 32 - LocalVarsSize +save_rbx equ rsp + 40 - LocalVarsSize +save_rbp equ rsp + 48 - LocalVarsSize +save_r12 equ rsp + 56 - LocalVarsSize +save_r13 equ rsp + 64 - LocalVarsSize +;save_r14 equ rsp + 72 - LocalVarsSize +;save_r15 equ rsp + 80 - LocalVarsSize + + + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + +IFDEF INFOZIP + +_DATA SEGMENT +COMM window_size:DWORD +; WMask ; 7fff +COMM window:BYTE:010040H +COMM prev:WORD:08000H +; MatchLen : unused +; PrevMatch : unused +COMM strstart:DWORD +COMM match_start:DWORD +; Lookahead : ignore +COMM prev_length:DWORD ; PrevLen +COMM max_chain_length:DWORD +COMM good_match:DWORD +COMM nice_match:DWORD +prev_ad equ OFFSET prev +window_ad equ OFFSET window +nicematch equ nice_match +_DATA ENDS +WMask equ 07fffh + +ELSE + + IFNDEF zlib1222add + zlib1222add equ 8 + ENDIF +dsWSize equ 56+zlib1222add+(zlib1222add/2) +dsWMask equ 64+zlib1222add+(zlib1222add/2) +dsWindow equ 72+zlib1222add +dsPrev equ 88+zlib1222add +dsMatchLen equ 128+zlib1222add +dsPrevMatch equ 132+zlib1222add +dsStrStart equ 140+zlib1222add +dsMatchStart equ 144+zlib1222add +dsLookahead equ 148+zlib1222add +dsPrevLen equ 152+zlib1222add +dsMaxChainLen equ 156+zlib1222add +dsGoodMatch equ 172+zlib1222add +dsNiceMatch equ 176+zlib1222add + +window_size equ [ rcx + dsWSize] +WMask equ [ rcx + dsWMask] +window_ad equ [ rcx + dsWindow] +prev_ad equ [ rcx + dsPrev] +strstart equ [ rcx + dsStrStart] +match_start equ [ rcx + dsMatchStart] +Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip +prev_length equ [ rcx + dsPrevLen] +max_chain_length equ [ rcx + dsMaxChainLen] +good_match equ [ rcx + dsGoodMatch] +nice_match equ [ rcx + dsNiceMatch] +ENDIF + +; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + + + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) + +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx + + mov [save_rdi],rdi + mov [save_rsi],rsi + mov [save_rbx],rbx + mov [save_rbp],rbp +IFDEF INFOZIP + mov r8d,ecx +ELSE + mov r8d,edx +ENDIF + mov [save_r12],r12 + mov [save_r13],r13 +; mov [save_r14],r14 +; mov [save_r15],r15 + + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +;;; on zlib only +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + +IFDEF INFOZIP + mov [chainlenwmask], ebx +; on infozip nice_match = [nice_match] +ELSE + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d +ENDIF + +;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; +IFDEF INFOZIP + mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) +ELSE + mov eax, window_size + sub eax, MIN_LOOKAHEAD +ENDIF + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +;;; int best_len = s->prev_length; + + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 + jmp LookupLoopIsZero + + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + jnz LookupLoop1 + + +;;; Store the current value of chainlen. + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + lea rsi,[r8+r10] + mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + jmp short LoopCmps +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0000FFFFh + jnz LenLower + + test eax,0ffffffffh + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + jnz LenLower + +LenLower32: + shr eax,16 + add rdx,2 +LenLower: sub al, 1 + adc rdx, 0 +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// + + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + jge LeaveNow + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: +IFDEF INFOZIP + mov eax,r11d +ELSE + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d +ENDIF + +;;; Restore the stack and return from whence we came. + + + mov rsi,[save_rsi] + mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] +; mov r14,[save_r14] +; mov r15,[save_r15] + + + ret 0 +; please don't remove this string ! +; Your can freely use gvmat64 in any free or commercial app +; but it is far better don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 +longest_match ENDP + +match_init PROC + ret 0 +match_init ENDP + + +END diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.obj b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.obj new file mode 100644 index 0000000000000000000000000000000000000000..a49ca029c63e24f907d7cd5d6eaa25f016c9aea5 GIT binary patch literal 4119 zcma*qeRNah9l-Hl+gQ3}CE>k*%H@!u&{Eq{OKC-E36g5cL57oQHb_Z|(WdE=w1AW2 z?RYuXODCSOO;ntFW8=*291wxYSKDiCowQkgQCE3QVX-I8>>I|vScF4pfx2Mg0)?*y>^#t9Qd=#!2`(C28u~T*0Xz&?Ze?m}y_3?uK3;D^n`cJtW zgGTqOr1q7F1&beZ}q78&b^c8IrsV1}U zy|x9O`rkP>wsV8-^CEfTe6oc&)iBYS)2Jz{(VR@9MLCV!S&d4D8g)K%VOmbJ&*?$> zfu9gtJ=@TlOeR|w)Vp2I4G$4A@;-)=?|tpcRf-%yC@J*H+h5+CL|sXRV#nP(Sd*2sO9q89g_Z>pjMxr>FZ_hEeZv zA71Oer?=YG$ix>7P5ike-EY{hZeq1Gx>KLt&6HO9h$c5QJW zoCw9rv{kWiA`xoWDre8GEu&R?S16X?!bDUHM1opPwbrsmTM%w*3&pjsMBCZ|?Fp@_ zqT=>qyA0SE)IT_ez2!WXAF@9h$yn;alhx$FM<7v+IR{mBIUFCM-4Y&*K_zF6a zpOQWr`PJy-@HM;<_v2*zJ>G(ca0VX63VZ`=@J+16x3CW1#yR*N-i7aDBmNOR_-DKa zPvS!S3*L`^#ie)({dgJ!cosu=4j;wy*nt-@j+d|t`TpyV;T2qq|Hg0Oe{ns2h8yuJ z_9Bz2Z-!yG1&i@n9F8xd3x9;8aXXI1mvJ02hcW^8;El+f$xV0wZ^i+fgv^m>coe4~ zb0Pe+^%Hmtet^@EIg#ne97riLW+}suaRy$-3j7aNB4d$ilB4d%+ zI11}WW+=RsPZQP7c<9Cr*|2}>PU%)N+L!?gs zF;b`h47cJAd=7t!&*M&f5r2(8z*muL^#jPY`fu^4IDp&n5OOd5P5e2&jlaO7_%gnW z+*^Mie}#X-UHBosf+uk|p20o%5$?zH_&WX#e}k8>4=-asUcrO-Ir3~>^7(z?Fr*K< z1CL-a(ieRM{sG6~ah!>6N<4+L@HEyTebn#73pfwyo9@NGV>5n? zi}4~pfb?1S<3I5Per8FZb+s2gMea7q8$tO0EqT$FN2FTDj^O=4j;X6Sia5KrHHTNk zqVZ^JLc4YGG_5&6Noz>0*P$3KD#T?zMqQx}X3ad5c`mCU!pgeh;br0WaDw?Pl$qCD zr3Rs%r!2@^)fR1E8Hy*CnODm=xgq^1Um%`nR<~RbjRs{*Rz)=WXlI8n8ttf*(K+dk z`Kbi}quHU%&x{a^RTHTOQ*Xe~!$VpmFo8k|KVo@2HQ`a#s(h-;OS-DW4 zE2IXfDk^K(qcXFST~(ViU)eP|-4C_N@wX(V6=d*~JlYY$&nggrDk;=qmHW7Fo_mt6obT60{<_Ji&&j_CklOvm(3fA^L)u+h;{~d51{7t~%tn71`w@ zB3`Y@U9cj%TqPQA=JE?ukzGa;seRTVC01mYQX=&YbI5I0WS0ga_0@97d@HicQlgP& z&TmC_X(t+G=3-W4m-R$y4|m9uR%Dm0L}Sd{HY;LmL}Sg|J}a`z8$@c~cgPVdvdd|r z5;J$!iWnQwcr%yJTfU0yGLC41nVV=uc9}sm(acp^5o04#?-Y#9iWnQwO=iw-MU0K; zW-}MFBD>fq7n-yB=_kXb$fcGCb>uUFg_5VHhuTcumX)8oA{yx^4+p!ptrhjAS|Hhf z0jcGoATRySr0$bCvj6&FEuc-hCS&$rKB`9rdFpSUvP=V_?7w={C<^lK$f-{kRGm8V zL{kerhZ>YxhEf@~yTUwFjoD`vm~*Gzvs8wUhNF~o7iT6ji;{Zx$YdHRske_zM!kcn z_lr#CtCZ9mMkW)YG@fE6(?MoRPUf3r=H_HJkns&=(#u8nP=;#x9;e!+`Dcw{JCWM2 zGa2=krFQO2W`GR)pq24iD}~yPGi~0XjoLpm8TGcMcEVJ~r}hI=w*t5609pOaK4? literal 0 HcmV?d00001 diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffas8664.c b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffas8664.c new file mode 100644 index 000000000..3af764de9 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffas8664.c @@ -0,0 +1,186 @@ +/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding + * version for AMD64 on Windows using Microsoft C compiler + * + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->write; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.asm b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.asm new file mode 100644 index 000000000..b5d93a272 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.asm @@ -0,0 +1,392 @@ +; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding +; version for AMD64 on Windows using Microsoft C compiler +; +; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c +; inffasx64.asm is called by inffas8664.c, which contain more info. + + +; to compile this file, I use option +; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +; with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK +; +; (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from +; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) +; + +.code +inffas8664fnc PROC + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. + + + mov [rsp-8],rsi + mov [rsp-16],rdi + mov [rsp-24],r12 + mov [rsp-32],r13 + mov [rsp-40],r14 + mov [rsp-48],r15 + mov [rsp-56],rbx + + mov rax,rcx + + mov [rax+8], rbp ; /* save regs rbp and rsp */ + mov [rax], rsp + + mov rsp, rax ; /* make rsp point to &ar */ + + mov rsi, [rsp+16] ; /* rsi = in */ + mov rdi, [rsp+32] ; /* rdi = out */ + mov r9, [rsp+24] ; /* r9 = last */ + mov r10, [rsp+48] ; /* r10 = end */ + mov rbp, [rsp+64] ; /* rbp = lcode */ + mov r11, [rsp+72] ; /* r11 = dcode */ + mov rdx, [rsp+80] ; /* rdx = hold */ + mov ebx, [rsp+88] ; /* ebx = bits */ + mov r12d, [rsp+100] ; /* r12d = lmask */ + mov r13d, [rsp+104] ; /* r13d = dmask */ + ; /* r14d = len */ + ; /* r15d = dist */ + + + cld + cmp r10, rdi + je L_one_time ; /* if only one decode left */ + cmp r9, rsi + + jne L_do_loop + + +L_one_time: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code_one_time + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + jmp L_get_length_code_one_time + +ALIGN 4 +L_while_test: + cmp r10, rdi + jbe L_break_loop + cmp r9, rsi + jbe L_break_loop + +L_do_loop: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_length_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + mov r8, r12 ; /* r8 = lmask */ + shr eax, 16 ; /* output this.val char */ + stosb + +L_get_length_code_one_time: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + shr eax, 16 ; /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov r14d, eax ; /* len = this */ + shr r14d, 16 ; /* len = this.val */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ + and cl, 15 ; /* op &= 15 */ + jz L_decode_distance ; /* if (!op) */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r14d, eax ; /* len += hold & mask[op] */ + +L_decode_distance: + mov r8, r13 ; /* r8 = dmask */ + cmp bl, 32 + ja L_get_distance_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_distance_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ + +L_dodist: + mov r15d, eax ; /* dist = this */ + shr r15d, 16 ; /* dist = this.val */ + mov cl, ah + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + mov cl, al ; /* cl = this.op */ + + test al, 16 ; /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 ; /* op &= 15 */ + jz L_check_dist_one + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax ; /* (1 << op) - 1 */ + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov r8, rsi ; /* save in so from can use it's reg */ + mov rax, rdi + sub rax, [rsp+40] ; /* nbytes = out - beg */ + + cmp eax, r15d + jb L_clip_window ; /* if (dist > nbytes) 4.2% */ + + mov ecx, r14d ; /* ecx = len */ + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two ; /* if len % 2 == 0 */ + + rep movsw + mov al, [rsi] + mov [rdi], al + inc rdi + + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +L_copy_two: + rep movsw + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp r15d, 1 ; /* if dist 1, is a memset */ + jne L_check_window + cmp [rsp+40], rdi ; /* if out == beg, outside window */ + je L_check_window + + mov ecx, r14d ; /* ecx = len */ + mov al, [rdi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [rdi], al + inc rdi + +L_set_two: + rep stosw + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r14d ; /* eax += len */ + mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r15d ; /* eax += dist */ + mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax ; /* ecx = nbytes */ + mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ + neg ecx ; /* nbytes = -nbytes */ + + cmp eax, r15d + jb L_invalid_distance_too_far ; /* if (dist > wsize) */ + + add ecx, r15d ; /* nbytes = dist - nbytes */ + cmp dword ptr [rsp+96], 0 + jne L_wrap_around_window ; /* if (write != 0) */ + + mov rsi, [rsp+56] ; /* from = window */ + sub eax, ecx ; /* eax -= nbytes */ + add rsi, rax ; /* from += wsize - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp r14d, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* eax -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = &out[ -dist ] */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [rsp+96] ; /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window ; /* if (write >= nbytes) */ + + mov esi, [rsp+92] ; /* from = wsize */ + add rsi, [rsp+56] ; /* from += window */ + add rsi, rax ; /* from += write */ + sub rsi, rcx ; /* from -= nbytes */ + sub ecx, eax ; /* nbytes -= write */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, [rsp+56] ; /* from = window */ + mov ecx, [rsp+96] ; /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + mov rsi, [rsp+56] ; /* rsi = window */ + add rsi, rax + sub rsi, rcx ; /* from += write - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy ; /* if (nbytes >= len) */ + +ALIGN 4 +L_do_copy: + mov ecx, eax ; /* ecx = len */ + rep movsb + + mov rsi, r8 ; /* move in back to %esi, toss from */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [rsp+116], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [rsp+116], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [rsp+116], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov dword ptr [rsp+116], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [rsp+116], 0 + +L_break_loop_with_status: +; /* put in, out, bits, and hold back into ar and pop esp */ + mov [rsp+16], rsi ; /* in */ + mov [rsp+32], rdi ; /* out */ + mov [rsp+88], ebx ; /* bits */ + mov [rsp+80], rdx ; /* hold */ + + mov rax, [rsp] ; /* restore rbp and rsp */ + mov rbp, [rsp+8] + mov rsp, rax + + + + mov rsi,[rsp-8] + mov rdi,[rsp-16] + mov r12,[rsp-24] + mov r13,[rsp-32] + mov r14,[rsp-40] + mov r15,[rsp-48] + mov rbx,[rsp-56] + + ret 0 +; : +; : "m" (ar) +; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", +; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" +; ); + +inffas8664fnc ENDP +;_TEXT ENDS +END diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.obj b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.obj new file mode 100644 index 0000000000000000000000000000000000000000..8df5d82616098e1f791526c3cd9875b24f5ad8c0 GIT binary patch literal 5913 zcmb8z3v?9K8Nl(IERQguBm@ePmyxWz0udxoBpyv-ltGr7A}ZE!Hk*AUD@zu$8xl2~ z-YTHUs!e++#};ixx;!>xxG`5wChdPX?jzR9_iL2VSAL@%^H*0xhpZrfwec7(&m*n0Y{b;wIez>Q^ z*FuSm&6lPML8*+*3kl4UBdsMJxqC_?rJF?a!C7zWM?c!wR+me$_7jcp!M>djBwVhWAodhZAZJKow<9sR;jIbdE`Y^w}E%OEHdQw z(nx=C`zM*^ePdU;-@H=Upeyw|BK!47hn`nzpHW=ck#XBEC|Vpjq({D7n)l_AuR>XU zzK5EJ-8o#3b}Wtbo{WAQjgnE}XN1MKM^oxv&@XDV&j>%mY0XQb&E1?e)HtEf_t?op zl=8LgEXvr_&6N}FD7Nia-E;DbGsn9I9PcQmH7Dmp)%lUmNU6R2%VS0rpHo$|y>fe_ zy+YKTrylX5ymsBzTO8S6T6k)GFt5FDd#wIFZu*onD+)W;FQQzzZlf?o^}JJgos=(Z zUtbg}PM#4`LE-|-`MI2L+#q&N?2J*C0;#HQecM%kyni|x-I){CI!f)~6sp)WO+^e3 z(KAU!413X&rJ^A!N>dSmP-8k%jp-bQ?<&2CF{wv}*wrviGly`$8p6E}M(GI$>23#Y z>2i=etTTK&_o@r_@wq@<@2bV+w*>r^bLQn=sQ#6^gEiq=e`WbvS7>d+!h&*tjnC%_ z5#^H*;xkUk=A){dnR4ZnEp?BiZ=L=22U}V=i*q*!E^9Dxyb7-ry(CX3#a28oQZQW4;SEUT#Ou(mtsDa zBJGw-k+SlKI1kl#&V_g#&c|{rKo?$wmB_WE7Ynfp`8tv};w2cs5)9&HSc}|Cs%Lfu z*5MMYM;&iL>L54Zl_+r;Zp5qb4lKjF@kiK#D{w1bgTKOS@jj%^@;7)r{uY0Xzr!1F zJJJ@p16SjtSb@8cw#nb48=poGK8v(bK8LhX{t2t`&q!Nk8?M2UpW<=64Nu}m?7>ZV3OD0tcn5xg z&Df6-{2K4VZ;(Ee-{L)}2JX)=73ots6n~CsxCPVkmpBUPYnh4n;%KDLBzu z4)P4-B&6@GXW}ws%**A-n3rWZ2Uj3t zU#`TtcrDJuRd^w;M&1SK!UA+7?}YT?53mXsp&u{804~NL^3F&#gI;ir3-;cpYxXRrokw zk56DZK8w6_ayM3B8@g~0dhh^x@gP>?-;sAv9>cZx7S`aq$U7;I<4xFuwb+Zio3an< zu^$`oG~SGS_6Nv&Lt!z-n)d{qfnac*m}pH_dBe_t zx27sw?Q{n{USat5rm_t$uW z^~wF~4z9b|8LkhC34_b4>!=P%?&A=ZQzy)@o^Yl&LbR*KLwnbI17_E-s?MsV zkGGa{2mI^eHJ)NUP+#j>=XBKu>$r{CqNE3-mb?C{x?o+%>92{G7&uB)vss0ntzKTP z8}vCV13~v17NV9S{+ji!fS<5p@O&&fPpLDg%Ga^mw=B*oHi4^ttM3FnVc3r;Tv#oW5h_Xtu3F}{!SOKv#ivI$s%EvbAUz3>C)beT2X8lW& zy0a}s{VnO@q;l53BB|QiQdC<9Z|a!ZQs~=MVYkmUwpfOVOaXh3CS|T*Z{L}W!x@`O4xY&n2p6AjK8Y(gu=hn$rkOpKk(M&|kx{>- z#LiMzR^K-)=`3ZQq)bs#W-l3*IhHc7l2MC!{+sP$SuWHvK9ONzEuKiq^pn}0lwmO{ zx{@+1_e6hEri8r$9x<5rVreDR5-*WqF(lODERkWkBU+O(s&;AtmMEiYr54`Pvw?soo)X9uEX&gT4riG zY4G%{Dsh%M+2})KBDUNhY4&w6gMaswn>aeKSK?=#$;T&GhchvA(#MINq-pfOw_mask == 0x7fff +; longest_match_686 : written by Brian raiter (1998), optimized for Pentium Pro +; +; for using an seembly version of longest_match, you need define ASMV in project +; There is two way in using gvmat32.asm +; +; A) Suggested method +; if you want include both longest_match_7fff and longest_match_686 +; compile the asm file running +; ml /coff /Zi /Flgvmat32.lst /c gvmat32.asm +; and include gvmat32c.c in your project +; if you have an old cpu (386,486 or first Pentium) and s->w_mask==0x7fff, +; longest_match_7fff will be used +; if you have a more modern CPU (Pentium Pro, II and higher) +; longest_match_686 will be used +; on old cpu with s->w_mask!=0x7fff, longest_match_686 will be used, +; but this is not a sitation you'll find often +; +; B) Alternative +; if you are not interresed in old cpu performance and want the smaller +; binaries possible +; +; compile the asm file running +; ml /coff /Zi /c /Flgvmat32.lst /DNOOLDPENTIUMCODE gvmat32.asm +; and do not include gvmat32c.c in your project (ou define also +; NOOLDPENTIUMCODE) +; +; note : as I known, longest_match_686 is very faster than longest_match_7fff +; on pentium Pro/II/III, faster (but less) in P4, but it seem +; longest_match_7fff can be faster (very very litte) on AMD Athlon64/K8 +; +; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 + +;uInt longest_match_7fff(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + zlib1222add equ 8 + +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 74h+zlib1222add + dep_window equ 30h+zlib1222add + dep_strstart equ 64h+zlib1222add + dep_prev_length equ 70h+zlib1222add + dep_nice_match equ 88h+zlib1222add + dep_w_size equ 24h+zlib1222add + dep_prev equ 38h+zlib1222add + dep_w_mask equ 2ch+zlib1222add + dep_good_match equ 84h+zlib1222add + dep_match_start equ 68h+zlib1222add + dep_lookahead equ 6ch+zlib1222add + + +_TEXT segment + +IFDEF NOUNDERLINE + IFDEF NOOLDPENTIUMCODE + public longest_match + public match_init + ELSE + public longest_match_7fff + public cpudetect32 + public longest_match_686 + ENDIF +ELSE + IFDEF NOOLDPENTIUMCODE + public _longest_match + public _match_init + ELSE + public _longest_match_7fff + public _cpudetect32 + public _longest_match_686 + ENDIF +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +IFNDEF NOOLDPENTIUMCODE +IFDEF NOUNDERLINE +longest_match_7fff proc near +ELSE +_longest_match_7fff proc near +ENDIF + + mov edx,[esp+4] + + + + push ebp + push edi + push esi + push ebx + + sub esp,NbStackAdd + +; initialize or check the variables used in match.asm. + mov ebp,edx + +; chain_length = s->max_chain_length +; if (prev_length>=good_match) chain_length >>= 2 + mov edx,[ebp+dep_chain_length] + mov ebx,[ebp+dep_prev_length] + cmp [ebp+dep_good_match],ebx + ja noshr + shr edx,2 +noshr: +; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop + inc edx + mov edi,[ebp+dep_nice_match] + mov chain_length,edx + mov eax,[ebp+dep_lookahead] + cmp eax,edi +; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + jae nolookaheadnicematch + mov edi,eax +nolookaheadnicematch: +; best_len = s->prev_length + mov best_len,ebx + +; window = s->window + mov esi,[ebp+dep_window] + mov ecx,[ebp+dep_strstart] + mov window,esi + + mov nice_match,edi +; scan = window + strstart + add esi,ecx + mov scan,esi +; dx = *window + mov dx,word ptr [esi] +; bx = *(window+best_len-1) + mov bx,word ptr [esi+ebx-1] + add esi,MAX_MATCH-1 +; scan_start = *scan + mov scan_start,dx +; strend = scan + MAX_MATCH-1 + mov strend,esi +; bx = scan_end = *(window+best_len-1) + +; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov esi,[ebp+dep_w_size] + sub esi,MIN_LOOKAHEAD +; here esi = MAX_DIST(s) + sub ecx,esi + ja nodist + xor ecx,ecx +nodist: + mov limit,ecx + +; prev = s->prev + mov edx,[ebp+dep_prev] + mov prev,edx + +; + mov edx,dword ptr [ebp+dep_match_start] + mov bp,scan_start + mov eax,cur_match + mov match_start,edx + + mov edx,window + mov edi,edx + add edi,best_len + mov esi,prev + dec edi +; windowlen = window + best_len -1 + mov windowlen,edi + + jmp beginloop2 + align 4 + +; here, in the loop +; eax = ax = cur_match +; ecx = limit +; bx = scan_end +; bp = scan_start +; edi = windowlen (window + best_len -1) +; esi = prev + + +;// here; chain_length <=16 +normalbeg0add16: + add chain_length,16 + jz exitloop +normalbeg0: + cmp word ptr[edi+eax],bx + je normalbeg2noroll +rcontlabnoroll: +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax + jnb exitloop +; if --chain_length != 0, go to exitloop + dec chain_length + jnz normalbeg0 + jmp exitloop + +normalbeg2noroll: +; if (scan_start==*(cur_match+window)) goto normalbeg2 + cmp bp,word ptr[edx+eax] + jne rcontlabnoroll + jmp normalbeg2 + +contloop3: + mov edi,windowlen + +; cur_match = prev[cur_match & wmask] + and eax,7fffh + mov ax,word ptr[esi+eax*2] +; if cur_match > limit, go to exitloop + cmp ecx,eax +jnbexitloopshort1: + jnb exitloop +; if --chain_length != 0, go to exitloop + + +; begin the main loop +beginloop2: + sub chain_length,16+1 +; if chain_length <=16, don't use the unrolled loop + jna normalbeg0add16 + +do16: + cmp word ptr[edi+eax],bx + je normalbeg2dc0 + +maccn MACRO lab + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + cmp word ptr[edi+eax],bx + je lab + ENDM + +rcontloop0: + maccn normalbeg2dc1 + +rcontloop1: + maccn normalbeg2dc2 + +rcontloop2: + maccn normalbeg2dc3 + +rcontloop3: + maccn normalbeg2dc4 + +rcontloop4: + maccn normalbeg2dc5 + +rcontloop5: + maccn normalbeg2dc6 + +rcontloop6: + maccn normalbeg2dc7 + +rcontloop7: + maccn normalbeg2dc8 + +rcontloop8: + maccn normalbeg2dc9 + +rcontloop9: + maccn normalbeg2dc10 + +rcontloop10: + maccn short normalbeg2dc11 + +rcontloop11: + maccn short normalbeg2dc12 + +rcontloop12: + maccn short normalbeg2dc13 + +rcontloop13: + maccn short normalbeg2dc14 + +rcontloop14: + maccn short normalbeg2dc15 + +rcontloop15: + and eax,7fffh + mov ax,word ptr[esi+eax*2] + cmp ecx,eax + jnb exitloop + + sub chain_length,16 + ja do16 + jmp normalbeg0add16 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +normbeg MACRO rcontlab,valsub +; if we are here, we know that *(match+best_len-1) == scan_end + cmp bp,word ptr[edx+eax] +; if (match != scan_start) goto rcontlab + jne rcontlab +; calculate the good chain_length, and we'll compare scan and match string + add chain_length,16-valsub + jmp iseq + ENDM + + +normalbeg2dc11: + normbeg rcontloop11,11 + +normalbeg2dc12: + normbeg short rcontloop12,12 + +normalbeg2dc13: + normbeg short rcontloop13,13 + +normalbeg2dc14: + normbeg short rcontloop14,14 + +normalbeg2dc15: + normbeg short rcontloop15,15 + +normalbeg2dc10: + normbeg rcontloop10,10 + +normalbeg2dc9: + normbeg rcontloop9,9 + +normalbeg2dc8: + normbeg rcontloop8,8 + +normalbeg2dc7: + normbeg rcontloop7,7 + +normalbeg2dc6: + normbeg rcontloop6,6 + +normalbeg2dc5: + normbeg rcontloop5,5 + +normalbeg2dc4: + normbeg rcontloop4,4 + +normalbeg2dc3: + normbeg rcontloop3,3 + +normalbeg2dc2: + normbeg rcontloop2,2 + +normalbeg2dc1: + normbeg rcontloop1,1 + +normalbeg2dc0: + normbeg rcontloop0,0 + + +; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end + +normalbeg2: + mov edi,window + + cmp bp,word ptr[edi+eax] + jne contloop3 ; if *(ushf*)match != scan_start, continue + +iseq: +; if we are here, we know that *(match+best_len-1) == scan_end +; and (match == scan_start) + + mov edi,edx + mov esi,scan ; esi = scan + add edi,eax ; edi = window + cur_match = match + + mov edx,[esi+3] ; compare manually dword at match+3 + xor edx,[edi+3] ; and scan +3 + + jz begincompare ; if equal, go to long compare + +; we will determine the unmatch byte and calculate len (in esi) + or dl,dl + je eq1rr + mov esi,3 + jmp trfinval +eq1rr: + or dx,dx + je eq1 + + mov esi,4 + jmp trfinval +eq1: + and edx,0ffffffh + jz eq11 + mov esi,5 + jmp trfinval +eq11: + mov esi,6 + jmp trfinval + +begincompare: + ; here we now scan and match begin same + add edi,6 + add esi,6 + mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes + repe cmpsd ; loop until mismatch + + je trfin ; go to trfin if not unmatch +; we determine the unmatch byte + sub esi,4 + mov edx,[edi-4] + xor edx,[esi] + + or dl,dl + jnz trfin + inc esi + + or dx,dx + jnz trfin + inc esi + + and edx,0ffffffh + jnz trfin + inc esi + +trfin: + sub esi,scan ; esi = len +trfinval: +; here we have finised compare, and esi contain len of equal string + cmp esi,best_len ; if len > best_len, go newbestlen + ja short newbestlen +; now we restore edx, ecx and esi, for the big loop + mov esi,prev + mov ecx,limit + mov edx,window + jmp contloop3 + +newbestlen: + mov best_len,esi ; len become best_len + + mov match_start,eax ; save new position as match_start + cmp esi,nice_match ; if best_len >= nice_match, exit + jae exitloop + mov ecx,scan + mov edx,window ; restore edx=window + add ecx,esi + add esi,edx + + dec esi + mov windowlen,esi ; windowlen = window + best_len-1 + mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end + +; now we restore ecx and esi, for the big loop : + mov esi,prev + mov ecx,limit + jmp contloop3 + +exitloop: +; exit : s->match_start=match_start + mov ebx,match_start + mov ebp,str_s + mov ecx,best_len + mov dword ptr [ebp+dep_match_start],ebx + mov eax,dword ptr [ebp+dep_lookahead] + cmp ecx,eax + ja minexlo + mov eax,ecx +minexlo: +; return min(best_len,s->lookahead) + +; restore stack and register ebx,esi,edi,ebp + add esp,NbStackAdd + + pop ebx + pop esi + pop edi + pop ebp + ret +InfoAuthor: +; please don't remove this string ! +; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary! + db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah + + + +IFDEF NOUNDERLINE +longest_match_7fff endp +ELSE +_longest_match_7fff endp +ENDIF + + +IFDEF NOUNDERLINE +cpudetect32 proc near +ELSE +_cpudetect32 proc near +ENDIF + + push ebx + + pushfd ; push original EFLAGS + pop eax ; get original EFLAGS + mov ecx, eax ; save original EFLAGS + xor eax, 40000h ; flip AC bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + xor eax, ecx ; cant toggle AC bit, processor=80386 + jz end_cpu_is_386 ; jump if 80386 processor + push ecx + popfd ; restore AC bit in EFLAGS first + + pushfd + pushfd + pop ecx + + mov eax, ecx ; get original EFLAGS + xor eax, 200000h ; flip ID bit in EFLAGS + push eax ; save new EFLAGS value on stack + popfd ; replace current EFLAGS value + pushfd ; get new EFLAGS + pop eax ; store new EFLAGS in EAX + popfd ; restore original EFLAGS + xor eax, ecx ; cant toggle ID bit, + je is_old_486 ; processor=old + + mov eax,1 + db 0fh,0a2h ;CPUID + +exitcpudetect: + pop ebx + ret + +end_cpu_is_386: + mov eax,0300h + jmp exitcpudetect + +is_old_486: + mov eax,0400h + jmp exitcpudetect + +IFDEF NOUNDERLINE +cpudetect32 endp +ELSE +_cpudetect32 endp +ENDIF +ENDIF + +MAX_MATCH equ 258 +MIN_MATCH equ 3 +MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) +MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) + + +;;; stack frame offsets + +chainlenwmask equ esp + 0 ; high word: current chain len + ; low word: s->wmask +window equ esp + 4 ; local copy of s->window +windowbestlen equ esp + 8 ; s->window + bestlen +scanstart equ esp + 16 ; first two bytes of string +scanend equ esp + 12 ; last two bytes of string +scanalign equ esp + 20 ; dword-misalignment of string +nicematch equ esp + 24 ; a good enough match size +bestlen equ esp + 28 ; size of best match so far +scan equ esp + 32 ; ptr to string wanting match + +LocalVarsSize equ 36 +; saved ebx byte esp + 36 +; saved edi byte esp + 40 +; saved esi byte esp + 44 +; saved ebp byte esp + 48 +; return address byte esp + 52 +deflatestate equ esp + 56 ; the function arguments +curmatch equ esp + 60 + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +dsWSize equ 36+zlib1222add +dsWMask equ 44+zlib1222add +dsWindow equ 48+zlib1222add +dsPrev equ 56+zlib1222add +dsMatchLen equ 88+zlib1222add +dsPrevMatch equ 92+zlib1222add +dsStrStart equ 100+zlib1222add +dsMatchStart equ 104+zlib1222add +dsLookahead equ 108+zlib1222add +dsPrevLen equ 112+zlib1222add +dsMaxChainLen equ 116+zlib1222add +dsGoodMatch equ 132+zlib1222add +dsNiceMatch equ 136+zlib1222add + + +;;; match.asm -- Pentium-Pro-optimized version of longest_match() +;;; Written for zlib 1.1.2 +;;; Copyright (C) 1998 Brian Raiter +;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html +;;; +;;; This is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License. + +;GLOBAL _longest_match, _match_init + + +;SECTION .text + +;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) + +;_longest_match: +IFDEF NOOLDPENTIUMCODE + IFDEF NOUNDERLINE + longest_match proc near + ELSE + _longest_match proc near + ENDIF +ELSE + IFDEF NOUNDERLINE + longest_match_686 proc near + ELSE + _longest_match_686 proc near + ENDIF +ENDIF + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + push ebp + push edi + push esi + push ebx + sub esp, LocalVarsSize + +;;; Retrieve the function arguments. ecx will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + + mov edx, [deflatestate] + mov ecx, [curmatch] + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov eax, [edx + dsPrevLen] + mov ebx, [edx + dsGoodMatch] + cmp eax, ebx + mov eax, [edx + dsWMask] + mov ebx, [edx + dsMaxChainLen] + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + mov [chainlenwmask], ebx + +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + mov eax, [edx + dsNiceMatch] + mov ebx, [edx + dsLookahead] + cmp ebx, eax + jl LookaheadLess + mov ebx, eax +LookaheadLess: mov [nicematch], ebx + +;;; register Bytef *scan = s->window + s->strstart; + + mov esi, [edx + dsWindow] + mov [window], esi + mov ebp, [edx + dsStrStart] + lea edi, [esi + ebp] + mov [scan], edi + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov eax, edi + neg eax + and eax, 3 + mov [scanalign], eax + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov eax, [edx + dsWSize] + sub eax, MIN_LOOKAHEAD + sub ebp, eax + jg LimitPositive + xor ebp, ebp +LimitPositive: + +;;; int best_len = s->prev_length; + + mov eax, [edx + dsPrevLen] + mov [bestlen], eax + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + add esi, eax + mov [windowbestlen], esi + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx ebx, word ptr [edi] + mov [scanstart], ebx + movzx ebx, word ptr [edi + eax - 1] + mov [scanend], ebx + mov edi, [edx + dsPrev] + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + jmp short LoopEntry + +align 4 + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; ecx = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and ecx, edx + movzx ecx, word ptr [edi + ecx*2] + cmp ecx, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow +LoopEntry: movzx eax, word ptr [esi + ecx - 1] + cmp eax, ebx + jnz LookupLoop + mov eax, [window] + movzx eax, word ptr [eax + ecx] + cmp eax, [scanstart] + jnz LookupLoop + +;;; Store the current value of chainlen. + + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + mov esi, [window] + mov edi, [scan] + add esi, ecx + mov eax, [scanalign] + mov edx, 0fffffef8h; -(MAX_MATCH_8) + lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] + lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust edx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (esi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + +LoopCmps: + mov eax, [esi + edx] + xor eax, [edi + edx] + jnz LeaveLoopCmps + mov eax, [esi + edx + 4] + xor eax, [edi + edx + 4] + jnz LeaveLoopCmps4 + add edx, 8 + jnz LoopCmps + jmp short LenMaximum +LeaveLoopCmps4: add edx, 4 +LeaveLoopCmps: test eax, 0000FFFFh + jnz LenLower + add edx, 2 + shr eax, 16 +LenLower: sub al, 1 + adc edx, 0 + +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea eax, [edi + edx] + mov edi, [scan] + sub eax, edi + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. + + mov edx, [deflatestate] + mov ebx, [bestlen] + cmp eax, ebx + jg LongerMatch + mov esi, [windowbestlen] + mov edi, [edx + dsPrev] + mov ebx, [scanend] + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: mov ebx, [nicematch] + mov [bestlen], eax + mov [edx + dsMatchStart], ecx + cmp eax, ebx + jge LeaveNow + mov esi, [window] + add esi, eax + mov [windowbestlen], esi + movzx ebx, word ptr [edi + eax - 1] + mov edi, [edx + dsPrev] + mov [scanend], ebx + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: mov edx, [deflatestate] + mov dword ptr [bestlen], MAX_MATCH + mov [edx + dsMatchStart], ecx + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: + mov edx, [deflatestate] + mov ebx, [bestlen] + mov eax, [edx + dsLookahead] + cmp ebx, eax + jg LookaheadRet + mov eax, ebx +LookaheadRet: + +;;; Restore the stack and return from whence we came. + + add esp, LocalVarsSize + pop ebx + pop esi + pop edi + pop ebp + + ret +; please don't remove this string ! +; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah + + +IFDEF NOOLDPENTIUMCODE + IFDEF NOUNDERLINE + longest_match endp + ELSE + _longest_match endp + ENDIF + + IFDEF NOUNDERLINE + match_init proc near + ret + match_init endp + ELSE + _match_init proc near + ret + _match_init endp + ENDIF +ELSE + IFDEF NOUNDERLINE + longest_match_686 endp + ELSE + _longest_match_686 endp + ENDIF +ENDIF + +_TEXT ends +end diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.obj b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.obj new file mode 100644 index 0000000000000000000000000000000000000000..ebb326238aed552f381eacbfa69f9ed48d3eb1a3 GIT binary patch literal 10241 zcmai(33L=yzQ(_sZbGO8I>;&pXtdEFkjVxl1V;z~6chH{AY|z**hz<^LjYk|!WK&z z^*Qe;g2VIp-i+Ibih|;(2!hLig3ic0>WB(z4Dv)#cpN3~`&U$*cq0cEU{)RgJd>xZp78%ty8(T13ex0>>O!}Qr>nd#MM*Oci2 zUy`2Z%V*lnk@)mWu2pP3$_XntBsz) zgq9g$EvaE+nQ3@h28NBvrjgjvjkmauW|n88ho*jsk4=K>qCUr! zG1nCut{o3`euZ}#TBeu9i*}2iuU9U|H*Q-|(hq9NPkT1ERyF8}4JkNY^oA3I$wUx6#a#Nnq&FsXw ztC^J`S+1k5@24;;u1ufb8mZG<$ntt2pZb9BCYDTYT3919%$p4{`u@g)nYZ4yXyJjb z+N3!JMWKvzZ?Gm*Syfr*FZCAH)%mN611r2G!BW4sp|&y<@>hG)va?4H&(87|ukcQ) z3w3Z8dSphBIg{MXzk0Xnt9HZwh*SE>+m~%kS&D0mHTIJf`5_8M`FB0QVG$r}; z^)g%P3qm<3R>kNiI8*l3YqNOlZhcAM?o}heNzJPtzHp-Pq>Cr2r=B}(xG^_=y(T8( zTQ*KJ$@QI_EYF^Ste)uEQ<&9Ck)W>}tM~M^^t6=H@ua(Xvv^(SnAP*8i@Y!IemN_SM|}70RQaR3 z(=*(o>wD^X>F$iY(eC=rjjzYmH@7TpeBJ#RZx__ZHohLS|LeqIs_{7Pc8`|Uh915l zhILox8z-mGmy~m0O%HYzCqtDH_w+SS;mtJn4ay?}0?JC;tMya3$Fr zSCM@%fb55X9EHW?4JaXhYkYT%#qHGNP(|h%c$Vxm-F2OTo6<#2#@e)~s zm&v7govgzlGK4qDdK@8F;260Q?~`}n1o=CBOs>OcoG0(a zMe;seCLhL?yj}hindGCGO8yB;$j7mfd>w!s0Yae^*HHK`^aAERkDvdK=xH{kpt8_ z zIqLRsJDutY`Qpp)AjhwAUkn>bFIbY?Fx2hY-LN%UTs3wuO zseH0XO(RRxEV5M1BmHUtS*C6y%T+O1p-Rb0RYu;f%E^GbovczpvPRXBOH~6|t5%WA z)LODZZ6KGcE#wNNlPlF$@(y(mxk}wfu2%Px>(zgd8`J~jM)e@MNo^xHtB1%fswXcp z@ENrWpOc;N1sRJ|WM_Oy#-WAmf-|IsZ^?L^B@^(!WLKOcyWt1YgY#q}ek8BJPh<~V zAba8>*&CP0K4>NTN=KZV6xk0k5laq09O;FJ^dXTPjP7JIdXq!YmmG%v zh z^2i~WKwgiV$f1}_4nqN%ikV~@=8)-_M`mCFnTbMj1QwIoC?Q9qoXo)zatx};8&FH; zB1DeIGBOV<$O%|YPR3gD7HlN*v6(DD6FCJsITKsSS-6j!hx^I-cz|4lhseeFBUyw; z$zuGOEWs0GIsQUcU>CU#&ywr$0@;YYdvMf^76EYK-ZGry=V z#82sxib=s>sUss8yuGNxUsRg!ud8!p@Pj)vEm&6>s$AyhFX2_SkKVt$ zG8E0SAF#i=bP+QaRn{%a;6<^WNjkwm>7q=!GJxzh1CZB+3_$*NvJJp_p+}XKmGPYr zJ+A6tT}3S?S(_1v9BOrCiQl+A`1-KrmsZw=_?oaewN*udVt;vRQE6$KW60IPNS6H& zYvryF6csa<%Pziae%(~MnPehsM!RliyY7f~UB}sr_BN{BvRUoA+4kE$+Co}t z`*vFUc6$4EM*DVV`}PR?HILp2>7^xUX&vUIcbJpWVNPa;IUSE6)&4Bn$ClkuMpj1| zqdLlP%&7K0Ms!reF~8YsWOP)+F{jvTq;*uoahF>)>`w?ICrj;fgnwyTZ7n}4qmK{` zdwC|)>~p2@+?52YYKm(8_I5(GWtG+TiPkWd6$R`!a<#vqnD3>4-%&F1kfXabimJ+L z|MEc4Uis$gvf#M-5N85oij-BUtg_>cm8mEVe<80nyk||N@f(EeAj5mdR2sh?SpgmBuxZd?ibJV@#!S?IPc?;>|IY#`T7L z)ruE1m4-D`Lk+LdR2u%BN@4`@*k&pXPf`sxyj`Z!@EVmw5#n*sR2nW)$r>Xb5@{Bt zA(89O-xyv`Q)w7Nm1=myO{HNxRhr>VGL?oER9y{kwW%~bK$UKI+fAk6F{%v1d&*QA z-lEDhyd$R4@DUZ`Z5-dHrqb{emBc>camiE~68L#E%J33RrQuqtEW^9rR2p)rBw`Ye ziKfypmuj@(-D)ZgA*vk1TW%^1cT!25B_3N%rC}S@4TkrysWj}Ol6QYRcAHAWAu0)y z#^Y^MY516Gtl^zBm4@%B#u=Whr$sS>#MgMP;mOKbl!gIR;|)*N#iBH1Qso(5mZ>yM zrkY@QQ%t2{G1WxFleMiV4a=w|8Qw}$X$;p%%tyw2uc&ybfb94P6N<%-YDTX(|R6I7SsfL$jDh*SprWxK0 zQ)#H6nr?UjQ)yUFHN)^WnM%WUs+oqj(^MLsrN@s!L$vQ`rhEl3q4X?sf8dg&k8s0in z@!6+ZXn5O9#b=-DHpAOxDh)4FEi$~GDi7bX3V^RbSagkof15d*tZMzJzP$&vIgXlNEFJd7TLcQCx-uBw!BEG$lk4_<%nHM zc5m;GWE+1Y`?ivhv*c28FaP={dGb^6B1U__$Nd08{^q(I=zj* zDS>dAeM}i;km3(J(w0@Lw;Yh;$H9N{#EaTStDFVj$K-lweU&y9{xpoceeAmqn$|a>sZCvyIfnV_ow7SIezjk z$}>k8YvfEMB^D*M!j4=si6L1|F&&8sS&rO!5&;T3krlB-Zmcp5EF)1F%h^O{P}Ipc zSH=>XvC7CDCD9bi*-1wtB4Hp}<_0x$JO?>Bv3<|Cv|0ic_1qJeBa4lgyn3d z+~{x~WNN3wd6X&Hui!tkucs+x@4|9kqLh6M%Xx!R_B1T#7^UoQSk5Puve#ib&6Kk5 zVL3li${vX2D5hjT#B#bawbS7wF(rE-R+*tp$$p6CNYAo2VmUW6CHo|nGmk0RGqId< zrey!ba_Z^GUW(;3(n)nV_tKF)7OTu3>BxSI<;YiSnZwyfNA_W?GV(nudoq^uAsyMD zv7FO%9(OoD(2;$ca2aC(#%n42Hen~c1mm&W9hLyTvpe!(4%vaR`nt@PWgjN&gqL9a zf_FMxgUSAhRV$ut$Zm<*yBT7Uy^gRGS$oNDhE=OKYi*A@gP3X)W;CKt65fi2#M%^) zIHWW9$eGR-am;sw870q*Ey{!#4k#MaRb+n5gd>T3TO5$HVI=q$?L?w`&d^+&c$_T= zR~-yQ#%4vzqAO}M7-ppr4#q^oUeTOLtjh{;{W_{;3uQ%PI;m!hJn}S4rdu+@l9`qq zVabt}9A(KYOJ-Y=5u|9(T<%-i)?u2h$241)X(M1Atr7omB-5R_8O~&;Gufu8R7Y;M lBbDVyjdG+$I#SL?ojp2-(`KxWR_tSeBM4#(YS=;){|^SIQ+xmb literal 0 HcmV?d00001 diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32c.c b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32c.c new file mode 100644 index 000000000..7ad2b2794 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32c.c @@ -0,0 +1,62 @@ +/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 + * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. + * File written by Gilles Vollant, by modifiying the longest_match + * from Jean-loup Gailly in deflate.c + * it prepare all parameters and call the assembly longest_match_gvasm + * longest_match execute standard C code is wmask != 0x7fff + * (assembly code is faster with a fixed wmask) + * + * Read comment at beginning of gvmat32.asm for more information + */ + +#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) +#include "deflate.h" + +/* if your C compiler don't add underline before function name, + define ADD_UNDERLINE_ASMFUNC */ +#ifdef ADD_UNDERLINE_ASMFUNC +#define longest_match_7fff _longest_match_7fff +#define longest_match_686 _longest_match_686 +#define cpudetect32 _cpudetect32 +#endif + + +unsigned long cpudetect32(); + +uInt longest_match_c( + deflate_state *s, + IPos cur_match); /* current match */ + + +uInt longest_match_7fff( + deflate_state *s, + IPos cur_match); /* current match */ + +uInt longest_match_686( + deflate_state *s, + IPos cur_match); /* current match */ + + +static uInt iIsPPro=2; + +void match_init () +{ + iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0; +} + +uInt longest_match( + deflate_state *s, + IPos cur_match) /* current match */ +{ + if (iIsPPro!=0) + return longest_match_686(s,cur_match); + + if (s->w_mask != 0x7fff) + return longest_match_686(s,cur_match); + + /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */ + return longest_match_7fff(s,cur_match); +} + + +#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */ diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.asm b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.asm new file mode 100644 index 000000000..4a205125e --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.asm @@ -0,0 +1,1083 @@ +;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding +; * +; * inffas32.asm is derivated from inffas86.c, with translation of assembly code +; * +; * Copyright (C) 1995-2003 Mark Adler +; * For conditions of distribution and use, see copyright notice in zlib.h +; * +; * Copyright (C) 2003 Chris Anderson +; * Please use the copyright conditions above. +; * +; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from +; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at +; * the moment. I have successfully compiled and tested this code with gcc2.96, +; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S +; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX +; * enabled. I will attempt to merge the MMX code into this version. Newer +; * versions of this and inffast.S can be found at +; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ +; * +; * 2005 : modification by Gilles Vollant +; */ +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is in directory \MASM611C of Win95 DDK +; ml.exe is also distributed in http://www.masm32.com/masmdl.htm +; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ +; +; +; compile with command line option +; ml /coff /Zi /c /Flinffas32.lst inffas32.asm + +; if you define NO_GZIP (see inflate.h), compile with +; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm + + +; zlib122sup is 0 fort zlib 1.2.2.1 and lower +; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head +; in inflate_state in inflate.h) +zlib1222sup equ 8 + + +IFDEF GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 +ELSE + IFNDEF NO_GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 + ELSE + INFLATE_MODE_TYPE equ 3 + INFLATE_MODE_BAD equ 17 + ENDIF +ENDIF + + +; 75 "inffast.S" +;FILE "inffast.S" + +;;;GLOBAL _inflate_fast + +;;;SECTION .text + + + + .586p + .mmx + + name inflate_fast_x86 + .MODEL FLAT + +_DATA segment +inflate_fast_use_mmx: + dd 1 + + +_TEXT segment +PUBLIC _inflate_fast + +ALIGN 4 +_inflate_fast: + jmp inflate_fast_entry + + + +ALIGN 4 + db 'Fast decoding Code from Chris Anderson' + db 0 + +ALIGN 4 +invalid_literal_length_code_msg: + db 'invalid literal/length code' + db 0 + +ALIGN 4 +invalid_distance_code_msg: + db 'invalid distance code' + db 0 + +ALIGN 4 +invalid_distance_too_far_msg: + db 'invalid distance too far back' + db 0 + + +ALIGN 4 +inflate_fast_mask: +dd 0 +dd 1 +dd 3 +dd 7 +dd 15 +dd 31 +dd 63 +dd 127 +dd 255 +dd 511 +dd 1023 +dd 2047 +dd 4095 +dd 8191 +dd 16383 +dd 32767 +dd 65535 +dd 131071 +dd 262143 +dd 524287 +dd 1048575 +dd 2097151 +dd 4194303 +dd 8388607 +dd 16777215 +dd 33554431 +dd 67108863 +dd 134217727 +dd 268435455 +dd 536870911 +dd 1073741823 +dd 2147483647 +dd 4294967295 + + +mode_state equ 0 ;/* state->mode */ +wsize_state equ (32+zlib1222sup) ;/* state->wsize */ +write_state equ (36+4+zlib1222sup) ;/* state->write */ +window_state equ (40+4+zlib1222sup) ;/* state->window */ +hold_state equ (44+4+zlib1222sup) ;/* state->hold */ +bits_state equ (48+4+zlib1222sup) ;/* state->bits */ +lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ +distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ +lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ +distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ + + +;;SECTION .text +; 205 "inffast.S" +;GLOBAL inflate_fast_use_mmx + +;SECTION .data + + +; GLOBAL inflate_fast_use_mmx:object +;.size inflate_fast_use_mmx, 4 +; 226 "inffast.S" +;SECTION .text + +ALIGN 4 +inflate_fast_entry: + push edi + push esi + push ebp + push ebx + pushfd + sub esp,64 + cld + + + + + mov esi, [esp+88] + mov edi, [esi+28] + + + + + + + + mov edx, [esi+4] + mov eax, [esi+0] + + add edx,eax + sub edx,11 + + mov [esp+44],eax + mov [esp+20],edx + + mov ebp, [esp+92] + mov ecx, [esi+16] + mov ebx, [esi+12] + + sub ebp,ecx + neg ebp + add ebp,ebx + + sub ecx,257 + add ecx,ebx + + mov [esp+60],ebx + mov [esp+40],ebp + mov [esp+16],ecx +; 285 "inffast.S" + mov eax, [edi+lencode_state] + mov ecx, [edi+distcode_state] + + mov [esp+8],eax + mov [esp+12],ecx + + mov eax,1 + mov ecx, [edi+lenbits_state] + shl eax,cl + dec eax + mov [esp+0],eax + + mov eax,1 + mov ecx, [edi+distbits_state] + shl eax,cl + dec eax + mov [esp+4],eax + + mov eax, [edi+wsize_state] + mov ecx, [edi+write_state] + mov edx, [edi+window_state] + + mov [esp+52],eax + mov [esp+48],ecx + mov [esp+56],edx + + mov ebp, [edi+hold_state] + mov ebx, [edi+bits_state] +; 321 "inffast.S" + mov esi, [esp+44] + mov ecx, [esp+20] + cmp ecx,esi + ja L_align_long + + add ecx,11 + sub ecx,esi + mov eax,12 + sub eax,ecx + lea edi, [esp+28] + rep movsb + mov ecx,eax + xor eax,eax + rep stosb + lea esi, [esp+28] + mov [esp+20],esi + jmp L_is_aligned + + +L_align_long: + test esi,3 + jz L_is_aligned + xor eax,eax + mov al, [esi] + inc esi + mov ecx,ebx + add ebx,8 + shl eax,cl + or ebp,eax + jmp L_align_long + +L_is_aligned: + mov edi, [esp+60] +; 366 "inffast.S" +L_check_mmx: + cmp dword ptr [inflate_fast_use_mmx],2 + je L_init_mmx + ja L_do_loop + + push eax + push ebx + push ecx + push edx + pushfd + mov eax, [esp] + xor dword ptr [esp],0200000h + + + + + popfd + pushfd + pop edx + xor edx,eax + jz L_dont_use_mmx + xor eax,eax + cpuid + cmp ebx,0756e6547h + jne L_dont_use_mmx + cmp ecx,06c65746eh + jne L_dont_use_mmx + cmp edx,049656e69h + jne L_dont_use_mmx + mov eax,1 + cpuid + shr eax,8 + and eax,15 + cmp eax,6 + jne L_dont_use_mmx + test edx,0800000h + jnz L_use_mmx + jmp L_dont_use_mmx +L_use_mmx: + mov dword ptr [inflate_fast_use_mmx],2 + jmp L_check_mmx_pop +L_dont_use_mmx: + mov dword ptr [inflate_fast_use_mmx],3 +L_check_mmx_pop: + pop edx + pop ecx + pop ebx + pop eax + jmp L_check_mmx +; 426 "inffast.S" +ALIGN 4 +L_do_loop: +; 437 "inffast.S" + cmp bl,15 + ja L_get_length_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_length_code: + mov edx, [esp+0] + mov ecx, [esp+8] + and edx,ebp + mov eax, [ecx+edx*4] + +L_dolen: + + + + + + + mov cl,ah + sub bl,ah + shr ebp,cl + + + + + + + test al,al + jnz L_test_for_length_base + + shr eax,16 + stosb + +L_while_test: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop + jmp L_break_loop + +L_test_for_length_base: +; 502 "inffast.S" + mov edx,eax + shr edx,16 + mov cl,al + + test al,16 + jz L_test_for_second_level_length + and cl,15 + jz L_save_len + cmp bl,cl + jae L_add_bits_to_len + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_len: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + +L_save_len: + mov [esp+24],edx + + +L_decode_distance: +; 549 "inffast.S" + cmp bl,15 + ja L_get_distance_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_distance_code: + mov edx, [esp+4] + mov ecx, [esp+12] + and edx,ebp + mov eax, [ecx+edx*4] + + +L_dodist: + mov edx,eax + shr edx,16 + mov cl,ah + sub bl,ah + shr ebp,cl +; 584 "inffast.S" + mov cl,al + + test al,16 + jz L_test_for_second_level_dist + and cl,15 + jz L_check_dist_one + cmp bl,cl + jae L_add_bits_to_dist + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_dist: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + jmp L_check_window + +L_check_window: +; 625 "inffast.S" + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,edx + jb L_clip_window + + mov ecx, [esp+24] + mov esi,edi + sub esi,edx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp edx,1 + jne L_check_window + cmp [esp+40],edi + je L_check_window + + dec edi + mov ecx, [esp+24] + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + + + + + test al,64 + jnz L_test_for_end_of_block + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+8] + mov eax, [edx+eax*4] + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + + + + + test al,64 + jnz L_invalid_distance_code + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+12] + mov eax, [edx+eax*4] + jmp L_dodist + +ALIGN 4 +L_clip_window: +; 721 "inffast.S" + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,edx + jb L_invalid_distance_too_far + + add ecx,edx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window + + sub eax,ecx + add esi,eax +; 749 "inffast.S" + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_wrap_around_window: +; 793 "inffast.S" + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_contiguous_in_window: +; 836 "inffast.S" + add esi,eax + sub esi,ecx + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + +L_do_copy1: +; 862 "inffast.S" + mov ecx,eax + rep movsb + + mov esi, [esp+44] + jmp L_while_test +; 878 "inffast.S" +ALIGN 4 +L_init_mmx: + emms + + + + + + movd mm0,ebp + mov ebp,ebx +; 896 "inffast.S" + movd mm4,[esp+0] + movq mm3,mm4 + movd mm5,[esp+4] + movq mm2,mm5 + pxor mm1,mm1 + mov ebx, [esp+8] + jmp L_do_loop_mmx + +ALIGN 4 +L_do_loop_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_length_code_mmx + + movd mm6,ebp + movd mm7,[esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_length_code_mmx: + pand mm4,mm0 + movd eax,mm4 + movq mm4,mm3 + mov eax, [ebx+eax*4] + +L_dolen_mmx: + movzx ecx,ah + movd mm1,ecx + sub ebp,ecx + + test al,al + jnz L_test_for_length_base_mmx + + shr eax,16 + stosb + +L_while_test_mmx: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop_mmx + jmp L_break_loop + +L_test_for_length_base_mmx: + + mov edx,eax + shr edx,16 + + test al,16 + jz L_test_for_second_level_length_mmx + and eax,15 + jz L_decode_distance_mmx + + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add edx,ecx + +L_decode_distance_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_dist_code_mmx + + movd mm6,ebp + movd mm7,[esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_dist_code_mmx: + mov ebx, [esp+12] + pand mm5,mm0 + movd eax,mm5 + movq mm5,mm2 + mov eax, [ebx+eax*4] + +L_dodist_mmx: + + movzx ecx,ah + mov ebx,eax + shr ebx,16 + sub ebp,ecx + movd mm1,ecx + + test al,16 + jz L_test_for_second_level_dist_mmx + and eax,15 + jz L_check_dist_one_mmx + +L_add_bits_to_dist_mmx: + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add ebx,ecx + +L_check_window_mmx: + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,ebx + jb L_clip_window_mmx + + mov ecx,edx + mov esi,edi + sub esi,ebx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_check_dist_one_mmx: + cmp ebx,1 + jne L_check_window_mmx + cmp [esp+40],edi + je L_check_window_mmx + + dec edi + mov ecx,edx + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_test_for_second_level_length_mmx: + test al,64 + jnz L_test_for_end_of_block + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + add ecx,edx + mov eax, [ebx+ecx*4] + jmp L_dolen_mmx + +ALIGN 4 +L_test_for_second_level_dist_mmx: + test al,64 + jnz L_invalid_distance_code + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + mov eax, [esp+12] + add ecx,ebx + mov eax, [eax+ecx*4] + jmp L_dodist_mmx + +ALIGN 4 +L_clip_window_mmx: + + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,ebx + jb L_invalid_distance_too_far + + add ecx,ebx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window_mmx + + sub eax,ecx + add esi,eax + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_wrap_around_window_mmx: + + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window_mmx + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_contiguous_in_window_mmx: + + add esi,eax + sub esi,ecx + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + +L_do_copy1_mmx: + + + mov ecx,edx + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx +; 1174 "inffast.S" +L_invalid_distance_code: + + + + + + mov ecx, invalid_distance_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_test_for_end_of_block: + + + + + + test al,32 + jz L_invalid_literal_length_code + + mov ecx,0 + mov edx,INFLATE_MODE_TYPE + jmp L_update_stream_state + +L_invalid_literal_length_code: + + + + + + mov ecx, invalid_literal_length_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_invalid_distance_too_far: + + + + mov esi, [esp+44] + mov ecx, invalid_distance_too_far_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_update_stream_state: + + mov eax, [esp+88] + test ecx,ecx + jz L_skip_msg + mov [eax+24],ecx +L_skip_msg: + mov eax, [eax+28] + mov [eax+mode_state],edx + jmp L_break_loop + +ALIGN 4 +L_break_loop: +; 1243 "inffast.S" + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_next_in + + + + mov ebx,ebp + +L_update_next_in: +; 1266 "inffast.S" + mov eax, [esp+88] + mov ecx,ebx + mov edx, [eax+28] + shr ecx,3 + sub esi,ecx + shl ecx,3 + sub ebx,ecx + mov [eax+12],edi + mov [edx+bits_state],ebx + mov ecx,ebx + + lea ebx, [esp+28] + cmp [esp+20],ebx + jne L_buf_not_used + + sub esi,ebx + mov ebx, [eax+0] + mov [esp+20],ebx + add esi,ebx + mov ebx, [eax+4] + sub ebx,11 + add [esp+20],ebx + +L_buf_not_used: + mov [eax+0],esi + + mov ebx,1 + shl ebx,cl + dec ebx + + + + + + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_hold + + + + psrlq mm0,mm1 + movd ebp,mm0 + + emms + +L_update_hold: + + + + and ebp,ebx + mov [edx+hold_state],ebp + + + + + mov ebx, [esp+20] + cmp ebx,esi + jbe L_last_is_smaller + + sub ebx,esi + add ebx,11 + mov [eax+4],ebx + jmp L_fixup_out +L_last_is_smaller: + sub esi,ebx + neg esi + add esi,11 + mov [eax+4],esi + + + + +L_fixup_out: + + mov ebx, [esp+16] + cmp ebx,edi + jbe L_end_is_smaller + + sub ebx,edi + add ebx,257 + mov [eax+16],ebx + jmp L_done +L_end_is_smaller: + sub edi,ebx + neg edi + add edi,257 + mov [eax+16],edi + + + + + +L_done: + add esp,64 + popfd + pop ebx + pop ebp + pop esi + pop edi + ret + +_TEXT ends +end diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.obj b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.obj new file mode 100644 index 0000000000000000000000000000000000000000..bd6664d111d573b4aa7a4d4a182d33b90d705700 GIT binary patch literal 14893 zcmb`O33L?2*2iyE1qhwMgiQjXj4&V&3@DLBP(TnwgX|DC$AnBEkYq5KB)~(qppcBn zCa#Ex`b1EkPZ3;D35cvBilPXziAan-Hhrid`Tn=NGCduF`p)_0ocZzZ+qbH#Yn|LG z5=8{%JyPZNeQk&alJ$uX_$CFk=6{~9Mzj|H_KzgmhHo?tkZ$UKUwmqEAX(pMzX*KS zT*b=%bff+o<5PVpxnn(po<%MUx#vqf7q`? z38Hy@s8@1Mz@6$F<4;Y`8td-iPxZOevi+Iv9^d7d(~`5@Dam6dP_T^4gi?^g zmtPC7M2+$7itluM*`W*$WpF5iLm3>(;7|sKGB}jMp$raXa43UA863*sPzHxGIF!Kw zUxBZ}w;H}Kd>iB272oOjmJJ&^WYE%rAG=))20Tf@X^nzIBZ5`co`N5u3VV857Y_E+ z4Q6;o1@DOo-WwfPa{e1tIkFv6p+lK85pCnDIpMX+Dn;IIT-B*42Zp3yPr?-=xUK@nO96Fqf1@6K;hP#hJv z`>kkX6jwZNs;AMp7lPZ`Z9KPXUcl3+FyN_M8hidDuD3u;yNyLvdj)qEY>wP}B3B^mx5byi==CIp(M(m(0|Z?flGrCo|y?AA~!v=bVR#7fu8L)x>n4*(A$@lo7-{b zZ&?9fMsC}gzo%#U`sB7S3+-A_d@{1&h^ye&s<~I4-$XQna%E}s)+%P^K&fGAF35=C zBa=$!ESPb@m0zRX#y(92)=4Z!BkIM%Jsw*tJAn0+qpRJzPMtP4uvlrimQR4t2=SOZRc%y ztyRF2piak~iQ^18MZD>QY*GBSxV|=&rY`$wugG$1aGQSn+9-9f%$4uT+7c{vWqCZV z>EF7tGCUEk=|8wmZ4Zv}M3#yLuD!(tf4K8&yRv?9W!+ZrQH1Nvp-aw#St?dr>32quGnzDX9f%wlw#lBWNRZ;Xqwv?#kNcnpPZlvT5{# zu#)=p$`3?|qFo10x~83UO-IM&hX%hYE{%yR!LvEvS9HF^D#>?$SU1`1n)NbVgF8^q z=l-ITa5a?NfCj|8TyR0;zGe26*ZT!`RMJySXP(}IW`8+km4{0+t+@OJcLXDXCA-YJ z=RUQj5+5{KwAvYrm}~VMXWv2LS0IhrY4sg9_npq4<|V~_YWACRrT5_KuFzFC-EUgh z{Ra12nfJ^4%%^z`L;f+`XW$W8ZVB$N`iuE)9+dlSJe}TY2$Z&7=?+9&*HL`kDC}Mg z53#UoLP3%q+#XPccg6<0H7blLB|RhN%HTJAGq^L@zfp0CiaS$$RK@KtoD^L+qDye+ zyiuM;okn@;=GKin7mURWUss(ACPfsKMhWP`w(s)HzW3X^%X5n~>wAkUziDaV_>L%c z-Oh*djJQJuo1+SoB1(<8bLS5gd=ynUF#`8uIv>uf5qEgzW?nxElVVD1#9cUlc;;5~ za#BpehuxkTIr?7jW;%lVycSlaThWy*)hDFNFiF-h?+(L6Y^ft56;ZX^_7W7=R8`sx zRnt^^p<+yR7Rt)G8&+0J)xsU3NIZQQRR@#E0Ebf)ID(?VkyHa5MKR!Lss*M{J#Y-g zf)nU!FoUiEv#2rXrzYV2)EvyFR$zeQ!Cbl#%%cQw614{>Q%7(L-2zUfZr}rSJ2;(s zfivhXa3^L2~7nbqv_z|Gz)x^9s-}DBJgQ?1bl`Tg3IVpa5+5zK1WNz6|@X|o|c0z((~Xy z=|%7*S_Q78SHPF)HE?Khe}R2L0{w3vDez0G0)9o+!2MJM{F+?g0jdWcr261D zbPafj8iR+)10JE~;8AJ`9;4Rax6}qaPB((zQ3vn@bppSq&R_}M0scU}!5{Hkndm<> z5IjYLz|%AsJVQgkvy=p$r;*^VG#dP!yx;{&1~1YW@DEA@FVQ%#jK+gfWP(cE4@QU_ zu!_h7Yl=yrOH2V{#8j}pmYfLi_^WE6#&n@jG~*xCkbTOJIuNAM>d~f@vZG z94icPoTve&3l}(E)B-1nI$)-#2WE--pkFiqCyJ}V`^B|jws3qUi~tvk(cmI+AGlbI0Us4<;1ZDzJ|-rBPY6HwqzHh|hEH@61AJc0244^lfiH?e@FnpuxKhjqUlxnNRbmOaT09QEDwcw8ie=zB@dEgk zco}?KtOnl^uYm80HQ)yE8u*@A3%)PbgCB?u;8yWIxJ`Tr?hxC-onj}rOY8za7Q4aS zVh{L<_#E6Lz63uN2f=;f5cs7y27V=ugZsrv@PPOMJSa|shs0U%us9DM5x;@Q#0BtM z@dx;wz#qtTLMZTiQ3Wg!)xaM_b+A-Kfj^2G;7`H@o)Wdd)1nS|R@4K}iTdErq5=4e zxElPgxCZ=PTnAndO~H$z8F)#w1j|GmNb&|y$TnbvYzJ16H-lAW2QX500;|i;pdq`0 zQL+aZE$;wp$ljn!_5ow$-C!-*7pyJ&fpz2nu)Z7w#>ye!)p9u4NR9-rk)y%J(hIs} zGI*UF12&O9u(=!yUN6(ZmNFA;B?Dl*%mWkTWbkJB53qxr4tA8Yz)o@wc#A9oJIi@s z7r79;RXz%Kmyd%z@U}Y z1LQm4VEG<6L~aC!%1vOB{16;2KLSU}?cgZ615B2?!4&y9m@2;lee!ECO&$iv%cI}~ zc^u4?C%`QEBj}f>z=`qbL4q2Ab$sQDF3uGg3wrmW}kxjw5vN>2NTY^QhH5im_!1?kfaDhw!7s?LcBH0OC zEW3b92RRgf z$_?Ny`2qN`ECxT3TfjYX7x=l{4Spd%2fvhGf?vt6!Ts_Z@N0P-JRnbi2W1KPjXVt= zm1n_Y@>lS5IiYAkq-N(Zl1 z6F|4h1g}$mu!+h6o2q=!qb7sR)IY%M)dOG)H63iJW`eC$0T`zq1ly=NU|UrPwo^ec zLCpi(tNCCDwGiy67K5GC67V+lIM`J^33gY{fVZpXz#i(K;N5C9n5bR@`>NN$A!;o+ zRILM()VtttwGkYlHi0Q>D>z2&0#ns)aJ>2qoS?o0Gt@yaQyl{DSI59?bsWr5C%}Lz z0rS+4V7~efI7yubA5iDPY3es{mbw5wq{_fKO5ksjxheuIRMo&DRUHhfXz*cG6P%}N zfsd%V;CyuzxKK3&7pZH(#mWsXQBAxb0GFxu;BwU& zd`{g8u28puE7cv~%c?i{s=5nYqxyocsea%(H2_?%27?<^68N4P0lu$Bfg9DmV6jRD zH>p%`vq}TEsBz#&YCO1AWrEw(MDP<80Qaao@KZGj+^eR5pQ{<*7pefm+c;ksBpSJ%iTWy#)SBe z2?+^qETqVjKUXDs1HPPqH_e~zwW7q{l;j+r$M$HL=+&WNZ+Xbri_owaq2X(7ueyoe zG2?t=CYU~6f0oainK>!ezF#xZo9g$D@lTw5Bj0hR%+F4q=uOV{=VqmP^V73Z{rPq6 zl!l%1YTH^X(VLu_>P<-x>W zZQqOJ+T;u?6k)Xxe$iKPm z(&$Qc$O)WTh5Eb?741*+reyfXOlWCm)wsM5RMJ)WrCZsq?mv5K#Wuhw$w0MPot$sh zvong~S4XR|+1Z(MbIjp%mF*jy=uOG?B~S2jCl7Dr%erMFJ5g=tnBiJ+K0YmdQtm{r zKQ~Z$n_~F#IB<4z#~ZcAFL!HRvB>*q_<3mVr&$&eLy;bjr!77={txy2w}xkUS1514 zP+!qg7B^maeO)#v!t2X%)0Y*L}y3A6#JJQqL!UmHQnQ!rOzLip5ZfB1?T({8Z%+*M0iy? zdl#H4%olpnawai1Gku|zrSgu)+mvSKt87*ZZ!l*Oxb2;lYBhj0`kb?$bMgB76LWZ< z`?HB4d}VM9nZH^Ioo#@HA&@>c*Pok%Ir>l6N@wMluQ<+P=ksi=(sWg!c_j?`#-n|KR(r?QzuP zN-eKP3cUZ{7L32Mo;oYOvOdEv;2av^zs{U%gr-3TAq7k|E%8_V^tA^TgRb>_yYrah*SYoHdh@o94~(o0D;>bNuL3RwwEaUX1ABpp@tC&f zv@)>!hA6OUE7r=uUKwJ-rtN@M26n0t88U4bv@*#E&OTD$}o3Jao7oEiHD7q zft?;il1y6c9v@(cy%vzeZe`;kQs)@LmY1^WeftVtqWTve|D}#7Hs^m|$>0}&lWb)#wHy%JVv zbEun48}Ev+GAJ5<#56Y@P zjyPNOR|>_)+@k1|Rt8l;^zb&*R$VKDIBsl>BaR(gwE! zD}%N{S^Z^~Rt6n~vgWYwv@%HG1Zz(-zbaZ8)D+5^*RI#fpiWRtOut*TGN>PvHC6{{ zg*goBI@2#hD}xH5tZ_6?E0h`P4%6=itx(TUy-eFitqeK_)!Ve4(8?fHy?lIB(+YJ8 zb*JgqTq}cafof*jZqo{L7*rqAcAr)TO@Xr3fN5G8^c2)xrr$EHP^VDVys=9wgMNmx z=8a#qGN_hOKCji&%AlK}?l$x5q?JJK|P`FGHrKiWl%PhHTLtgGUyQ~ ztF9JlWzZ_9K4#iATA`mpSz~LLR_Gg0RvVqv%Ah}>tnntWWU#{6hqA`e^;#L!8OoaP zyJ}_7ASi2H7^W503Mgyd&DF}F*-%zLn5&gR&p}yp`-@s(>_b^?zELaGGt}MYyM3k= z#v7EiZvCni<}mnFHCMf}XAFuYg=_2*##ALCvEO(mJ`F)D(}q(8WqgtaKW(jzlH{CB z>qfUR{>+K->8TgpwQ&>^yNeWl?w_Ba1V=3Sw7<>@|CFEkXA7H^h+ygXl%Mx!BbQ7G zKJkC4GM~Y0KnLZTnvn-sKovI_h znB%hmSA6=)F7r#U@NT7T*#rykl-m~mmCie+w&esYe7?lCT!4j7Z`hWqCF!e^dr%PCm+M67M$za}<0EPSesPhQ$SjbPzZn6{+_EPR&Hwse5S>ft;p zb=(~1Uc!BP!-vlr+NlP^!YBD`3!g*dvu?H}7gu}=&9?AKGd{6oTb_Z1fB)MSK0n5% zc5Dlu6XWwYw&gG^Z5);#Vc}CRwh#Yr9X>B&TbdwOKEYsHZiR)<3fLAtNyR(ywj~7? z-etEf6Jg;UblWlu7TyuJELKztX8=N$#khaj-}}~{Q_fg&?5D!d-dr^|Geaq_uw&;; zp(8_~M3rq5p_MBOxxjo`A$5onx18}Jj%Jvh#oqbG<>i~8VLp)Iv1-J6ted>A16BU$ zO5PH8E7_7Z(^%Whkf9f~U2gmI;e9rc3_^+nh)b literal 0 HcmV?d00001 diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/mkasm.bat b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/mkasm.bat new file mode 100644 index 000000000..70a51f837 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/mkasm.bat @@ -0,0 +1,3 @@ +cl /DASMV /I..\.. /O2 /c gvmat32c.c +ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm +ml /coff /Zi /c /Flinffas32.lst inffas32.asm diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/readme.txt b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/readme.txt new file mode 100644 index 000000000..7b57167b7 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/readme.txt @@ -0,0 +1,21 @@ + +Summary +------- +This directory contains ASM implementations of the functions +longest_match() and inflate_fast(). + + +Use instructions +---------------- +Copy these files into the zlib source directory, then run the +appropriate makefile, as suggested below. + + +Build instructions +------------------ +* With Microsoft C and MASM: +nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj" + +* With Borland C and TASM: +make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="gvmat32c.obj gvmat32.obj inffas32.obj" OBJPA="+gvmat32c.obj+gvmat32.obj+inffas32.obj" + diff --git a/tools/vio2sf/src/vio2sf/zlib/crc32.c b/tools/vio2sf/src/vio2sf/zlib/crc32.c new file mode 100644 index 000000000..32814c20c --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/crc32.c @@ -0,0 +1,423 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case */ + if (len2 == 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320L; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} diff --git a/tools/vio2sf/src/vio2sf/zlib/crc32.h b/tools/vio2sf/src/vio2sf/zlib/crc32.h new file mode 100644 index 000000000..5de49bc97 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/tools/vio2sf/src/vio2sf/zlib/crypt.h b/tools/vio2sf/src/vio2sf/zlib/crypt.h new file mode 100644 index 000000000..9c7a89cbe --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.00, September 10th, 2003 + + Copyright (C) 1998-2003 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/tools/vio2sf/src/vio2sf/zlib/infback.c b/tools/vio2sf/src/vio2sf/zlib/infback.c new file mode 100644 index 000000000..1e03e1bab --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/infback.c @@ -0,0 +1,623 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->write = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + + /* process literal */ + if (this.op == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(this.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/tools/vio2sf/src/vio2sf/zlib/inffast.c b/tools/vio2sf/src/vio2sf/zlib/inffast.c new file mode 100644 index 000000000..fa31cad90 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inffast.c @@ -0,0 +1,318 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code this; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + write = state->write; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = lcode[hold & lmask]; + dolen: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op == 0) { /* literal */ + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + PUP(out) = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + this = dcode[hold & dmask]; + dodist: + op = (unsigned)(this.bits); + hold >>= op; + bits -= op; + op = (unsigned)(this.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + from = window - OFF; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (write < op) { /* wrap around window */ + from += wsize + write - op; + op -= write; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += write - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + this = dcode[this.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + this = lcode[this.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and write == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/tools/vio2sf/src/vio2sf/zlib/inffast.h b/tools/vio2sf/src/vio2sf/zlib/inffast.h new file mode 100644 index 000000000..614fa7877 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/tools/vio2sf/src/vio2sf/zlib/inffixed.h b/tools/vio2sf/src/vio2sf/zlib/inffixed.h new file mode 100644 index 000000000..423d5c5b5 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/tools/vio2sf/src/vio2sf/zlib/inflate.c b/tools/vio2sf/src/vio2sf/zlib/inflate.c new file mode 100644 index 000000000..33ea90292 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inflate.c @@ -0,0 +1,1368 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common write == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->write = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + if (windowBits < 0) { + state->wrap = 0; + windowBits = -windowBits; + } + else { + state->wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) windowBits &= 15; +#endif + } + if (windowBits < 8 || windowBits > 15) { + ZFREE(strm, state); + strm->state = Z_NULL; + return Z_STREAM_ERROR; + } + state->wbits = (unsigned)windowBits; + state->window = Z_NULL; + return inflateReset(strm); +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->write = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->write = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->write; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->write, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->write = copy; + state->whave = state->wsize; + } + else { + state->write += dist; + if (state->write == state->wsize) state->write = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code this; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.val < 16) { + NEEDBITS(this.bits); + DROPBITS(this.bits); + state->lens[state->have++] = this.val; + } + else { + if (this.val == 16) { + NEEDBITS(this.bits + 2); + DROPBITS(this.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (this.val == 17) { + NEEDBITS(this.bits + 3); + DROPBITS(this.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(this.bits + 7); + DROPBITS(this.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* build code tables */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + break; + } + for (;;) { + this = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if (this.op && (this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + state->length = (unsigned)this.val; + if ((int)(this.op) == 0) { + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); + state->mode = LIT; + break; + } + if (this.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + if (this.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(this.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->mode = DIST; + case DIST: + for (;;) { + this = state->distcode[BITS(state->distbits)]; + if ((unsigned)(this.bits) <= bits) break; + PULLBYTE(); + } + if ((this.op & 0xf0) == 0) { + last = this; + for (;;) { + this = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + this.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(this.bits); + if (this.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)this.val; + state->extra = (unsigned)(this.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + if (state->offset > state->whave + out - left) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->write) { + copy -= state->write; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->write - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} diff --git a/tools/vio2sf/src/vio2sf/zlib/inflate.h b/tools/vio2sf/src/vio2sf/zlib/inflate.h new file mode 100644 index 000000000..fbbc87143 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/tools/vio2sf/src/vio2sf/zlib/inftrees.c b/tools/vio2sf/src/vio2sf/zlib/inftrees.c new file mode 100644 index 000000000..38ded81c3 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inftrees.c @@ -0,0 +1,329 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)1; + this.val = (unsigned short)0; + *(*table)++ = this; /* make a table to force an error */ + *(*table)++ = this; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked when a LENS table is being made + against the space in *table, ENOUGH, minus the maximum space needed by + the worst case distance code, MAXD. This should never happen, but the + sufficiency of ENOUGH has not been proven exhaustively, hence the check. + This assumes that when type == LENS, bits == 9. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if (type == LENS && used >= ENOUGH - MAXD) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/tools/vio2sf/src/vio2sf/zlib/inftrees.h b/tools/vio2sf/src/vio2sf/zlib/inftrees.h new file mode 100644 index 000000000..dc0fd567e --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/tools/vio2sf/src/vio2sf/zlib/uncompr.c b/tools/vio2sf/src/vio2sf/zlib/uncompr.c new file mode 100644 index 000000000..ad6db0a67 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/uncompr.c @@ -0,0 +1,61 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/tools/vio2sf/src/vio2sf/zlib/zconf.h b/tools/vio2sf/src/vio2sf/zlib/zconf.h new file mode 100644 index 000000000..e3b0c962e --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/tools/vio2sf/src/vio2sf/zlib/zlib.h b/tools/vio2sf/src/vio2sf/zlib/zlib.h new file mode 100644 index 000000000..62d0e4675 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/tools/vio2sf/src/vio2sf/zlib/zutil.c b/tools/vio2sf/src/vio2sf/zlib/zutil.c new file mode 100644 index 000000000..0f4bd7871 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch (sizeof(uInt)) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch (sizeof(uLong)) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch (sizeof(voidpf)) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch (sizeof(z_off_t)) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/tools/vio2sf/src/vio2sf/zlib/zutil.h b/tools/vio2sf/src/vio2sf/zlib/zutil.h new file mode 100644 index 000000000..0ba6e0208 --- /dev/null +++ b/tools/vio2sf/src/vio2sf/zlib/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/tools/vio2sf/src/xsfc/drvimpl.h b/tools/vio2sf/src/xsfc/drvimpl.h new file mode 100644 index 000000000..680d8e898 --- /dev/null +++ b/tools/vio2sf/src/xsfc/drvimpl.h @@ -0,0 +1,18 @@ +#define XSF_FALSE (0) +#define XSF_TRUE (!XSF_FALSE) + +#ifdef __cplusplus +extern "C" { +#endif + +int xsf_start(void *pfile, unsigned bytes); +int xsf_gen(void *pbuffer, unsigned samples); +int xsf_get_lib(char *pfilename, void **ppbuffer, unsigned *plength); +void xsf_term(void); +void xsf_set_extend_param(unsigned dwId, const wchar_t *lpPtr); +extern unsigned long dwChannelMute; +extern unsigned long dwChannelMute; + +#ifdef __cplusplus +} +#endif diff --git a/tools/vio2sf/src/xsfc/foo_input_xsf.cpp b/tools/vio2sf/src/xsfc/foo_input_xsf.cpp new file mode 100644 index 000000000..9a7186da9 --- /dev/null +++ b/tools/vio2sf/src/xsfc/foo_input_xsf.cpp @@ -0,0 +1,719 @@ +#include "leakchk.h" + +#include "foobar2000/SDK/foobar2000.h" + +#include "../pversion.h" + +#include "../loadpe/loadpe.h" +#include "xsfdrv.h" + +#include "tagget.h" +#include "xsfcfg.h" + +enum +{ + xsf_bits_per_sample = 16, + xsf_channels = 2, +#ifndef XSFDRIVER_SAMPLERATE + xsf_sample_rate = 44100, +#else + xsf_sample_rate = XSFDRIVER_SAMPLERATE, +#endif + + xsf_bytes_per_sample = xsf_bits_per_sample / 8, + xsf_total_sample_width = xsf_bytes_per_sample * xsf_channels, +}; + +#define DEFAULT_BUFFER_SIZE (1024) + +#define CHECK_SILENCE_BIAS 0x8000000 +#ifndef CHECK_SILENCE_LEVEL +#define CHECK_SILENCE_LEVEL 7 +#endif + +typedef signed short xsfsample_t; + +static HMODULE hDLL; + +class xsf_drv +{ +protected: + void *lpDrv; + IXSFDRV *lpif; + pfc::string8 m_libpath; + bool m_genok; + + unsigned detectedSilenceSec; + unsigned detectedSilenceSample; + unsigned skipSilenceOnStartSec; + unsigned long prevSampleL; + unsigned long prevSampleR; + +public: + bool isUTF8; + + xsf_drv() + { + m_genok = false; + isUTF8 = false; + lpDrv = 0; + lpif = 0; + } + + ~xsf_drv() + { + freeDrv(); + } + void setlibpath(pfc::string8 &p_libpath) + { + m_libpath.set_string(p_libpath.get_ptr()); + } + + void start(void *p, DWORD l) + { + if (loadDrv()) + m_genok = !lpif->Start(p, l); + + skipSilenceOnStartSec = CFGGetSkipSilenceOnStartSec(); + + detectedSilenceSec = 0; + detectedSilenceSample = 0; + + prevSampleL = CHECK_SILENCE_BIAS; + prevSampleR = CHECK_SILENCE_BIAS; + } + + unsigned long get_detect_silence() + { + return detectedSilenceSec; + } + + int gen(void *pbuf, unsigned bufsize) + { + if (!lpif) return 0; + if (!m_genok) return 0; + + xsfsample_t *ptop = static_cast(pbuf); + unsigned detectSilence = CFGGetDetectSilenceSec(); + unsigned pos = 0; + + if (lpif->dwInterfaceVersion >= 2) + { + bool output = false; + for (int i = 0; i < 4; i++) + { + unsigned long mute = CFGGetChannelMute(i); + output |= (mute != ~unsigned long(0)); + lpif->SetChannelMute(i, mute); + } + if (!output) detectSilence = 0; + } + + while (pos < bufsize) + { + unsigned ofs; + xsfsample_t *pblk = ptop + (pos << 1); + unsigned remain = bufsize - pos; + lpif->Gen(pblk, remain); + if (detectSilence || skipSilenceOnStartSec) + { + xsfsample_t *pskp = 0; + xsfsample_t *pcur = pblk; + for (ofs = 0; ofs < remain; ofs++) + { + long smpl = pcur[0]; + long smpr = pcur[1]; + bool silence = (((unsigned long)(smpl + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleL <= (CHECK_SILENCE_LEVEL) * 2) && (((unsigned long)(smpr + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleR <= (CHECK_SILENCE_LEVEL) * 2); + + if (silence) + { + if (++detectedSilenceSample >= xsf_sample_rate) + { + detectedSilenceSample -= xsf_sample_rate; + detectedSilenceSec++; + if (skipSilenceOnStartSec && detectedSilenceSec >= skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + detectedSilenceSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + } + else + { + detectedSilenceSample = 0; + detectedSilenceSec = 0; + if (skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + prevSampleL = smpl + CHECK_SILENCE_BIAS; + prevSampleR = smpr + CHECK_SILENCE_BIAS; + pcur += 2; + } + if (skipSilenceOnStartSec) + { + } + else if (pskp) + { + while (pskp < pcur) + { + *(pblk++)= *(pskp++); + *(pblk++)= *(pskp++); + pos++; + } + } + else + { + pos += remain; + } + } + else + { + pos += remain; + } + } + return bufsize; + } + + + void stop() + { + if (!lpif) return; + lpif->Term(); + m_genok = false; + } + +protected: + bool aogetlib(pfc::string8 &filename, void **ppBuffer, DWORD *pdwSize) + { + try + { + if (!lpif) return false; + service_ptr_t xsflib; + abort_callback_impl abort_cb; + xsfc::TStringM path(true, xsfc::TWin32::CanonicalizePath(xsfc::TString(true, m_libpath.get_ptr()) + xsfc::TString(true, filename.get_ptr()))); + pfc::string8 xsfpath(path.GetM()); + filesystem::g_open_read(xsflib, xsfpath, abort_cb); + DWORD dwfilesize = DWORD(xsflib->get_size_ex(abort_cb)); + void *ret = lpif->LibAlloc(dwfilesize); + if (!ret) return false; + xsflib->read(ret, dwfilesize, abort_cb); + *ppBuffer = ret; + *pdwSize = dwfilesize; + return true; + } catch (xsfc::EShortOfMemory e) { + } catch (exception_io e) { + } + return false; + } + static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize) + { + xsf_drv *pthis = static_cast(lpWork); + pfc::string8 filename; + if (pthis->isUTF8) + { + filename.set_string(static_cast(lpszFilename)); + } + else + { + pfc::stringcvt::string_utf8_from_ansi valuea(static_cast(lpszFilename)); + filename.set_string(valuea.get_ptr()); + } + return pthis->aogetlib(filename, ppBuffer, pdwSize) ? 0 : 1; + } + bool loadDrv(void) + { + if (lpif) return true; + pfc::string8 dllpath; + uGetModuleFileName(hDLL, dllpath); + pfc::string8 binpath(dllpath, pfc::scan_filename(dllpath)); + binpath.add_string(XSFDRIVER_MODULENAME); + + if (xsfc::TWin32::IsUnicodeSupportedOS()) + { + pfc::stringcvt::string_wide_from_utf8 dllpathw(binpath); + lpDrv = XLoadLibraryW(dllpathw.get_ptr()); + } + else + { + pfc::stringcvt::string_ansi_from_utf8 dllpatha(binpath); + lpDrv = XLoadLibraryA(dllpatha.get_ptr()); + } + if (!lpDrv) return false; + + LPFNXSFDRVSETUP xsfsetup = (LPFNXSFDRVSETUP)XGetProcAddress(lpDrv, XSFDRIVER_ENTRYNAME); + if (!xsfsetup) + { + XFreeLibrary(lpDrv); + lpDrv = 0; + return false; + } + + lpif = xsfsetup(XSFGETLIBCALLBACK, this); + return true; + } + + void freeDrv(void) + { + if (lpif) + { + lpif->Term(); + lpif = 0; + } + if (lpDrv) + { + XFreeLibrary(lpDrv); + lpDrv = 0; + } + } +}; + +class input_xsf +{ +protected: + xsf_drv drv; + pfc::array_t m_filebuffer; + foobar2000_io::t_filesize m_filesize; + t_uint64 cur_smp; + t_uint64 len_smp; + t_uint64 fad_smp; + t_uint64 end_smp; + + service_ptr_t m_file; + pfc::array_t m_buffer; + + double m_volume; + bool m_hasvolume; + bool m_haslength; + + bool m_write_UTF8; + unsigned m_flags; + + typedef struct + { + class input_xsf *pThis; + file_info * p_info; + bool isUTF8; + } tagloadcbwork; + + void tagloadsub(file_info & p_info, pfc::string8 &name, pfc::string8 &value) + { + if (!stricmp_utf8(name.get_ptr(), "game")) + p_info.meta_add("album", value.get_ptr()); + else if (!stricmp_utf8(name.get_ptr(), "year")) + p_info.meta_add("date", value.get_ptr()); + else if (!_strnicmp(name.get_ptr(), "_lib", 4) || !stricmp_utf8(name.get_ptr(), "fade") || !stricmp_utf8(name.get_ptr(), "length") || !stricmp_utf8(name.get_ptr(), "volume")) + p_info.info_set(name.get_ptr(), value.get_ptr()); + else if (!stricmp_utf8(name.get_ptr(), "replaygain_track_gain")) + { + replaygain_info rg = p_info.get_replaygain(); + rg.set_track_gain_text(value.get_ptr()); + p_info.set_replaygain(rg); + } + else if (!stricmp_utf8(name.get_ptr(), "replaygain_track_peak")) + { + replaygain_info rg = p_info.get_replaygain(); + rg.set_track_peak_text(value.get_ptr()); + p_info.set_replaygain(rg); + } + else if (!stricmp_utf8(name.get_ptr(), "replaygain_album_gain")) + { + replaygain_info rg = p_info.get_replaygain(); + rg.set_album_gain_text(value.get_ptr()); + p_info.set_replaygain(rg); + } + else if (!stricmp_utf8(name.get_ptr(), "replaygain_album_peak")) + { + replaygain_info rg = p_info.get_replaygain(); + rg.set_album_peak_text(value.get_ptr()); + p_info.set_replaygain(rg); + } + else + p_info.meta_add(name.get_ptr(), value.get_ptr()); + } + + static enum XSFTag::enum_callback_returnvalue tagloadcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + if (pNameTop == pNameEnd) return XSFTag::enum_continue; + + tagloadcbwork *pcbwork = static_cast(pWork); + + pfc::string8 name; + name.set_string(pNameTop, pNameEnd - pNameTop); + + pfc::string8 value; + if (pcbwork->isUTF8) + { + value.set_string(pValueTop, pValueEnd - pValueTop); + } + else + { + pfc::stringcvt::string_utf8_from_ansi valuea(pValueTop, pValueEnd - pValueTop); + value.set_string(valuea.get_ptr()); + } + + pcbwork->pThis->tagloadsub(*pcbwork->p_info, name, value); + return XSFTag::enum_continue; + } + + void tagload(file_info & p_info) + { + BYTE *pData = m_filebuffer.get_ptr(); + DWORD dwSize = DWORD(m_filesize); + bool isUTF8 = XSFTag::Exists("utf8", pData, dwSize); + drv.isUTF8 = isUTF8; + + tagloadcbwork cbwork; + cbwork.isUTF8 = isUTF8; + cbwork.pThis = this; + cbwork.p_info= &p_info; + XSFTag::Enum(tagloadcb, &cbwork, pData, dwSize); + return; + } + + void tagsave(const file_info & p_info, abort_callback & p_abort) + { + BYTE *pData = m_filebuffer.get_ptr(); + DWORD dwSize = DWORD(m_filesize); + + DWORD dwPos = XSFTag::SearchRaw(pData, dwSize); + if (!dwPos || dwPos >= dwSize) return; + + m_file->truncate(dwPos, p_abort); + m_file->seek(dwPos, p_abort); + + m_write_UTF8 = p_info.meta_exists("utf8"); + + tag_write("[TAG]", p_abort); + if (m_write_UTF8) + tag_writel("utf8=1\x0a", p_abort); + + /* write play info */ + t_size icnt = p_info.info_get_count(); + for (t_size i = 0; i < icnt; i++) + { + const char *name = p_info.info_enum_name(i); + if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume")) + { + const char *value = p_info.info_enum_value(i); + if (*value) + { + tag_writel(name, p_abort); + tag_writel("=", p_abort); + tag_write(value, p_abort); + tag_writel("\x0a", p_abort); + } + } + } + + /* write meta data */ + t_size mcnt = p_info.meta_get_count(); + for (t_size m = 0; m < mcnt; m++) + { + const char *name = p_info.meta_enum_name(m); + if (!stricmp_utf8(name, "utf8")) + continue; + else if (!stricmp_utf8(name, "album")) + name = "game"; + else if (!stricmp_utf8(name, "date")) + name = "year"; + t_size ncnt = p_info.meta_enum_value_count(m); + for (t_size n = 0; n < ncnt; n++) + { + const char *value = p_info.meta_enum_value(m, n); + if (*value) + { + tag_writel(name, p_abort); + tag_writel("=", p_abort); + tag_write(value, p_abort); + tag_writel("\x0a", p_abort); + } + } + } + + /* write replay gain */ + pfc::array_t rgbuf; + replaygain_info rg = p_info.get_replaygain(); + rgbuf.set_size(rg.text_buffer_size); + + if (rg.m_album_gain > rg.gain_invalid) + { + rg.format_album_gain(rgbuf.get_ptr()); + tag_writel("replaygain_album_gain", p_abort); + tag_writel("=", p_abort); + tag_write(rgbuf.get_ptr(), p_abort); + tag_writel("\x0a", p_abort); + } + if (rg.m_album_peak > rg.peak_invalid) + { + rg.format_album_peak(rgbuf.get_ptr()); + tag_writel("replaygain_album_peak", p_abort); + tag_writel("=", p_abort); + tag_write(rgbuf.get_ptr(), p_abort); + tag_writel("\x0a", p_abort); + } + if (rg.m_track_gain > rg.gain_invalid) + { + rg.format_track_gain(rgbuf.get_ptr()); + tag_writel("replaygain_track_gain", p_abort); + tag_writel("=", p_abort); + tag_write(rgbuf.get_ptr(), p_abort); + tag_writel("\x0a", p_abort); + } + if (rg.m_track_peak > rg.peak_invalid) + { + rg.format_track_peak(rgbuf.get_ptr()); + tag_writel("replaygain_track_peak", p_abort); + tag_writel("=", p_abort); + tag_write(rgbuf.get_ptr(), p_abort); + tag_writel("\x0a", p_abort); + } + m_file->set_eof(p_abort); + } + + void tag_writel(const char *p, abort_callback & p_abort) + { + t_size l = strlen(p); + pfc::array_t lbuf; + lbuf.set_size(l); + char *d = lbuf.get_ptr(); + for (t_size i = 0; i < l; i++) + d[i] = pfc::ascii_tolower(p[i]); + m_file->write(d, l, p_abort); + } + + void tag_writeA(const char *p, t_size l, abort_callback & p_abort) + { + pfc::stringcvt::string_ansi_from_utf8 valuea(p, l); + m_file->write(valuea.get_ptr(), valuea.length(), p_abort); + } + + void tag_write(const char *p, abort_callback & p_abort) + { + t_size l = strlen(p); + pfc::array_t lbuf; + lbuf.set_size(l); + char *d = lbuf.get_ptr(); + for (t_size i = 0; i < l; i++) + { + if (p[i] == 0x0a) + d[i] = ';'; + else if (p[i] > 0x00 && p[i] < 0x20) + d[i] = ' '; + else + d[i] = p[i]; + } + if (m_write_UTF8) + m_file->write(d, l, p_abort); + else + tag_writeA(d, l, p_abort); + } + + void xsf_restart() + { + drv.start(m_filebuffer.get_ptr(), DWORD(m_filebuffer.get_size())); + cur_smp = 0; + } + + void xsf_reopen(service_ptr_t & p_file, abort_callback & p_abort) + { + m_filesize = p_file->get_size_ex(p_abort); + m_filebuffer.set_size(t_size(m_filesize)); + p_file->read(m_filebuffer.get_ptr(), t_size(m_filesize), p_abort); + xsf_reload(); + } + + void xsf_reload(void) + { + xsfc::TString tagvolume = XSFTag::Get("volume", m_filebuffer.get_ptr(), size_t(m_filesize)); + + t_uint32 length = XSFTag::GetLengthMS(m_filebuffer.get_ptr(), size_t(m_filesize), CFGGetDefaultLength()); + t_uint32 fade = XSFTag::GetFadeMS(m_filebuffer.get_ptr(), size_t(m_filesize), CFGGetDefaultFade()); + + m_haslength = XSFTag::Exists("length", m_filebuffer.get_ptr(), size_t(m_filesize)); + + m_volume = 1.0; + m_hasvolume = false; + if (tagvolume[0]) + { + m_volume = tagvolume.GetFloat(); + m_hasvolume = (m_volume != 1.0); + } + + len_smp = t_uint64(length) * xsf_sample_rate / 1000; + fad_smp = t_uint64(fade) * xsf_sample_rate / 1000; + end_smp = len_smp + fad_smp; + } + + void xsf_seek(t_uint64 &seek_smp, abort_callback & p_abort) + { + t_size bufsize = m_buffer.get_size() / xsf_total_sample_width; + if (bufsize < xsf_total_sample_width) + { + bufsize = DEFAULT_BUFFER_SIZE; + m_buffer.set_size(bufsize * xsf_total_sample_width); + } + if (seek_smp < cur_smp) + { + xsf_restart(); + } + while (seek_smp - cur_smp > bufsize) + { + if (p_abort.is_aborting()) + return; + drv.gen(m_buffer.get_ptr(), DWORD(bufsize)); + cur_smp += bufsize; + } + if (seek_smp - cur_smp > 0) + { + drv.gen(m_buffer.get_ptr(), DWORD(seek_smp - cur_smp)); + cur_smp = seek_smp; + } + } + +public: + void open(service_ptr_t p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort) + { + + m_file = p_filehint;//p_filehint may be null, hence next line + input_open_file_helper(m_file,p_path,p_reason,p_abort);//if m_file is null, opens file with appropriate privileges for our operation (read/write for writing tags, read-only otherwise). + + pfc::string8 libpath(p_path, pfc::scan_filename(p_path)); + drv.setlibpath(libpath); + + xsf_reopen(m_file, p_abort); + + if (p_reason == input_open_decode) + xsf_restart(); + } + + void get_info(file_info & p_info,abort_callback & p_abort) + { + (void)p_abort; + p_info.set_length(audio_math::samples_to_time( end_smp, xsf_sample_rate)); + + p_info.info_set_int("samplerate",xsf_sample_rate); + p_info.info_set_int("channels",xsf_channels); + p_info.info_set_int("bitspersample",xsf_bits_per_sample); + p_info.info_set("encoding",FOOBAR2000COMPONENT_ENCODING); + p_info.info_set_bitrate((xsf_bits_per_sample * xsf_channels * xsf_sample_rate + 500 /* rounding for bps to kbps*/ ) / 1000 /* bps to kbps */); + + tagload(p_info); + } + t_filestats get_file_stats(abort_callback & p_abort) {return m_file->get_stats(p_abort);} + + void decode_initialize(unsigned p_flags,abort_callback & p_abort) + { + (void)p_abort; + m_flags = p_flags; + } + + bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort) + { + (void)p_abort; + bool fPlayInfinitely = CFGGetPlayInfinitely() && !(m_flags & input_flag_no_looping) && (m_flags & input_flag_playback); + + if ((cur_smp >= end_smp && !fPlayInfinitely) || (!m_haslength && CFGGetDetectSilenceSec() && CFGGetDetectSilenceSec() <= drv.get_detect_silence())) + { + return false; + } + m_buffer.set_size(DEFAULT_BUFFER_SIZE * xsf_total_sample_width); + t_size bufsize = m_buffer.get_size() / xsf_total_sample_width; + drv.gen(m_buffer.get_ptr(), DWORD(bufsize)); + + if (!fPlayInfinitely && cur_smp + bufsize > end_smp) + bufsize = t_size(end_smp - cur_smp); + + cur_smp += bufsize; + + p_chunk.set_data_fixedpoint(m_buffer.get_ptr(),bufsize * xsf_total_sample_width,xsf_sample_rate,xsf_channels,xsf_bits_per_sample,audio_chunk::g_guess_channel_config(xsf_channels)); + + double cfgvolume = 1; + bool hascfgvolume = (m_flags & input_flag_playback) && CFGGetVolume(cfgvolume); + if (hascfgvolume || m_hasvolume || (!fPlayInfinitely && (fad_smp && cur_smp + bufsize >= len_smp))) + { + audio_sample *psmp = p_chunk.get_data(); + t_uint64 i; + double volume = m_volume * cfgvolume; + for (i = cur_smp; i < cur_smp + bufsize; i++) + { + if (fPlayInfinitely || i < len_smp) + { + psmp[0] = float(psmp[0] * volume); + psmp[1] = float(psmp[1] * volume); + } + else if (i < end_smp) + { + double scale = volume * double(len_smp + fad_smp - i) / double(fad_smp); + psmp[0] = float(psmp[0] * scale); + psmp[1] = float(psmp[1] * scale); + } + else + { + psmp[0] = 0; + psmp[1] = 0; + } + psmp += 2; + } + } + + return true; + } + void decode_seek(double p_seconds,abort_callback & p_abort) + { + if (!decode_can_seek()) + { + throw exception_io_object_not_seekable(); + } + else + { + t_uint64 seek_pos(t_uint64(p_seconds * xsf_sample_rate)); + xsf_seek(seek_pos, p_abort); + } + } + bool decode_can_seek() {return true;} + bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta) { (void)p_out, p_timestamp_delta; return false; } + bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) { (void)p_out, p_timestamp_delta; return false; } + void decode_on_idle(abort_callback & p_abort) { m_file->on_idle(p_abort); } + + void retag(const file_info & p_info,abort_callback & p_abort) + { + tagsave(p_info, p_abort); + + m_file->reopen(p_abort); + xsf_reopen(m_file, p_abort); + } + + static bool g_is_our_content_type(const char * p_content_type) { (void)p_content_type; return false;} + static bool g_is_our_path(const char * p_path,const char * p_extension) { (void)p_path, p_extension; return FOOBAR2000COMPONENT_EXT_CHECK; } +}; + + +static input_singletrack_factory_t g_input_xsf_factory; + +DECLARE_COMPONENT_VERSION(FOOBAR2000COMPONENT_NAME,FOOBAR2000COMPONENT_VERSION,FOOBAR2000COMPONENT_ABOUT); +DECLARE_FILE_TYPE(FOOBAR2000COMPONENT_TYPE,FOOBAR2000COMPONENT_EXTS); + +extern "C" void fb2k_config_init(HINSTANCE hinstDLL); + +BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + hDLL = hModule; + fb2k_config_init(hDLL); + } + else if (ul_reason_for_call == DLL_PROCESS_DETACH) + { + } + return TRUE; +} + + + diff --git a/tools/vio2sf/src/xsfc/foo_input_xsf8.cpp b/tools/vio2sf/src/xsfc/foo_input_xsf8.cpp new file mode 100644 index 000000000..a65f81f63 --- /dev/null +++ b/tools/vio2sf/src/xsfc/foo_input_xsf8.cpp @@ -0,0 +1,709 @@ +#include "foobar2000/SDK/foobar2000.h" + +#include "../pversion.h" + +#include "../loadpe/loadpe.h" +#include "xsfdrv.h" + +#include "tagget.h" +#include "xsfcfg.h" + +enum +{ + xsf_bits_per_sample = 16, + xsf_channels = 2, +#ifndef XSFDRIVER_SAMPLERATE + xsf_sample_rate = 44100, +#else + xsf_sample_rate = XSFDRIVER_SAMPLERATE, +#endif + + xsf_bytes_per_sample = xsf_bits_per_sample / 8, + xsf_total_sample_width = xsf_bytes_per_sample * xsf_channels +}; + +#define DEFAULT_BUFFER_SIZE (1024) + +#define CHECK_SILENCE_BIAS 0x8000000 +#ifndef CHECK_SILENCE_LEVEL +#define CHECK_SILENCE_LEVEL 7 +#endif + +typedef signed short xsfsample_t; + +static HMODULE hDLL; + +class ReaderHolder +{ + void Free() + { + if (ptr) + { + ptr->reader_release(); + ptr = 0; + } + } +public: + reader *ptr; + ReaderHolder(reader *p = 0) + : ptr(p) + { + } + ~ReaderHolder() + { + Free(); + } + reader *GetReader() + { + return ptr; + } + void SetReader(reader * p) + { + Free(); + ptr = p; + } + bool Open(const xsfc::TString &fn) + { + SetReader(file::g_open(xsfc::TStringM(true, fn), reader::MODE_READ)); + return ptr != 0; + } +}; + +class xsf_drv +{ +protected: + void *lpDrv; + IXSFDRV *lpif; + xsfc::TString m_libpath; + bool m_genok; + + unsigned detectedSilenceSec; + unsigned detectedSilenceSample; + unsigned skipSilenceOnStartSec; + unsigned long prevSampleL; + unsigned long prevSampleR; + +public: + bool isUTF8; + + xsf_drv() + { + m_genok = false; + isUTF8 = false; + lpDrv = 0; + lpif = 0; + } + + ~xsf_drv() + { + freeDrv(); + } + void setlibpath(const xsfc::TString &p_libpath) + { + m_libpath = p_libpath; + } + + void start(void *p, DWORD l) + { + if (loadDrv()) + { + if (lpif->dwInterfaceVersion >= 3) + { + lpif->SetExtendParam(1, CFGGetExtendParam1()); + lpif->SetExtendParam(2, CFGGetExtendParam2()); + } + m_genok = !lpif->Start(p, l); + } + + skipSilenceOnStartSec = CFGGetSkipSilenceOnStartSec(); + + detectedSilenceSec = 0; + detectedSilenceSample = 0; + + prevSampleL = CHECK_SILENCE_BIAS; + prevSampleR = CHECK_SILENCE_BIAS; + } + + unsigned long get_detect_silence() + { + return detectedSilenceSec; + } + + int gen(void *pbuf, unsigned bufsize) + { + if (!lpif) return 0; + if (!m_genok) return 0; + + xsfsample_t *ptop = static_cast(pbuf); + unsigned detectSilence = CFGGetDetectSilenceSec(); + unsigned pos = 0; + + if (lpif->dwInterfaceVersion >= 2) + { + bool output = false; + for (int i = 0; i < 4; i++) + { + unsigned long mute = CFGGetChannelMute(i); + output |= (mute != ~unsigned long(0)); + lpif->SetChannelMute(i, mute); + } + if (!output) detectSilence = 0; + } + + while (pos < bufsize) + { + unsigned ofs; + xsfsample_t *pblk = ptop + (pos << 1); + unsigned remain = bufsize - pos; + lpif->Gen(pblk, remain); + if (detectSilence || skipSilenceOnStartSec) + { + xsfsample_t *pskp = 0; + xsfsample_t *pcur = pblk; + for (ofs = 0; ofs < remain; ofs++) + { + long smpl = pcur[0]; + long smpr = pcur[1]; + bool silence = (((unsigned long)(smpl + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleL <= (CHECK_SILENCE_LEVEL) * 2) && (((unsigned long)(smpr + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleR <= (CHECK_SILENCE_LEVEL) * 2); + + if (silence) + { + if (++detectedSilenceSample >= xsf_sample_rate) + { + detectedSilenceSample -= xsf_sample_rate; + detectedSilenceSec++; + if (skipSilenceOnStartSec && detectedSilenceSec >= skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + detectedSilenceSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + } + else + { + detectedSilenceSample = 0; + detectedSilenceSec = 0; + if (skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + prevSampleL = smpl + CHECK_SILENCE_BIAS; + prevSampleR = smpr + CHECK_SILENCE_BIAS; + pcur += 2; + } + if (skipSilenceOnStartSec) + { + } + else if (pskp) + { + while (pskp < pcur) + { + *(pblk++)= *(pskp++); + *(pblk++)= *(pskp++); + pos++; + } + } + else + { + pos += remain; + } + } + else + { + pos += remain; + } + } + return bufsize; + } + + + void stop() + { + if (!lpif) return; + lpif->Term(); + m_genok = false; + } + + +protected: + bool aogetlib(xsfc::TString filename, void **ppBuffer, DWORD *pdwSize) + { + if (!lpif) return false; + ReaderHolder xsflib; + xsfc::TString path = xsfc::TWin32::CanonicalizePath(m_libpath + filename); + if (!xsflib.Open(path)) return false; + __int64 filesize64 = xsflib.GetReader()->get_length(); + DWORD dwfilesize = DWORD(filesize64); + if (filesize64 == -1 || filesize64 != dwfilesize) return false; + void *ret = lpif->LibAlloc(dwfilesize); + if (!ret) return false; + xsflib.GetReader()->read(ret, dwfilesize); + *ppBuffer = ret; + *pdwSize = dwfilesize; + return true; + } + static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize) + { + xsf_drv *pthis = static_cast(lpWork); + xsfc::TString filename; + if (pthis->isUTF8) + { + filename = xsfc::TString(true, lpszFilename); + } + else + { + filename = xsfc::TString(false, lpszFilename); + } + return pthis->aogetlib(filename, ppBuffer, pdwSize) ? 0 : 1; + } + bool loadDrv(void) + { + if (lpif) return true; + xsfc::TString binpath = xsfc::TWin32::ExtractPath(xsfc::TWin32::ModulePath(hDLL)) + XSFDRIVER_MODULENAME; + + if (xsfc::TWin32::IsUnicodeSupportedOS()) + { + lpDrv = XLoadLibraryW(binpath); + } + else + { + lpDrv = XLoadLibraryA(xsfc::TStringM(binpath)); + } + if (!lpDrv) return false; + + LPFNXSFDRVSETUP xsfsetup = (LPFNXSFDRVSETUP)XGetProcAddress(lpDrv, XSFDRIVER_ENTRYNAME); + if (!xsfsetup) + { + XFreeLibrary(lpDrv); + lpDrv = 0; + return false; + } + + lpif = xsfsetup(XSFGETLIBCALLBACK, this); + return true; + } + + void freeDrv(void) + { + if (lpif) + { + lpif->Term(); + lpif = 0; + } + if (lpDrv) + { + XFreeLibrary(lpDrv); + lpDrv = 0; + } + } +}; + +class input_xsf : public input_pcm +{ +protected: + typedef signed short audio_sample_t; + typedef __int64 t_size; + typedef unsigned __int64 t_uint64; + xsf_drv drv; + array_t m_filebuffer; + t_size m_filesize; + t_uint64 cur_smp; + t_uint64 len_smp; + t_uint64 fad_smp; + t_uint64 end_smp; + + array_t m_buffer; + + double m_volume; + bool m_hasvolume; + bool m_haslength; + + bool m_write_UTF8; + unsigned m_flags; + + typedef struct + { + class input_xsf *pThis; + file_info * p_info; + bool isUTF8; + } tagloadcbwork; + + void tagloadsub(file_info & p_info, const char *name, const xsfc::TStringM &value) + { + if (!stricmp_utf8(name, "game")) + p_info.meta_add("album", value); + else if (!stricmp_utf8(name, "year")) + p_info.meta_add("date", value); + else if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume")) + p_info.info_set(name, value); + else if (!stricmp_utf8(name, "replaygain_track_gain")) + { + p_info.info_set_replaygain_track_gain(pfc_string_to_float(value)); + } + else if (!stricmp_utf8(name, "replaygain_track_peak")) + { + p_info.info_set_replaygain_track_peak(pfc_string_to_float(value)); + } + else if (!stricmp_utf8(name, "replaygain_album_gain")) + { + p_info.info_set_replaygain_album_gain(pfc_string_to_float(value)); + } + else if (!stricmp_utf8(name, "replaygain_album_peak")) + { + p_info.info_set_replaygain_album_peak(pfc_string_to_float(value)); + } + else + p_info.meta_add(name, value); + } + + static enum XSFTag::enum_callback_returnvalue tagloadcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + if (pNameTop == pNameEnd) return XSFTag::enum_continue; + + tagloadcbwork *pcbwork = static_cast(pWork); + + xsfc::TString name; + xsfc::TString value; + + if (pcbwork->isUTF8) + { + name = xsfc::TString(true, pNameTop, pNameEnd - pNameTop); + value = xsfc::TString(true, pValueTop, pValueEnd - pValueTop); + } + else + { + name = xsfc::TString(false, pNameTop, pNameEnd - pNameTop); + value = xsfc::TString(false, pValueTop, pValueEnd - pValueTop); + } + + pcbwork->pThis->tagloadsub(*pcbwork->p_info, xsfc::TStringM(true, name), xsfc::TStringM(true, value)); + return XSFTag::enum_continue; + } + + void tagload(file_info & p_info) + { + BYTE *pData = &m_filebuffer[0]; + DWORD dwSize = DWORD(m_filesize); + bool isUTF8 = XSFTag::Exists("utf8", pData, dwSize); + drv.isUTF8 = isUTF8; + + tagloadcbwork cbwork; + cbwork.isUTF8 = isUTF8; + cbwork.pThis = this; + cbwork.p_info= &p_info; + XSFTag::Enum(tagloadcb, &cbwork, pData, dwSize); + return; + } + + bool tag_writel(const char *p, reader *r) + { + string8 value; + value.convert_to_lower_ascii(p); + const char *pL = value.get_ptr(); + t_size lL = strlen(p); + return r->write(pL, lL) == lL; + } + + bool tag_writeA(const char *p, t_size l, reader *r) + { + xsfc::TString value(true, p, l); + xsfc::TStringM valueA(false, value); + const char *pA = valueA; + t_size lA = strlen(pA); + return r->write(pA, lA) == lA; + } + + bool tag_writeU(const char *p, t_size l, reader *r) + { + return r->write(p, l) == l; + } + + bool tag_write(const char *p, reader *r) + { + t_size l = strlen(p); + array_t lbuf; + if (!lbuf.resize(l)) return false; + char *d = &lbuf[0]; + for (t_size i = 0; i < l; i++) + { + if (p[i] == 0x0a) + d[i] = ';'; + else if (p[i] > 0x00 && p[i] < 0x20) + d[i] = ' '; + else + d[i] = p[i]; + } + return (m_write_UTF8) ? tag_writeU(d, l, r) : tag_writeA(d, l, r); + } + + bool tagsave(reader *r, const file_info & p_info) + { + BYTE *pData = &m_filebuffer[0]; + DWORD dwSize = DWORD(m_filesize); + + DWORD dwPos = XSFTag::SearchRaw(pData, dwSize); + if (!dwPos || dwPos >= dwSize) return false; + + if (!r->seek(dwPos)) return false; + + m_write_UTF8 = p_info.meta_get_count_by_name("utf8") > 0; + + tag_write("[TAG]", r); + if (m_write_UTF8) + tag_writel("utf8=1\x0a", r); + + /* write play info */ + t_size icnt = p_info.info_get_count(); + for (t_size i = 0; i < icnt; i++) + { + const char *name = p_info.info_enum_name(i); + if (!_strnicmp(name, "_lib", 4) || !stricmp_utf8(name, "fade") || !stricmp_utf8(name, "length") || !stricmp_utf8(name, "volume") || !stricmp_utf8(name, "replaygain_album_gain") || !stricmp_utf8(name, "replaygain_album_peak") || !stricmp_utf8(name, "replaygain_track_gain") || !stricmp_utf8(name, "replaygain_track_peak")) + { + const char *value = p_info.info_enum_value(i); + if (*value) + { + tag_writel(name, r); + tag_writel("=", r); + tag_write(value, r); + tag_writel("\x0a", r); + } + } + } + + /* write meta data */ + t_size mcnt = p_info.meta_get_count(); + for (t_size m = 0; m < mcnt; m++) + { + const char *name = p_info.meta_enum_name(m); + if (!stricmp_utf8(name, "utf8")) + continue; + else if (!stricmp_utf8(name, "album")) + name = "game"; + else if (!stricmp_utf8(name, "date")) + name = "year"; + const char *value = p_info.meta_enum_value(m); + if (*value) + { + tag_writel(name, r); + tag_writel("=", r); + tag_write(value, r); + tag_writel("\x0a", r); + } + } + + r->set_eof(); + return true; + } + + void xsf_restart() + { + drv.start(&m_filebuffer[0], DWORD(m_filebuffer.size())); + cur_smp = 0; + } + + bool xsf_reopen(reader *r) + { + m_filesize = r->get_length(); + t_size l = t_size(m_filesize); + if (!m_filebuffer.resize(t_size(m_filesize))) return false; + return r->read(&m_filebuffer[0], l) == l; + } + + void xsf_reload(void) + { + xsfc::TString tagvolume = XSFTag::Get("volume", &m_filebuffer[0], size_t(m_filesize)) ; + + unsigned length = XSFTag::GetLengthMS(&m_filebuffer[0], size_t(m_filesize), CFGGetDefaultLength()); + unsigned fade = XSFTag::GetFadeMS(&m_filebuffer[0], size_t(m_filesize), CFGGetDefaultFade()); + + m_haslength = XSFTag::Exists("length", &m_filebuffer[0], size_t(m_filesize)); + + m_volume = 1.0; + m_hasvolume = false; + if (tagvolume[0]) + { + m_volume = tagvolume.GetFloat(); + m_hasvolume = (m_volume != 1.0); + } + + len_smp = t_uint64(length) * xsf_sample_rate / 1000; + fad_smp = t_uint64(fade) * xsf_sample_rate / 1000; + end_smp = len_smp + fad_smp; + } + + void xsf_seek(t_uint64 &seek_smp) + { + t_size bufsize = m_buffer.size() / xsf_total_sample_width; + if (bufsize < xsf_total_sample_width) + { + bufsize = DEFAULT_BUFFER_SIZE; + m_buffer.resize(bufsize * xsf_total_sample_width); + } + if (seek_smp < cur_smp) + { + xsf_restart(); + } + while (seek_smp - cur_smp > bufsize) + { + drv.gen(&m_buffer[0], DWORD(bufsize)); + cur_smp += bufsize; + } + if (seek_smp - cur_smp > 0) + { + drv.gen(&m_buffer[0], DWORD(seek_smp - cur_smp)); + cur_smp = seek_smp; + } + } + +public: + void get_info(file_info & p_info) + { + p_info.set_length(::MulDiv(end_smp, 1, xsf_sample_rate)); + + p_info.info_set_int("samplerate",xsf_sample_rate); + p_info.info_set_int("channels",xsf_channels); + p_info.info_set_int("bitspersample",xsf_bits_per_sample); + p_info.info_set("encoding",FOOBAR2000COMPONENT_ENCODING); + p_info.info_set_bitrate((xsf_bits_per_sample * xsf_channels * xsf_sample_rate + 500 /* rounding for bps to kbps*/ ) / 1000 /* bps to kbps */); + + tagload(p_info); + } + + bool open(reader * r,file_info * info,unsigned flags) + { + m_flags = flags; + xsf_reopen(r); + xsf_reload(); + + if( flags & input::OPEN_FLAG_GET_INFO) + get_info(*info); + + if (flags & input::OPEN_FLAG_DECODE) + { + const char *playpathutf8 = info->get_file_path(); + xsfc::TString playpath(true, playpathutf8); + xsfc::TString libpath = xsfc::TWin32::ExtractPath(playpath); + drv.setlibpath(libpath); + xsf_restart(); + } + return true; + } + + inline audio_sample_t clip_mul(signed s1, double s2) + { + double r = s1 * s2; + if (r > 0x7fff) + r = 0x7fff; + else if (r < -0x8000) + r = -0x8000; + return audio_sample_t(r); + } + + int get_samples_pcm(void ** out_buffer,int * out_size, int * srate, int * bps, int * nch) + { + bool fPlayInfinitely = CFGGetPlayInfinitely() && !(m_flags & OPEN_FLAG_NO_LOOPING); + + if ((cur_smp >= end_smp && !fPlayInfinitely) || (!m_haslength && CFGGetDetectSilenceSec() && CFGGetDetectSilenceSec() <= drv.get_detect_silence())) + { + return false; + } + unsigned reqssize = DEFAULT_BUFFER_SIZE * xsf_total_sample_width; + if (m_buffer.size() < reqssize && !m_buffer.resize(reqssize)) + return false; + + t_size bufsize = m_buffer.size() / xsf_total_sample_width; + drv.gen(&m_buffer[0], DWORD(bufsize)); + + if (!fPlayInfinitely && cur_smp + bufsize > end_smp) + bufsize = t_size(end_smp - cur_smp); + + *out_buffer = &m_buffer[0]; + *out_size = bufsize * xsf_total_sample_width; + *srate = xsf_sample_rate; + *bps = xsf_bits_per_sample; + *nch = xsf_channels; + + cur_smp += bufsize; + + double cfgvolume = 1; + bool hascfgvolume = CFGGetVolume(cfgvolume); + if (hascfgvolume || m_hasvolume || (!fPlayInfinitely && (fad_smp && cur_smp + bufsize >= len_smp))) + { + audio_sample_t *psmp = (audio_sample_t *)&m_buffer[0]; + t_uint64 i; + double volume = m_volume * cfgvolume; + for (i = cur_smp; i < cur_smp + bufsize; i++) + { + if (fPlayInfinitely || i < len_smp) + { + psmp[0] = clip_mul(psmp[0] , volume); + psmp[1] = clip_mul(psmp[1] , volume); + } + else if (i < end_smp) + { + double scale = volume * double(__int64(len_smp + fad_smp - i)) / double(__int64(fad_smp)); + psmp[0] = clip_mul(psmp[0] , scale); + psmp[1] = clip_mul(psmp[1] , scale); + } + else + { + psmp[0] = 0; + psmp[1] = 0; + } + psmp += 2; + } + } + + return true; + } + + bool can_seek() {return true;} + + bool seek(double p_seconds) + { + if (can_seek()) + { + t_uint64 seek_pos(t_uint64(p_seconds * xsf_sample_rate)); + xsf_seek(seek_pos); + return true; + } + return false; + } + + bool is_our_content_type(const char * url,const char * type) { (void)url, type; return false;} + bool test_filename(const char * p_path,const char * p_extension) { (void)p_path, p_extension; return FOOBAR2000COMPONENT_EXT_CHECK; } + + set_info_t set_info(reader *r, const file_info * info) + { + xsf_reopen(r); + return tagsave(r, *info) ? SET_INFO_SUCCESS : SET_INFO_FAILURE; + } + +}; + + +static input_factory g_input_xsf_factory; + +DECLARE_COMPONENT_VERSION(FOOBAR2000COMPONENT_NAME,FOOBAR2000COMPONENT_VERSION,FOOBAR2000COMPONENT_ABOUT); +DECLARE_FILE_TYPE(FOOBAR2000COMPONENT_TYPE,FOOBAR2000COMPONENT_EXTS); + +extern "C" void fb2k_config_init(HINSTANCE hinstDLL); + +BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + hDLL = hModule; + fb2k_config_init(hDLL); + } + else if (ul_reason_for_call == DLL_PROCESS_DETACH) + { + } + return TRUE; +} + + + diff --git a/tools/vio2sf/src/xsfc/foo_input_xsfcfg.cpp b/tools/vio2sf/src/xsfc/foo_input_xsfcfg.cpp new file mode 100644 index 000000000..0a3f7dd43 --- /dev/null +++ b/tools/vio2sf/src/xsfc/foo_input_xsfcfg.cpp @@ -0,0 +1,269 @@ +#include "leakchk.h" + +#include "foobar2000/SDK/foobar2000.h" + +#include "../pversion.h" + +#include "tagget.h" +#include "xsfcfg.h" + +namespace +{ + +HMODULE hDLL; + +const GUID cfgguid1 = XSFDRIVER_GUID1; +const GUID cfgguid2 = XSFDRIVER_GUID2; +cfg_string cfg_fooxsf(cfgguid2, ""); + +class foo_config : public IConfigIO +{ +protected: + typedef struct + { + xsfc::TString output; + xsfc::TString newvalue; + xsfc::TStringM newname; + size_t newnamelen; + bool exist; + } + cbw_t; + + static enum XSFTag::enum_callback_returnvalue scv_cb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + cbw_t *pcbw = static_cast(pWork); + xsfc::TString name(true, pNameTop, pNameEnd - pNameTop); + if (pcbw->newnamelen == pNameEnd - pNameTop && !_strnicmp(pNameTop, pcbw->newname, pcbw->newnamelen)) + { + pcbw->exist = true; + pcbw->output = pcbw->output + name + xsfc::TString(L"=") + pcbw->newvalue + xsfc::TString(L"\n"); + } + else + { + xsfc::TString value(true, pValueTop, pValueEnd - pValueTop); + pcbw->output = pcbw->output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n"); + } + return XSFTag::enum_continue; + } + + void SetConfigValue(const wchar_t *name, xsfc::TString value) + { + const char *idata = cfg_fooxsf.get_ptr(); + size_t isize = xsfc::StrNLen(idata); + cbw_t cbw; + cbw.newvalue = value; + cbw.newname = xsfc::TStringM(true, name); + cbw.newnamelen = xsfc::StrNLen(cbw.newname); + cbw.exist = false; + XSFTag::EnumRaw(scv_cb, &cbw, idata, isize); + if (!cbw.exist) + { + cbw.output = cbw.output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n"); + } + xsfc::TStringM oututf8(true, cbw.output); + cfg_fooxsf = oututf8; + } + + xsfc::TString GetConfigValue(const wchar_t *name) + { + xsfc::TStringM tag(true, name); + const char *idata = cfg_fooxsf.get_ptr(); + size_t isize = xsfc::StrNLen(idata); + return XSFTag::GetRaw(true, tag, idata, isize); + } + +public: + foo_config() + { + } + ~foo_config() + { + } + + void SetULong(const wchar_t *name, const unsigned long value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw() + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value.GetULong(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetFloat(const wchar_t *name, const double value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw() + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value.GetFloat(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetString(const wchar_t *name, const wchar_t *value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw() + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value; + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } +}; + +static foo_config icfg; + +class foo_input_xsfcfg : public preferences_page_v2 +{ +protected: + bool initialized; + foo_config *pcfg; + HWND hwnd; + + bool OnCommand(HWND hwndDlg, DWORD id, DWORD cmd) + { + switch (id) + { + case 0x200: case 0x201: case 0x202: + case 0x203: case 0x204: case 0x205: + if (initialized) + { + CFGUpdate(pcfg, hwndDlg); + CFGSave(pcfg); + } + break; + case 0x206: + if (cmd == LBN_SELCHANGE) + { + CFGMuteChange(hwndDlg, 0x206); + } + break; + default: + break; + } + return FALSE; + } + + bool OnInit(HWND hwndDlg) + { + hwnd = hwndDlg; + pcfg = &icfg; + xsfc::TWin32::WndSetLongPtr(hwndDlg, DWLP_USER, this); + + initialized = false; + CFGReset(pcfg, hwndDlg); + initialized = true; + return TRUE; + } + + static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + { + foo_input_xsfcfg *pthis = static_cast(xsfc::TWin32::WndGetLongPtr(hwndDlg, DWLP_USER)); + return pthis->OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam)); + } + + case WM_INITDIALOG: + { + foo_input_xsfcfg *pthis = static_cast((void *)lParam); + return pthis->OnInit(hwndDlg) ? TRUE : FALSE; + } + } + return FALSE; + } + +public: + HWND create(HWND p_parent) + { + return static_cast(xsfc::TWin32::DlgCreate(hDLL, 1, p_parent, DialogProc, this)); + } + const char * get_name() { return XSFDRIVER_SIMPLENAME; } + GUID get_guid() { return cfgguid1; } + GUID get_parent_guid() { return guid_input; } + bool reset_query() { return true; } + void reset() + { + CFGDefault(); + CFGReset(pcfg, hwnd); + CFGSave(pcfg); + } + bool get_help_url(pfc::string_base & p_out) { return false; } + double get_sort_priority() { return 0; } + + foo_input_xsfcfg() + : initialized(false) + { + } + ~foo_input_xsfcfg() + { + } +}; + +class foo_initquit : public initquit +{ + void on_init() + { + CFGLoad(&icfg); + } + void on_quit() + { + } +}; + +static preferences_page_factory_t g_input_xsfcfg_factory; + +static initquit_factory_t g_input_xsfiq_factory; + +} + + +extern "C" void fb2k_config_init(HINSTANCE hinstDLL) +{ + hDLL = (HMODULE)hinstDLL; +} diff --git a/tools/vio2sf/src/xsfc/foo_input_xsfcfg8.cpp b/tools/vio2sf/src/xsfc/foo_input_xsfcfg8.cpp new file mode 100644 index 000000000..73802e45d --- /dev/null +++ b/tools/vio2sf/src/xsfc/foo_input_xsfcfg8.cpp @@ -0,0 +1,255 @@ +#include "foobar2000/SDK/foobar2000.h" + +#include "../pversion.h" + +#include "tagget.h" +#include "xsfcfg.h" + +namespace +{ + +HMODULE hDLL; + +cfg_string cfg_fooxsf(XSFDRIVER_SIMPLENAME "/config", ""); + +class foo_config : public IConfigIO +{ +protected: + typedef struct + { + xsfc::TString output; + xsfc::TString newvalue; + xsfc::TStringM newname; + size_t newnamelen; + bool exist; + } + cbw_t; + + static enum XSFTag::enum_callback_returnvalue scv_cb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + cbw_t *pcbw = static_cast(pWork); + xsfc::TString name(true, pNameTop, pNameEnd - pNameTop); + if (pcbw->newnamelen == unsigned(pNameEnd - pNameTop) && !_strnicmp(pNameTop, pcbw->newname, pcbw->newnamelen)) + { + pcbw->exist = true; + pcbw->output = pcbw->output + name + xsfc::TString(L"=") + pcbw->newvalue + xsfc::TString(L"\n"); + } + else + { + xsfc::TString value(true, pValueTop, pValueEnd - pValueTop); + pcbw->output = pcbw->output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n"); + } + return XSFTag::enum_continue; + } + + void SetConfigValue(const wchar_t *name, xsfc::TString value) + { + const char *idata = cfg_fooxsf.get_val(); + size_t isize = xsfc::StrNLen(idata); + cbw_t cbw; + cbw.newvalue = value; + cbw.newname = xsfc::TStringM(true, name); + cbw.newnamelen = xsfc::StrNLen(cbw.newname); + cbw.exist = false; + XSFTag::EnumRaw(scv_cb, &cbw, idata, isize); + if (!cbw.exist) + { + cbw.output = cbw.output + name + xsfc::TString(L"=") + value + xsfc::TString(L"\n"); + } + xsfc::TStringM oututf8(true, cbw.output); + cfg_fooxsf = oututf8; + } + + xsfc::TString GetConfigValue(const wchar_t *name) + { + xsfc::TStringM tag(true, name); + const char *idata = cfg_fooxsf.get_val(); + size_t isize = xsfc::StrNLen(idata); + return XSFTag::GetRaw(true, tag, idata, isize); + } + +public: + foo_config() + { + } + ~foo_config() + { + } + + void SetULong(const wchar_t *name, const unsigned long value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw() + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value.GetULong(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetFloat(const wchar_t *name, const double value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw() + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value.GetFloat(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetString(const wchar_t *name, const wchar_t *value) throw() + { + try + { + xsfc::TString sValue(value); + SetConfigValue(name, sValue); + } + catch (xsfc::EShortOfMemory e) + { + } + } + xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) + { + try + { + xsfc::TString value = GetConfigValue(name); + if (value[0]) + return value; + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } +}; + +static foo_config icfg; + +class foo_input_xsfcfg : public config +{ +protected: + bool initialized; + foo_config *pcfg; + HWND hwnd; + + bool OnCommand(HWND hwndDlg, DWORD id, DWORD cmd) + { + switch (id) + { + case 0x200: case 0x201: case 0x202: + case 0x203: case 0x204: case 0x205: + if (initialized) + { + CFGUpdate(pcfg, hwndDlg); + CFGSave(pcfg); + } + break; + case 0x206: + if (cmd == LBN_SELCHANGE) + { + CFGMuteChange(hwndDlg, 0x206); + } + break; + default: + break; + } + return FALSE; + } + + bool OnInit(HWND hwndDlg) + { + hwnd = hwndDlg; + pcfg = &icfg; + xsfc::TWin32::WndSetLongPtr(hwndDlg, DWL_USER, this); + + initialized = false; + CFGReset(pcfg, hwndDlg); + initialized = true; + return TRUE; + } + + static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case WM_COMMAND: + { + foo_input_xsfcfg *pthis = static_cast(xsfc::TWin32::WndGetLongPtr(hwndDlg, DWL_USER)); + return pthis->OnCommand(hwndDlg, LOWORD(wParam), HIWORD(wParam)); + } + + case WM_INITDIALOG: + { + foo_input_xsfcfg *pthis = static_cast((void *)lParam); + return pthis->OnInit(hwndDlg) ? TRUE : FALSE; + } + } + return FALSE; + } + +public: + HWND create(HWND p_parent) + { + return (HWND)xsfc::TWin32::DlgCreate(hDLL, 1, p_parent, DialogProc, this); + } + const char * get_name() { return XSFDRIVER_SIMPLENAME; } + const char * get_parent_name() {return "Input";} + + foo_input_xsfcfg() + : initialized(false) + { + } + ~foo_input_xsfcfg() + { + } +}; + +class foo_initquit : public initquit +{ + void on_init() + { + CFGLoad(&icfg); + } + void on_quit() + { + } +}; + +static config_factory g_input_xsfcfg_factory; + +static initquit_factory g_input_xsfiq_factory; + +} + + +extern "C" void fb2k_config_init(HINSTANCE hinstDLL) +{ + hDLL = (HMODULE)hinstDLL; +} diff --git a/tools/vio2sf/src/xsfc/in_xsf.cpp b/tools/vio2sf/src/xsfc/in_xsf.cpp new file mode 100644 index 000000000..29b6b9b41 --- /dev/null +++ b/tools/vio2sf/src/xsfc/in_xsf.cpp @@ -0,0 +1,1964 @@ +extern unsigned long dwInterpolation; + +#ifndef ENABLE_UNICODE_PLUGIN +#define ENABLE_UNICODE_PLUGIN 0 +#endif +#ifndef ENABLE_GETEXTENDINFO +#define ENABLE_GETEXTENDINFO 1 +#endif +#ifndef ENABLE_GETEXTENDINFOW +#define ENABLE_GETEXTENDINFOW 1 +#endif +#ifndef ENABLE_TAGWRITER +#define ENABLE_TAGWRITER 1 +#endif +#ifndef ENABLE_EXTENDREADER +#define ENABLE_EXTENDREADER 1 +#endif + +#define WIN32_LEAN_AND_MEAN +#define NOGDI +#include "leakchk.h" + +#include +#include +#include +#include + +#if _MSC_VER >= 1400 +#include +#endif + +#if ENABLE_UNICODE_PLUGIN +#define UNICODE_INPUT_PLUGIN +#else +#undef UNICODE_INPUT_PLUGIN +#endif + +/* Winamp SDK headers */ +#include +#include + +#if !defined(_DEBUG) +#include "../loadpe/loadpe.h" +#else +#define XLoadLibraryW LoadLibraryW +#define XLoadLibraryA LoadLibraryA +#define XGetProcAddress(h,n) GetProcAddress((HMODULE)h,n) +#define XFreeLibrary(h) FreeLibrary((HMODULE)h) +#endif + +#include "xsfdrv.h" + +#include "../pversion.h" +#include "tagget.h" + +#include "in_xsfcfg.h" + +#if _MSC_VER >= 1200 +#pragma comment(linker, "/EXPORT:winampGetInModule2=_winampGetInModule2") + +#if ENABLE_GETEXTENDINFO +#pragma comment(linker, "/EXPORT:winampGetExtendedFileInfo=_winampGetExtendedFileInfo") +#endif + +#if ENABLE_GETEXTENDINFOW +#pragma comment(linker, "/EXPORT:winampGetExtendedFileInfoW=_winampGetExtendedFileInfoW") +#endif + +#if ENABLE_TAGWRITER +#pragma comment(linker, "/EXPORT:winampSetExtendedFileInfo=_winampSetExtendedFileInfo") +#pragma comment(linker, "/EXPORT:winampSetExtendedFileInfoW=_winampSetExtendedFileInfoW") +#pragma comment(linker, "/EXPORT:winampWriteExtendedFileInfo=_winampWriteExtendedFileInfo") +#endif + +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW || ENABLE_TAGWRITER +#pragma comment(linker, "/EXPORT:winampUseUnifiedFileInfoDlg=_winampUseUnifiedFileInfoDlg") +#pragma comment(linker, "/EXPORT:winampAddUnifiedFileInfoPane=_winampAddUnifiedFileInfoPane") +#endif + +#if ENABLE_EXTENDREADER +#ifdef UNICODE_INPUT_PLUGIN +#pragma comment(linker, "/EXPORT:winampGetExtendedRead_openW=_winampGetExtendedRead_openW") +#else +#pragma comment(linker, "/EXPORT:winampGetExtendedRead_open=_winampGetExtendedRead_open") +#endif +#pragma comment(linker, "/EXPORT:winampGetExtendedRead_getData=_winampGetExtendedRead_getData") +#pragma comment(linker, "/EXPORT:winampGetExtendedRead_setTime=_winampGetExtendedRead_setTime") +#pragma comment(linker, "/EXPORT:winampGetExtendedRead_close=_winampGetExtendedRead_close") +#endif + +#endif + +#if defined(_MSC_VER) && !defined(_DEBUG) +#pragma comment(linker,"/MERGE:.rdata=.text") +#endif + +namespace +{ + +#define CHECK_SILENCE_BIAS 0x8000000 +#ifndef CHECK_SILENCE_LEVEL +#define CHECK_SILENCE_LEVEL 7 +#endif + +#define SIZE_OF_BUFFER (576 * 4) + +typedef signed short xsfsample_t; + +static void wstrncpychk(wchar_t *d, const wchar_t *s, size_t m) +{ + size_t l = wcslen(s) + 1; + wcsncpy(d, s, (l > m) ? m : l); +} + +static void mstrncpychk(char *d, const char *s, size_t m) +{ + size_t l = strlen(s) + 1; + strncpy(d, s, (l > m) ? m : l); +} + +static void icsncpy(in_char *d, const in_char *s, size_t m) +{ +#if _MSC_VER >= 1200 +#ifndef STATUS_ACCESS_VIOLATION +#define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L) +#endif + __try + { +#endif +#ifdef UNICODE_INPUT_PLUGIN + wstrncpychk(d, s, m); +#else + mstrncpychk(d, s, m); +#endif +#if _MSC_VER >= 1200 + } + __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION) + { + } +#endif +} + +class XSFDriver +{ +public: + + IXSFDRV *lpif; + + xsfc::TAutoBuffer xsfdata; + + unsigned cur_smp; + unsigned len_smp; + unsigned fad_smp; + + int hasvolume; + bool haslength; + float volume; + enum + { +#ifndef XSFDRIVER_SAMPLERATE + samplerate = 44100, +#else + samplerate = XSFDRIVER_SAMPLERATE, +#endif + samplebits = 16, + ch = 2, + blockshift = 2, + }; + int length_in_ms; int fade_in_ms; + + volatile unsigned seek_pos; + volatile int seek_req; + volatile int seek_kil; + +protected: + unsigned detectedSilenceSec; + unsigned detectedSilenceSample; + unsigned skipSilenceOnStartSec; + unsigned long prevSampleL; + unsigned long prevSampleR; + + void *hDriver; + xsfc::TString sLibBasePath; + bool fUTF8; + + static void *liballoc_cb(void *pwork, size_t s) + { + IXSFDRV *lpif = static_cast(pwork); + return lpif->LibAlloc(DWORD(s)); + } + static void libfree_cb(void *pwork, void *p) + { + IXSFDRV *lpif = static_cast(pwork); + lpif->LibFree(p); + } + + static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize) + { + XSFDriver *lpDrv = static_cast(lpWork); + + size_t libsize; + xsfc::TString sLibName = xsfc::TString(lpDrv->fUTF8, lpszFilename); + + void *libdata = xsfc::TWin32::LoadEx(xsfc::TWin32::CanonicalizePath(lpDrv->sLibBasePath + sLibName), libsize, lpDrv->lpif, liballoc_cb, libfree_cb); + if (!libdata) + { + /* in_zip.dll */ + libdata = xsfc::TWin32::LoadEx(lpDrv->sLibBasePath + xsfc::TWin32::ExtractFileName(sLibName), libsize, lpDrv->lpif, liballoc_cb, libfree_cb); + } + if (!libdata) + return 1; + + *ppBuffer = libdata; + *pdwSize = DWORD(libsize); + + return 0; + } + + void SeekTop() + { + cur_smp = 0; + + skipSilenceOnStartSec = CFGGetSkipSilenceOnStartSec(); + + detectedSilenceSec = 0; + detectedSilenceSample = 0; + + prevSampleL = CHECK_SILENCE_BIAS; + prevSampleR = CHECK_SILENCE_BIAS; + } + +public: + + XSFDriver() throw() + : hDriver(0), lpif(0) + { + } + ~XSFDriver() + { + } + + void Free() + { + if (lpif) + { + lpif->Term(); + lpif = 0; + } + if (hDriver) + { + XFreeLibrary(hDriver); + hDriver = 0; + } + xsfdata.Free(); + } + + bool Init(HINSTANCE hDll) + { + xsfc::TString sDrvPath = xsfc::TWin32::ExtractPath(xsfc::TWin32::ModulePath(hDll)) + XSFDRIVER_MODULENAME; + hDriver = xsfc::TWin32::IsUnicodeSupportedOS() ? XLoadLibraryW(sDrvPath) : XLoadLibraryA(xsfc::TStringM(sDrvPath)); + if (!hDriver) + return false; + LPFNXSFDRVSETUP lpfnXSFSetup = (LPFNXSFDRVSETUP)XGetProcAddress(hDriver, XSFDRIVER_ENTRYNAME); + lpif = lpfnXSFSetup ? lpfnXSFSetup(XSFGETLIBCALLBACK ,this) : 0; + if (!lpif) + { + Free(); + return false; + } + return true; + } + + bool Load(xsfc::TString fn) + { + + length_in_ms = CFGGetDefaultLength(); + fade_in_ms = CFGGetDefaultFade(); + hasvolume = 0; + volume = 1; + + sLibBasePath = xsfc::TWin32::ExtractPath(fn); + + xsfdata = xsfc::TWin32::Map(fn); + if (!xsfdata.Ptr()) + return false; + + fUTF8 = XSFTag::Exists("utf8", xsfdata.Ptr(), xsfdata.Len()) != 0; + if (lpif->dwInterfaceVersion >= 3) + { + lpif->SetExtendParam(1, CFGGetExtendParam1()); + lpif->SetExtendParam(2, CFGGetExtendParam2()); + } + if (lpif->Start(xsfdata.Ptr(), xsfdata.Len())) + { + return false; + } + + if (!XSFTag::GetVolume(&volume, "volume", xsfdata, 0)) + hasvolume = 1; + length_in_ms = XSFTag::GetLengthMS(xsfdata, CFGGetDefaultLength()); + fade_in_ms = XSFTag::GetFadeMS(xsfdata, CFGGetDefaultFade()); + + haslength = XSFTag::Exists("length", xsfdata.Ptr(), xsfdata.Len()) != 0; + + return true; + } + + void Start() + { + len_smp = MulDiv(length_in_ms, samplerate, 1000); + fad_smp = MulDiv(fade_in_ms, samplerate, 1000); + seek_pos = 0; + seek_kil = 0; + seek_req = 0; + SeekTop(); + } + + int Gen(void *pbuf, unsigned bufsize) + { + xsfsample_t *ptop = static_cast(pbuf); + unsigned detectSilence = CFGGetDetectSilenceSec(); + unsigned pos = 0; + if (lpif->dwInterfaceVersion >= 2) + { + bool output = false; + for (int i = 0; i < 4; i++) + { + unsigned long mute = CFGGetChannelMute(i); + output |= (mute != ~unsigned long(0)); + lpif->SetChannelMute(i, mute); + } + if (!output) detectSilence = 0; + } + if (lpif->dwInterfaceVersion >= 4) + { + lpif->SetExtendParamImmediate(EXTEND_PARAM_IMMEDIATE_INTERPOLATION,&dwInterpolation); + } + while (pos < bufsize) + { + unsigned ofs; + xsfsample_t *pblk = ptop + (pos << 1); + unsigned remain = bufsize - pos; + lpif->Gen(pblk, remain); + if (detectSilence || skipSilenceOnStartSec) + { + xsfsample_t *pskp = 0; + xsfsample_t *pcur = pblk; + for (ofs = 0; ofs < remain; ofs++) + { + long smpl = pcur[0]; + long smpr = pcur[1]; + bool silence = (((unsigned long)(smpl + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleL <= (CHECK_SILENCE_LEVEL) * 2) && (((unsigned long)(smpr + CHECK_SILENCE_BIAS + CHECK_SILENCE_LEVEL)) - prevSampleR <= (CHECK_SILENCE_LEVEL) * 2); + + if (silence) + { + if (++detectedSilenceSample >= samplerate) + { + detectedSilenceSample -= samplerate; + detectedSilenceSec++; + if (skipSilenceOnStartSec && detectedSilenceSec >= skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + detectedSilenceSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + } + else + { + detectedSilenceSample = 0; + detectedSilenceSec = 0; + if (skipSilenceOnStartSec) + { + skipSilenceOnStartSec = 0; + if (pblk != pcur) pskp = pcur; + } + } + prevSampleL = smpl + CHECK_SILENCE_BIAS; + prevSampleR = smpr + CHECK_SILENCE_BIAS; + pcur += 2; + } + if (skipSilenceOnStartSec) + { + } + else if (pskp) + { + while (pskp < pcur) + { + *(pblk++)= *(pskp++); + *(pblk++)= *(pskp++); + pos++; + } + } + else + { + pos += remain; + } + } + else + { + pos += remain; + } + } + return bufsize; + } + unsigned DetectedSilenceSec() + { + return detectedSilenceSec; + } + + int FillBuffer(void *pbuf, unsigned bufbytes, unsigned *writebytes, unsigned isdecoder) + { + int end_flag = 0; + unsigned bufsize = bufbytes >> blockshift; + unsigned cur = MulDiv(cur_smp, 1000, samplerate); + int len = bufsize; + Gen(pbuf, bufsize); + + /* detect end */ + if (!CFGGetPlayInfinitely() || isdecoder) + { + if (cur_smp >= len_smp + fad_smp) + { + end_flag = 1; + *writebytes = 0; + return 1; + } + if (cur_smp + len >= len_smp + fad_smp) + { + len = len_smp + fad_smp - cur_smp; + end_flag = 1; + } + } + + double cfgvolume = 1; + bool hascfgvolume = !isdecoder && CFGGetVolume(cfgvolume); + /* volume */ + if (hasvolume || hascfgvolume) + { + float scale = float(volume * cfgvolume); + xsfsample_t *p = static_cast(pbuf); + unsigned i; + for (i = cur_smp; i < cur_smp + len; i++) + { + float s1, s2; + s1 = float(p[0]); + s2 = float(p[1]); + s1 *= scale; + if (s1 > float(0x7fff)) + s1 = float(0x7fff); + else if (s1 < float(-0x8000)) + s1 = float(-0x8000); + s2 *= scale; + if (s2 > float(0x7fff)) + s2 = float(0x7fff); + else if (s2 < float(-0x8000)) + s2 = float(-0x8000); + p[0] = xsfsample_t(s1); + p[1] = xsfsample_t(s2); + p += 2; + } + } + + /* fader */ + if ((!CFGGetPlayInfinitely() || isdecoder) && fad_smp && cur_smp + len >= len_smp) + { + xsfsample_t *p = static_cast(pbuf); + unsigned i; + for (i = cur_smp; i < cur_smp + len; i++) + { + if (i < len_smp) + ; + else if (i < len_smp + fad_smp) + { + int scale = MulDiv(len_smp + fad_smp - i, 0x10000, fad_smp); + p[0] = (p[0] * scale) >> 16; + p[1] = (p[1] * scale) >> 16; + } + else + { + p[0] = 0; + p[1] = 0; + } + p += 2; + } + } + + cur_smp += len ; + *writebytes = len << blockshift; + return end_flag; + } + + int Seek(unsigned seek_pos, volatile int *killswitch, void *pbuf, unsigned bufbytes, Out_Module *outMod) + { + unsigned bufsize = bufbytes >> blockshift; + unsigned seek_smp = MulDiv(seek_pos, samplerate, 1000); + DWORD prevTimer = outMod ? GetTickCount() : 0; + if (seek_smp < cur_smp) + { + lpif->Start(xsfdata.Ptr(), xsfdata.Len()); + SeekTop(); + } + while (seek_smp - cur_smp > bufsize) + { + unsigned cur = MulDiv(cur_smp, 1000, samplerate); + if (killswitch && *killswitch) + return 1; + if (outMod) + { + DWORD curTimer = GetTickCount(); + if (DWORD(curTimer - prevTimer) >= 500) + { + prevTimer = curTimer; + outMod->Flush(cur); + } + } + + Gen(pbuf, bufsize); + cur_smp += bufsize; + } + if (seek_smp - cur_smp > 0) + { + Gen(pbuf, seek_smp - cur_smp); + cur_smp = seek_smp; + } + if (outMod) outMod->Flush(seek_pos); + return 0; + } + + void Reinit() + { + Free(); + seek_pos = 0; + } +}; + +enum REQUEST +{ + REQUEST_STOP, + REQUEST_SEEK, + REQUEST_RESTART +}; + +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW || ENABLE_TAGWRITER + +static const char * const tag_table[] = +{ + "title","title", + "artist","artist", + "album","game", + "albumartist","copyright", + "year","year", + "genre","genre", + "composer","composer", + "publisher",WINAMPPLUGIN_TAG_XSFBY, + "disc","disc", + "track","track", + "replaygain_album_gain","replaygain_album_gain", + "replaygain_album_peak","replaygain_album_peak", + "replaygain_track_gain","replaygain_track_gain", + "replaygain_track_peak","replaygain_track_peak", + + "GracenoteFileID",0, + "GracenoteExtData",0, + "streamtype",0, + "bpm",0, + + "type","\x01", + "streamname","\x02", + "length","\x03", + "comment","\x04", + "formatinformation","\x05", + + 0,0 +}; + +enum EXINFO +{ + EXINFO_NOT_SUPPORTED = 0, + EXINFO_SUPPORTED = 1 +}; + +enum XSF_TAG_TYPE +{ + XSF_TAG_TYPE_DIRECTSUPPORT = 0, + XSF_TAG_TYPE_EXTENDSUPPORT = 1, + XSF_TAG_TYPE_SYSTEM = 2, + XSF_TAG_TYPE_UNKNOWN = -1, + XSF_TAG_TYPE_ALL = -2 +}; + +class TagReader +{ +protected: + typedef struct + { + char *ptr; + const char *tag; + int taglen; + int count; + unsigned need; + enum XSF_TAG_TYPE mode; + } xsf_multitagget_work_t; + + static enum XSF_TAG_TYPE xsf_multitagget_type(const char *tag, int taglen) + { + const char * const *ptbl; + if (!taglen) + return XSF_TAG_TYPE_UNKNOWN; + if (XSFDRIVER_ISSYSTEMTAG(taglen, tag)) + return XSF_TAG_TYPE_SYSTEM; + for (ptbl = tag_table; ptbl[0]; ptbl += 2) + { + if (!ptbl[1]) + continue; + if ('\x00' < ptbl[1][0] && ptbl[1][0] <= '\x05') + continue; + if (!_strnicmp(tag, ptbl[1], taglen)) + return XSF_TAG_TYPE_DIRECTSUPPORT; + } + return XSF_TAG_TYPE_EXTENDSUPPORT; + } + + static enum XSFTag::enum_callback_returnvalue getmultitaqg_cb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + xsf_multitagget_work_t *pwork = static_cast(pWork); + enum XSF_TAG_TYPE tagtype = xsf_multitagget_type(pNameTop, pNameEnd - pNameTop); + if (pwork->mode != XSF_TAG_TYPE_ALL && pwork->mode != tagtype) + return XSFTag::enum_continue; + if (pwork->mode != XSF_TAG_TYPE_ALL && tagtype == XSF_TAG_TYPE_DIRECTSUPPORT) + { + if (pNameEnd - pNameTop != pwork->taglen || _strnicmp(pNameTop, pwork->tag, pwork->taglen)) + return XSFTag::enum_continue; + if (pwork->ptr) + { + if (0 != pwork->count++) + { + pwork->ptr[0] = ' '; + pwork->ptr[1] = ';'; + pwork->ptr[2] = ' '; + pwork->ptr += 3; + } + if (pValueEnd-pValueTop > 0) + memcpy(pwork->ptr, pValueTop, pValueEnd-pValueTop); + pwork->ptr += pValueEnd-pValueTop; + } + else + { + if (0 != pwork->count++) + pwork->need += 3; + pwork->need += pValueEnd-pValueTop; + } + } + else + { + if (pwork->ptr) + { + if (0 != pwork->count++) + { + pwork->ptr[0] = '\x0d'; + pwork->ptr[1] = '\x0a'; + pwork->ptr += 2; + } + if (pNameEnd-pNameTop > 0) + memcpy(pwork->ptr, pNameTop, pNameEnd-pNameTop); + pwork->ptr += pNameEnd-pNameTop; + pwork->ptr[0] = '='; + pwork->ptr += 1; + if (pValueEnd-pValueTop > 0) + memcpy(pwork->ptr, pValueTop, pValueEnd-pValueTop); + pwork->ptr += pValueEnd-pValueTop; + } + else + { + if (0 != pwork->count++) + { + pwork->need += 2; + } + pwork->need += pNameEnd-pNameTop + 1 + pValueEnd-pValueTop; + } + } + return XSFTag::enum_continue; + } + + static wchar_t *TagFunc(const wchar_t * tag, void * p) + { + return 0; + } + + static void TagFree(wchar_t *tag, void *p) + { + } + + static int get_tag_formattitleW(HWND hwndWinamp, const wchar_t *fn, wchar_t *title, unsigned l) + { + waFormatTitleExtended fmt; + fmt.filename = fn; + fmt.useExtendedInfo = 1; + fmt.spec = NULL; + fmt.p = NULL; + fmt.out = title; + fmt.out_len = l; + fmt.TAGFUNC = TagFunc; + fmt.TAGFREEFUNC = TagFree; + if (l > 0) + { + title[0] = 0; + xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &fmt, IPC_FORMAT_TITLE_EXTENDED); + if (title[0]) + return 1; + } + return 0; + } + +#ifdef UNICODE_INPUT_PLUGIN +#else + static int get_tag_formattitleA(HWND hwndWinamp, const char *fn, char *title, unsigned l) + { + int r = 0; + wchar_t wbuf[GETFILEINFO_TITLE_LENGTH]; + r = get_tag_formattitleW(hwndWinamp, xsfc::TString(fn), wbuf, GETFILEINFO_TITLE_LENGTH); + xsfc::TStringM mbuf(wbuf, GETFILEINFO_TITLE_LENGTH); + icsncpy(title, mbuf, l); + return r; + } +#endif + +public: + + static xsfc::TString XSFTagGetMulti(xsfc::TAutoBuffer idata, const char *metadata, enum XSF_TAG_TYPE mode) + { + xsfc::TString ret; + xsfc::TSimpleArray tag; + xsf_multitagget_work_t cbw; + cbw.mode = mode; + cbw.tag = metadata; + cbw.taglen = metadata ? strlen(metadata) : 0; + cbw.count = 0; + cbw.need = 0; + cbw.ptr = 0; + XSFTag::Enum(getmultitaqg_cb, &cbw, idata.Ptr(), idata.Len()); + if (cbw.need && tag.Resize(cbw.need + 1)) + { + bool futf8 = XSFTag::Exists("utf8", idata.Ptr(), idata.Len()); + char *ptr = tag.Ptr(); + ptr[cbw.need] = '\x00'; + cbw.count = 0; + cbw.ptr = ptr; + XSFTag::Enum(getmultitaqg_cb, &cbw, idata.Ptr(), idata.Len()); + ret = xsfc::TString(futf8, ptr); + } + return ret; + } +#endif + + static void get_tag_title(in_char *title, unsigned l, xsfc::TAutoBuffer idata) + { + xsfc::TString tagtitle; +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW || ENABLE_TAGWRITER + tagtitle = XSFTagGetMulti(idata, "title", XSF_TAG_TYPE_DIRECTSUPPORT); +#else + tagtitle = XSFTag::Get("title", idata.Ptr(), idata.Len()); +#endif + if (l > 0) title[0] = 0; + if (tagtitle[0]) + { +#ifdef UNICODE_INPUT_PLUGIN + icsncpy(title, tagtitle, l); +#else + icsncpy(title, xsfc::TStringM(tagtitle), l); +#endif + } + } + + static void get_tag_formattitle(HWND hwndWinamp, const in_char *fn, in_char *title, unsigned l, xsfc::TAutoBuffer idata) + { + if (l > 0) title[0] = 0; +#ifdef UNICODE_INPUT_PLUGIN + get_tag_formattitleW(hwndWinamp, fn, title, l); +#else + get_tag_formattitleA(hwndWinamp, fn, title, l); +#endif + if (l > 0 && !title[0]) + { + get_tag_title(title, l, idata); + } + if (l > 0 && !title[0]) + { + icsncpy(title, xsfc::TWin32T::ExtractFilename(fn), l); + } + } + +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW || ENABLE_TAGWRITER + class TagReturn + { + protected: + xsfc::TString ret; + size_t l; + wchar_t *wbuf; + char *mbuf; + public: + TagReturn() + : l(0), wbuf(0), mbuf(0) + { + } + TagReturn(char *buf, size_t buflen) + : l(buflen), wbuf(0), mbuf(buf) + { + } + TagReturn(wchar_t *buf, size_t buflen) + : l(buflen), wbuf(buf), mbuf(0) + { + } + ~TagReturn() + { + } + void Set(const xsfc::TString &value) + { + ret = value; + if (l && wbuf) + wstrncpychk(wbuf, ret, l); + if (l && mbuf) + mstrncpychk(mbuf, xsfc::TStringM(ret), l); + } + void Set(bool futf8, const char *tag) + { + Set(xsfc::TString(futf8, tag)); + } + xsfc::TString Get() + { + return ret; + } + }; + + static int getfinfo(xsfc::TAutoBuffer idata, const char *metadata, TagReturn &result) + { + bool futf8 = XSFTag::Exists("utf8", idata.Ptr(), idata.Len()); + int taglen = strlen(metadata); + const char * const *ptbl; + for (ptbl = tag_table; ptbl[0]; ptbl += 2) + { + if (!_strnicmp(metadata, ptbl[0], taglen)) + { + if (!ptbl[1]) + break; + else if (ptbl[1][0] == '\x01') + { + result.Set(futf8, "0"); + } + else if (ptbl[1][0] == '\x02') + { + result.Set(futf8, ""); + } + else if (ptbl[1][0] == '\x03') + { + char tbuf[16]; + unsigned length = XSFTag::GetLengthMS(idata, CFGGetDefaultLength()); + unsigned fade = XSFTag::GetFadeMS(idata, CFGGetDefaultFade()); +#if defined(HAVE_SPRINTF_S) + sprintf_s(tbuf, sizeof(tbuf), "%10d", (length + fade)); +#elif defined(HAVE_SNPRINTF) + snprintf(tbuf, sizeof(tbuf), "%10d", (length + fade)); +#elif defined(HAVE_SNPRINTF_) + _snprintf(tbuf, sizeof(tbuf), "%10d", (length + fade)); +#else + sprintf(tbuf, "%10d", (length + fade)); +#endif + result.Set(futf8, tbuf); + } + else if (ptbl[1][0] == '\x04') + { + xsfc::TString tag = XSFTagGetMulti(idata, 0, XSF_TAG_TYPE_EXTENDSUPPORT); + result.Set(futf8, xsfc::TStringM(futf8, tag)); + } + else if (ptbl[1][0] == '\x05') + { + xsfc::TString tag = XSFTagGetMulti(idata, 0, XSF_TAG_TYPE_SYSTEM); + result.Set(futf8, xsfc::TStringM(futf8, tag)); + } + else + { + xsfc::TString tag = XSFTagGetMulti(idata, ptbl[1], XSF_TAG_TYPE_DIRECTSUPPORT); + result.Set(futf8, xsfc::TStringM(futf8, tag)); + } + return EXINFO_SUPPORTED; + } + } + return EXINFO_NOT_SUPPORTED; + } +#endif + +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW + static bool getfinfo_map(xsfc::TAutoBuffer &idata, const wchar_t *fn) + { + idata = xsfc::TWin32::Map(fn); + return idata.Ptr() != 0; + } +#endif + +}; + +class WinampPlugin +{ +protected: + static XSFDriver xsfdrv; + static HMODULE m_hDLL; + static HANDLE m_hThread; + static HANDLE m_hEvent; + static HANDLE m_hEvent2; + static volatile LONG m_lRequest; + static int m_paused; + static in_char m_title[GETFILEINFO_TITLE_LENGTH]; + static HANDLE m_hFindWindowThread; + +public: + static In_Module mod; + + static void Init(HINSTANCE hinstDLL) + { + m_hDLL = (HMODULE)hinstDLL; + } + + static HMODULE ConfigInit() + { + winamp_config_load(mod.hMainWindow); + return m_hDLL; + } + +protected: + static DWORD __stdcall PlayWorkerThread(LPVOID argp) + { + try + { + unsigned char buffer[SIZE_OF_BUFFER * 2]; + unsigned seek_pos; + unsigned end_flag; + + int request1; + + xsfdrv.Start(); + + m_paused = 0; + request1 = 0; + ::ResetEvent(m_hEvent); + + end_flag = 0; + do + { + unsigned timeout; + unsigned writebytes; + int len; + unsigned detectsilencesec = CFGGetDetectSilenceSec(); + unsigned playinfinitely = CFGGetPlayInfinitely(); + unsigned cur = MulDiv(xsfdrv.cur_smp, 1000, xsfdrv.samplerate); + bool haslength = xsfdrv.haslength; + end_flag = xsfdrv.FillBuffer(buffer, SIZE_OF_BUFFER, &writebytes, 0); + + if (!playinfinitely && !haslength && detectsilencesec && detectsilencesec <= xsfdrv.DetectedSilenceSec()) + end_flag = 1; + + len = writebytes >> xsfdrv.blockshift; + if (len == 0) + { + end_flag = 1; + continue; + } + + if (len >= 576) + { + mod.SAAddPCMData(buffer, xsfdrv.ch, xsfdrv.samplebits, cur); + mod.VSAAddPCMData(buffer, xsfdrv.ch, xsfdrv.samplebits, cur); + } + if(mod.dsp_isactive()) + len = mod.dsp_dosamples((xsfsample_t *)(buffer), len, xsfdrv.samplebits, xsfdrv.ch, xsfdrv.samplerate); + len <<= xsfdrv.blockshift; + timeout = 0; + request1 = 0; + do + { + if (::WaitForSingleObject(m_hEvent, timeout) != WAIT_TIMEOUT) + { + request1 = ::InterlockedExchange((LPLONG)&m_lRequest, 0); + break; + } + timeout = 10; + } while (mod.outMod->CanWrite() < len); + if (request1 & (1 << REQUEST_STOP)) + break; + if (request1 & (1 << REQUEST_RESTART)) + { + seek_pos = 0; + request1 |= (1 << REQUEST_SEEK); + } + else if (request1 & (1 << REQUEST_SEEK)) + { + seek_pos = xsfdrv.seek_pos; + if (!seek_pos) + request1 &= ~(1 << REQUEST_SEEK); + } + if (request1 & (1 << REQUEST_SEEK)) + { + xsfdrv.seek_kil = 0; + xsfdrv.Seek(seek_pos, &xsfdrv.seek_kil, buffer, SIZE_OF_BUFFER, mod.outMod); + xsfdrv.seek_pos = 0; + continue; + } + if (mod.outMod->CanWrite() >= len) + mod.outMod->Write((char *)(buffer), len); + } while (!end_flag); + + if (end_flag) + { + unsigned timeout = 0; + do + { + if (::WaitForSingleObject(m_hEvent, timeout) != WAIT_TIMEOUT) + { + int request2 = ::InterlockedExchange((LPLONG)&m_lRequest, 0); + if (request2 & (1 << REQUEST_STOP)) + { + request1 |= (1 << REQUEST_STOP); + break; + } + } + timeout = 10; + } while (mod.outMod->IsPlaying()); + } + + xsfdrv.Free(); + + if (!(request1 & (1 << REQUEST_STOP))) + { + xsfc::TWin32::WndMsgPost(mod.hMainWindow, WM_WA_MPEG_EOF); + } + } + catch (xsfc::EShortOfMemory ex) + { + } + return 0; + } + + static int __cdecl play(const in_char *fn) + { + try + { + DWORD dwThreadId; + int maxlatency; + + if (m_hThread) + return 1; + + if (!m_hEvent) + return 1; + + xsfdrv.Free(); + + ConfigInit(); + + if (!xsfdrv.Init(m_hDLL) || !xsfdrv.Load(xsfc::TString(fn))) + { + xsfdrv.Free(); + return 1; + } + + if (!XSFTag::GetVolume(&xsfdrv.volume, "replaygain_album_gain", xsfdrv.xsfdata, 1)) + xsfdrv.hasvolume = 1; + else if (!XSFTag::GetVolume(&xsfdrv.volume, "replaygain_track_gain", xsfdrv.xsfdata, 1)) + xsfdrv.hasvolume = 1; + + TagReader::get_tag_formattitle(mod.hMainWindow, fn, m_title, GETFILEINFO_TITLE_LENGTH, xsfdrv.xsfdata); + + maxlatency = mod.outMod->Open(xsfdrv.samplerate, xsfdrv.ch, xsfdrv.samplebits, 0, 0); + if (maxlatency < 0) + { + xsfdrv.Free(); + return 1; + } + + xsfc::TWin32::WndMsgSend(mod.hMainWindow, WM_WA_IPC, 0, IPC_UPDTITLE); + + mod.SetInfo(xsfdrv.samplerate * xsfdrv.samplebits * xsfdrv.ch / 1000, xsfdrv.samplerate / 1000, xsfdrv.ch, 0); + mod.SAVSAInit(maxlatency, xsfdrv.samplerate); + mod.VSASetInfo(xsfdrv.samplerate, xsfdrv.ch); + mod.outMod->SetVolume(-666); + m_hThread = ::CreateThread(NULL, 0, PlayWorkerThread, NULL, 0, &dwThreadId); + if (!m_hThread) + { + mod.SAVSADeInit(); + mod.outMod->Close(); + xsfdrv.Free(); + return 1; + } + return 0; + } + catch (xsfc::EShortOfMemory ex) + { + } + return 1; + } + + static void Request(enum REQUEST request_code) + { + if (m_hEvent) + { + m_lRequest |= 1 << request_code; + ::SetEvent(m_hEvent); + } + } + + static void __cdecl stop(void) + { + if (m_hThread) + { + do + { + xsfdrv.seek_kil = 1; + Request(REQUEST_STOP); + } while (::WaitForSingleObject(m_hThread, 20) == WAIT_TIMEOUT); + ::CloseHandle(m_hThread); + m_hThread = NULL; + mod.SAVSADeInit(); + mod.outMod->Close(); + } + } + + typedef struct + { + bool found; + HWND hwnd; + } ftw_work_t; + + static BOOL CALLBACK ftw_cb(HWND hwnd, LPARAM lParam) + { + ftw_work_t *pftww = (ftw_work_t *)lParam; + char buf[32]; + if (::GetClassNameA(hwnd, buf, sizeof(buf))) + { + if (!::lstrcmpA(buf, "Winamp v1.x")) + { + pftww->found = true; + pftww->hwnd = hwnd; + return FALSE; + } + } + return TRUE; + } + + static DWORD CALLBACK FindThreadWindow(LPVOID argp) + { + ftw_work_t ftww = { false, 0 }; + DWORD dwThreadId = (DWORD)argp; + do + { + Sleep(500); + ::EnumThreadWindows(dwThreadId, ftw_cb, (LPARAM)&ftww); + } + while (!ftww.found && (*(volatile HANDLE *)&m_hEvent) != 0); + if (ftww.found) + winamp_config_add_prefs(ftww.hwnd); + return 0; + } + + static void closeevent(void) + { + if (m_hEvent) + { + ::CloseHandle(m_hEvent); + m_hEvent = 0; + } + } + static void termfindwindowthread(void) + { + if (m_hFindWindowThread) + { + TerminateThread(m_hFindWindowThread, 1); + ::CloseHandle(m_hFindWindowThread); + m_hFindWindowThread = 0; + } + } + + static void __cdecl init(void) + { + try + { + m_lRequest = 0; + m_hThread = 0; + m_title[0] = '\0'; + closeevent(); + m_hEvent = ::CreateEventA(NULL, FALSE, FALSE, NULL); + xsfdrv.Reinit(); + ConfigInit(); + if (mod.hMainWindow) + winamp_config_add_prefs(mod.hMainWindow); + else + { + DWORD dwThreadId; + termfindwindowthread(); + m_hFindWindowThread = ::CreateThread(NULL, 0, FindThreadWindow, (LPVOID)::GetCurrentThreadId(), 0, &dwThreadId); + } + } + catch (xsfc::EShortOfMemory ex) + { + } + } + + static void __cdecl quit(void) + { + try + { + termfindwindowthread(); + winamp_config_remove_prefs(mod.hMainWindow); + xsfdrv.Free(); + closeevent(); + } + catch (xsfc::EShortOfMemory ex) + { + } + } + + static void __cdecl getfileinfo(const in_char *fn, in_char *title, int *length_in_ms) + { + try + { + if (title) *title = '\0'; + if (length_in_ms) *length_in_ms = CFGGetDefaultLength() + CFGGetDefaultFade(); + if (!fn || !*fn) + { + if (title) + icsncpy(title, m_title, GETFILEINFO_TITLE_LENGTH); + if (length_in_ms) + *length_in_ms = xsfdrv.length_in_ms + xsfdrv.fade_in_ms; + return; + } + xsfc::TAutoBuffer idata = xsfc::TWin32::Map(xsfc::TString(fn)); + if (idata.Ptr()) + { + if (title) + { + TagReader::get_tag_formattitle(mod.hMainWindow, fn, title, GETFILEINFO_TITLE_LENGTH, idata); + } + + if (length_in_ms) + { + unsigned length = XSFTag::GetLengthMS(idata, CFGGetDefaultLength()); + unsigned fade = XSFTag::GetFadeMS(idata, CFGGetDefaultFade()); + *length_in_ms = length + fade; + } + } + } + catch (xsfc::EShortOfMemory ex) + { + } + } + + static void __cdecl pause(void) { m_paused = 1; mod.outMod->Pause(1); } + static void __cdecl unpause(void) { m_paused = 0; mod.outMod->Pause(0); } + static int __cdecl getoutputtime(void) { return mod.outMod->GetOutputTime(); } + static void __cdecl setvolume(int volume) { mod.outMod->SetVolume(volume); } + static void __cdecl setpan(int pan) { mod.outMod->SetPan(pan); } + static void __cdecl config(HWND hwnd) + { + winamp_config_dialog(mod.hMainWindow, hwnd); + } + static void __cdecl about(HWND hwnd) { MessageBoxA(hwnd, WINAMPPLUGIN_COPYRIGHT , WINAMPPLUGIN_NAME, MB_OK); } + static int __cdecl infobox(const in_char *fn, HWND hwnd) + { + try + { + /* This function is obsolete in Winamp5. */ + /* Current version of 'in_zip.dll' and XMPlay cannot handle 'winampUseUnifiedFileInfoDlg' function. */ + xsfc::TAutoBuffer idata = xsfc::TWin32::Map(xsfc::TString(fn)); + if (idata.Ptr()) + { + int futf8 = XSFTag::Exists("utf8", idata.Ptr(), idata.Len()); + xsfc::TString tag = TagReader::XSFTagGetMulti(idata, 0, XSF_TAG_TYPE_ALL); + if (tag[0]) + { +#ifdef UNICODE_INPUT_PLUGIN + MessageBoxW(hwnd, tag, xsfc::TWin32T::ExtractFilename(fn), MB_OK); +#else + MessageBoxA(hwnd, xsfc::TStringM(tag), xsfc::TWin32T::ExtractFilename(fn), MB_OK); +#endif + return 1; + } + } + } + catch (xsfc::EShortOfMemory ex) + { + } + return 0; + } + static int __cdecl isourfile(const in_char *fn) { return 0; } + static void __cdecl eq_set(int on, char data[10], int preamp) {} + static int __cdecl ispaused(void) { return m_paused; } + static int __cdecl getlength(void) { return xsfdrv.length_in_ms + xsfdrv.fade_in_ms; } + static void __cdecl setoutputtime(int time_in_ms) + { + xsfdrv.seek_kil = 1; + if (time_in_ms) + { + xsfdrv.seek_pos = time_in_ms; + Request(REQUEST_SEEK); + } + else + { + Request(REQUEST_RESTART); + } + } + +}; + +XSFDriver WinampPlugin::xsfdrv; +HMODULE WinampPlugin::m_hDLL = 0; +HANDLE WinampPlugin::m_hThread = 0; +HANDLE WinampPlugin::m_hEvent = 0; +volatile LONG WinampPlugin::m_lRequest = 0; +int WinampPlugin::m_paused = 0; +in_char WinampPlugin::m_title[GETFILEINFO_TITLE_LENGTH]; +HANDLE WinampPlugin::m_hFindWindowThread = 0; + +In_Module WinampPlugin::mod = +{ + IN_VER, + WINAMPPLUGIN_NAME, + 0, /* hMainWindow */ + 0, /* hDllInstance */ + WINAMPPLUGIN_EXTS, + 1, /* is_seekable */ + 1, /* UsesOutputPlug */ + WinampPlugin::config, + WinampPlugin::about, + WinampPlugin::init, + WinampPlugin::quit, + WinampPlugin::getfileinfo, + WinampPlugin::infobox, + WinampPlugin::isourfile, + WinampPlugin::play, + WinampPlugin::pause, + WinampPlugin::unpause, + WinampPlugin::ispaused, + WinampPlugin::stop, + + WinampPlugin::getlength, + WinampPlugin::getoutputtime, + WinampPlugin::setoutputtime, + WinampPlugin::setvolume, + WinampPlugin::setpan, + + /* pointers filled in by winamp */ + 0,0,0,0,0,0,0,0,0, /* vis stuff */ + 0,0, /* dsp */ + + WinampPlugin::eq_set, /* EQ, not used */ + NULL, /* setinfo */ + 0 /* out_mod */ +}; + + +extern "C" In_Module * __cdecl winampGetInModule2(void) +{ + return &WinampPlugin::mod; +} + +#if ENABLE_GETEXTENDINFO +extern "C" int __cdecl winampGetExtendedFileInfo(char *filename, char *metadata, char *ret, int retlen) +{ + int e = EXINFO_NOT_SUPPORTED; + try + { + xsfc::TAutoBuffer idata; + WinampPlugin::ConfigInit(); + if (filename && *filename && TagReader::getfinfo_map(idata, xsfc::TString(filename))) + { + TagReader::TagReturn result(ret, retlen); + e = TagReader::getfinfo(idata, metadata, result); +// if (ret && retlen > 0 && !ret[0] && !strcmp(metadata, "title")) +// { +// mstrncpychk(ret, xsfc::TWin32T::ExtractFilename(filename), retlen); +// e = EXINFO_SUPPORTED; +// } + } + else if (!strcmp(metadata, "type")) + { + if (retlen > 0) ret[0] = '0'; + if (retlen > 1) ret[1] = 0; + e = EXINFO_SUPPORTED; + } + } + catch (xsfc::EShortOfMemory ex) + { + } + return e; +} +#endif + +#if ENABLE_GETEXTENDINFOW +extern "C" int __cdecl winampGetExtendedFileInfoW(WCHAR *filename, char *metadata, WCHAR *ret, int retlen) +{ + int e = EXINFO_NOT_SUPPORTED; + try + { + xsfc::TAutoBuffer idata; + WinampPlugin::ConfigInit(); + if (filename && *filename && TagReader::getfinfo_map(idata, filename)) + { + TagReader::TagReturn result(ret, retlen); + e = TagReader::getfinfo(idata, metadata, result); +// if (ret && retlen > 0 && !ret[0] && !strcmp(metadata, "title")) +// { +// wstrncpychk(ret, xsfc::TWin32T::ExtractFilename(filename), retlen); +// e = EXINFO_SUPPORTED; +// } + } + else if (!strcmp(metadata, "type")) + { + if (retlen > 0) ret[0] = L'0'; + if (retlen > 1) ret[1] = 0; + e = EXINFO_SUPPORTED; + } + } + catch (xsfc::EShortOfMemory ex) + { + } + return e; +} +#endif + +#if ENABLE_TAGWRITER + +class TagWriter +{ +protected: + + class tagwriternode + { + public: + class tagwriternode *pnext; + xsfc::TStringM tag; + xsfc::TStringM valueu8; + + tagwriternode() throw() + : pnext(0) + { + } + ~tagwriternode() + { + } + + static tagwriternode *get_node(tagwriternode *ptop, const char *tag) + { + tagwriternode *pcur = ptop; + while (pcur) + { + tagwriternode *pnext = pcur->pnext; + if (pcur->tag && !strcmp(pcur->tag, tag)) + break; + pcur = pnext; + } + return pcur; + } + }; + + class tagwriterfile + { + public: + xsfc::TStringM filenameu8; + tagwriternode *ptop; + tagwriterfile() throw() + : ptop(0) + { + } + ~tagwriterfile() + { + tagwriternode *pcur = ptop; + while (pcur) + { + tagwriternode *pnext = pcur->pnext; + delete pcur; + pcur = pnext; + } + } + }; + + static tagwriterfile * volatile ptarget; + static CRITICAL_SECTION cs; + + static tagwriterfile *GetTarget(tagwriterfile *pnewtarget) + { + tagwriterfile *poldtarget; + ::EnterCriticalSection(&cs); + poldtarget = ptarget; + ptarget = pnewtarget; + ::LeaveCriticalSection(&cs); + return poldtarget; + } + + static void FreeFile(tagwriterfile *pfile) + { + if (pfile) + { + delete pfile; + } + } + TagWriter() + { + } + ~TagWriter() + { + } + + static xsfc::TStringM Get(tagwriternode *ptop, xsfc::TAutoBuffer idata, const char *tag) + { + tagwriternode *pnode = tagwriternode::get_node(ptop, tag); + xsfc::TStringM valueu8; + if (pnode) + valueu8 = pnode->valueu8; + else + { + TagReader::TagReturn result; + TagReader::getfinfo(idata, tag, result); + valueu8 = xsfc::TStringM(true, result.Get()); + } + return valueu8; + } + + static void WriteSingle(HANDLE h, bool futf8, const char *pname, unsigned uname, const char *pvalue, unsigned uvalue) + { + if (uname && uvalue) + { + DWORD dwNumberOfByteWritten; + if (futf8) + { + WriteFile(h, pname, uname, &dwNumberOfByteWritten, NULL); + WriteFile(h, "=", 1, &dwNumberOfByteWritten, NULL); + WriteFile(h, pvalue, uvalue, &dwNumberOfByteWritten, NULL); + WriteFile(h, "\x0a", 1, &dwNumberOfByteWritten, NULL); + } + else + { + xsfc::TStringM name(xsfc::TString(true, pname, uname)); + xsfc::TStringM value(xsfc::TString(true, pvalue, uvalue)); + WriteFile(h, name, strlen(name), &dwNumberOfByteWritten, NULL); + WriteFile(h, "=", 1, &dwNumberOfByteWritten, NULL); + WriteFile(h, value, strlen(value), &dwNumberOfByteWritten, NULL); + WriteFile(h, "\x0a", 1, &dwNumberOfByteWritten, NULL); + } + } + } + + static const char *Split(const char *p) + { + int l; + for (l = 0; p[l]; l++) + { + if (p[l + 0] == ' ' && p[l + 1] == ';' && p[l + 2] == ' ') + break; + } + return p + l; + } + + static void WriteMulti(HANDLE h, bool futf8, const char *tag, const char *value) + { + int taglen = strlen(tag); + if (!value) return; + do + { + const char *top = value; + value = Split(value); + WriteSingle(h, futf8, tag, taglen, top, value-top); + if (*value) value += 3; + } while (*value); + } + + typedef struct + { + HANDLE h; + bool futf8; + char ignoresystemtag; + } writetagmultiline_work_t; + + static XSFTag::enum_callback_returnvalue tagwriter_wmlcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + writetagmultiline_work_t *pwork = static_cast(pWork); + if (pwork->ignoresystemtag && XSFDRIVER_ISSYSTEMTAG(pNameEnd - pNameTop, pNameTop)) + return XSFTag::enum_continue; + WriteSingle(pwork->h, pwork->futf8, pNameTop, pNameEnd-pNameTop, pValueTop, pValueEnd-pValueTop); + return XSFTag::enum_continue; + } + + static void WriteMultiLine(HANDLE h, bool futf8, const char *value) + { + writetagmultiline_work_t cbw; + cbw.h = h; + cbw.futf8 = futf8; + cbw.ignoresystemtag = 1; + if (!value) return; + XSFTag::EnumRaw(tagwriter_wmlcb, &cbw, value, strlen(value)); + } + + static void WriteSysMultiLine(HANDLE h, bool futf8, const char *value) + { + writetagmultiline_work_t cbw; + cbw.h = h; + cbw.futf8 = futf8; + cbw.ignoresystemtag = 0; + if (!value) return; + XSFTag::EnumRaw(tagwriter_wmlcb, &cbw, value, strlen(value)); + } + + static int WriteAll(HANDLE h, tagwriternode *ptop, xsfc::TAutoBuffer idata) + { + const char * const *ptbl; + bool futf8 = false; + xsfc::TStringM comment = Get(ptop, idata, "comment"); + xsfc::TStringM formatinformation = Get(0, idata, "formatinformation"); + xsfc::TString utf8 = XSFTag::GetRaw("utf8", comment.GetM(), strlen(comment)); + if (utf8[0]) futf8 = true; + if (formatinformation[0]) + WriteSysMultiLine(h, futf8, formatinformation); + if (comment[0]) + WriteMultiLine(h, futf8, comment); + for (ptbl = tag_table; ptbl[0]; ptbl += 2) + { + if (!ptbl[1]) + continue; + if ('\x00' < ptbl[1][0] && ptbl[1][0] <= '\x05') + continue; + WriteMulti(h, futf8, ptbl[1], Get(ptop, idata, ptbl[0])); + } + return EXINFO_SUPPORTED; + } + + static xsfc::TString fnextend(const wchar_t *fn) + { + if (fn && fn[0] == L'\\' && fn[1] == L'\\' && fn[2] != L'?') + return xsfc::TString("\\\\?\\UNC") + (fn + 1); + if (fn && fn[0] && fn[1] == L':' && fn[2] == L'\\') + return xsfc::TString("\\\\?\\") + fn; + return xsfc::TString(); + } + + static HANDLE createfileW(const WCHAR *fn) + { + HANDLE h = INVALID_HANDLE_VALUE; + if (xsfc::TWin32::IsUnicodeSupportedOS()) + { + xsfc::TString fnw = fnextend(fn); + h = CreateFileW(fnw[0] ? fnw : fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } + else + { + h = CreateFileA(xsfc::TStringM(fn), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } + return h; + } + + static int WriteTarget(tagwriterfile *pfile) + { + int e = EXINFO_NOT_SUPPORTED; + if (pfile && pfile->filenameu8 && pfile->ptop) + { + xsfc::TString fnw(true, pfile->filenameu8); + xsfc::TAutoBuffer idata = xsfc::TWin32::Map(fnw); + if (idata.Ptr()) + { + DWORD dwTagOffset = XSFTag::SearchRaw(idata.Ptr(), idata.Len()); + if (dwTagOffset) + { + HANDLE h = createfileW(fnw); + if (h != INVALID_HANDLE_VALUE) + { + DWORD dwNumberOfByteWritten; + WriteFile(h, idata.Ptr(), dwTagOffset, &dwNumberOfByteWritten, NULL); + WriteFile(h, "[TAG]", 5, &dwNumberOfByteWritten, NULL); + e = WriteAll(h, pfile->ptop, idata); + ::CloseHandle(h); + } + } + } + } + return e; + } + +public: + static int Write() + { + int e = EXINFO_NOT_SUPPORTED; + tagwriterfile *ptarget = GetTarget(0); + if (ptarget) + { + e = WriteTarget(ptarget); + FreeFile(ptarget); + } + return e; + } + + static int SetFInfo(xsfc::TStringM filenameu8, xsfc::TStringM tag, xsfc::TStringM valueu8) + { + tagwriterfile *pfile = GetTarget(0); + if (pfile) + { + if (strcmp(pfile->filenameu8, filenameu8)) + { + FreeFile(pfile); + pfile = 0; + } + } + if (!pfile) + { + pfile = new(xsfc::nothrow) tagwriterfile; + if (pfile) + { + pfile->filenameu8 = filenameu8; + pfile->ptop = 0; + } + } + + if (pfile) + { + tagwriternode *pnode = tagwriternode::get_node(pfile->ptop, tag); + if (!pnode) + { + pnode = new(xsfc::nothrow) tagwriternode; + if (pnode) + { + pnode->pnext = pfile->ptop; + pnode->tag = tag; + pfile->ptop = pnode; + } + } + if (pnode) + { + if (strcmp(pnode->valueu8, valueu8)) + pnode->valueu8 = valueu8; + } + } + + pfile = GetTarget(pfile); + FreeFile(pfile); + return EXINFO_SUPPORTED; + } + + static void Init() + { + ptarget = 0; + ::InitializeCriticalSection(&cs); + } + static void Term() + { + FreeFile(GetTarget(0)); + ::DeleteCriticalSection(&cs); + } +}; + +TagWriter::tagwriterfile * volatile TagWriter::ptarget = 0; +CRITICAL_SECTION TagWriter::cs; + +extern "C" int __cdecl winampSetExtendedFileInfo(char *filename,char *metadata,char *ret,int retlen) +{ + try + { + xsfc::TStringM fnu8(true, xsfc::TString(filename)); + xsfc::TStringM tgu8(true, xsfc::TString(metadata)); + xsfc::TStringM tvu8(true, xsfc::TString(ret)); + return TagWriter::SetFInfo(fnu8, tgu8, tvu8); + } + catch (xsfc::EShortOfMemory ex) + { + } + return EXINFO_NOT_SUPPORTED; +} +extern "C" int __cdecl winampSetExtendedFileInfoW(WCHAR *filename,char *metadata,WCHAR *ret,int retlen) +{ + try + { + xsfc::TStringM fnu8(true, filename); + xsfc::TStringM tgu8(true, xsfc::TString(metadata)); + xsfc::TStringM tvu8(true, ret); + return TagWriter::SetFInfo(fnu8, tgu8, tvu8); + } + catch (xsfc::EShortOfMemory ex) + { + } + return EXINFO_NOT_SUPPORTED; +} +extern "C" int __cdecl winampWriteExtendedFileInfo(void) +{ + try + { + return TagWriter::Write(); + } + catch (xsfc::EShortOfMemory ex) + { + } + return EXINFO_NOT_SUPPORTED; +} +#endif + +#if ENABLE_GETEXTENDINFO || ENABLE_GETEXTENDINFOW || ENABLE_TAGWRITER +/* + return 1 if you want winamp to show it's own file info dialogue, 0 if you want to show your own (via In_Module.InfoBox) + if returning 1, remember to implement winampGetExtendedFileInfo("formatinformation")! +*/ +extern "C" int __cdecl winampUseUnifiedFileInfoDlg(const wchar_t * fn) +{ + return EXINFO_SUPPORTED; +} +/* + should return a child window of 513x271 pixels (341x164 in msvc dlg units), or return NULL for no tab. + Fill in name (a buffer of namelen characters), this is the title of the tab (defaults to "Advanced"). + filename will be valid for the life of your window. n is the tab number. This function will first be + called with n == 0, then n == 1 and so on until you return NULL (so you can add as many tabs as you like). + The window you return will recieve WM_COMMAND, IDOK/IDCANCEL messages when the user clicks OK or Cancel. + when the user edits a field which is duplicated in another pane, do a SendMessage(GetParent(hwnd),WM_USER,(WPARAM)L"fieldname",(LPARAM)L"newvalue"); + this will be broadcast to all panes (including yours) as a WM_USER. +*/ +extern "C" HWND __cdecl winampAddUnifiedFileInfoPane(int n, const wchar_t * filename, HWND parent, wchar_t *name, size_t namelen) +{ + return NULL; +} +#endif + +#if ENABLE_EXTENDREADER +static void * __cdecl winampGetExtendedRead_opensub(xsfc::TString fn, int *size, int *bps, int *nch, int *srate) +{ + try + { + xsfc::TAutoPtr pDrv(new(xsfc::nothrow) XSFDriver); + if (!pDrv) + return NULL; + if (!pDrv->Init(WinampPlugin::ConfigInit()) || !pDrv->Load(fn)) + { + pDrv->Free(); + return NULL; + } + pDrv->Start(); + if (size) *size = (pDrv->len_smp + pDrv->fad_smp) << pDrv->blockshift; + if (bps) *bps = pDrv->samplebits; + if (nch) *nch = pDrv->ch; + if (srate) *srate = pDrv->samplerate; + return pDrv.Detach(); + } + catch (xsfc::EShortOfMemory ex) + { + } + return NULL; +} +extern "C" void * __cdecl winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate) +{ + return winampGetExtendedRead_opensub(xsfc::TString(fn), size, bps, nch, srate); +} +extern "C" void * __cdecl winampGetExtendedRead_open(const char *fn, int *size, int *bps, int *nch, int *srate) +{ + return winampGetExtendedRead_opensub(xsfc::TString(fn), size, bps, nch, srate); +} +static int winampGetExtendedRead_getData_seeksub(XSFDriver *pDrv, unsigned seek_pos, volatile int *killswitch) +{ + char buf[576 * 4]; + return pDrv->Seek(seek_pos, killswitch, buf, sizeof(buf), 0); +} + +extern "C" int __cdecl winampGetExtendedRead_getData(void *handle, char *dest, int len, volatile int *killswitch) +{ + try + { + XSFDriver *pDrv = static_cast(handle); + const int block = 576 * 4; + int genlen = 0; + int endflag = 0; + if (!pDrv) + return 0; + if (pDrv->seek_req) + { + unsigned seek_pos = pDrv->seek_pos; + pDrv->seek_req = 0; + if (winampGetExtendedRead_getData_seeksub(pDrv, seek_pos, killswitch)) + return genlen; + } + while (genlen < len && !endflag) + { + unsigned writebytes; + endflag = pDrv->FillBuffer(dest + genlen, ((len - genlen) > block) ? block : (len - genlen), &writebytes, 1); + genlen += writebytes; + if (killswitch && *killswitch) + break; + } + return genlen; + } + catch (xsfc::EShortOfMemory ex) + { + } + return 0; +} +extern "C" int __cdecl winampGetExtendedRead_setTime(void *handle, int millisecs) +{ + try + { + XSFDriver *pDrv = static_cast(handle); + if (pDrv) + { + pDrv->seek_pos = millisecs; + pDrv->seek_req = 1; + return 1; + } + } + catch (xsfc::EShortOfMemory ex) + { + } + return 0; +} +extern "C" void __cdecl winampGetExtendedRead_close(void *handle) +{ + try + { + XSFDriver *pDrv = static_cast(handle); + if (pDrv) + { + pDrv->Free(); + delete pDrv; + } + } + catch (xsfc::EShortOfMemory ex) + { + } +} +#endif + +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + { + try + { +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + WinampPlugin::Init(hinstDLL); + winamp_config_init(hinstDLL); +#if ENABLE_TAGWRITER + TagWriter::Init(); +#endif + DisableThreadLibraryCalls(hinstDLL); + } + catch (xsfc::EShortOfMemory ex) + { + return FALSE; + } + } + else if (fdwReason == DLL_PROCESS_DETACH) + { +#if ENABLE_TAGWRITER + try + { + TagWriter::Term(); + } + catch (xsfc::EShortOfMemory ex) + { + } +#endif + } + return TRUE; +} diff --git a/tools/vio2sf/src/xsfc/in_xsfcfg.cpp b/tools/vio2sf/src/xsfc/in_xsfcfg.cpp new file mode 100644 index 000000000..51a89bf89 --- /dev/null +++ b/tools/vio2sf/src/xsfc/in_xsfcfg.cpp @@ -0,0 +1,291 @@ +#define WIN32_LEAN_AND_MEAN +#include "leakchk.h" + +#include +#include + +/* Winamp SDK headers */ +#include + +#include "../pversion.h" +#include "in_xsfcfg.h" +#include "xsfui.rh" + +#if _MSC_VER >= 1200 +#pragma warning(disable:4290) +#endif + +extern unsigned long dwInterpolation; + +namespace +{ + +xsfc::TAutoPtr pcfg; +prefsDlgRec prefwork; +int prefreg = 0; +HMODULE hDLL = 0; + +} + +class IniConfig : public IConfigIO +{ + xsfc::TString sIniPath; +protected: + IniConfig() throw() + { + } + + bool Initialize(HWND hwndWinamp) throw(xsfc::EShortOfMemory) + { + char *ini = (char *)(::SendMessageA(hwndWinamp, WM_WA_IPC, 0, IPC_GETINIFILE)); + if (ini && int(ini) != 1 && !IsBadStringPtrA(ini, MAX_PATH)) + sIniPath = xsfc::TString(ini); + else + sIniPath = xsfc::TWin32::ExtractPath(xsfc::TWin32::ModulePath(NULL)) + "winamp.ini"; + return true; + } + +public: + ~IniConfig() throw() + { + } + + void SetULong(const wchar_t *name, const unsigned long value) throw() + { + try + { + xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(value)); + } + catch (xsfc::EShortOfMemory e) + { + } + } + unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw() + { + try + { + xsfc::TString value = xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(defaultvalue)); + if (value[0]) return value.GetULong(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetFloat(const wchar_t *name, const double value) throw() + { + try + { + xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(value)); + } + catch (xsfc::EShortOfMemory e) + { + } + } + double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw() + { + try + { + xsfc::TString value = xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, xsfc::TString(defaultvalue)); + if (value[0]) return value.GetFloat(); + } + catch (xsfc::EShortOfMemory e) + { + } + return defaultvalue; + } + void SetString(const wchar_t *name, const wchar_t *value) throw() + { + try + { + xsfc::TWin32::SetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, value); + } + catch (xsfc::EShortOfMemory e) + { + } + } + xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw(xsfc::EShortOfMemory) + { + return xsfc::TWin32::GetPrivateProfile(sIniPath, xsfc::TString(XSFDRIVER_SIMPLENAME), name, defaultvalue); + } + + static LPIConfigIO Create(HWND hwndWinamp) throw(xsfc::EShortOfMemory) + { + xsfc::TAutoPtr cfg(new(xsfc::nothrow) IniConfig); + return (cfg && cfg->Initialize(hwndWinamp)) ? cfg.Detach() : 0; + } +}; + +static BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + case IDC_COMBO_INTERPOLATION: + if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) + { + dwInterpolation = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION)); + } + break; + case IDOK: + CFGUpdate(pcfg, hwndDlg); + CFGSave(pcfg); + ::EndDialog(hwndDlg, IDOK); + break; + case IDCANCEL: + ::EndDialog(hwndDlg, IDCANCEL); + break; + case 0x206: + if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) + { + CFGMuteChange(hwndDlg, 0x206); + } + break; + default: + return FALSE; + } + break; + case WM_INITDIALOG: + ::SetWindowTextA(hwndDlg, WINAMPPLUGIN_NAME); + ::ShowWindow(GetDlgItem(hwndDlg, IDOK), SW_SHOWNA); + ::ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_SHOWNA); + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "None"); + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Linear"); + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Cosine"); + ComboBox_SetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), dwInterpolation); + CFGLoad(pcfg); + CFGReset(pcfg, hwndDlg); + return TRUE; + } + return FALSE; +} + +static BOOL CALLBACK DialogProcPref(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static bool initialized = false; + switch (uMsg) + { + case WM_COMMAND: + switch (GET_WM_COMMAND_ID(wParam, LpARAM)) + { + case IDC_COMBO_INTERPOLATION: + if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) + { + dwInterpolation = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION)); + CFGSave(pcfg); + } + break; + + case 0x200: case 0x201: case 0x202: + case 0x203: case 0x204: case 0x205: + if (initialized) + { + CFGUpdate(pcfg, hwndDlg); + CFGSave(pcfg); + } + break; + case 0x206: + if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_SELCHANGE) + { + CFGMuteChange(hwndDlg, 0x206); + } + break; + default: + return FALSE; + } + break; + case WM_INITDIALOG: + initialized = false; + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "None"); + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Linear"); + ComboBox_AddString(GetDlgItem(hwndDlg, IDC_COMBO_INTERPOLATION), "Cosine"); + CFGLoad(pcfg); + CFGReset(pcfg, hwndDlg); + initialized = true; + return TRUE; + } + return FALSE; +} + +void winamp_config_init(HINSTANCE hinstDLL) +{ + hDLL = hinstDLL; +} +void winamp_config_load(HWND hwndWinamp) +{ + if (!pcfg) + { + pcfg = IniConfig::Create(hwndWinamp); + if (!pcfg) pcfg = NullConfig::Create(); + CFGLoad(pcfg); + } +} + + +void winamp_config_add_prefs(HWND hwndWinamp) +{ + if (prefreg) return; + + if (((LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, 0, IPC_GETVERSION) & 0xffffU) >= 0x2090) + { + /* 2.9+ */ + prefwork.hInst = hDLL; + prefwork.dlgID = 1; + prefwork.proc = (void *)DialogProcPref; + prefwork.name = XSFDRIVER_SIMPLENAME; + prefwork.where = 0; + prefwork._id = 0; + prefwork.next = 0; + prefreg = !(LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_ADD_PREFS_DLG); + } +} + +void winamp_config_remove_prefs(HWND hwndWinamp) +{ + + if (pcfg) pcfg.Release(); + if (prefreg) + { + xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_REMOVE_PREFS_DLG); + prefreg = 0; + } +} + +void winamp_config_dialog(HWND hwndWinamp, HWND hwndParent) +{ + HRSRC hrsrc; + DWORD dwSize; + HGLOBAL hGlobal; + xsfc::TSimpleArray resbuf; + if (prefreg) + { + if (((LONG)xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, 0, IPC_GETVERSION) & 0xffffU) >= 0x5000) + { + xsfc::TWin32::WndMsgSend(hwndWinamp, WM_WA_IPC, &prefwork, IPC_OPENPREFSTOPAGE); + return; + } + } + + hrsrc = ::FindResourceA(hDLL, MAKEINTRESOURCE(1), RT_DIALOG); + if (!hrsrc) return; + + dwSize = ::SizeofResource(hDLL, hrsrc); + hGlobal = ::LoadResource(hDLL, hrsrc); + + if (dwSize < 4 || !hGlobal) return; + + if (!resbuf.Resize(dwSize)) return; + + LPBYTE lpResource = resbuf.Ptr(); + + ::CopyMemory(lpResource, hGlobal, dwSize); + + lpResource[0] = '\xc0'; + lpResource[1] = '\x08'; + lpResource[2] = '\xc8'; + lpResource[3] = '\x80'; + + xsfc::TWin32::DlgInvoke(::GetModuleHandleA(NULL), lpResource, NULL, DialogProc, NULL); +} \ No newline at end of file diff --git a/tools/vio2sf/src/xsfc/in_xsfcfg.h b/tools/vio2sf/src/xsfc/in_xsfcfg.h new file mode 100644 index 000000000..c2f701150 --- /dev/null +++ b/tools/vio2sf/src/xsfc/in_xsfcfg.h @@ -0,0 +1,17 @@ +#include "xsfcfg.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +void winamp_config_init(HINSTANCE hinstDLL); +void winamp_config_load(HWND hwndWinamp); +void winamp_config_add_prefs(HWND hwndWinamp); +void winamp_config_remove_prefs(HWND hwndWinamp); +void winamp_config_dialog(HWND hwndWinamp, HWND hwndParent); + +#ifdef __cplusplus +} +#endif + diff --git a/tools/vio2sf/src/xsfc/kpixsf.c b/tools/vio2sf/src/xsfc/kpixsf.c new file mode 100644 index 000000000..6f9bbdb2d --- /dev/null +++ b/tools/vio2sf/src/xsfc/kpixsf.c @@ -0,0 +1,353 @@ +#define STRICT +#define WIN32_LEAN_AND_MEAN +#include "leakchk.h" + +#include +#include +#include +#include + +#include "../kobarin/kmp_pi.h" + +#include "xsfdrv.h" + +#include "../pversion.h" +#include "tagget.h" + +#ifndef ENABLE_LOADPE +#if !defined(_DEBUG) +#define ENABLE_LOADPE 1 +#else +#define ENABLE_LOADPE 0 +#endif +#endif + +#if ENABLE_LOADPE +#include "../loadpe/loadpe.h" +#else +#define XLoadLibraryA LoadLibraryA +#define XLoadLibraryW LoadLibraryW +#define XGetProcAddress GetProcAddress +#define XFreeLibrary FreeLibrary +#endif + +#if _MSC_VER >= 1200 +#pragma comment(linker, "/EXPORT:kmp_GetTestModule=_kmp_GetTestModule@0") +#endif + +#if defined(_MSC_VER) && !defined(_DEBUG) +#pragma comment(linker,"/MERGE:.rdata=.text") +#endif + +static HMODULE hDLL = 0; +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + (void)lpvReserved; + if (fdwReason == DLL_PROCESS_ATTACH) + { +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + hDLL = hinstDLL; + DisableThreadLibraryCalls(hinstDLL); + } + return TRUE; +} + +typedef struct { + char sBasepath[MAX_PATH]; + HMODULE hDrv; + IXSFDRV *lpif; + int bTop; + int bVolume; + float fVolume; + DWORD dwFileLen; + BYTE bFileBuf[4]; +} KMP; + + +static void *loadfileA(const char *fn, unsigned *plength) +{ + void *ret = NULL; + HANDLE h = CreateFileA(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h != INVALID_HANDLE_VALUE) + { + unsigned length; + void *buf; + length = GetFileSize(h, NULL); + buf = malloc(length); + if (buf) + { + DWORD dwNumberOfBytesRead; + ReadFile(h, buf, length, &dwNumberOfBytesRead, NULL); + ret = buf; + if (plength) *plength = length; + } + CloseHandle(h); + } + return ret; +} + + +static int PASCAL XSFGETLIBCALLBACK(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize) +{ + DWORD dwNumberOfBytesRead; + void *filebuf; + DWORD size; + KMP *p = lpWork; + + HANDLE h = CreateFileA(lpszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h == INVALID_HANDLE_VALUE) + { + char sCanPath[MAX_PATH]; + char sExtPath[MAX_PATH]; + if (lstrlenA(p->sBasepath) + lstrlenA(lpszFilename) + 1 >= MAX_PATH) + { + return 1; + } + lstrcpyA(sExtPath, p->sBasepath); + lstrcatA(sExtPath, lpszFilename); + if (!PathCanonicalizeA(sCanPath, sExtPath)) + lstrcpyA(sCanPath, sExtPath); + h = CreateFileA(sCanPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h == INVALID_HANDLE_VALUE) + { + lstrcpyA(sExtPath, p->sBasepath); + lstrcatA(sExtPath, PathFindFileNameA(lpszFilename)); + if (!PathCanonicalizeA(sCanPath, sExtPath)) + lstrcpyA(sCanPath, sExtPath); + h = CreateFileA(sCanPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h == INVALID_HANDLE_VALUE) + { + return 1; + } + } + } + + size = GetFileSize(h, NULL); + + filebuf = p->lpif->LibAlloc(size); + + if (!filebuf) + { + CloseHandle(h); + return 1; + } + + ReadFile(h, filebuf, size, &dwNumberOfBytesRead, NULL); + CloseHandle(h); + + *ppBuffer = filebuf; + *pdwSize = size; + + return 0; +} + + +static HKMP WINAPI OpenFromBufferSub(const char *cszFileName, const BYTE *Buffer, DWORD dwSize, SOUNDINFO *pInfo) +{ + HKMP ret = NULL; + KMP *p; + LPFNXSFDRVSETUP lpfnXSFSetup; + LPSTR lpFilePart; + char *taglength; + char *tagvolume; + DWORD dwLength; + + CHAR dllpath[MAX_PATH]; + CHAR binpath[MAX_PATH]; + + if (!pInfo) return ret; + p = (KMP *)malloc(sizeof(KMP) + dwSize - 4); + if (!p) return ret; + + if (cszFileName) + { + LPSTR lpscut = 0; + GetFullPathNameA(cszFileName, MAX_PATH, p->sBasepath, &lpscut); + if (lpscut) *lpscut = 0; + } + else + { + p->sBasepath[0] = 0; + } + + p->lpif = 0; + p->dwFileLen = dwSize; + + GetModuleFileNameA(hDLL, dllpath, MAX_PATH); + GetFullPathNameA(dllpath, MAX_PATH, binpath, &lpFilePart); + lstrcpyA(lpFilePart, XSFDRIVER_MODULENAME); + + p->hDrv = XLoadLibraryA(binpath); + if (!p->hDrv) + { + free(p); + return ret; + } + + lpfnXSFSetup = (LPFNXSFDRVSETUP)XGetProcAddress(p->hDrv, XSFDRIVER_ENTRYNAME); + if (!lpfnXSFSetup) + { + XFreeLibrary(p->hDrv); + p->hDrv = 0; + free(p); + return ret; + } + + CopyMemory(p->bFileBuf, Buffer, dwSize); + + p->lpif = lpfnXSFSetup(XSFGETLIBCALLBACK ,p); + if (!p->lpif || p->lpif->Start(p->bFileBuf, p->dwFileLen)) + { + if (p->lpif) + p->lpif->Term(); + XFreeLibrary(p->hDrv); + p->lpif = 0; + p->hDrv = 0; + free(p); + return ret; + } + p->bTop = 1; + + ret = (HKMP)p; +#ifndef XSFDRIVER_SAMPLERATE + pInfo->dwSamplesPerSec = 44100; +#else + pInfo->dwSamplesPerSec = XSFDRIVER_SAMPLERATE; +#endif + pInfo->dwChannels = 2; + pInfo->dwBitsPerSample = 16; + pInfo->dwLength = 0xFFFFFFFF; + pInfo->dwSeekable = 0; + pInfo->dwUnitRender = 0x100; + pInfo->dwReserved1 = 1; + pInfo->dwReserved2 = 0; + taglength = xsf_tagget("length", p->bFileBuf,p->dwFileLen); + if (taglength) + { + dwLength = tag2ms(taglength); + if (dwLength) + { + pInfo->dwLength = dwLength; + } + free(taglength); + } + p->bVolume = 0; + p->fVolume = 1.0; + tagvolume = xsf_tagget("volume", p->bFileBuf,p->dwFileLen); + if (tagvolume) + { + float volume = (float)atof(tagvolume); + p->fVolume = volume; + p->bVolume = (p->fVolume != 1.0); + free(tagvolume); + } + return ret; +} + +static HKMP WINAPI Open(const char *cszFileName, SOUNDINFO *pInfo) +{ + HKMP ret = NULL; + void *buffer; + DWORD size; + if (!pInfo) return ret; + buffer = loadfileA(cszFileName, &size); + if (buffer) + { + ret = OpenFromBufferSub(cszFileName, (const BYTE *)buffer, size, pInfo); + free(buffer); + } + return ret; +} + + +static void WINAPI Close(HKMP hKMP) +{ + KMP *p = (KMP *)hKMP; + if (p) + { + if (p->lpif) + { + p->lpif->Term(); + p->lpif = 0; + } + if (p->hDrv) + { + XFreeLibrary(p->hDrv); + p->hDrv = 0; + } + free(p); + } +} + +static DWORD WINAPI Render(HKMP hKMP, BYTE* Buffer, DWORD dwSize) +{ + KMP *p = (KMP *)hKMP; + p->bTop = 0; + p->lpif->Gen(Buffer, (dwSize >> 2)); + if (p->bVolume) + { + DWORD i; + for (i = 0; i < dwSize; i += 4) + { + float s1 = ((short *)(Buffer + i))[0]; + float s2 = ((short *)(Buffer + i))[1]; + s1 *= p->fVolume; + if (s1 > (float)0x7fff) + s1 = (float)0x7fff; + else if (s1 < (float)-0x8000) + s1 = (float)-0x8000; + s2 *= p->fVolume; + if (s2 > (float)0x7fff) + s2 = (float)0x7fff; + else if (s2 < (float)-0x8000) + s2 = (float)-0x8000; + ((short *)(Buffer + i))[0] = (short)s1; + ((short *)(Buffer + i))[1] = (short)s2; + } + } + return dwSize; +} + +static DWORD WINAPI SetPosition(HKMP hKMP, DWORD dwPos) +{ + KMP *p = (KMP *)hKMP; + if (p->bTop && dwPos == 0) + { + } + else + { + p->lpif->Start(p->bFileBuf, p->dwFileLen); + p->bTop = 1; + } + return 0; +} + +KBMEDIAPLUGIN_EXTS(exts) + +static const KMPMODULE mod = +{ + KMPMODULE_VERSION, + KBMEDIAPLUGIN_VERSION, + KBMEDIAPLUGIN_COPYRIGHT, + KBMEDIAPLUGIN_NAME, + (const char **)exts, +#if ENABLE_LOADPE + 1, +#else + 0, +#endif + NULL, + NULL, + Open, + NULL, + Close, + Render, + SetPosition +}; + +KMPMODULE* WINAPI KMP_GETMODULE(void) +{ + return (KMPMODULE*)&mod; +} \ No newline at end of file diff --git a/tools/vio2sf/src/xsfc/leakchk.h b/tools/vio2sf/src/xsfc/leakchk.h new file mode 100644 index 000000000..23a9e887e --- /dev/null +++ b/tools/vio2sf/src/xsfc/leakchk.h @@ -0,0 +1,13 @@ +#ifndef LEAKCHK_H +#define LEAKCHK_H + +#if defined(_MSC_VER) && defined(_DEBUG) +#define _CRTDBG_MAP_ALLOC +#include +#include +/* +#define new ::new(_CLIENT_BLOCK, __FILE__, __LINE__) +*/ +#endif + +#endif diff --git a/tools/vio2sf/src/xsfc/tagget.h b/tools/vio2sf/src/xsfc/tagget.h new file mode 100644 index 000000000..bdc7e48e3 --- /dev/null +++ b/tools/vio2sf/src/xsfc/tagget.h @@ -0,0 +1,525 @@ +#ifdef __cplusplus + +#include "xsfc.h" +class XSFTag +{ +protected: + XSFTag() + { + } + + ~XSFTag() + { + } + + static unsigned long GetWordLE(const void *pData) + { + const unsigned char *pdata = static_cast(pData); + return pdata[0] | (unsigned long(pdata[1]) << 8) | (unsigned long(pdata[2]) << 16) | (unsigned long(pdata[3]) << 24); + } + +public: + + static unsigned long SearchRaw(const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + unsigned long dwPos; + unsigned long dwReservedAreaSize; + unsigned long dwProgramLength; + unsigned long dwProgramCRC; + if (dwSize < 16 + 5 + 1) return 0; + if (pdata[0] != 'P') return 0; + if (pdata[1] != 'S') return 0; + if (pdata[2] != 'F') return 0; + dwReservedAreaSize = GetWordLE(pdata + 4); + dwProgramLength = GetWordLE(pdata + 8); + dwProgramCRC = GetWordLE(pdata + 12); + dwPos = 16 + dwReservedAreaSize + dwProgramLength; + if (dwPos >= dwSize) return 0; + return dwPos; + } + + static int Search(unsigned long *pdwRet, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + unsigned long dwPos = SearchRaw(pdata, dwSize); + if (dwSize < dwPos + 5) return 0; + if (memcmp(pdata + dwPos, "[TAG]", 5)) return 0; + *pdwRet = dwPos + 5; + return 1; + } + + enum enum_callback_returnvalue + { + enum_continue = 0, + enum_break = 1 + }; + + typedef enum enum_callback_returnvalue (*pfnenum_callback_t)(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd); + static int EnumRaw(pfnenum_callback_t pCallBack, void *pWork, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + unsigned long dwPos = 0; + while (dwPos < dwSize) + { + unsigned long dwNameTop; + unsigned long dwNameEnd; + unsigned long dwValueTop; + unsigned long dwValueEnd; + if (dwPos < dwSize && pdata[dwPos] == 0x0a) dwPos++; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && 0x00 <= pdata[dwPos] && pdata[dwPos] <= 0x20) + dwPos++; + if (dwPos >= dwSize || pdata[dwPos] == 0x0a) continue; + dwNameTop = dwPos; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && pdata[dwPos] != '=') + dwPos++; + if (dwPos >= dwSize || pdata[dwPos] == 0x0a) continue; + dwNameEnd = dwPos; + while (dwNameTop < dwNameEnd && 0x00 <= pdata[dwNameEnd - 1] && pdata[dwNameEnd - 1] <= 0x20) + dwNameEnd--; + if (dwPos < dwSize && pdata[dwPos] == '=') dwPos++; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && 0x00 <= pdata[dwPos] && pdata[dwPos] <= 0x20) + dwPos++; + dwValueTop = dwPos; + while (dwPos < dwSize && pdata[dwPos] != 0x0a) + dwPos++; + dwValueEnd = dwPos; + while (dwValueTop < dwValueEnd && 0x00 <= pdata[dwValueEnd - 1] && pdata[dwValueEnd - 1] <= 0x20) + dwValueEnd--; + + if (pCallBack) + { + if (enum_continue != pCallBack(pWork, pdata + dwNameTop, pdata + dwNameEnd, pdata + dwValueTop, pdata + dwValueEnd)) + return -1; + } + } + return 1; + } + + static int Enum(pfnenum_callback_t pCallBack, void *pWork, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + unsigned long dwPos = 0; + if (!Search(&dwPos, pdata, dwSize)) + return 0; + return EnumRaw(pCallBack, pWork, pdata + dwPos, dwSize - dwPos); + } + +protected: + + typedef struct + { + int taglen; + const char *tag; + bool ret; + } xsf_tagexists_work_t; + + static enum enum_callback_returnvalue enum_callback_tagexists(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + xsf_tagexists_work_t *pwork = static_cast(pWork); + (void)pValueTop, pValueEnd; + if (pwork->taglen == pNameEnd - pNameTop && !_strnicmp(pNameTop, pwork->tag, pwork->taglen)) + { + pwork->ret = true; + return enum_break; + } + return enum_continue; + } + +public: + + static bool ExistsRaw(const char *tag, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + xsf_tagexists_work_t work; + work.ret = false; + work.tag = tag; + work.taglen = (unsigned long)strlen(tag); + EnumRaw(enum_callback_tagexists, &work, pdata, dwSize); + return work.ret; + } + + static bool Exists(const char *tag, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + xsf_tagexists_work_t work; + work.ret = false; + work.tag = tag; + work.taglen = (unsigned long)strlen(tag); + Enum(enum_callback_tagexists, &work, pdata, dwSize); + return work.ret; + } + +protected: + + typedef struct + { + int taglen; + const char *tag; + xsfc::TString ret; + bool futf8; + } xsf_tagget_work_t; + + static enum enum_callback_returnvalue enum_callback_tagget(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) + { + xsf_tagget_work_t *pwork = static_cast(pWork); + if (pwork->taglen == pNameEnd - pNameTop && !_strnicmp(pNameTop, pwork->tag, pwork->taglen)) + { + pwork->ret = xsfc::TString(pwork->futf8, pValueTop, pValueEnd - pValueTop); + return enum_break; + } + return enum_continue; + } + +public: + + static xsfc::TString GetRaw(bool fUTF8, const char *tag, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + xsf_tagget_work_t work; + xsfc::TString ret; + work.futf8 = fUTF8; + work.tag = tag; + work.taglen = (unsigned long)strlen(tag); + EnumRaw(enum_callback_tagget, &work, pdata, dwSize); + ret = work.ret; + return ret; + } + static xsfc::TString GetRaw(const char *tag, const void *pData, size_t dwSize) + { + return GetRaw(ExistsRaw("utf8", pData, dwSize), tag, pData, dwSize); + } + + static xsfc::TString Get(bool fUTF8, const char *tag, const void *pData, size_t dwSize) + { + const char *pdata = static_cast(pData); + xsf_tagget_work_t work; + xsfc::TString ret; + work.futf8 = fUTF8; + work.tag = tag; + work.taglen = (unsigned long)strlen(tag); + Enum(enum_callback_tagget, &work, pdata, dwSize); + ret = work.ret; + return ret; + } + static xsfc::TString Get(const char *tag, const void *pData, size_t dwSize) + { + return Get(Exists("utf8", pData, dwSize), tag, pData, dwSize); + } + + + static int GetInt(const char *tag, const void *pData, size_t dwSize, int value_default) + { + const char *pdata = static_cast(pData); + int ret = value_default; + xsfc::TString value = Get(tag, pdata, dwSize); + if (value[0]) ret = atoi(xsfc::TStringM(value)); + return ret; + } + + static double GetFloat(const char *tag, const void *pData, size_t dwSize, double value_default) + { + const char *pdata = static_cast(pData); + double ret = value_default; + xsfc::TString value = Get(tag, pdata, dwSize); + if (value[0]) ret = atof(xsfc::TStringM(value)); + return ret; + } + + static unsigned long ToMS(const wchar_t *p) + { + int f = 0; + unsigned long b = 0; + unsigned long r = 0; + for (;*p; p++) + { + if (*p >= L'0' && *p <= L'9') + { + if (f < 1000) + { + r = r * 10 + *p - L'0'; + if (f) f *= 10; + continue; + } + break; + } + if (*p == L'.') + { + f = 1; + continue; + } + if (*p == L':') + { + b = (b + r) * 60; + r = 0; + continue; + } + break; + } + if (f < 10) + r *= 1000; + else if (f == 10) + r *= 100; + else if (f == 100) + r *= 10; + r += b * 1000; + return r; + } + + static unsigned GetLengthMS(const void *idata, size_t isize, unsigned defaultlength) + { + unsigned length = 0; + xsfc::TString taglength = XSFTag::Get("length", idata, isize); + if (taglength[0]) length = XSFTag::ToMS(taglength); + if (!length) length = defaultlength; + return length; + } + static unsigned GetLengthMS(xsfc::TAutoBuffer idata, unsigned defaultlength) + { + return GetLengthMS(idata.Ptr(), idata.Len(), defaultlength); + } + + static unsigned GetFadeMS(const void *idata, size_t isize, unsigned defaultfade) + { + unsigned fade = defaultfade; + xsfc::TString tagfade = XSFTag::Get("fade", idata, isize); + if (tagfade[0]) fade = XSFTag::ToMS(tagfade); + return fade; + } + static unsigned GetFadeMS(xsfc::TAutoBuffer idata, unsigned defaultfade) + { + return GetFadeMS(idata.Ptr(), idata.Len(), defaultfade); + } + + static bool GetVolume(float *pvolume, const char *tag, xsfc::TAutoBuffer idata, int isgain) + { + bool hasvolume = false; + xsfc::TString tagvolume = XSFTag::Get(tag, idata.Ptr(), idata.Len()); + if (tagvolume[0]) + { + float value = float(tagvolume.GetFloat()); + if (isgain) + *pvolume *= float(pow(2.0, value / 6.0)); + else + *pvolume = value; + hasvolume = (*pvolume != 1.0); + } + return !hasvolume; + } + +}; +#else + +static DWORD getdwordle(const BYTE *pData) +{ + return pData[0] | (((DWORD)pData[1]) << 8) | (((DWORD)pData[2]) << 16) | (((DWORD)pData[3]) << 24); +} + +static DWORD xsf_tagsearchraw(const void *pData, DWORD dwSize) +{ + const BYTE *pdata = (const BYTE *)pData; + DWORD dwPos; + DWORD dwReservedAreaSize; + DWORD dwProgramLength; + DWORD dwProgramCRC; + if (dwSize < 16 + 5 + 1) return 0; + if (pdata[0] != 'P') return 0; + if (pdata[1] != 'S') return 0; + if (pdata[2] != 'F') return 0; + dwReservedAreaSize = getdwordle(pdata + 4); + dwProgramLength = getdwordle(pdata + 8); + dwProgramCRC = getdwordle(pdata + 12); + dwPos = 16 + dwReservedAreaSize + dwProgramLength; + if (dwPos >= dwSize) return 0; + return dwPos; +} +static int xsf_tagsearch(DWORD *pdwRet, const BYTE *pData, DWORD dwSize) +{ + DWORD dwPos = xsf_tagsearchraw(pData, dwSize); + if (dwSize < dwPos + 5) return 0; + if (memcmp(pData + dwPos, "[TAG]", 5)) return 0; + *pdwRet = dwPos + 5; + return 1; +} + +enum xsf_tagenum_callback_returnvalue +{ + xsf_tagenum_callback_returnvaluecontinue = 0, + xsf_tagenum_callback_returnvaluebreak = 1 +}; +typedef int (*pfnxsf_tagenum_callback_t)(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd); +static int xsf_tagenumraw(pfnxsf_tagenum_callback_t pCallBack, void *pWork, const void *pData, DWORD dwSize) +{ + const char *pdata = (const char *)pData; + DWORD dwPos = 0; + while (dwPos < dwSize) + { + DWORD dwNameTop; + DWORD dwNameEnd; + DWORD dwValueTop; + DWORD dwValueEnd; + if (dwPos < dwSize && pdata[dwPos] == 0x0a) dwPos++; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && 0x00 <= pdata[dwPos] && pdata[dwPos] <= 0x20) + dwPos++; + if (dwPos >= dwSize || pdata[dwPos] == 0x0a) continue; + dwNameTop = dwPos; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && pdata[dwPos] != '=') + dwPos++; + if (dwPos >= dwSize || pdata[dwPos] == 0x0a) continue; + dwNameEnd = dwPos; + while (dwNameTop < dwNameEnd && 0x00 <= pdata[dwNameEnd - 1] && pdata[dwNameEnd - 1] <= 0x20) + dwNameEnd--; + if (dwPos < dwSize && pdata[dwPos] == '=') dwPos++; + while (dwPos < dwSize && pdata[dwPos] != 0x0a && 0x00 <= pdata[dwPos] && pdata[dwPos] <= 0x20) + dwPos++; + dwValueTop = dwPos; + while (dwPos < dwSize && pdata[dwPos] != 0x0a) + dwPos++; + dwValueEnd = dwPos; + while (dwValueTop < dwValueEnd && 0x00 <= pdata[dwValueEnd - 1] && pdata[dwValueEnd - 1] <= 0x20) + dwValueEnd--; + + if (pCallBack) + { + if (xsf_tagenum_callback_returnvaluecontinue != pCallBack(pWork, (const char *)pdata + dwNameTop, (const char *)pdata + dwNameEnd, (const char *)pdata + dwValueTop, (const char *)pdata + dwValueEnd)) + return -1; + } + } + return 1; +} + +static int xsf_tagenum(pfnxsf_tagenum_callback_t pCallBack, void *pWork, const void *pData, DWORD dwSize) +{ + const BYTE *pdata = (const BYTE *)pData; + DWORD dwPos = 0; + if (!xsf_tagsearch(&dwPos, pdata, dwSize)) + return 0; + return xsf_tagenumraw(pCallBack, pWork, pdata + dwPos, dwSize - dwPos); +} + +typedef struct +{ + int taglen; + const char *tag; + char *ret; +} xsf_tagget_work_t; + +static int xsf_tagenum_callback_tagget(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) +{ + xsf_tagget_work_t *pwork = (xsf_tagget_work_t *)pWork; + if (pwork->taglen == pNameEnd - pNameTop && !_strnicmp(pNameTop, pwork->tag, pwork->taglen)) + { + char *ret = (char *)malloc(pValueEnd - pValueTop + 1); + if (!ret) return xsf_tagenum_callback_returnvaluecontinue; + memcpy(ret, pValueTop, pValueEnd - pValueTop); + ret[pValueEnd - pValueTop] = 0; + pwork->ret = ret; + return xsf_tagenum_callback_returnvaluebreak; + } + return xsf_tagenum_callback_returnvaluecontinue; +} + +static char *xsf_taggetraw(const char *tag, const void *pData, DWORD dwSize) +{ + const BYTE *pdata = (const BYTE *)pData; + xsf_tagget_work_t work; + work.ret = 0; + work.tag = tag; + work.taglen = (DWORD)strlen(tag); + xsf_tagenumraw(xsf_tagenum_callback_tagget, &work, pdata, dwSize); + return work.ret; +} + +static char *xsf_tagget(const char *tag, const void *pData, DWORD dwSize) +{ + const BYTE *pdata = (const BYTE *)pData; + xsf_tagget_work_t work; + work.ret = 0; + work.tag = tag; + work.taglen = (DWORD)strlen(tag); + xsf_tagenum(xsf_tagenum_callback_tagget, &work, pdata, dwSize); + return work.ret; +} + +static int xsf_tagget_exist(const char *tag, const void *pData, DWORD dwSize) +{ + const BYTE *pdata = (const BYTE *)pData; + int exists; + char *value = xsf_tagget(tag, pdata, dwSize); + if (value) + { + exists = 1; + free(value); + } + else + { + exists = 0; + } + return exists; +} + +static int xsf_tagget_int(const char *tag, const BYTE *pData, DWORD dwSize, int value_default) +{ + int ret = value_default; + char *value = xsf_tagget(tag, pData, dwSize); + if (value) + { + if (*value) ret = atoi(value); + free(value); + } + return ret; +} + +static double xsf_tagget_float(const char *tag, const BYTE *pData, DWORD dwSize, double value_default) +{ + double ret = value_default; + char *value = xsf_tagget(tag, pData, dwSize); + if (value) + { + if (*value) ret = atof(value); + free(value); + } + return ret; +} + +static DWORD tag2ms(const char *p) +{ + int f = 0; + DWORD b = 0; + DWORD r = 0; + for (;*p; p++) + { + if (*p >= '0' && *p <= '9') + { + if (f < 1000) + { + r = r * 10 + *p - '0'; + if (f) f *= 10; + continue; + } + break; + } + if (*p == '.') + { + f = 1; + continue; + } + if (*p == ':') + { + b = (b + r) * 60; + r = 0; + continue; + } + break; + } + if (f < 10) + r *= 1000; + else if (f == 10) + r *= 100; + else if (f == 100) + r *= 10; + r += b * 1000; + return r; +} + +#endif diff --git a/tools/vio2sf/src/xsfc/winresx.h b/tools/vio2sf/src/xsfc/winresx.h new file mode 100644 index 000000000..724086da3 --- /dev/null +++ b/tools/vio2sf/src/xsfc/winresx.h @@ -0,0 +1,8 @@ +#if defined(_MSC_VER) && (_MSC_VER < 1400) +# include +#else +# include +#endif +#ifndef IDC_STATIC +# define IDC_STATIC -1 +#endif diff --git a/tools/vio2sf/src/xsfc/xsfc.cpp b/tools/vio2sf/src/xsfc/xsfc.cpp new file mode 100644 index 000000000..50bef9b97 --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfc.cpp @@ -0,0 +1,534 @@ +#ifdef HAVE_STDINT_H +#include +#elif (defined(_MSC_VER) && (_MSC_VER >= 1200)) +#define int64_t signed __int64 +#define uint64_t unsigned __int64 +#elif (defined(__BORLANDC__ ) && (__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__)) +#define int64_t signed __int64 +#define uint64_t unsigned __int64 +#elif (defined(__WATCOMC__) && (__WATCOMC__ >= 1100)) +#define int64_t signed __int64 +#define uint64_t unsigned __int64 +#else +#error "64 bit integer variables are required." +#endif + +#define WIN32_LEAN_AND_MEAN +#include "leakchk.h" + +#include +#include + +#include "xsfc.h" + + +#if _MSC_VER >= 1200 +#pragma warning(disable:4290) +#endif + +namespace +{ + +class FileHandle +{ +protected: + HANDLE h; + + inline HANDLE Handle() + { + return h; + } + + static xsfc::TString FNExtend(const wchar_t *fn) throw(xsfc::EShortOfMemory) + { + if (fn && fn[0] == L'\\' && fn[1] == L'\\' && fn[2] != L'?') + return xsfc::TString("\\\\?\\UNC") + (fn + 1); + if (fn && fn[0] && fn[1] == L':' && fn[2] == L'\\') + return xsfc::TString("\\\\?\\") + fn; + return xsfc::TString(); + } + + static HANDLE ReadOpen(const WCHAR *fn) throw() + { + HANDLE h = INVALID_HANDLE_VALUE; + try + { + if (xsfc::TWin32::IsUnicodeSupportedOS()) + { + xsfc::TString fnw = FNExtend(fn); + h = CreateFileW(fnw ? fnw : fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); +/* + if (h == INVALID_HANDLE_VALUE) + { + h = CreateFileW(fn, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h == INVALID_HANDLE_VALUE) + { + DWORD dw = GetLastError(); + OutputDebugStringA(""); + (void)dw; + } + } +*/ + } + else + { + h = CreateFileA(xsfc::TStringM(fn), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + } + } + catch (xsfc::EShortOfMemory e) + { + } + return h; + } + +public: + inline bool Opened() + { + return Handle() != INVALID_HANDLE_VALUE; + } + + FileHandle(HANDLE hfile = INVALID_HANDLE_VALUE) + : h(hfile) + { + } + + FileHandle(const wchar_t *path) + : h(ReadOpen(path)) + { + } + + ~FileHandle() + { + if (Opened()) + { + CloseHandle(Handle()); + } + } + + size_t Length() + { + if (Opened()) + { + DWORD dwH = 0; + DWORD dwL = GetFileSize(Handle(), &dwH); + if (dwL != DWORD(0xFFFFFFFF) || GetLastError() == NO_ERROR) + { + if (dwH) + { + uint64_t s64 = ((((uint64_t)dwH) << 32) | dwL); + size_t s = size_t(s64); + if (s == s64) return s; + } + else + { + size_t s = size_t(dwL); + if (s == dwL) return s; + } + } + } + return 0; + } + size_t Read(void *p, size_t l) + { + if (Opened()) + { + DWORD nNumberOfBytesToRead = DWORD(l); + DWORD dwNumberOfBytesRead = 0; + if (l == nNumberOfBytesToRead) + { + if (!ReadFile(Handle(), p, nNumberOfBytesToRead, &dwNumberOfBytesRead, 0)) + dwNumberOfBytesRead = 0; + } + size_t s = size_t(dwNumberOfBytesRead); + if (s == dwNumberOfBytesRead) + return s; + } + return 0; + } +}; + +} + +namespace xsfc +{ + +static UINT GetFileCP(void) throw() +{ + return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; +} + +size_t TIConv::ToWide(bool isUTF8, const char *s, size_t sl, wchar_t *d, size_t dl) throw() +{ + UINT cp = isUTF8 ? CP_UTF8 : GetFileCP(); + DWORD flag = 0; + return ::MultiByteToWideChar(cp, flag, s, (int)sl, d, (int)dl); +} + +size_t TIConv::ToMulti(bool isUTF8, const wchar_t *s, size_t sl, char *d, size_t dl) throw() +{ + UINT cp = isUTF8 ? CP_UTF8 : GetFileCP(); + DWORD flag = 0; + return ::WideCharToMultiByte(cp, flag, s, (int)sl, d, (int)dl, 0, 0); +} + +bool TWin32::IsUnicodeSupportedOS(void) throw() +{ + return !(::GetVersion() & 0x80000000); +} + +bool TWin32::IsPathSeparator(char c) throw() +{ + return c == ':' || c == '\\' || c == '/' || c == '|'; +} + +bool TWin32::IsPathSeparator(wchar_t c) throw() +{ + return c == L':' || c == L'\\' || c == L'/' || c == L'|'; +} + +const char *TWin32::NextChar(const char *p) +{ + return ::IsDBCSLeadByte(*p) ? p + 2 : p + 1; +} + +const wchar_t *TWin32::NextChar(const wchar_t *p) +{ + return p + 1; +} + +template class WndMsgSendHelper +{ +public: + static void *Invoke(void *hwnd, unsigned msg, T1 wp, T2 lp) throw() + { + return (void *)(TWin32::IsUnicodeSupportedOS() ? ::SendMessageW : ::SendMessageA) (static_cast(hwnd), msg, WPARAM(wp), LPARAM(lp)); + } +}; + +void *TWin32::WndMsgSend(void *hwnd, unsigned msg, const void *wp, const void *lp) +{ + return WndMsgSendHelper::Invoke(hwnd, msg, wp, lp); +} +void *TWin32::WndMsgSend(void *hwnd, unsigned msg, const void *wp, int lp) +{ + return WndMsgSendHelper::Invoke(hwnd, msg, wp, lp); +} +void *TWin32::WndMsgSend(void *hwnd, unsigned msg, int wp, const void *lp) +{ + return WndMsgSendHelper::Invoke(hwnd, msg, wp, lp); +} +void *TWin32::WndMsgSend(void *hwnd, unsigned msg, int wp, int lp) +{ + return WndMsgSendHelper::Invoke(hwnd, msg, wp, lp); +} + +void TWin32::WndMsgPost(void *hwnd, unsigned msg, const void *wp, const void *lp) +{ + (IsUnicodeSupportedOS() ? ::PostMessageW : ::PostMessageA) (static_cast(hwnd), msg, WPARAM(wp), LPARAM(lp)); +} + +void *TWin32::WndGetLongPtr(void *hwnd, int idx) +{ +#ifdef GetWindowLongPtr + return (void *)(LONG_PTR)(IsUnicodeSupportedOS() ? ::GetWindowLongPtrW : ::GetWindowLongPtrA) (static_cast(hwnd), idx); +#else + return (void *)(IsUnicodeSupportedOS() ? ::GetWindowLongW : ::GetWindowLongA) (static_cast(hwnd), idx); +#endif +} +void *TWin32::WndSetLongPtr(void *hwnd, int idx, void *ptr) +{ +#ifdef SetWindowLongPtr +#ifdef _WIN64 + if (IsUnicodeSupportedOS()) + return (void *)(LONG_PTR) ::SetWindowLongPtrW(static_cast(hwnd), idx, (LONG_PTR)ptr); + else + return (void *)(LONG_PTR) ::SetWindowLongPtrA(static_cast(hwnd), idx, (LONG_PTR)ptr); +#else + if (IsUnicodeSupportedOS()) + return (void *)(LONG_PTR) ::SetWindowLongW(static_cast(hwnd), idx, (LONG)(LONG_PTR)ptr); + else + return (void *)(LONG_PTR) ::SetWindowLongA(static_cast(hwnd), idx, (LONG)(LONG_PTR)ptr); +#endif +#else + return (void *)(IsUnicodeSupportedOS() ? ::SetWindowLongW : ::SetWindowLongA) (static_cast(hwnd), idx, (LONG)ptr); +#endif +} + +TString TWin32::ModulePath(void *hmod) throw(EShortOfMemory) +{ + TString ret; + if (IsUnicodeSupportedOS()) + { + WCHAR wbuf[MAX_PATH]; + wbuf[0] = 0; + ::GetModuleFileNameW((HINSTANCE)hmod, wbuf, MAX_PATH); + ret.SetW(wbuf, MAX_PATH); + } + else + { + char mbuf[MAX_PATH]; + mbuf[0] = 0; + ::GetModuleFileNameA((HINSTANCE)hmod, mbuf, MAX_PATH); + ret.SetM(mbuf, MAX_PATH); + } + return ret; +} + +TString TWin32::ExtractPath(const wchar_t *p) throw(EShortOfMemory) +{ + int i, s; + for (s = i = 0; p[i]; i++) + { + if (IsPathSeparator(p[i])) + s = i + 1; + } + + return TString(p, s); +} + +TString TWin32::ExtractFileName(const wchar_t *p) throw(EShortOfMemory) +{ + return TString(TWin32T::ExtractFilename(p)); +} + +TString TWin32::CanonicalizePath(const wchar_t *p) throw(EShortOfMemory) +{ + size_t wl = StrNLen(p); + TAutoBuffer buf; + buf.Resize(wl + 1); + wchar_t *b = buf.Ptr(); + ::lstrcpyW(b, p); + bool e; + do + { + e = false; + wchar_t *f = 0; + for (wchar_t *c = b; *c; c++) + { + if (TWin32::IsPathSeparator(*c)) + { + if (f && c[1] == L'.' && c[2] == L'.') + { + f += 1; + c += 4; + while (0 != (*(f++) = *(c++))); + e = true; + break; + } + else + { + f = c; + } + } + } + } while (e); + TString ret(b); + buf.Free(); + return ret; +} + + +TString TWin32::GetPrivateProfile(const wchar_t *ininame, const wchar_t *appname, const wchar_t *keyname, const wchar_t *defaultvalue) throw(EShortOfMemory) +{ + if (IsUnicodeSupportedOS()) + { + size_t ret = 0; + size_t prevret = 0; + size_t bufsize = MAX_PATH; + TAutoBuffer buf; + do + { + prevret = ret; + bufsize += bufsize; + if (!buf.Resize(bufsize)) + throw EShortOfMemory(); + ret = ::GetPrivateProfileStringW(appname, keyname, defaultvalue, buf.Ptr(), DWORD(bufsize), ininame); + } + while (ret + 1== bufsize && ret != prevret); + return TString(buf.Ptr(), buf.Len()); + } + else + { + size_t ret = 0; + size_t prevret = 0; + size_t bufsize = MAX_PATH; + TAutoBuffer buf; + TStringM ininameM(ininame), appnameM(appname), keynameM(keyname), defaultvalueM(defaultvalue); + do + { + prevret = ret; + bufsize += bufsize; + if (!buf.Resize(bufsize)) + throw EShortOfMemory(); + ret = ::GetPrivateProfileStringA(appnameM, keynameM, defaultvalueM, buf.Ptr(), DWORD(bufsize), ininameM); + } + while (ret + 1 == bufsize && ret != prevret); + return TString(buf.Ptr(), buf.Len()); + } +} + +void TWin32::SetPrivateProfile(const wchar_t *ininame, const wchar_t *appname, const wchar_t *keyname, const wchar_t *value) throw() +{ + try + { + if (IsUnicodeSupportedOS()) + { + ::WritePrivateProfileStringW(appname, keyname, value, ininame); + } + else + { + TStringM ininameM(ininame), appnameM(appname), keynameM(keyname), valueM(value); + ::WritePrivateProfileStringA(appnameM, keynameM, valueM, ininameM); + } + } + catch (xsfc::EShortOfMemory e) + { + } +} + +void *TWin32::DlgCreate(void *hinst, int id, void *hwndParent, DLGPROC pProc, void *param) +{ + if (IsUnicodeSupportedOS()) + return (void *)::CreateDialogParamW(static_cast(hinst), MAKEINTRESOURCEW(id), static_cast(hwndParent), pProc, LPARAM(param)); + else + return (void *)::CreateDialogParamA(static_cast(hinst), MAKEINTRESOURCEA(id), static_cast(hwndParent), pProc, LPARAM(param)); +} +void *TWin32::DlgInvoke(void *hinst, const void *ptemp, void *hwndParent, DLGPROC pProc, void *param) +{ + if (IsUnicodeSupportedOS()) + return (void *)::DialogBoxIndirectParamW(static_cast(hinst), static_cast(ptemp), static_cast(hwndParent), pProc, LPARAM(param)); + else + return (void *)::DialogBoxIndirectParamA(static_cast(hinst), static_cast(ptemp), static_cast(hwndParent), pProc, LPARAM(param)); +} + + +void TWin32::DlgSetText(void *hwndDlg, int itm, TString text) throw() +{ + try + { + if (IsUnicodeSupportedOS()) + ::SetDlgItemTextW(static_cast(hwndDlg), itm, text); + else + ::SetDlgItemTextA(static_cast(hwndDlg), itm, TStringM(text)); + } + catch (xsfc::EShortOfMemory e) + { + } +} + +TString TWin32::DlgGetText(void *hwndDlg, int itm) throw(EShortOfMemory) +{ + TString ret; + if (IsUnicodeSupportedOS()) + { + WCHAR buf[32]; + ::GetDlgItemTextW(static_cast(hwndDlg), itm, buf, 32); + ret.SetW(buf, 32); + } + else + { + char buf[32]; + ::GetDlgItemTextA(static_cast(hwndDlg), itm, buf, 32); + ret.SetM(buf, 32); + } + return ret; +} + +static void *DlgItem(void *hwndDlg, int itm) +{ + return ::GetDlgItem(static_cast(hwndDlg), itm); +} + +void TWin32::DlgSetEnabled(void *hwndDlg, int itm, bool chk) +{ + ::EnableWindow(::GetDlgItem(static_cast(hwndDlg), itm), chk ? TRUE : FALSE); +} + + +void TWin32::DlgSetCheck(void *hwndDlg, int itm, bool chk) +{ + WndMsgSend(DlgItem(hwndDlg, itm), BM_SETCHECK, chk ? BST_CHECKED : BST_UNCHECKED, 0); +} + +bool TWin32::DlgGetCheck(void *hwndDlg, int itm) +{ + return (INT_PTR)WndMsgSend(DlgItem(hwndDlg, itm), BM_GETCHECK, 0, 0) == BST_CHECKED; +} + +void TWin32::DlgAddList(void *hwndDlg, int itm, TString item) +{ + try + { + if (IsUnicodeSupportedOS()) + WndMsgSend(DlgItem(hwndDlg, itm), LB_ADDSTRING, 0, item.GetW()); + else + WndMsgSend(DlgItem(hwndDlg, itm), LB_ADDSTRING, 0, TStringM(item).GetM()); + } + catch (xsfc::EShortOfMemory e) + { + } +} + +int TWin32::DlgCntList(void *hwndDlg, int itm) +{ + return (int)(INT_PTR)WndMsgSend(DlgItem(hwndDlg, itm), LB_GETCOUNT, 0, 0); +} + +int TWin32::DlgCurList(void *hwndDlg, int itm) +{ + return (int)(INT_PTR)WndMsgSend(DlgItem(hwndDlg, itm), LB_GETCURSEL, 0, 0); +} + +bool TWin32::DlgGetList(void *hwndDlg, int itm, int cur) +{ + return (INT_PTR)WndMsgSend(DlgItem(hwndDlg, itm), LB_GETSEL, cur, 0) > 0; +} + +void *TWin32::LoadEx(const wchar_t *path, size_t &loadsize, void *pwork, lpfnalloc palloc, lpfnfree pfree) +{ + void *p = 0; + void *ret = 0; + try + { + FileHandle h(path); + size_t s = h.Length(); + if (s && palloc) + { + p = palloc(pwork, s); + if (p && s == h.Read(p, s)) + { + loadsize = s; + ret = p; + p = 0; + } + } + } + catch (EShortOfMemory e) + { + } + if (p && pfree) pfree(pwork, p); + return ret; +} + +TAutoBuffer TWin32::Map(const wchar_t *path) +{ + TAutoBuffer ret; + try + { + FileHandle h(path); + size_t s = h.Length(); + if (s && ret.Resize(s)) + { + if (s != h.Read(ret.Ptr(), s)) + { + ret.Free(); + } + } + } + catch (EShortOfMemory e) + { + } + return ret; +} + +} diff --git a/tools/vio2sf/src/xsfc/xsfc.h b/tools/vio2sf/src/xsfc/xsfc.h new file mode 100644 index 000000000..3364aed08 --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfc.h @@ -0,0 +1,671 @@ +#if _MSC_VER >= 1200 +# pragma once +#endif + +#ifndef XSFC_H__ +#define XSFC_H__ + +#if _MSC_VER >= 1200 +#pragma warning(push) +#pragma warning(disable:4290) +#endif + +#ifdef __cplusplus + +#include +#include +#include +#include + +#if !defined(HAVE_SPRINTF_S) && !defined(HAVE_SNPRINTF_) && defined(_MSC_VER) +# if _MSC_VER >= 1400 +# define HAVE_SPRINTF_S +# elif _MSC_VER >= 1200 +# define HAVE_SNPRINTF_ +# endif +#endif + +namespace xsfc +{ + +const std::nothrow_t nothrow; + +class EBaseException +{ +protected: + EBaseException(int c) throw() + : Code(c) + { + } +public: + int Code; + EBaseException(const EBaseException &e) throw() + : Code(e.Code) + { + } + ~EBaseException() throw() {} +}; + +class EShortOfMemory : public EBaseException +{ +public: + EShortOfMemory() throw() + : EBaseException(1) + { + } + EShortOfMemory(const EShortOfMemory &e) throw() + : EBaseException(e) + { + } + ~EShortOfMemory() throw() {} +}; + +template class TAutoPtr +{ +protected: + T *ptr; + +public: + void Release() throw() + { + if (ptr) + { + delete ptr; + ptr = 0; + } + } + T *Ptr() const throw() + { + return ptr; + } + T *Detach() throw() + { + T *ret = ptr; + ptr = 0; + return ret; + } + TAutoPtr(T *p = 0) throw() + : ptr(p) + { + } + ~TAutoPtr() throw() + { + Release(); + } + T * operator->() const throw() + { + return ptr; + } + operator T *() const throw() + { + return ptr; + } + TAutoPtr &operator =(T *p) throw() + { + Release(); + ptr = p; + return *this; + } +}; + +template class TSimpleArray +{ +protected: + T *ptr; + size_t length; + + void Free() throw() + { + if (ptr) + { + delete [] ptr; + ptr = 0; + } + length = 0; + } + +public: + + ~TSimpleArray() throw() + { + Free(); + } + + TSimpleArray() throw() + : ptr(0), length(0) + { + } + + bool Resize(size_t l) throw() + { + Free(); + if (l > 0) + { + ptr = new(nothrow) T[l]; + if (ptr) length = l; + } + return ptr != 0 || l == 0; + } + + bool ResizeE(size_t l) + { + Free(); + if (l > 0) + { + ptr = new(nothrow) T[l]; + if (ptr) length = l; + } + return ptr != 0 || l == 0; + } + + inline T* Ptr() const throw() + { + return ptr; + } + + inline size_t Len() const throw() + { + return length; + } +}; + +template class TRefCnt +{ +protected: + T target; + unsigned count; + + ~TRefCnt() throw() + { + } + + TRefCnt() throw() + : count(0) + { + } + +public: + + void Release() throw() + { + if (--count == 0) + { + delete this; + } + } + + TRefCnt *AddRef() throw() + { + ++count; + return this; + } + + inline T &Target() throw() + { + return target; + } + + static TRefCnt *Create() throw() + { + TRefCnt *ret = new(nothrow) TRefCnt(); + return ret ? ret->AddRef() : 0; + } +}; + +template class TReference +{ +protected: + TRefCnt *refbuf; +public: + void Free() throw() + { + if (refbuf) + { + refbuf->Release(); + refbuf = 0; + } + } + + ~TReference() throw() + { + Free(); + } + + TReference(const bool fInitialze = true) throw() + : refbuf(fInitialze ? TRefCnt::Create() : 0) + { + } + + TReference(const TReference &s) throw() + : refbuf(s.refbuf ? s.refbuf->AddRef() : 0) + { + } + + TReference &operator =(const TReference &s) throw() + { + // AddRef must be called before than Free because refbuf may be equal to s.refbuf. + TRefCnt *newbuf = s.refbuf ? s.refbuf->AddRef() : 0; + Free(); + refbuf = newbuf; + return *this; + } + + inline T *Ptr() const throw() + { + return refbuf ? &refbuf->Target() : 0; + } +}; + +template class TAutoBuffer +{ +protected: + typedef TSimpleArray array_t; + TReference ref; + +public: + inline void Free() throw() + { + ref.Free(); + } + + bool Resize(size_t l) throw() + { + ref = TReference(true); + if (ref.Ptr() && !ref.Ptr()->Resize(l)) + { + ref.Free(); + } + return ref.Ptr()->Ptr() != 0; + } + + ~TAutoBuffer() throw() + { + } + + TAutoBuffer() throw() + : ref(false) + { + } + + TAutoBuffer(const TAutoBuffer &s) throw() + : ref(s.ref) + { + } + + TAutoBuffer &operator =(const TAutoBuffer &s) throw() + { + ref = s.ref; + return *this; + } + + T * Ptr() const throw() + { + array_t *ptr = ref.Ptr(); + return ptr ? ptr->Ptr() : 0; + } + + size_t Len() const throw() + { + array_t *ptr = ref.Ptr(); + return ptr ? ptr->Len() : 0; + } +}; + +class TIConv +{ +public: + static size_t ToWide(bool isUTF8, const char *s, size_t sl, wchar_t *d, size_t dl) throw(); + static size_t ToMulti(bool isUTF8, const wchar_t *s, size_t sl, char *d, size_t dl) throw(); +}; + +template size_t StrNLen(const T *s, size_t n = -1) throw() +{ + size_t l; + for (l = 0; s && ((n == (size_t)-1) || (l < n)) && s[l]; l++) + ; + return l; +} + +class TStringM +{ +protected: + TAutoBuffer buf; + bool isutf8; + + void SetWU(bool isUTF8, const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + isutf8 = isUTF8; + size_t sl = StrNLen(p, n); + size_t l = TIConv::ToMulti(isutf8, p, sl, 0, 0); + if (!buf.Resize(l + 1)) + throw EShortOfMemory(); + else + { + char *ptr = buf.Ptr(); + ptr[l] = '\0'; + if (l > 0) + TIConv::ToMulti(isutf8, p, sl, ptr, l); + } + } + + + void SetMU(bool isUTF8, const char *p, size_t n = -1) throw(EShortOfMemory) + { + isutf8 = isUTF8; + size_t l = StrNLen(p, n); + if (!buf.Resize(l + 1)) + throw EShortOfMemory(); + else + { + char *ptr = buf.Ptr(); + ptr[l] = L'\0'; + memcpy(ptr, p, l * sizeof(char)); + } + } + +public: + TStringM(bool utf8, const char *p, size_t n = -1) throw(EShortOfMemory) + { + SetMU(utf8, p, n); + } + + TStringM(const TStringM &p) throw() + : buf(p.buf), isutf8(p.isutf8) + { + } + + TStringM &operator =(const TStringM &s) throw() + { + buf = s.buf; + isutf8 = s.isutf8; + return *this; + } + + void SetW(const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + SetWU(false, p, n); + } + + void SetW(bool utf8, const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + SetWU(utf8, p, n); + } + + const char *GetM(void) const throw() + { + return buf.Len() ? buf.Ptr() : ""; + } + + operator const char *(void) const throw() + { + return GetM(); + } + + TStringM() throw() + : isutf8(false) + { + } + + TStringM(const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + SetWU(false, p, n); + } + + TStringM(bool utf8, const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + SetWU(utf8, p, n); + } + + ~TStringM() throw() + { + } + + inline bool IsUTF8(void) const throw() + { + return isutf8; + } +}; + +class TString +{ +protected: + TAutoBuffer buf; + + void SetMU(bool isUTF8, const char *p, size_t n = -1) throw(EShortOfMemory) + { + size_t sl = StrNLen(p, n); + size_t l = TIConv::ToWide(isUTF8, p, sl, 0, 0); + if (!buf.Resize(l + 1)) + throw EShortOfMemory(); + else + { + wchar_t *ptr = buf.Ptr(); + if (ptr) ptr[l] = L'\0'; + if (l > 0) + TIConv::ToWide(isUTF8, p, sl, ptr, l); + } + } + + void SetFloat(const double &s) throw(EShortOfMemory) + { + char buf[32]; +#if defined(HAVE_SPRINTF_S) + sprintf_s(buf, sizeof(buf), "%g", s); +#elif defined(HAVE_SNPRINTF) + snprintf(buf, sizeof(buf), "%g", s); +#elif defined(HAVE_SNPRINTF_) + _snprintf(buf, sizeof(buf), "%g", s); +#else + sprintf(buf, "%g", s); +#endif + SetMU(false, buf, sizeof(buf)); + } + + void SetULong(const unsigned long &s) throw(EShortOfMemory) + { + char buf[32]; +#if defined(HAVE_SPRINTF_S) + sprintf_s(buf, sizeof(buf), "%lu", s); +#elif defined(HAVE_SNPRINTF) + snprintf(buf, sizeof(buf), "%lu", s); +#elif defined(HAVE_SNPRINTF_) + _snprintf(buf, sizeof(buf), "%lu", s); +#else + sprintf(buf, "%lu", s); +#endif + SetMU(false, buf, sizeof(buf)); + } + +public: + + void SetW(const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + size_t l = StrNLen(p, n); + if (!buf.Resize(l + 1)) + throw EShortOfMemory(); + else + { + wchar_t *ptr = buf.Ptr(); + ptr[l] = L'\0'; + memcpy(ptr, p, l * sizeof(wchar_t)); + } + } + + void SetM(const char *p, size_t n = -1) throw(EShortOfMemory) + { + SetMU(false, p, n); + } + + void SetUTF8(const char *p, size_t n = -1) throw(EShortOfMemory) + { + SetMU(true, p, n); + } + + const wchar_t *GetW(void) const throw() + { + return buf.Len() ? buf.Ptr() : L""; + } + + operator const wchar_t *(void) const throw() + { + return GetW(); + } + + TString() throw() + { + } + + TString(const TString &p) throw() + : buf(p.buf) + { + } + + TString(const TStringM & p) throw(EShortOfMemory) + { + SetMU(p.IsUTF8(), p); + } + + TString(const wchar_t *p, size_t n = -1) throw(EShortOfMemory) + { + SetW(p, n); + } + + TString(const char *p, size_t n = -1) throw(EShortOfMemory) + { + SetM(p, n); + } + + TString(bool isUTF8, const char *p, size_t n = -1) throw(EShortOfMemory) + { + SetMU(isUTF8, p, n); + } + + TString(unsigned long s) throw(EShortOfMemory) + { + SetULong(s); + } + + TString(double s) throw(EShortOfMemory) + { + SetFloat(s); + } + + ~TString() throw() + { + } + + TString &operator =(const TString &s) throw() + { + buf = s.buf; + return *this; + } + + TString &operator =(const TStringM &s) throw() + { + SetMU(s.IsUTF8(), s); + return *this; + } + + static friend TString operator+(const wchar_t *p, const TString &s) throw(EShortOfMemory) + { + TString r; + const wchar_t *p2 = s.GetW(); + size_t l1 = StrNLen(p); + size_t l2 = StrNLen(p2); + if (!r.buf.Resize(l1 + l2 + 1)) + throw EShortOfMemory(); + else + { + wchar_t *des = r.buf.Ptr(); + des[l1 + l2] = L'\0'; + if (l1) + memcpy(des, p, l1 * sizeof(wchar_t)); + if (l2) + memcpy(des + l1, p2, l2 * sizeof(wchar_t)); + } + return r; + } + + double GetFloat() const throw(EShortOfMemory) + { + return atof(TStringM(GetW())); + } + unsigned long GetULong() const throw(EShortOfMemory) + { + return unsigned long(atol(TStringM(GetW()))); + } +}; + +class TWin32 +{ +public: + // System + static bool IsUnicodeSupportedOS(void) throw(); + static bool IsPathSeparator(char c) throw(); + static bool IsPathSeparator(wchar_t c) throw(); + static const char *NextChar(const char *p) throw(); + static const wchar_t *NextChar(const wchar_t *p) throw(); + static TString ModulePath(void *hmod) throw(EShortOfMemory); + static TString ExtractPath(const wchar_t *p) throw(EShortOfMemory); + static TString ExtractFileName(const wchar_t *p) throw(EShortOfMemory); + static TString CanonicalizePath(const wchar_t *p) throw(EShortOfMemory); + // Setting + static TString GetPrivateProfile(const wchar_t *ininame, const wchar_t *appname, const wchar_t *keyname, const wchar_t *defaultvalue) throw(EShortOfMemory); + static void SetPrivateProfile(const wchar_t *ininame, const wchar_t *appname, const wchar_t *keyname, const wchar_t *value) throw(); + // Window + static void *WndMsgSend(void *hwnd, unsigned msg, const void *wp, const void *lp) throw(); + static void *WndMsgSend(void *hwnd, unsigned msg, const void *wp, int lp) throw(); + static void *WndMsgSend(void *hwnd, unsigned msg, int wp, const void *lp) throw(); + static void *WndMsgSend(void *hwnd, unsigned msg, int wp, int lp) throw(); + static void WndMsgPost(void *hwnd, unsigned msg, const void *wp = 0, const void *lp = 0) throw(); + static void *WndGetLongPtr(void *hwnd, int idx) throw(); + static void *WndSetLongPtr(void *hwnd, int idx, void *ptr) throw(); + // Dialog + static void *DlgCreate(void *hinst, int id, void *hwndParent, DLGPROC pProc, void *param) throw(); + static void *DlgInvoke(void *hinst, const void *ptemp, void *hwndParent, DLGPROC pProc, void *param) throw(); + static void DlgSetText(void *hwndDlg, int itm, TString text) throw(); + static TString DlgGetText(void *hwndDlg, int itm) throw(EShortOfMemory); + static void DlgSetEnabled(void *hwndDlg, int itm, bool chk) throw(); + static void DlgSetCheck(void *hwndDlg, int itm, bool chk) throw(); + static bool DlgGetCheck(void *hwndDlg, int itm) throw(); + static void DlgAddList(void *hwndDlg, int itm, TString item) throw(); + static int DlgCntList(void *hwndDlg, int itm) throw(); + static int DlgCurList(void *hwndDlg, int itm) throw(); + static bool DlgGetList(void *hwndDlg, int itm, int cur) throw(); + // File + typedef void *(*lpfnalloc)(void *pwork, size_t s); + typedef void (*lpfnfree)(void *pwork, void *p); + static void *LoadEx(const wchar_t *path, size_t &loadsize, void *pwork, lpfnalloc palloc, lpfnfree pfree) throw(); + static TAutoBuffer Map(const wchar_t *path) throw(EShortOfMemory); +// TReference Create(const wchar_t *path); +}; + +template class TWin32T +{ +public: + static const T *ExtractFilename(const T * fn) throw() + { + const T *fname = fn; + const T *p = fn; + while (*p) + { + if (TWin32::IsPathSeparator(*p)) + fname = p + 1; + p = TWin32::NextChar(p); + } + if (!*fname) + fname = fn; + return fname; + } +}; + + +} + +#endif + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#endif + +#endif diff --git a/tools/vio2sf/src/xsfc/xsfcfg.cpp b/tools/vio2sf/src/xsfc/xsfcfg.cpp new file mode 100644 index 000000000..557cad2c0 --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfcfg.cpp @@ -0,0 +1,286 @@ +#define WIN32_LEAN_AND_MEAN +#include "leakchk.h" + +#include +#include + +#include "xsfcfg.h" +#include "tagget.h" +#include "../pversion.h" +#include "xsfui.rh" + +#include "vio2sf/desmume/spu.h" + +unsigned long dwChannelMute[4] = { 0, 0, 0, 0 }; + +unsigned long dwInterpolation; + +namespace +{ + +const int VolumeBase = 16; + +unsigned long dwPlayInfinitely; +unsigned long dwSkipSilenceOnStartSec; +unsigned long dwDetectSilenceSec; +unsigned long dwDefaultLength; +unsigned long dwDefaultFade; +double dVolume; + +xsfc::TString sDefaultLengthC(L"1:55"); +xsfc::TString sDefaultFadeC(L"5"); +xsfc::TString sDefaultLength; +xsfc::TString sDefaultFade; + +typedef struct +{ + int devch; + const char *devname; +} CHANNELMAP; + +const CHANNELMAP chmap[] = XSFDRIVER_CHANNELMAP; + +#ifdef XSFDRIVER_EXTENDPARAM1NAME +xsfc::TString sExtendParam1C(XSFDRIVER_EXTENDPARAM1DEFAULT); +xsfc::TString sExtendParam1; +#endif + +#ifdef XSFDRIVER_EXTENDPARAM2NAME +xsfc::TString sExtendParam2C(XSFDRIVER_EXTENDPARAM2DEFAULT); +xsfc::TString sExtendParam2; +#endif + +} + +unsigned long CFGGetChannelMute(int page) +{ + return (page < 4) ? dwChannelMute[page] : ~unsigned long(0); +} + +void CFGSetChannelMute(int ch, bool mute) +{ + int page = ch >> 5; + if (page < 4) + { + if (mute) + dwChannelMute[page] |= ((unsigned long(1)) << (ch & 0x1f)); + else + dwChannelMute[page] &= ~((unsigned long(1)) << (ch & 0x1f)); + } +} + + +unsigned CFGGetPlayInfinitely(void) +{ + return dwPlayInfinitely; +} +unsigned CFGGetSkipSilenceOnStartSec(void) +{ + return dwSkipSilenceOnStartSec; +} +unsigned CFGGetDetectSilenceSec(void) +{ + return dwDetectSilenceSec; +} +unsigned CFGGetDefaultLength(void) +{ + return dwDefaultLength; +} +unsigned CFGGetDefaultFade(void) +{ + return dwDefaultFade; +} +bool CFGGetVolume(double &vol) +{ + int iVolume = int(dVolume); + if (iVolume == 0 || iVolume == VolumeBase) + { + vol = 1; + return false; + } + vol = dVolume / VolumeBase; + return true; +} + +const wchar_t *CFGGetExtendParam1(void) +{ +#ifdef XSFDRIVER_EXTENDPARAM1NAME + return sExtendParam1; +#else + return 0; +#endif +} +const wchar_t *CFGGetExtendParam2(void) +{ +#ifdef XSFDRIVER_EXTENDPARAM2NAME + return sExtendParam2; +#else + return 0; +#endif +} + +void CFGDefault(void) +{ + dwPlayInfinitely = 0; + dwInterpolation = (unsigned long)SPUInterpolation_Linear; + dwSkipSilenceOnStartSec = 5; + dwDetectSilenceSec = 5; + dwDefaultLength = (1 * 60 + 55) * 1000; + dwDefaultFade = 5 * 1000; + dVolume = VolumeBase; + + sDefaultLength = sDefaultLengthC; + sDefaultFade = sDefaultFadeC; + +#ifdef XSFDRIVER_EXTENDPARAM1NAME + sExtendParam1 = sExtendParam1C; +#endif +#ifdef XSFDRIVER_EXTENDPARAM2NAME + sExtendParam2 = sExtendParam2C; +#endif + + int tch = 0; + for (const CHANNELMAP *pchmap = &chmap[0]; pchmap->devch; pchmap++) + { + for (int ch = 1; ch <= pchmap->devch; ch++) + { + CFGSetChannelMute(tch++, false); + } + } + while (tch < 32 * 4) + CFGSetChannelMute(tch++, true); +} + +void CFGLoad(LPIConfigIO pcfg) +{ + try + { + + CFGDefault(); + dwInterpolation = pcfg->GetULong(L"Interpolation", dwInterpolation); + dwPlayInfinitely = pcfg->GetULong(L"PlayInfinitely", dwPlayInfinitely); + dwSkipSilenceOnStartSec = pcfg->GetULong(L"SkipSilenceOnStartSec", dwSkipSilenceOnStartSec); + dwDetectSilenceSec = pcfg->GetULong(L"DetectSilenceSec", dwDetectSilenceSec); + dVolume = pcfg->GetFloat(L"Volume", dVolume / dVolume) * VolumeBase; + sDefaultLength = pcfg->GetString(L"DefaultLength", sDefaultLength); + sDefaultFade = pcfg->GetString(L"DefaultFade", sDefaultFade); +#ifdef XSFDRIVER_EXTENDPARAM1NAME + sExtendParam1 = pcfg->GetString(XSFDRIVER_EXTENDPARAM1NAME, sExtendParam1); +#endif +#ifdef XSFDRIVER_EXTENDPARAM2NAME + sExtendParam2 = pcfg->GetString(XSFDRIVER_EXTENDPARAM2NAME, sExtendParam2); +#endif + + dwDefaultLength = XSFTag::ToMS(sDefaultLength); + dwDefaultFade = XSFTag::ToMS(sDefaultFade); + } + catch (xsfc::EShortOfMemory e) + { + } +} + +void CFGSave(LPIConfigIO pcfg) +{ + try + { + pcfg->SetULong(L"PlayInfinitely", dwPlayInfinitely); + pcfg->SetULong(L"Interpolation", dwInterpolation); + pcfg->SetULong(L"SkipSilenceOnStartSec", dwSkipSilenceOnStartSec); + pcfg->SetULong(L"DetectSilenceSec", dwDetectSilenceSec); + pcfg->SetFloat(L"Volume", dVolume / VolumeBase); + pcfg->SetString(L"DefaultLength", sDefaultLength); + pcfg->SetString(L"DefaultFade", sDefaultFade); +#ifdef XSFDRIVER_EXTENDPARAM1NAME + pcfg->SetString(XSFDRIVER_EXTENDPARAM1NAME, sExtendParam1); +#endif +#ifdef XSFDRIVER_EXTENDPARAM2NAME + pcfg->SetString(XSFDRIVER_EXTENDPARAM2NAME, sExtendParam2); +#endif + } + catch (xsfc::EShortOfMemory e) + { + } +} + +void CFGReset(LPIConfigIO pcfg, void *hwndDlg) +{ + (void)pcfg; + try + { + char buf[128]; + xsfc::TWin32::DlgSetCheck(hwndDlg, 0x200, dwPlayInfinitely == 1); + ComboBox_SetCurSel(GetDlgItem((HWND)hwndDlg, IDC_COMBO_INTERPOLATION), dwInterpolation); + xsfc::TWin32::DlgSetText(hwndDlg, 0x201, sDefaultLength); + xsfc::TWin32::DlgSetText(hwndDlg, 0x202, sDefaultFade); + xsfc::TWin32::DlgSetText(hwndDlg, 0x203, xsfc::TString(dwSkipSilenceOnStartSec)); + xsfc::TWin32::DlgSetText(hwndDlg, 0x204, xsfc::TString(dwDetectSilenceSec)); + xsfc::TWin32::DlgSetText(hwndDlg, 0x205, xsfc::TString(dVolume / VolumeBase)); +#ifdef XSFDRIVER_EXTENDPARAM1NAME + xsfc::TWin32::DlgSetText(hwndDlg, 0x207, xsfc::TString(XSFDRIVER_EXTENDPARAM1LABEL)); + xsfc::TWin32::DlgSetText(hwndDlg, 0x208, sExtendParam1); + xsfc::TWin32::DlgSetEnabled(hwndDlg, 0x208, true); +#endif +#ifdef XSFDRIVER_EXTENDPARAM2NAME + xsfc::TWin32::DlgSetText(hwndDlg, 0x209, xsfc::TString(XSFDRIVER_EXTENDPARAM2LABEL)); + xsfc::TWin32::DlgSetText(hwndDlg, 0x20a, sExtendParam2); + xsfc::TWin32::DlgSetEnabled(hwndDlg, 0x20a, true); +#endif + for (const CHANNELMAP *pchmap = &chmap[0]; pchmap->devch; pchmap++) + { + for (int ch = 1; ch <= pchmap->devch; ch++) + { +#if defined(HAVE_SPRINTF_S) + sprintf_s(buf, sizeof(buf), pchmap->devname, ch); +#elif defined(HAVE_SNPRINTF) + snprintf(buf, sizeof(buf), pchmap->devname, ch); + buf[sizeof(buf) - 1] = 0; +#elif defined(HAVE_SNPRINTF_) + _snprintf(buf, sizeof(buf), pchmap->devname, ch); +#else + sprintf(buf, pchmap->devname, ch); +#endif + xsfc::TWin32::DlgAddList(hwndDlg, 0x206, buf); + } + } + } + catch (xsfc::EShortOfMemory e) + { + } +} + +void CFGUpdate(LPIConfigIO pcfg, void *hwndDlg) +{ + (void)pcfg; + try + { + dwPlayInfinitely = xsfc::TWin32::DlgGetCheck(hwndDlg, 0x200) ? 1 : 0; + sDefaultLength = xsfc::TWin32::DlgGetText(hwndDlg, 0x201); + sDefaultFade = xsfc::TWin32::DlgGetText(hwndDlg, 0x202); + dwSkipSilenceOnStartSec = xsfc::TWin32::DlgGetText(hwndDlg, 0x203).GetULong(); + dwDetectSilenceSec = xsfc::TWin32::DlgGetText(hwndDlg, 0x204).GetULong(); + dVolume = xsfc::TWin32::DlgGetText(hwndDlg, 0x205).GetFloat() * VolumeBase; +#ifdef XSFDRIVER_EXTENDPARAM1NAME + sExtendParam1 = xsfc::TWin32::DlgGetText(hwndDlg, 0x208); +#endif +#ifdef XSFDRIVER_EXTENDPARAM2NAME + sExtendParam2 = xsfc::TWin32::DlgGetText(hwndDlg, 0x20a); +#endif + + dwDefaultLength = XSFTag::ToMS(sDefaultLength); + dwDefaultFade = XSFTag::ToMS(sDefaultFade); + } + catch (xsfc::EShortOfMemory e) + { + } +} + +void CFGMuteChange(void *hwndDlg, int itm) +{ + int cnt = xsfc::TWin32::DlgCntList(hwndDlg, itm); + for (int ch = 0; ch < cnt; ch++) + { + bool mute = xsfc::TWin32::DlgGetList(hwndDlg, itm, ch); + CFGSetChannelMute(ch, mute); + } +} + diff --git a/tools/vio2sf/src/xsfc/xsfcfg.h b/tools/vio2sf/src/xsfc/xsfcfg.h new file mode 100644 index 000000000..7b6538f0b --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfcfg.h @@ -0,0 +1,75 @@ +#ifdef __cplusplus +extern "C" +{ +#endif + +unsigned CFGGetPlayInfinitely(void); +unsigned CFGGetSkipSilenceOnStartSec(void); +unsigned CFGGetDetectSilenceSec(void); +unsigned CFGGetDefaultLength(void); +unsigned CFGGetDefaultFade(void); +bool CFGGetVolume(double &vol); +unsigned long CFGGetChannelMute(int page); +void CFGSetChannelMute(int ch, bool mute); +const wchar_t *CFGGetExtendParam1(void); +const wchar_t *CFGGetExtendParam2(void); + +#ifdef __cplusplus +} + +#include "xsfc.h" + +#if _MSC_VER >= 1200 +#pragma warning(push) +#pragma warning(disable:4290) +#endif + +class IConfigIO +{ +protected: + IConfigIO() {} +public: + virtual ~IConfigIO() {} + + virtual void SetULong(const wchar_t *name, const unsigned long value) throw() = 0; + virtual unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw() = 0; + virtual void SetFloat(const wchar_t *name, const double value) throw() = 0; + virtual double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw() = 0; + virtual void SetString(const wchar_t *name, const wchar_t *value) throw() = 0; + virtual xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw(xsfc::EShortOfMemory) = 0; +}; +typedef IConfigIO *LPIConfigIO; + +class NullConfig : public IConfigIO +{ +protected: + NullConfig() throw() {} +public: + ~NullConfig() throw() {} + + void SetULong(const wchar_t *name, const unsigned long value) throw() { (void)name, value; } + unsigned long GetULong(const wchar_t *name, const unsigned long defaultvalue = 0) throw() { (void)name; return defaultvalue; } + void SetFloat(const wchar_t *name, const double value) throw() { (void)name, value; } + double GetFloat(const wchar_t *name, const double defaultvalue = 0) throw() { (void)name; return defaultvalue; } + void SetString(const wchar_t *name, const wchar_t *value) throw() { (void)name, value; } + xsfc::TString GetString(const wchar_t *name, const wchar_t *defaultvalue = 0) throw(xsfc::EShortOfMemory) { (void)name; return xsfc::TString(defaultvalue); } + + static LPIConfigIO Create() throw() + { + static NullConfig singleton; + return &singleton; + } +}; + +void CFGDefault(void); +void CFGLoad(LPIConfigIO pcfg); +void CFGReset(LPIConfigIO pcfg, void *hwndDlg); +void CFGUpdate(LPIConfigIO pcfg, void *hwndDlg); +void CFGSave(LPIConfigIO pcfg); +void CFGMuteChange(void *hwndDlg, int itm); + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#endif + +#endif \ No newline at end of file diff --git a/tools/vio2sf/src/xsfc/xsfdrv.c b/tools/vio2sf/src/xsfc/xsfdrv.c new file mode 100644 index 000000000..3f7a25b8e --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfdrv.c @@ -0,0 +1,112 @@ +#define STRICT +#define WIN32_LEAN_AND_MEAN +#include "leakchk.h" + +#include +#include +#include + +#include "../pversion.h" + +#include "drvimpl.h" +#include "xsfdrv.h" + +long dwInterpolation = 0; + +#if _MSC_VER >= 1200 +#pragma comment(linker, "/EXPORT:XSFSetup=_XSFSetup@8") +#endif + +#if defined(_MSC_VER) && !defined(_DEBUG) +#pragma comment(linker,"/MERGE:.rdata=.text") +#endif + +static void * PASCAL XSFLibAlloc(DWORD dwSize) +{ + return malloc(dwSize); +} +static void PASCAL XSFLibFree(void *lpPtr) +{ + free(lpPtr); +} +static int PASCAL XSFStart(void *lpPtr, DWORD dwSize) +{ + return !xsf_start(lpPtr, dwSize); +} +static void PASCAL XSFGen(void *lpPtr, DWORD dwSamples) +{ + xsf_gen(lpPtr, dwSamples); +} +static void PASCAL XSFTerm(void) +{ + xsf_term(); +} + +unsigned long dwChannelMute = 0; + +static void PASCAL XSFSetChannelMute(DWORD dwPage, DWORD dwMute) +{ + if (dwPage == 0) + dwChannelMute = dwMute; +} + +#ifdef XSFDRIVER_EXTENDPARAM1NAME +static void PASCAL XSFSetExtendParam(DWORD dwId, LPCWSTR lpPtr) +{ + //xsf_set_extend_param(dwId, lpPtr); +} +#endif + +static void PASCAL XSFSetExtendParamImmediate(DWORD dwId, LPVOID lpPtr) +{ + switch(dwId) + { + case EXTEND_PARAM_IMMEDIATE_INTERPOLATION: + dwInterpolation = *(unsigned long*)lpPtr; + break; + } +} + +static void *lpUserWrok = 0; +static LPFNGETLIB_XSFDRV lpfnGetLib = 0; +static IXSFDRV ifaossf = +{ + XSFLibAlloc, + XSFLibFree, + XSFStart, + XSFGen, + XSFTerm, + 4, + XSFSetChannelMute, + XSFSetExtendParam, + XSFSetExtendParamImmediate +}; + +IXSFDRV * PASCAL XSFSetup(LPFNGETLIB_XSFDRV lpfn, void *lpWork) +{ + lpfnGetLib = lpfn; + lpUserWrok = lpWork; + return &ifaossf; +} + +int xsf_get_lib(char *pfilename, void **ppbuffer, unsigned *plength) +{ + DWORD length32; + if (!lpfnGetLib || lpfnGetLib(lpUserWrok, pfilename, ppbuffer, &length32)) return 0; + if (plength) *plength = length32; + return 1; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + { +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + DisableThreadLibraryCalls(hinstDLL); + } + return TRUE; +} + + diff --git a/tools/vio2sf/src/xsfc/xsfdrv.h b/tools/vio2sf/src/xsfc/xsfdrv.h new file mode 100644 index 000000000..dbd96164a --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfdrv.h @@ -0,0 +1,37 @@ +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (PASCAL * LPFNGETLIB_XSFDRV)(void *lpWork, LPSTR lpszFilename, void **ppBuffer, DWORD *pdwSize); +typedef struct +{ + /* V1 */ + void * (PASCAL * LibAlloc)(DWORD dwSize); + void (PASCAL * LibFree)(void *lpPtr); + int (PASCAL * Start)(void *lpPtr, DWORD dwSize); + void (PASCAL * Gen)(void *lpPtr, DWORD dwSamples); + void (PASCAL * Term)(void); + + /* V2 */ + DWORD dwInterfaceVersion; + void (PASCAL * SetChannelMute)(DWORD dwPage, DWORD dwMute); + + /* V3 */ + void (PASCAL * SetExtendParam)(DWORD dwId, LPCWSTR lpPtr); + + /* V4 */ + void (PASCAL * SetExtendParamImmediate)(DWORD dwId, LPVOID lpPtr); +} IXSFDRV; + +#define EXTEND_PARAM_IMMEDIATE_INTERPOLATION 0 +#define EXTEND_PARAM_IMMEDIATE_INTERPOLATION_NONE 0 +#define EXTEND_PARAM_IMMEDIATE_INTERPOLATION_LINEAR 1 +#define EXTEND_PARAM_IMMEDIATE_INTERPOLATION_COSINE 2 + +typedef IXSFDRV * (PASCAL * LPFNXSFDRVSETUP)(LPFNGETLIB_XSFDRV lpfn, void *lpWork); +/* IXSFDRV * PASCAL XSFDRVSetup(LPFNGETLIB_XSFDRV lpfn, void *lpWork); */ + +#ifdef __cplusplus +} +#endif + diff --git a/tools/vio2sf/src/xsfc/xsfui.rc b/tools/vio2sf/src/xsfc/xsfui.rc new file mode 100644 index 000000000..2d6e1e335 --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfui.rc @@ -0,0 +1,125 @@ +// Microsoft Visual C++ generated resource script. +// +#include "xsfui.rh" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winresx.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Japanese resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) +#ifdef _WIN32 +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT +#pragma code_page(932) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "xsfui.rh\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winresx.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Japanese resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +1 DIALOGEX 0, 0, 172, 202 +STYLE DS_SETFONT | WS_CHILD +FONT 9, "MS UI Gothic", 0, 0, 0x0 +BEGIN + GROUPBOX "General",IDC_STATIC,5,5,160,90 + CONTROL "Play infinitely",512,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,15,60,10 + EDITTEXT 513,100,30,25,12,ES_RIGHT | ES_AUTOHSCROLL + LTEXT "Default play length (m:s)",IDC_STATIC,10,30,85,9 + EDITTEXT 514,100,45,25,12,ES_RIGHT | ES_AUTOHSCROLL + LTEXT "Default fadeout length (m:s)",IDC_STATIC,10,45,85,9 + LTEXT "Skip silence on start(sec)",IDC_STATIC,10,60,80,9 + EDITTEXT 515,100,60,25,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Detect silence(sec)",IDC_STATIC,10,75,80,9 + EDITTEXT 516,100,75,25,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER + GROUPBOX "Output",IDC_STATIC,5,100,160,75 + LTEXT "Volume",IDC_STATIC,10,110,30,9 + EDITTEXT 517,45,110,25,12,ES_RIGHT | ES_AUTOHSCROLL + LTEXT "",519,10,125,50,9 + EDITTEXT 520,65,125,25,12,ES_RIGHT | ES_AUTOHSCROLL | WS_DISABLED + LTEXT "",521,10,140,50,9 + EDITTEXT 522,65,140,25,12,ES_RIGHT | ES_AUTOHSCROLL | WS_DISABLED + LISTBOX 518,100,105,60,45,LBS_MULTIPLESEL | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Mute",IDC_STATIC,80,110,20,9 + DEFPUSHBUTTON "OK",IDOK,84,181,35,15,NOT WS_VISIBLE + PUSHBUTTON "Cancel",IDCANCEL,129,181,35,15,NOT WS_VISIBLE + COMBOBOX IDC_COMBO_INTERPOLATION,10,156,78,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + 1, DIALOG + BEGIN + BOTTOMMARGIN, 192 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/tools/vio2sf/src/xsfc/xsfui.rh b/tools/vio2sf/src/xsfc/xsfui.rh new file mode 100644 index 000000000..7de4271cc --- /dev/null +++ b/tools/vio2sf/src/xsfc/xsfui.rh @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by xsfui.rc +// +#define IDC_COMBO_INTERPOLATION 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/tools/vio2sf/vio2sf.sln b/tools/vio2sf/vio2sf.sln new file mode 100644 index 000000000..45b1163bd --- /dev/null +++ b/tools/vio2sf/vio2sf.sln @@ -0,0 +1,47 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foo_xsf8", "foo_xsf8.vcproj", "{02361C60-7E8A-4002-890A-E2B0AC2C91D8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_xsf", "in_xsf.vcproj", "{035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "in_xsfu", "in_xsfu.vcproj", "{226CE519-0842-4808-B6F9-C02DE14BB3DC}" + ProjectSection(ProjectDependencies) = postProject + {1BEA83DD-D533-446B-B470-490A1604B594} = {1BEA83DD-D533-446B-B470-490A1604B594} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kpixsf", "kpixsf.vcproj", "{45AEABD2-996B-4C43-947C-E43D3A3DF79A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vio2sf", "vio2sf.vcproj", "{1BEA83DD-D533-446B-B470-490A1604B594}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {02361C60-7E8A-4002-890A-E2B0AC2C91D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {02361C60-7E8A-4002-890A-E2B0AC2C91D8}.Debug|Win32.Build.0 = Debug|Win32 + {02361C60-7E8A-4002-890A-E2B0AC2C91D8}.Release|Win32.ActiveCfg = Release|Win32 + {02361C60-7E8A-4002-890A-E2B0AC2C91D8}.Release|Win32.Build.0 = Release|Win32 + {035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}.Debug|Win32.ActiveCfg = Debug|Win32 + {035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}.Debug|Win32.Build.0 = Debug|Win32 + {035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}.Release|Win32.ActiveCfg = Release|Win32 + {035B66F9-6D8C-47AA-8CDC-F43DA0BDC1E7}.Release|Win32.Build.0 = Release|Win32 + {226CE519-0842-4808-B6F9-C02DE14BB3DC}.Debug|Win32.ActiveCfg = Debug|Win32 + {226CE519-0842-4808-B6F9-C02DE14BB3DC}.Debug|Win32.Build.0 = Debug|Win32 + {226CE519-0842-4808-B6F9-C02DE14BB3DC}.Release|Win32.ActiveCfg = Release|Win32 + {226CE519-0842-4808-B6F9-C02DE14BB3DC}.Release|Win32.Build.0 = Release|Win32 + {45AEABD2-996B-4C43-947C-E43D3A3DF79A}.Debug|Win32.ActiveCfg = Debug|Win32 + {45AEABD2-996B-4C43-947C-E43D3A3DF79A}.Debug|Win32.Build.0 = Debug|Win32 + {45AEABD2-996B-4C43-947C-E43D3A3DF79A}.Release|Win32.ActiveCfg = Release|Win32 + {45AEABD2-996B-4C43-947C-E43D3A3DF79A}.Release|Win32.Build.0 = Release|Win32 + {1BEA83DD-D533-446B-B470-490A1604B594}.Debug|Win32.ActiveCfg = Debug|Win32 + {1BEA83DD-D533-446B-B470-490A1604B594}.Debug|Win32.Build.0 = Debug|Win32 + {1BEA83DD-D533-446B-B470-490A1604B594}.Release|Win32.ActiveCfg = Release|Win32 + {1BEA83DD-D533-446B-B470-490A1604B594}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/vio2sf/vio2sf.vcproj b/tools/vio2sf/vio2sf.vcproj new file mode 100644 index 000000000..a5a8889a3 --- /dev/null +++ b/tools/vio2sf/vio2sf.vcproj @@ -0,0 +1,843 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +