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 ͕sjŁA Init Deinit */
+ /* NULL ̏ꍇ͏풓vOCƂĈAKbMedia Player 쒆͏Ƀ[h */
+ /* ꂽ܂܂ɂȂi̋@\j */
+ /* 풓vOCƂĂ̓ Init ďoɊJnADeinit ďoɏI邱ƁB */
+ /* iLoadLibrary ɓJnAFreeLibrary ɓI͕sj */
+ /* */
+ /* 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ŏ풓vOCJnB */
+ /* LoadLibrary ɏ풓vOCJnĂ͂ȂB */
+
+ void (WINAPI *Deinit)(void);
+ /* vOČnBFreeLibrary ̒OɈxĂB */
+ /* Init() xĂ Deinit() Ăԉ\邱ƂɒӁB */
+ /* KvȂꍇ NULL ɂĂǂB */
+ /* A풓vOCi̋@\j̏ꍇ͕K邱ƁB */
+ /* Deinit ̌Ăяoŏ풓vOCI */
+ /* FreeLibrary ɏ풓vOCIĂ͂Ȃ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);
+ /* nhBK邱Ɓ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@CuAKbMedia 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 000000000..a49ca029c
Binary files /dev/null and b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/gvmat64.obj differ
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 000000000..8df5d8261
Binary files /dev/null and b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/inffasx64.obj differ
diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/readme.txt b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/readme.txt
new file mode 100644
index 000000000..ee03115c5
--- /dev/null
+++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx64/readme.txt
@@ -0,0 +1,28 @@
+Summary
+-------
+This directory contains ASM implementations of the functions
+longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
+for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.
+
+gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
+ assembly optimized version from Jean-loup Gailly original longest_match function
+
+inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
+ original function from Mark Adler
+
+Use instructions
+----------------
+Copy these files into the zlib source directory.
+
+define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
+and inffasx64.obj and gvmat64.obj as object to link.
+
+
+Build instructions
+------------------
+run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
+
+ml64.exe is given with Visual Studio 2005, 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)
diff --git a/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/bld_ml32.bat b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/bld_ml32.bat
new file mode 100644
index 000000000..99144d07a
--- /dev/null
+++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/bld_ml32.bat
@@ -0,0 +1,2 @@
+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/gvmat32.asm b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.asm
new file mode 100644
index 000000000..874bb2d48
--- /dev/null
+++ b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.asm
@@ -0,0 +1,972 @@
+; gvmat32.asm -- Asm 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
+;
+; http://www.zlib.net
+; http://www.winimage.com/zLibDll
+; http://www.muppetlabs.com/~breadbox/software/assembly.html
+;
+; 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/
+;
+; this file contain two implementation of longest_match
+;
+; longest_match_7fff : written 1996 by Gilles Vollant optimized for
+; first Pentium. Assume s->w_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 000000000..ebb326238
Binary files /dev/null and b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/gvmat32.obj differ
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 000000000..bd6664d11
Binary files /dev/null and b/tools/vio2sf/src/vio2sf/zlib/contrib/masmx86/inffas32.obj differ
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