diff --git a/.gitignore b/.gitignore
index 4ed47fac3d..155da55558 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,3 +71,5 @@ ExternalCoreProjects/Virtu/bin/*.*
**/StyleCop.Cache
libsnes/vs2015/libsnes.VC.db
+waterbox/**/*.wbx
+waterbox/**/*.wbx.in
diff --git a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
index a25b5dfcfe..17b9e26884 100644
--- a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
+++ b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
@@ -97,6 +97,7 @@ namespace BizHawk.Client.ApiHawk
return CoreSystem.WonderSwan;
case "VB":
+ case "NGP":
return 0; // like I give a shit
default:
diff --git a/BizHawk.Emulation.Common/Database/Database.cs b/BizHawk.Emulation.Common/Database/Database.cs
index 9a791c87c0..5068cd22ed 100644
--- a/BizHawk.Emulation.Common/Database/Database.cs
+++ b/BizHawk.Emulation.Common/Database/Database.cs
@@ -335,6 +335,11 @@ namespace BizHawk.Emulation.Common
case ".VB":
game.System = "VB";
break;
+
+ case ".NGP":
+ case ".NGC":
+ game.System = "NGP";
+ break;
}
game.Name = Path.GetFileNameWithoutExtension(fileName)?.Replace('_', ' ');
diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 9869005551..5dc8ee9338 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -221,7 +221,7 @@
C64.cs
-
+
@@ -1209,6 +1209,8 @@
+
+
diff --git a/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeo.cs b/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeo.cs
new file mode 100644
index 0000000000..b0bfb58289
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeo.cs
@@ -0,0 +1,36 @@
+using BizHawk.Common.BizInvoke;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Consoles.SNK
+{
+ public abstract class LibNeoGeo
+ {
+ private const CallingConvention CC = CallingConvention.Cdecl;
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class EmulateSpec
+ {
+ public IntPtr Pixels;
+ public IntPtr SoundBuff;
+ public long MasterCycles;
+ public int SoundBufMaxSize;
+ public int SoundBufSize;
+ public int SkipRendering;
+ public int Buttons;
+ public int Lagged;
+ }
+ [BizImport(CC)]
+ public abstract bool LoadSystem(byte[] rom, int romlength, int language);
+ [BizImport(CC)]
+ public abstract void SetLayers(int enable); // 1, 2, 4 bg,fg,sprites
+ [BizImport(CC)]
+ public abstract void FrameAdvance([In, Out]EmulateSpec espec);
+ [BizImport(CC)]
+ public abstract void HardReset();
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeo.cs b/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeo.cs
new file mode 100644
index 0000000000..e648568c30
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/SNK/NeoGeo.cs
@@ -0,0 +1,153 @@
+using BizHawk.Common.BizInvoke;
+using BizHawk.Emulation.Common;
+using BizHawk.Emulation.Cores.Waterbox;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BizHawk.Emulation.Cores.Consoles.SNK
+{
+ [CoreAttributes("NeoPop", "Thomas Klausner", true, false, "0.9.44.1",
+ "https://mednafen.github.io/releases/", false)]
+ public class NeoGeo : IEmulator, IVideoProvider, ISoundProvider
+ {
+ private PeRunner _exe;
+ private LibNeoGeo _neopop;
+
+ [CoreConstructor("NGP")]
+ public NeoGeo(CoreComm comm, byte[] rom)
+ {
+ ServiceProvider = new BasicServiceProvider(this);
+ CoreComm = comm;
+
+ _exe = new PeRunner(new PeRunnerOptions
+ {
+ Path = comm.CoreFileProvider.DllPath(),
+ Filename = "ngp.wbx",
+ SbrkHeapSizeKB = 16 * 1024,
+ SealedHeapSizeKB = 16 * 1024,
+ InvisibleHeapSizeKB = 16 * 1024,
+ PlainHeapSizeKB = 16 * 1024,
+ MmapHeapSizeKB = 16 * 1024
+ });
+
+ _neopop = BizInvoker.GetInvoker(_exe, _exe);
+
+ if (!_neopop.LoadSystem(rom, rom.Length, 1))
+ {
+ throw new InvalidOperationException("Core rejected the rom");
+ }
+
+ _exe.Seal();
+ }
+
+ public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
+ {
+ if (controller.IsPressed("Power"))
+ _neopop.HardReset();
+
+ fixed (int* vp = _videoBuffer)
+ fixed (short* sp = _soundBuffer)
+ {
+ var spec = new LibNeoGeo.EmulateSpec
+ {
+ Pixels = (IntPtr)vp,
+ SoundBuff = (IntPtr)sp,
+ SoundBufMaxSize = _soundBuffer.Length / 2,
+ Buttons = 0,
+ SkipRendering = render ? 0 : 1
+ };
+
+ _neopop.FrameAdvance(spec);
+ _numSamples = spec.SoundBufSize;
+
+ Frame++;
+
+ /*IsLagFrame = spec.Lagged;
+ if (IsLagFrame)
+ LagCount++;*/
+ }
+ }
+
+ private bool _disposed = false;
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ _exe.Dispose();
+ _exe = null;
+ _disposed = true;
+ }
+ }
+
+ public int Frame { get; private set; }
+
+ public void ResetCounters()
+ {
+ Frame = 0;
+ }
+
+ public IEmulatorServiceProvider ServiceProvider { get; private set; }
+ public string SystemId { get { return "NGP"; } }
+ public bool DeterministicEmulation { get { return true; } }
+ public CoreComm CoreComm { get; }
+
+ public ControllerDefinition ControllerDefinition => NullController.Instance.Definition;
+
+ #region IVideoProvider
+
+ private int[] _videoBuffer = new int[160 * 152];
+
+ public int[] GetVideoBuffer()
+ {
+ return _videoBuffer;
+ }
+
+ public int VirtualWidth => 160;
+ public int VirtualHeight => 152;
+ public int BufferWidth => 160;
+ public int BufferHeight => 152;
+ public int VsyncNumerator { get; private set; } = 6144000;
+ public int VsyncDenominator { get; private set; } = 515 * 198;
+ public int BackgroundColor => unchecked((int)0xff000000);
+
+ #endregion
+
+ #region ISoundProvider
+
+ private short[] _soundBuffer = new short[16384];
+ private int _numSamples;
+
+ public void SetSyncMode(SyncSoundMode mode)
+ {
+ if (mode == SyncSoundMode.Async)
+ {
+ throw new NotSupportedException("Async mode is not supported.");
+ }
+ }
+
+ public void GetSamplesSync(out short[] samples, out int nsamp)
+ {
+ samples = _soundBuffer;
+ nsamp = _numSamples;
+ }
+
+ public void GetSamplesAsync(short[] samples)
+ {
+ throw new InvalidOperationException("Async mode is not supported.");
+ }
+
+ public void DiscardSamples()
+ {
+ }
+
+ public bool CanProvideAsync => false;
+
+ public SyncSoundMode SyncMode => SyncSoundMode.Sync;
+
+ #endregion
+ }
+}
diff --git a/waterbox/ngp/.vscode/settings.json b/waterbox/ngp/.vscode/settings.json
new file mode 100644
index 0000000000..109dd034cd
--- /dev/null
+++ b/waterbox/ngp/.vscode/settings.json
@@ -0,0 +1,11 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+ "editor.insertSpaces": false,
+ "editor.detectIndentation": false,
+ "files.associations": {
+ "algorithm": "cpp",
+ "vector": "cpp",
+ "xstring": "cpp",
+ "xutility": "cpp"
+ }
+}
\ No newline at end of file
diff --git a/waterbox/ngp/Makefile b/waterbox/ngp/Makefile
new file mode 100644
index 0000000000..22aaf5b968
--- /dev/null
+++ b/waterbox/ngp/Makefile
@@ -0,0 +1,44 @@
+CC = x86_64-nt64-midipix-g++
+
+CCFLAGS:= -I. -I../emulibc \
+ -Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \
+ -std=c++0x -fomit-frame-pointer -fvisibility=hidden -fno-exceptions -fno-rtti \
+ -DLSB_FIRST \
+ -O0 -g
+
+TARGET = ngp.wbx
+
+LDFLAGS = -Wl,--dynamicbase,--export-all-symbols
+
+ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+SRCS:=$(shell find $(ROOT_DIR) -type f -name '*.cpp')
+OBJ_DIR:=$(ROOT_DIR)/obj
+
+_OBJS:=$(SRCS:.cpp=.o)
+OBJS:=$(patsubst $(ROOT_DIR)%,$(OBJ_DIR)%,$(_OBJS))
+
+$(OBJ_DIR)/%.o: %.cpp
+ @mkdir -p $(@D)
+ @$(CC) -c -o $@ $< $(CCFLAGS)
+
+all: $(TARGET)
+
+.PHONY: clean all
+
+$(TARGET).in: $(OBJS)
+ @$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so
+
+$(TARGET): $(TARGET).in
+# strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104
+ cp $< $@
+
+clean:
+ rm -rf $(OBJ_DIR)
+ rm -f $(TARGET).in
+ rm -f $(TARGET)
+
+print-%:
+ @echo $* = $($*)
+
+#install:
+# $(CP) $(TARGET) $(DEST_$(ARCH))
diff --git a/waterbox/ngp/T6W28_Apu.cpp b/waterbox/ngp/T6W28_Apu.cpp
new file mode 100644
index 0000000000..ccc6452d98
--- /dev/null
+++ b/waterbox/ngp/T6W28_Apu.cpp
@@ -0,0 +1,422 @@
+// T6W28_Snd_Emu
+
+#include "defs.h"
+#include "T6W28_Apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+more details. You should have received a copy of the GNU Lesser General
+Public License along with this module; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+// T6W28_Osc
+
+namespace MDFN_IEN_NGP
+{
+
+T6W28_Osc::T6W28_Osc()
+{
+ outputs[0] = NULL; // always stays NULL
+ outputs[1] = NULL;
+ outputs[2] = NULL;
+ outputs[3] = NULL;
+}
+
+void T6W28_Osc::reset()
+{
+ delay = 0;
+ last_amp_left = 0;
+ last_amp_right = 0;
+
+ volume_left = 0;
+ volume_right = 0;
+}
+
+// T6W28_Square
+
+blip_inline void T6W28_Square::reset()
+{
+ period = 0;
+ phase = 0;
+ T6W28_Osc::reset();
+}
+
+void T6W28_Square::run(sms_time_t time, sms_time_t end_time)
+{
+ if ((!volume_left && !volume_right) || period <= 128)
+ {
+ // ignore 16kHz and higher
+ if (last_amp_left)
+ {
+ synth->offset(time, -last_amp_left, outputs[2]);
+ last_amp_left = 0;
+ }
+
+ if (last_amp_right)
+ {
+ synth->offset(time, -last_amp_right, outputs[1]);
+ last_amp_right = 0;
+ }
+
+ time += delay;
+ if (!period)
+ {
+ time = end_time;
+ }
+ else if (time < end_time)
+ {
+ // keep calculating phase
+ int count = (end_time - time + period - 1) / period;
+ phase = (phase + count) & 1;
+ time += count * period;
+ }
+ }
+ else
+ {
+ int amp_left = phase ? volume_left : -volume_left;
+ int amp_right = phase ? volume_right : -volume_right;
+
+ {
+ int delta_left = amp_left - last_amp_left;
+ int delta_right = amp_right - last_amp_right;
+
+ if (delta_left)
+ {
+ last_amp_left = amp_left;
+ synth->offset(time, delta_left, outputs[2]);
+ }
+
+ if (delta_right)
+ {
+ last_amp_right = amp_right;
+ synth->offset(time, delta_right, outputs[1]);
+ }
+ }
+
+ time += delay;
+ if (time < end_time)
+ {
+ Blip_Buffer *const output_left = this->outputs[2];
+ Blip_Buffer *const output_right = this->outputs[1];
+
+ int delta_left = amp_left * 2;
+ int delta_right = amp_right * 2;
+ do
+ {
+ delta_left = -delta_left;
+ delta_right = -delta_right;
+
+ synth->offset_inline(time, delta_left, output_left);
+ synth->offset_inline(time, delta_right, output_right);
+ time += period;
+ phase ^= 1;
+ } while (time < end_time);
+
+ this->last_amp_left = phase ? volume_left : -volume_left;
+ this->last_amp_right = phase ? volume_right : -volume_right;
+ }
+ }
+ delay = time - end_time;
+}
+
+// T6W28_Noise
+
+static const int noise_periods[3] = {0x100, 0x200, 0x400};
+
+blip_inline void T6W28_Noise::reset()
+{
+ period = &noise_periods[0];
+ shifter = 0x4000;
+ tap = 13;
+ T6W28_Osc::reset();
+}
+
+void T6W28_Noise::run(sms_time_t time, sms_time_t end_time)
+{
+ int amp_left = volume_left;
+ int amp_right = volume_right;
+
+ if (shifter & 1)
+ {
+ amp_left = -amp_left;
+ amp_right = -amp_right;
+ }
+
+ {
+ int delta_left = amp_left - last_amp_left;
+ int delta_right = amp_right - last_amp_right;
+
+ if (delta_left)
+ {
+ last_amp_left = amp_left;
+ synth.offset(time, delta_left, outputs[2]);
+ }
+
+ if (delta_right)
+ {
+ last_amp_right = amp_right;
+ synth.offset(time, delta_right, outputs[1]);
+ }
+ }
+
+ time += delay;
+
+ if (!volume_left && !volume_right)
+ time = end_time;
+
+ if (time < end_time)
+ {
+ Blip_Buffer *const output_left = this->outputs[2];
+ Blip_Buffer *const output_right = this->outputs[1];
+
+ unsigned l_shifter = this->shifter;
+ int delta_left = amp_left * 2;
+ int delta_right = amp_right * 2;
+
+ int l_period = *this->period * 2;
+ if (!l_period)
+ l_period = 16;
+
+ do
+ {
+ int changed = (l_shifter + 1) & 2; // set if prev and next bits differ
+ l_shifter = (((l_shifter << 14) ^ (l_shifter << tap)) & 0x4000) | (l_shifter >> 1);
+ if (changed)
+ {
+ delta_left = -delta_left;
+ synth.offset_inline(time, delta_left, output_left);
+
+ delta_right = -delta_right;
+ synth.offset_inline(time, delta_right, output_right);
+ }
+ time += l_period;
+ } while (time < end_time);
+
+ this->shifter = l_shifter;
+ this->last_amp_left = delta_left >> 1;
+ this->last_amp_right = delta_right >> 1;
+ }
+ delay = time - end_time;
+}
+
+// T6W28_Apu
+
+T6W28_Apu::T6W28_Apu()
+{
+ for (int i = 0; i < 3; i++)
+ {
+ squares[i].synth = &square_synth;
+ oscs[i] = &squares[i];
+ }
+ oscs[3] = &noise;
+
+ volume(1.0);
+ reset();
+}
+
+T6W28_Apu::~T6W28_Apu()
+{
+}
+
+void T6W28_Apu::volume(double vol)
+{
+ vol *= 0.85 / (osc_count * 64 * 2);
+ square_synth.volume(vol);
+ noise.synth.volume(vol);
+}
+
+void T6W28_Apu::treble_eq(const blip_eq_t &eq)
+{
+ square_synth.treble_eq(eq);
+ noise.synth.treble_eq(eq);
+}
+
+void T6W28_Apu::osc_output(int index, Blip_Buffer *center, Blip_Buffer *left, Blip_Buffer *right)
+{
+ require((unsigned)index < osc_count);
+ require((center && left && right) || (!center && !left && !right));
+ T6W28_Osc &osc = *oscs[index];
+ osc.outputs[1] = right;
+ osc.outputs[2] = left;
+ osc.outputs[3] = center;
+}
+
+void T6W28_Apu::output(Blip_Buffer *center, Blip_Buffer *left, Blip_Buffer *right)
+{
+ for (int i = 0; i < osc_count; i++)
+ osc_output(i, center, left, right);
+}
+
+void T6W28_Apu::reset()
+{
+ last_time = 0;
+ latch_left = 0;
+ latch_right = 0;
+
+ squares[0].reset();
+ squares[1].reset();
+ squares[2].reset();
+ noise.reset();
+}
+
+void T6W28_Apu::run_until(sms_time_t end_time)
+{
+ require(end_time >= last_time); // end_time must not be before previous time
+
+ if (end_time > last_time)
+ {
+ // run oscillators
+ for (int i = 0; i < osc_count; ++i)
+ {
+ T6W28_Osc &osc = *oscs[i];
+ if (osc.outputs[1])
+ {
+ if (i < 3)
+ squares[i].run(last_time, end_time);
+ else
+ noise.run(last_time, end_time);
+ }
+ }
+
+ last_time = end_time;
+ }
+}
+
+bool T6W28_Apu::end_frame(sms_time_t end_time)
+{
+ if (end_time > last_time)
+ run_until(end_time);
+
+ assert(last_time >= end_time);
+ last_time -= end_time;
+
+ return (1);
+}
+
+static const unsigned char volumes[16] = {
+ // volumes [i] = 64 * pow( 1.26, 15 - i ) / pow( 1.26, 15 )
+ 64, 50, 39, 31, 24, 19, 15, 12, 9, 7, 5, 4, 3, 2, 1, 0};
+
+void T6W28_Apu::write_data_left(sms_time_t time, int data)
+{
+ require((unsigned)data <= 0xFF);
+
+ run_until(time);
+
+ if (data & 0x80)
+ latch_left = data;
+
+ int index = (latch_left >> 5) & 3;
+
+ if (latch_left & 0x10)
+ {
+ oscs[index]->volume_left = volumes[data & 15];
+ }
+ else if (index < 3)
+ {
+ T6W28_Square &sq = squares[index];
+ if (data & 0x80)
+ sq.period = (sq.period & 0xFF00) | (data << 4 & 0x00FF);
+ else
+ sq.period = (sq.period & 0x00FF) | (data << 8 & 0x3F00);
+ }
+}
+
+void T6W28_Apu::write_data_right(sms_time_t time, int data)
+{
+ require((unsigned)data <= 0xFF);
+
+ run_until(time);
+
+ if (data & 0x80)
+ latch_right = data;
+
+ int index = (latch_right >> 5) & 3;
+ //printf("%d\n", index);
+
+ if (latch_right & 0x10)
+ {
+ oscs[index]->volume_right = volumes[data & 15];
+ }
+ else if (index == 2)
+ {
+ if (data & 0x80)
+ noise.period_extra = (noise.period_extra & 0xFF00) | (data << 4 & 0x00FF);
+ else
+ noise.period_extra = (noise.period_extra & 0x00FF) | (data << 8 & 0x3F00);
+ }
+ else if (index == 3)
+ {
+ int select = data & 3;
+ if (select < 3)
+ noise.period = &noise_periods[select];
+ else
+ noise.period = &noise.period_extra;
+
+ int const tap_disabled = 16;
+ noise.tap = (data & 0x04) ? 13 : tap_disabled;
+ noise.shifter = 0x4000;
+ }
+}
+
+void T6W28_Apu::save_state(T6W28_ApuState *ret)
+{
+ for (int x = 0; x < 4; x++)
+ {
+ ret->volume_left[x] = oscs[x]->volume_left;
+ ret->volume_right[x] = oscs[x]->volume_right;
+ }
+ for (int x = 0; x < 3; x++)
+ {
+ ret->sq_period[x] = squares[x].period;
+ ret->sq_phase[x] = squares[x].phase;
+ }
+ ret->noise_shifter = noise.shifter;
+ ret->noise_tap = noise.tap;
+ ret->noise_period_extra = noise.period_extra;
+
+ if (noise.period == &noise_periods[0])
+ ret->noise_period = 0;
+ else if (noise.period == &noise_periods[1])
+ ret->noise_period = 1;
+ else if (noise.period == &noise_periods[2])
+ ret->noise_period = 2;
+ else
+ ret->noise_period = 3;
+
+ ret->latch_left = latch_left;
+ ret->latch_right = latch_right;
+}
+
+void T6W28_Apu::load_state(const T6W28_ApuState *state)
+{
+ for (int x = 0; x < 4; x++)
+ {
+ oscs[x]->volume_left = state->volume_left[x];
+ oscs[x]->volume_right = state->volume_right[x];
+ }
+ for (int x = 0; x < 3; x++)
+ {
+ squares[x].period = state->sq_period[x] & 0x3FFF;
+ squares[x].phase = state->sq_phase[x];
+ }
+ noise.shifter = state->noise_shifter;
+ noise.tap = state->noise_tap;
+ noise.period_extra = state->noise_period_extra & 0x3FFF;
+
+ unsigned select = state->noise_period;
+
+ if (select < 3)
+ noise.period = &noise_periods[select];
+ else
+ noise.period = &noise.period_extra;
+
+ latch_left = state->latch_left;
+ latch_right = state->latch_right;
+}
+}
diff --git a/waterbox/ngp/T6W28_Apu.h b/waterbox/ngp/T6W28_Apu.h
new file mode 100644
index 0000000000..cbedba0923
--- /dev/null
+++ b/waterbox/ngp/T6W28_Apu.h
@@ -0,0 +1,95 @@
+// T6W28_Snd_Emu
+
+#ifndef SMS_APU_H
+#define SMS_APU_H
+
+namespace MDFN_IEN_NGP
+{
+
+typedef long sms_time_t; // clock cycle count
+
+}
+
+#include "T6W28_Oscs.h"
+
+namespace MDFN_IEN_NGP
+{
+
+typedef struct
+{
+ int32 sq_period[3];
+ int32 sq_phase[3];
+ uint32 noise_period;
+ uint32 noise_period_extra;
+ uint32 noise_shifter;
+ uint32 noise_tap;
+
+ int32 volume_left[4];
+ int32 volume_right[4];
+ uint8 latch_left, latch_right;
+} T6W28_ApuState;
+
+class T6W28_Apu {
+public:
+ // Set overall volume of all oscillators, where 1.0 is full volume
+ void volume( double );
+
+ // Set treble equalization
+ void treble_eq( const blip_eq_t& );
+
+ // Outputs can be assigned to a single buffer for mono output, or to three
+ // buffers for stereo output (using Stereo_Buffer to do the mixing).
+
+ // Assign all oscillator outputs to specified buffer(s). If buffer
+ // is NULL, silences all oscillators.
+ void output( Blip_Buffer* mono );
+ void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
+
+ // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3,
+ // which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL,
+ // silences oscillator.
+ enum { osc_count = 4 };
+ void osc_output( int index, Blip_Buffer* mono );
+ void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right );
+
+ // Reset oscillators and internal state
+ void reset();
+
+ // Write to data port
+ void write_data_left( sms_time_t, int );
+ void write_data_right( sms_time_t, int );
+
+ // Run all oscillators up to specified time, end current frame, then
+ // start a new frame at time 0. Returns true if any oscillators added
+ // sound to one of the left/right buffers, false if they only added
+ // to the center buffer.
+ bool end_frame( sms_time_t );
+
+ void save_state(T6W28_ApuState*);
+ void load_state(const T6W28_ApuState*);
+public:
+ T6W28_Apu();
+ ~T6W28_Apu();
+private:
+ // noncopyable
+ T6W28_Apu( const T6W28_Apu& );
+ T6W28_Apu& operator = ( const T6W28_Apu& );
+
+ T6W28_Osc* oscs [osc_count];
+ T6W28_Square squares [3];
+ T6W28_Square::Synth square_synth; // used by squares
+ sms_time_t last_time;
+ int latch_left, latch_right;
+ T6W28_Noise noise;
+
+ void run_until( sms_time_t );
+};
+
+inline void T6W28_Apu::output( Blip_Buffer* b ) { output( b, b, b ); }
+
+inline void T6W28_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); }
+
+}
+
+#endif
+
diff --git a/waterbox/ngp/T6W28_Oscs.h b/waterbox/ngp/T6W28_Oscs.h
new file mode 100644
index 0000000000..e946aaf90b
--- /dev/null
+++ b/waterbox/ngp/T6W28_Oscs.h
@@ -0,0 +1,60 @@
+
+// Private oscillators used by T6W28_Apu
+
+// T6W28_Snd_Emu
+
+#ifndef SMS_OSCS_H
+#define SMS_OSCS_H
+
+#include "sound/Blip_Buffer.h"
+
+namespace MDFN_IEN_NGP
+{
+
+struct T6W28_Osc
+{
+ Blip_Buffer* outputs [4]; // NULL, right, left, center
+ Blip_Buffer* output;
+ int output_select;
+
+ int delay;
+ int last_amp_left;
+ int last_amp_right;
+
+ int volume_left;
+ int volume_right;
+
+ T6W28_Osc();
+ void reset();
+};
+
+struct T6W28_Square : T6W28_Osc
+{
+ int period;
+ int phase;
+
+ typedef Blip_Synth Synth;
+ const Synth* synth;
+
+ void reset();
+ void run( sms_time_t, sms_time_t );
+};
+
+struct T6W28_Noise : T6W28_Osc
+{
+ const int* period;
+ int period_extra;
+ unsigned shifter;
+ unsigned tap;
+
+ typedef Blip_Synth Synth;
+ Synth synth;
+
+ void reset();
+ void run( sms_time_t, sms_time_t );
+};
+
+}
+
+#endif
+
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.cpp
new file mode 100644
index 0000000000..48cff31cb6
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.cpp
@@ -0,0 +1,641 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+25 JUL 2002 - neopop_uk
+=======================================
+- Added missing registers to disassmbly table (unused, I hope!)
+
+//---------------------------------------------------------------------------
+*/
+
+//=========================================================================
+
+#include "../neopop.h"
+#include "TLCS900h_disassemble.h"
+#include "TLCS900h_registers.h"
+#include "TLCS900h_interpret.h"
+#include "../mem.h"
+
+namespace TLCS900H
+{
+
+void TLCS900h_disassemble_extra(void);
+void TLCS900h_disassemble_src(int size);
+void TLCS900h_disassemble_dst(void);
+void TLCS900h_disassemble_reg(int size);
+
+//=========================================================================
+
+char str_R[8]; //Big R
+char str_r[8]; //Little R
+
+//Control register names
+const char* crName[3][0x40] =
+{
+ {
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+
+ 0,0, "DMAM0", 0,
+ 0,0, "DMAM1", 0,
+ 0,0, "DMAM2", 0,
+ 0,0, "DMAM3", 0,
+ },
+
+ {
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+
+ "DMAC0", 0,
+ "DMAC1", 0,
+ "DMAC2", 0,
+ "DMAC3", 0,
+
+ 0,0, //30
+ 0,0,
+ 0,0,
+ "NSP",0, //3C
+ },
+
+ {
+ "DMAS0", //00
+ "DMAS1",
+ "DMAS2",
+ "DMAS3",
+ "DMAD0", //10
+ "DMAD1",
+ "DMAD2",
+ "DMAD3",
+ 0, //20
+ 0,
+ 0,
+ 0,
+ 0, //30
+ 0,
+ 0,
+ "XNSP", //3C
+ }
+};
+
+//Register names
+const char* gprName[8][3] =
+{
+ {"W", "WA", "XWA"},
+ {"A", "BC", "XBC"},
+ {"B", "DE", "XDE"},
+ {"C", "HL", "XHL"},
+ {"D", "IX", "XIX"},
+ {"E", "IY", "XIY"},
+ {"H", "IZ", "XIZ"},
+ {"L", "SP", "XSP"}
+};
+
+//Condition Code names
+const char* ccName[] =
+{
+ "F","LT","LE","ULE",
+ "OV","MI","Z","C",
+ "T","GE","GT","UGT",
+ "NOV","PL","NZ","NC"
+};
+
+const char* regCodeName[3][256] =
+{
+ {
+ "RA0","RW0","QA0","QW0","RC0","RB0","QC0","QB0", //BANK 0
+ "RE0","RD0","QE0","QD0","RL0","RH0","QL0","QH0",
+ "RA1","RW1","QA1","QW1","RC1","RB1","QC1","QB1", //BANK 1
+ "RE1","RD1","QE1","QD1","RL1","RH1","QL1","QH1",
+ "RA2","RW2","QA2","QW2","RC2","RB2","QC2","QB2", //BANK 2
+ "RE2","RD2","QE2","QD2","RL2","RH2","QL2","QH2",
+ "RA3","RW3","QA3","QW3","RC3","RB3","QC3","QB3", //BANK 3
+ "RE3","RD3","QE3","QD3","RL3","RH3","QL3","QH3",
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+
+ "A'","W'","QA'","QW'","C'","B'","QC'","QB'", //Previous Bank
+ "E'","D'","QE'","QD'","L'","H'","QL'","QH'",
+ "A","W","QA","QW","C","B","QC","QB", //Current Bank
+ "E","D","QE","QD","L","H","QL","QH",
+
+ "IXL","IXH","QIXL","QIXH","IYL","IYH","QIYL","QIYH",
+ "IZL","IZH","QIZL","QIZH","SPL","SPH","QSPL","QSPX"
+ },
+
+ {
+ "RWA0","QWA0","RBC0","QBC0", //BANK 0
+ "RDE0","QDE0","RHL0","QHL0",
+ "RWA1","QWA1","RBC1","QBC1", //BANK 1
+ "RDE1","QDE1","RHL1","QHL1",
+ "RWA2","QWA2","RBC2","QBC2", //BANK 2
+ "RDE2","QDE2","RHL2","QHL2",
+ "RWA3","QWA3","RBC3","QBC3", //BANK 3
+ "RDE3","QDE3","RHL3","QHL3",
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+
+ "WA'","QWA'","BC'","QBC'","DE'","QDE'","HL'","QHL'",//Previous Bank
+ "WA","QWA","BC","QBC","DE","QDE","HL","QHL", //Current Bank
+
+ "IX","QIX","IY","QIY","IZ","QIZ","SP","QSP"
+ },
+
+ {
+ "XWA0","XBC0","XDE0","XHL0", //BANK 0
+ "XWA1","XBC1","XDE1","XHL1", //BANK 1
+ "XWA2","XBC2","XDE2","XHL2", //BANK 2
+ "XWA3","XBC3","XDE3","XHL3", //BANK 3
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,
+
+ "XWA'","XBC'","XDE'","XHL'", //Previous Bank
+ "XWA","XBC","XDE","XHL", //Current Bank
+
+ "XIX","XIY","XIZ","XSP"
+ }
+};
+
+//=========================================================================
+
+void get_rr_Name(void)
+{
+ sprintf(str_r, "???");
+
+ if (size == 0 && first == 0xC7)
+ {
+ sprintf(str_r, "%s", extra);
+ return;
+ }
+
+ switch(first & 7)
+ {
+ case 0: if (size == 1) sprintf(str_r, "XWA"); break;
+ case 1:
+ if (size == 0) sprintf(str_r, "WA");
+ if (size == 1) sprintf(str_r, "XBC");
+ break;
+ case 2: if (size == 1) sprintf(str_r, "XDE"); break;
+ case 3:
+ if (size == 0) sprintf(str_r, "BC");
+ if (size == 1) sprintf(str_r, "XHL");
+ break;
+ case 4: if (size == 1) sprintf(str_r, "XIX"); break;
+ case 5:
+ if (size == 0) sprintf(str_r, "DE");
+ if (size == 1) sprintf(str_r, "XIY");
+ break;
+ case 6: if (size == 1) sprintf(str_r, "XIZ"); break;
+ case 7:
+ if (size == 0) sprintf(str_r, "HL");
+ if (size == 1) sprintf(str_r, "XSP");
+ break;
+ }
+}
+
+void get_RR_Name(void)
+{
+ sprintf(str_R, "???");
+
+ switch(second & 7)
+ {
+ case 0: if (size == 1) sprintf(str_R, "XWA"); break;
+ case 1:
+ if (size == 0) sprintf(str_R, "WA");
+ if (size == 1) sprintf(str_R, "XBC");
+ break;
+ case 2: if (size == 1) sprintf(str_R, "XDE"); break;
+ case 3:
+ if (size == 0) sprintf(str_R, "BC");
+ if (size == 1) sprintf(str_R, "XHL");
+ break;
+ case 4: if (size == 1) sprintf(str_R, "XIX"); break;
+ case 5:
+ if (size == 0) sprintf(str_R, "DE");
+ if (size == 1) sprintf(str_R, "XIY");
+ break;
+ case 6: if (size == 1) sprintf(str_R, "XIZ"); break;
+ case 7:
+ if (size == 0) sprintf(str_R, "HL");
+ if (size == 1) sprintf(str_R, "XSP");
+ break;
+ }
+}
+
+//=============================================================================
+
+char instr[128]; //Print the disassembled instruction to this string
+uint8 bytes[16]; //Stores the bytes used
+uint8 bcnt; //Byte Counter for above
+
+//=============================================================================
+
+uint8 get8_dis(void)
+{
+ uint8 a = bytes[bcnt++] = loadB(pc++);
+ return a;
+}
+
+uint16 get16_dis(void)
+{
+ uint16 a = *(uint16*)(uint8*)(bytes + bcnt) = loadW(pc);
+ pc += 2; bcnt += 2;
+ return a;
+}
+
+uint32 get24_dis(void)
+{
+ uint8 b; uint16 a;
+ a = *(uint16*)(uint8*)(bytes + bcnt) = loadW(pc);
+ pc += 2; bcnt += 2;
+ b = bytes[bcnt++] = loadB(pc++);
+ return ((uint32)b << 16) | (uint32)a;
+}
+
+uint32 get32_dis(void)
+{
+ uint32 a = *(uint32*)(uint8*)(bytes + bcnt) = loadL(pc);
+ pc += 4; bcnt += 4;
+ return a;
+}
+
+//=========================================================================
+
+static void src_B() { TLCS900h_disassemble_src(0); }
+static void src_W() { TLCS900h_disassemble_src(1); }
+static void src_L() { TLCS900h_disassemble_src(2); }
+static void dst() { TLCS900h_disassemble_dst(); }
+static void reg_B() { TLCS900h_disassemble_reg(0);}
+static void reg_W() { TLCS900h_disassemble_reg(1);}
+static void reg_L() { TLCS900h_disassemble_reg(2);}
+
+//=========================================================================
+
+//Single Byte Opcode
+
+static void NOP()
+{
+ sprintf(instr, "NOP");
+}
+
+static void NORMAL()
+{
+ sprintf(instr, "NORMAL");
+}
+
+static void PUSHSR()
+{
+ sprintf(instr, "PUSH SR");
+}
+
+static void POPSR()
+{
+ sprintf(instr, "POP SR");
+}
+
+static void MAX()
+{
+ sprintf(instr, "MAX");
+}
+
+static void HALT()
+{
+ sprintf(instr, "HALT");
+}
+
+static void EI()
+{
+ uint8 value = get8_dis();
+
+ if (value == 7)
+ sprintf(instr, "DI");
+ else
+ sprintf(instr, "EI %d", value);
+}
+
+static void RETI()
+{
+ sprintf(instr, "RETI");
+}
+
+static void LD8_8()
+{
+ uint8 dst = get8_dis(), src = get8_dis();
+ sprintf(instr, "LD (0x%02X),0x%02X", dst, src);
+}
+
+static void PUSH8()
+{
+ sprintf(instr, "PUSH 0x%02X", get8_dis());
+}
+
+static void LD8_16()
+{
+ uint8 dst = get8_dis();
+ uint16 src = get16_dis();
+ sprintf(instr, "LD.w (0x%02X),0x%04X", dst, src);
+}
+
+static void PUSH16()
+{
+ sprintf(instr, "PUSH 0x%04X", get16_dis());
+}
+
+static void INCF()
+{
+ sprintf(instr, "INCF");
+}
+
+static void DECF()
+{
+ sprintf(instr, "DECF");
+}
+
+static void RET()
+{
+ sprintf(instr, "RET");
+}
+
+static void RETD()
+{
+ sprintf(instr, "RETD %d", get16_dis());
+}
+
+static void RCF()
+{
+ sprintf(instr, "RCF");
+}
+
+static void SCF()
+{
+ sprintf(instr, "SCF");
+}
+
+static void CCF()
+{
+ sprintf(instr, "CCF");
+}
+
+static void ZCF()
+{
+ sprintf(instr, "ZCF");
+}
+
+static void PUSHA()
+{
+ sprintf(instr, "PUSH A");
+}
+
+static void POPA()
+{
+ sprintf(instr, "POP A");
+}
+
+static void EX()
+{
+ sprintf(instr, "EX F,F'");
+}
+
+static void LDF()
+{
+ sprintf(instr, "LDF 0x%02X", get8_dis());
+}
+
+static void PUSHF()
+{
+ sprintf(instr, "PUSH F");
+}
+
+static void POPF()
+{
+ sprintf(instr, "POP F");
+}
+
+static void JP16()
+{
+ sprintf(instr, "JP 0x%04X", get16_dis());
+}
+
+static void JP24()
+{
+ sprintf(instr, "JP 0x%06X", get24_dis());
+}
+
+static void CALL16()
+{
+ sprintf(instr, "CALL 0x%04X", get16_dis());
+}
+
+static void CALL24()
+{
+ sprintf(instr, "CALL 0x%06X", get24_dis());
+}
+
+static void CALR()
+{
+ sprintf(instr, "CALR 0x%06X", (int16)get16_dis() + pc);
+}
+
+static void LDB()
+{
+ sprintf(instr, "LD %s,0x%02X", gprName[first & 7][0], get8_dis());
+}
+
+static void PUSHW()
+{
+ sprintf(instr, "PUSH %s", gprName[first & 7][1]);
+}
+
+static void LDW()
+{
+ sprintf(instr, "LD %s,0x%04X", gprName[first & 7][1], get16_dis());
+}
+
+static void PUSHL()
+{
+ sprintf(instr, "PUSH %s", gprName[first & 7][2]);
+}
+
+static void LDL()
+{
+ sprintf(instr, "LD %s,0x%08X", gprName[first & 7][2], get32_dis());
+}
+
+static void POPW()
+{
+ sprintf(instr, "POP %s", gprName[first & 7][1]);
+}
+
+static void POPL()
+{
+ sprintf(instr, "POP %s", gprName[first & 7][2]);
+}
+
+static void JR()
+{
+ sprintf(instr, "JR %s,0x%06X", ccName[first & 0xF], (int8)get8_dis() + pc);
+}
+
+static void JRL()
+{
+ sprintf(instr, "JRL %s,0x%06X", ccName[first & 0xF], (int16)get16_dis() + pc);
+}
+
+static void LDX()
+{
+ uint8 dst, src;
+
+ get8_dis(); //00
+ dst = get8_dis(); //#8
+ get8_dis(); //00
+ src = get8_dis(); //#
+ get8_dis(); //00
+ sprintf(instr, "LDX (0x%02X),0x%02X", dst, src);
+}
+
+static void SWI()
+{
+ sprintf(instr, "SWI %d", first & 7);
+}
+
+//=========================================================================
+
+static void dBIOSHLE()
+{
+ sprintf(instr, "BIOS-HLE");
+}
+
+//=========================================================================
+
+//Primary Instruction decode
+static void (*decode[256])() =
+{
+/*0*/ NOP, NORMAL, PUSHSR, POPSR, MAX, HALT, EI, RETI,
+ LD8_8, PUSH8, LD8_16, PUSH16, INCF, DECF, RET, RETD,
+/*1*/ RCF, SCF, CCF, ZCF, PUSHA, POPA, EX, LDF,
+ PUSHF, POPF, JP16, JP24, CALL16, CALL24, CALR, dBIOSHLE,
+/*2*/ LDB, LDB, LDB, LDB, LDB, LDB, LDB, LDB,
+ PUSHW, PUSHW, PUSHW, PUSHW, PUSHW, PUSHW, PUSHW, PUSHW,
+/*3*/ LDW, LDW, LDW, LDW, LDW, LDW, LDW, LDW,
+ PUSHL, PUSHL, PUSHL, PUSHL, PUSHL, PUSHL, PUSHL, PUSHL,
+/*4*/ LDL, LDL, LDL, LDL, LDL, LDL, LDL, LDL,
+ POPW, POPW, POPW, POPW, POPW, POPW, POPW, POPW,
+/*5*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ POPL, POPL, POPL, POPL, POPL, POPL, POPL, POPL,
+/*6*/ JR, JR, JR, JR, JR, JR, JR, JR,
+ JR, JR, JR, JR, JR, JR, JR, JR,
+/*7*/ JRL, JRL, JRL, JRL, JRL, JRL, JRL, JRL,
+ JRL, JRL, JRL, JRL, JRL, JRL, JRL, JRL,
+/*8*/ src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B,
+ src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B,
+/*9*/ src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W,
+ src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W,
+/*A*/ src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L,
+ src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L,
+/*B*/ dst, dst, dst, dst, dst, dst, dst, dst,
+ dst, dst, dst, dst, dst, dst, dst, dst,
+/*C*/ src_B, src_B, src_B, src_B, src_B, src_B, 0, reg_B,
+ reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B,
+/*D*/ src_W, src_W, src_W, src_W, src_W, src_W, 0, reg_W,
+ reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W,
+/*E*/ src_L, src_L, src_L, src_L, src_L, src_L, 0, reg_L,
+ reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L,
+/*F*/ dst, dst, dst, dst, dst, dst, 0, LDX,
+ SWI, SWI, SWI, SWI, SWI, SWI, SWI, SWI
+};
+
+//=============================================================================
+
+char* TLCS900h_disassemble(void)
+{
+ char str[80];
+ unsigned int i;
+
+ memset(str, 0, 80);
+
+ //Reset
+ bcnt = 0;
+ brCode = FALSE;
+ sprintf(instr, "unknown");
+ sprintf(extra, "unknown");
+
+ //Fix big addresses
+ pc &= 0xFFFFFF;
+
+ //Add the program counter
+ sprintf(str, "%06X: ", pc);
+
+ first = get8_dis(); //Get the first opcode
+
+ //Disassemble
+ if (decode[first])
+ {
+ //Decode any extra data
+ TLCS900h_disassemble_extra();
+ (*decode[first])();
+ }
+
+ //Add the instruction
+ strcat(str, instr);
+
+ //Add the bytes used
+ for (i = strlen(str); i < 32; i++)
+ str[i] = ' ';
+ str[32] = '\"';
+ for (i = 0; i < bcnt; i++)
+ {
+ char tmp[80];
+ sprintf(tmp, "%02X ", bytes[i]);
+ strcat(str, tmp);
+ }
+ str[strlen(str) - 1] = '\"';
+
+ return strdup(str);
+}
+};
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.h b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.h
new file mode 100644
index 0000000000..2995be36aa
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble.h
@@ -0,0 +1,77 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_DISASSEMBLE__
+#define __TLCS900H_DISASSEMBLE__
+
+namespace TLCS900H
+{
+//=============================================================================
+
+//Disassembles a single instruction from 'pc',
+//pc is incremented to the start of the next instruction.
+char* TLCS900h_disassemble(void);
+
+//Print to this string the disassembled instruction
+extern char instr[128];
+
+//Print the mnemonic for the addressing mode / reg code.
+extern char extra[256];
+
+//=============================================================================
+
+extern char str_R[8]; //Big R
+extern char str_r[8]; //Little R
+
+//Translate an rr or RR value for MUL/MULS/DIV/DIVS
+void get_rr_Name(void);
+void get_RR_Name(void);
+
+extern uint8 bytes[16]; //Stores the bytes used
+extern uint8 bcnt; //Byte Counter for above
+
+extern const char* gprName[8][3]; //8 regs * 3 names (byte, word, long)
+extern const char* regCodeName[3][256];
+extern const char* crName[3][0x40];
+
+extern const char* ccName[];
+
+uint8 get8_dis(void);
+uint16 get16_dis(void);
+uint32 get24_dis(void);
+uint32 get32_dis(void);
+
+};
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_dst.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_dst.cpp
new file mode 100644
index 0000000000..ff35e1f80a
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_dst.cpp
@@ -0,0 +1,240 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble_dst.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+//=========================================================================
+
+#include "../neopop.h"
+#include "TLCS900h_disassemble.h"
+#include "TLCS900h_registers.h"
+#include "TLCS900h_interpret.h"
+
+//=========================================================================
+namespace TLCS900H
+{
+
+static void LDBi()
+{
+ sprintf(instr, "LD (%s),0x%02X", extra, get8_dis());
+}
+
+static void LDWi()
+{
+ sprintf(instr, "LD (%s),0x%04X", extra, get16_dis());
+}
+
+static void POPB()
+{
+ sprintf(instr, "POP.b (%s)", extra);
+}
+
+static void POPW()
+{
+ sprintf(instr, "POP.w (%s)", extra);
+}
+
+static void LDBm16()
+{
+ sprintf(instr, "LD.b (%s),(0x%04X)", extra, get16_dis());
+}
+
+static void LDWm16()
+{
+ sprintf(instr, "LD.w (%s),(0x%04X)", extra, get16_dis());
+}
+
+static void LDAW()
+{
+ sprintf(instr, "LDA %s,%s", gprName[second & 7][1], extra);
+}
+
+static void LDAL()
+{
+ sprintf(instr, "LDA %s,%s", gprName[second & 7][2], extra);
+}
+
+static void ANDCFA()
+{
+ sprintf(instr, "ANDCF A,(%s)", extra);
+}
+
+static void ORCFA()
+{
+ sprintf(instr, "ORCF A,(%s)", extra);
+}
+
+static void XORCFA()
+{
+ sprintf(instr, "XORCF A,(%s)", extra);
+}
+
+static void LDCFA()
+{
+ sprintf(instr, "LDCF A,(%s)", extra);
+}
+
+static void STCFA()
+{
+ sprintf(instr, "STCF A,(%s)", extra);
+}
+
+static void LDBR()
+{
+ sprintf(instr, "LD (%s),%s", extra, gprName[second&7][0]);
+}
+
+static void LDWR()
+{
+ sprintf(instr, "LD (%s),%s", extra, gprName[second&7][1]);
+}
+
+static void LDLR()
+{
+ sprintf(instr, "LD (%s),%s", extra, gprName[second&7][2]);
+}
+
+static void ANDCF()
+{
+ sprintf(instr, "ANDCF %d,(%s)", second & 7, extra);
+}
+
+static void ORCF()
+{
+ sprintf(instr, "ORCF %d,(%s)", second & 7, extra);
+}
+
+static void XORCF()
+{
+ sprintf(instr, "XORCF %d,(%s)", second & 7, extra);
+}
+
+static void LDCF()
+{
+ sprintf(instr, "LDCF %d,(%s)", second & 7, extra);
+}
+
+static void STCF()
+{
+ sprintf(instr, "STCF %d,(%s)", second & 7, extra);
+}
+
+static void TSET()
+{
+ sprintf(instr, "TSET %d,(%s)", second & 7, extra);
+}
+
+static void RES()
+{
+ sprintf(instr, "RES %d,(%s)", second & 7, extra);
+}
+
+static void SET()
+{
+ sprintf(instr, "SET %d,(%s)", second & 7, extra);
+}
+
+static void CHG()
+{
+ sprintf(instr, "CHG %d,(%s)", second & 7, extra);
+}
+
+static void BIT()
+{
+ sprintf(instr, "BIT %d,(%s)", second & 7, extra);
+}
+
+static void JP()
+{
+ sprintf(instr, "JP %s,%s", ccName[second & 0xF], extra);
+}
+
+static void CALL()
+{
+ sprintf(instr, "CALL %s,%s", ccName[second & 0xF], extra);
+}
+
+static void RET()
+{
+ sprintf(instr, "RET %s", ccName[second & 0xF]);
+}
+
+//=========================================================================
+
+//Secondary (DST) Instruction decode
+static void (*decode[256])() =
+{
+/*0*/ LDBi, 0, LDWi, 0, POPB, 0, POPW, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*1*/ 0, 0, 0, 0, LDBm16, 0, LDWm16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*2*/ LDAW, LDAW, LDAW, LDAW, LDAW, LDAW, LDAW, LDAW,
+ ANDCFA, ORCFA, XORCFA, LDCFA, STCFA, 0, 0, 0,
+/*3*/ LDAL, LDAL, LDAL, LDAL, LDAL, LDAL, LDAL, LDAL,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*4*/ LDBR, LDBR, LDBR, LDBR, LDBR, LDBR, LDBR, LDBR,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*5*/ LDWR, LDWR, LDWR, LDWR, LDWR, LDWR, LDWR, LDWR,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*6*/ LDLR, LDLR, LDLR, LDLR, LDLR, LDLR, LDLR, LDLR,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*7*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*8*/ ANDCF, ANDCF, ANDCF, ANDCF, ANDCF, ANDCF, ANDCF, ANDCF,
+ ORCF, ORCF, ORCF, ORCF, ORCF, ORCF, ORCF, ORCF,
+/*9*/ XORCF, XORCF, XORCF, XORCF, XORCF, XORCF, XORCF, XORCF,
+ LDCF, LDCF, LDCF, LDCF, LDCF, LDCF, LDCF, LDCF,
+/*A*/ STCF, STCF, STCF, STCF, STCF, STCF, STCF, STCF,
+ TSET, TSET, TSET, TSET, TSET, TSET, TSET, TSET,
+/*B*/ RES, RES, RES, RES, RES, RES, RES, RES,
+ SET, SET, SET, SET, SET, SET, SET, SET,
+/*C*/ CHG, CHG, CHG, CHG, CHG, CHG, CHG, CHG,
+ BIT, BIT, BIT, BIT, BIT, BIT, BIT, BIT,
+/*D*/ JP, JP, JP, JP, JP, JP, JP, JP,
+ JP, JP, JP, JP, JP, JP, JP, JP,
+/*E*/ CALL, CALL, CALL, CALL, CALL, CALL, CALL, CALL,
+ CALL, CALL, CALL, CALL, CALL, CALL, CALL, CALL,
+/*F*/ RET, RET, RET, RET, RET, RET, RET, RET,
+ RET, RET, RET, RET, RET, RET, RET, RET
+};
+
+//=============================================================================
+
+void TLCS900h_disassemble_dst(void)
+{
+ second = get8_dis(); //Get the second opcode
+
+ if (decode[second])
+ (*decode[second])();
+ else
+ sprintf(instr, "unknown dst instr. %02X", second);
+}
+};
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_extra.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_extra.cpp
new file mode 100644
index 0000000000..cd69775c2d
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_extra.cpp
@@ -0,0 +1,199 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble_extra.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+02 SEP 2002 - neopop_uk
+=======================================
+- Added the undocumented type 0x13 R32 address mode.
+
+//---------------------------------------------------------------------------
+*/
+
+//=========================================================================
+
+#include "../neopop.h"
+#include "TLCS900h_disassemble.h"
+#include "TLCS900h_interpret.h"
+
+#define RCN_fetch(_a, _b) (regCodeName[(_a)][(_b)] ? regCodeName[(_a)][(_b)] : "-UNK-")
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+char extra[256]; //Print the mnemonic for the addressing mode here.
+
+//=========================================================================
+
+static void ExXWA() {sprintf(extra, "XWA");}
+static void ExXBC() {sprintf(extra, "XBC");}
+static void ExXDE() {sprintf(extra, "XDE");}
+static void ExXHL() {sprintf(extra, "XHL");}
+static void ExXIX() {sprintf(extra, "XIX");}
+static void ExXIY() {sprintf(extra, "XIY");}
+static void ExXIZ() {sprintf(extra, "XIZ");}
+static void ExXSP() {sprintf(extra, "XSP");}
+
+static void ExXWAd() {sprintf(extra, "XWA %+d", (int8)get8_dis());}
+static void ExXBCd() {sprintf(extra, "XBC %+d", (int8)get8_dis());}
+static void ExXDEd() {sprintf(extra, "XDE %+d", (int8)get8_dis());}
+static void ExXHLd() {sprintf(extra, "XHL %+d", (int8)get8_dis());}
+static void ExXIXd() {sprintf(extra, "XIX %+d", (int8)get8_dis());}
+static void ExXIYd() {sprintf(extra, "XIY %+d", (int8)get8_dis());}
+static void ExXIZd() {sprintf(extra, "XIZ %+d", (int8)get8_dis());}
+static void ExXSPd() {sprintf(extra, "XSP %+d", (int8)get8_dis());}
+
+static void Ex8() {sprintf(extra, "0x%02X", get8_dis());}
+static void Ex16() {sprintf(extra, "0x%04X", get16_dis());}
+static void Ex24() {sprintf(extra, "0x%06X", get24_dis());}
+
+static void ExR32()
+{
+ uint8 data = get8_dis();
+
+ if (data == 0x03)
+ {
+ uint8 rIndex, r32;
+ r32 = get8_dis(); //r32, upper 6 bits
+ rIndex = get8_dis(); //r8 / r16
+ sprintf(extra, "%s + %s",
+ RCN_fetch(2, r32 >> 2), RCN_fetch(0, rIndex >> 0));
+ return;
+ }
+
+ if (data == 0x07)
+ {
+ uint8 rIndex, r32;
+ r32 = get8_dis(); //r32, upper 6 bits
+ rIndex = get8_dis(); //r8 / r16
+ sprintf(extra, "%s + %s",
+ RCN_fetch(2, r32 >> 2), RCN_fetch(1, rIndex >> 1));
+ return;
+ }
+
+ //Undocumented mode.
+ if (data == 0x13)
+ {
+ sprintf(extra, "pc %+d", (int16)get16_dis());
+ return;
+ }
+
+ if ((data & 3) == 1)
+ sprintf(extra, "%s %+d", RCN_fetch(2, data >> 2), (int16)get16_dis());
+ else
+ sprintf(extra, "%s", RCN_fetch(2, data >> 2));
+}
+
+static void ExDec()
+{
+ uint8 data = get8_dis();
+ uint8 r32 = data & 0xFC;
+
+ switch(data & 3)
+ {
+ case 0: sprintf(extra, "1--%s", RCN_fetch(2, r32 >> 2)); break;
+ case 1: sprintf(extra, "2--%s", RCN_fetch(2, r32 >> 2)); break;
+ case 2: sprintf(extra, "4--%s", RCN_fetch(2, r32 >> 2)); break;
+ }
+}
+
+static void ExInc()
+{
+ uint8 data = get8_dis();
+ uint8 r32 = data & 0xFC;
+
+ switch(data & 3)
+ {
+ case 0: sprintf(extra, "%s++1", RCN_fetch(2, r32 >> 2)); break;
+ case 1: sprintf(extra, "%s++2", RCN_fetch(2, r32 >> 2)); break;
+ case 2: sprintf(extra, "%s++4", RCN_fetch(2, r32 >> 2)); break;
+ }
+}
+
+static void ExRCB()
+{
+ uint8 data = get8_dis();
+ sprintf(extra, "%s", RCN_fetch(0, data >> 0));
+ brCode = TRUE;
+}
+
+static void ExRCW()
+{
+ uint8 data = get8_dis();
+ sprintf(extra, "%s", RCN_fetch(1, data >> 1));
+ brCode = TRUE;
+}
+
+static void ExRCL()
+{
+ uint8 data = get8_dis();
+ sprintf(extra, "%s", RCN_fetch(2, data >> 2));
+ brCode = TRUE;
+}
+
+//=========================================================================
+
+//Address Mode & Register Code
+static void (*decodeExtra[256])() =
+{
+/*0*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*1*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*2*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*3*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*4*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*5*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*6*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*7*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*8*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*9*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*A*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*B*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*C*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRCB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*D*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRCW,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*E*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRCL,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*F*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void TLCS900h_disassemble_extra(void)
+{
+ //Is any extra data used by this instruction?
+ if (decodeExtra[first])
+ (*decodeExtra[first])();
+}
+
+};
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_reg.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_reg.cpp
new file mode 100644
index 0000000000..9d0eb10c07
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_reg.cpp
@@ -0,0 +1,662 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble_reg.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+22 JUL 2002 - neopop_uk
+=======================================
+- Fixed disassembly of Link, it's second operand is signed.
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Better disassembly of MUL/MULS/DIV/DIVS - operand size is shown.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_disassemble.h"
+#include "TLCS900h_registers.h"
+#include "TLCS900h_interpret.h"
+
+//=========================================================================
+
+namespace TLCS900H
+{
+
+static void LDi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "LD %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "LD %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "LD %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void PUSH()
+{
+ sprintf(instr, "PUSH %s", str_r);
+}
+
+static void POP()
+{
+ sprintf(instr, "POP %s", str_r);
+}
+
+static void CPL()
+{
+ sprintf(instr, "CPL %s", str_r);
+}
+
+static void NEG()
+{
+ sprintf(instr, "NEG %s", str_r);
+}
+
+static void MULi()
+{
+ get_rr_Name();
+
+ switch(size)
+ {
+ case 0: sprintf(instr, "MUL.b %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "MUL.w %s,0x%04X", str_r, get16_dis()); break;
+ }
+}
+
+static void MULSi()
+{
+ get_rr_Name();
+
+ switch(size)
+ {
+ case 0: sprintf(instr, "MULS.b %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "MULS.w %s,0x%04X", str_r, get16_dis()); break;
+ }
+}
+
+static void DIVi()
+{
+ get_rr_Name();
+
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIV.b %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "DIV.w %s,0x%04X", str_r, get16_dis()); break;
+ }
+}
+
+static void DIVSi()
+{
+ get_rr_Name();
+
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIVS.b %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "DIVS.w %s,0x%04X", str_r, get16_dis()); break;
+ }
+}
+
+static void LINK()
+{
+ sprintf(instr, "LINK %s, %d", str_r, (int16)get16_dis());
+}
+
+static void UNLK()
+{
+ sprintf(instr, "UNLK %s", str_r);
+}
+
+static void BS1F()
+{
+ sprintf(instr, "BS1F A,%s", str_r);
+}
+
+static void BS1B()
+{
+ sprintf(instr, "BS1B A,%s", str_r);
+}
+
+static void DAA()
+{
+ sprintf(instr, "DAA %s", str_r);
+}
+
+static void EXTZ()
+{
+ sprintf(instr, "EXTZ %s", str_r);
+}
+
+static void EXTS()
+{
+ sprintf(instr, "EXTS %s", str_r);
+}
+
+static void PAA()
+{
+ sprintf(instr, "PAA %s", str_r);
+}
+
+static void MIRR()
+{
+ sprintf(instr, "MIRR %s", str_r);
+}
+
+static void MULA()
+{
+ sprintf(instr, "MULA %s", str_r);
+}
+
+static void DJNZ()
+{
+ sprintf(instr, "DJNZ %s,0x%06X", str_r, (int8)get8_dis() + pc);
+}
+
+static void ANDCFi()
+{
+ sprintf(instr, "ANDCF %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void ORCFi()
+{
+ sprintf(instr, "ORCF %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void XORCFi()
+{
+ sprintf(instr, "XORCF %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void LDCFi()
+{
+ sprintf(instr, "LDCF %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void STCFi()
+{
+ sprintf(instr, "STCF %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void ANDCFA()
+{
+ sprintf(instr, "ANDCF A,%s", str_r);
+}
+
+static void ORCFA()
+{
+ sprintf(instr, "ORCF A,%s", str_r);
+}
+
+static void XORCFA()
+{
+ sprintf(instr, "XORCF A,%s", str_r);
+}
+
+static void LDCFA()
+{
+ sprintf(instr, "LDCF A,%s", str_r);
+}
+
+static void STCFA()
+{
+ sprintf(instr, "STCF A,%s", str_r);
+}
+
+static void LDCcrr()
+{
+ uint8 cr = get8_dis();
+ sprintf(instr, "LDC %s,%s", crName[size][cr >> size], str_r);
+}
+
+static void LDCrcr()
+{
+ uint8 cr = get8_dis();
+ sprintf(instr, "LDC %s,%s", str_r, crName[size][cr >> size]);
+}
+
+static void RES()
+{
+ sprintf(instr, "RES %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void SET()
+{
+ sprintf(instr, "SET %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void CHG()
+{
+ sprintf(instr, "CHG %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void BIT()
+{
+ sprintf(instr, "BIT %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void TSET()
+{
+ sprintf(instr, "TSET %d,%s", get8_dis() & 0xF, str_r);
+}
+
+static void MINC1()
+{
+ sprintf(instr, "MINC1 %d,%s", get16_dis()+1, str_r);
+}
+
+static void MINC2()
+{
+ sprintf(instr, "MINC2 %d,%s", get16_dis()+2, str_r);
+}
+
+static void MINC4()
+{
+ sprintf(instr, "MINC4 %d,%s", get16_dis()+4, str_r);
+}
+
+static void MDEC1()
+{
+ sprintf(instr, "MDEC1 %d,%s", get16_dis()+1, str_r);
+}
+
+static void MDEC2()
+{
+ sprintf(instr, "MDEC2 %d,%s", get16_dis()+2, str_r);
+}
+
+static void MDEC4()
+{
+ sprintf(instr, "MDEC4 %d,%s", get16_dis()+4, str_r);
+}
+
+static void MUL()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "MUL.b %s,%s", str_R, str_r); break;
+ case 1: sprintf(instr, "MUL.w %s,%s", str_R, str_r); break;
+ }
+}
+
+static void MULS()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "MULS.b %s,%s", str_R, str_r); break;
+ case 1: sprintf(instr, "MULS.w %s,%s", str_R, str_r); break;
+ }
+}
+
+static void DIV()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIV.b %s,%s", str_R, str_r); break;
+ case 1: sprintf(instr, "DIV.w %s,%s", str_R, str_r); break;
+ }
+}
+
+static void DIVS()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIVS.b %s,%s", str_R, str_r); break;
+ case 1: sprintf(instr, "DIVS.w %s,%s", str_R, str_r); break;
+ }
+}
+
+static void INC()
+{
+ uint8 val = (second & 7);
+ if (val == 0)
+ val = 8;
+
+ sprintf(instr, "INC %d,%s", val, str_r);
+}
+
+static void DEC()
+{
+ uint8 val = (second & 7);
+ if (val == 0)
+ val = 8;
+
+ sprintf(instr, "DEC %d,%s", val, str_r);
+}
+
+static void SCC()
+{
+ sprintf(instr, "SCC %s,%s", ccName[second & 0xF], str_r);
+}
+
+static void ADD()
+{
+ sprintf(instr, "ADD %s,%s", str_R, str_r);
+}
+
+static void LDRr()
+{
+ sprintf(instr, "LD %s,%s", str_R, str_r);
+}
+
+static void LDrR()
+{
+ sprintf(instr, "LD %s,%s", str_r, str_R);
+}
+
+static void ADC()
+{
+ sprintf(instr, "ADC %s,%s", str_R, str_r);
+}
+
+static void SUB()
+{
+ sprintf(instr, "SUB %s,%s", str_R, str_r);
+}
+
+static void SBC()
+{
+ sprintf(instr, "SBC %s,%s", str_R, str_r);
+}
+
+static void LDr3()
+{
+ sprintf(instr, "LD %s,%d", str_r, second & 7);
+}
+
+static void EX()
+{
+ sprintf(instr, "EX %s,%s", str_R, str_r);
+}
+
+static void AND()
+{
+ sprintf(instr, "AND %s,%s", str_R, str_r);
+}
+
+static void ADDi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "ADD %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "ADD %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "ADD %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void ADCi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "ADC %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "ADC %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "ADC %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void SUBi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "SUB %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "SUB %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "SUB %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void SBCi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "SBC %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "SBC %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "SBC %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void ANDi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "AND %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "AND %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "AND %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void XORi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "XOR %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "XOR %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "XOR %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void ORi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "OR %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "OR %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "OR %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void CPi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "CP %s,0x%02X", str_r, get8_dis()); break;
+ case 1: sprintf(instr, "CP %s,0x%04X", str_r, get16_dis()); break;
+ case 2: sprintf(instr, "CP %s,0x%08X", str_r, get32_dis()); break;
+ }
+}
+
+static void XOR()
+{
+ sprintf(instr, "XOR %s,%s", str_R, str_r);
+}
+
+static void CPr3()
+{
+ sprintf(instr,"CP %s,%d", str_r, second&7);
+}
+
+static void OR()
+{
+ sprintf(instr, "OR %s,%s", str_R, str_r);
+}
+
+static void RLCi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "RLC %d,%s", val, str_r);
+}
+
+static void RRCi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "RRC %d,%s", val, str_r);
+}
+
+static void RLi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "RL %d,%s", val, str_r);
+}
+
+static void RRi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "RR %d,%s", val, str_r);
+}
+
+static void SLAi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "SLA %d,%s", val, str_r);
+}
+
+static void SRAi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "SRA %d,%s", val, str_r);
+}
+
+static void SLLi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "SLL %d,%s", val, str_r);
+}
+
+static void SRLi()
+{
+ uint8 val = get8_dis() & 0xF;
+ if (val == 0) val = 16;
+ sprintf(instr, "SRL %d,%s", val, str_r);
+}
+
+static void CP()
+{
+ sprintf(instr, "CP %s,%s", str_R, str_r);
+}
+
+static void RLCA()
+{
+ sprintf(instr, "RLC A,%s", str_r);
+}
+
+static void RRCA()
+{
+ sprintf(instr, "RRC A,%s", str_r);
+}
+
+static void RLA()
+{
+ sprintf(instr, "RL A,%s", str_r);
+}
+
+static void RRA()
+{
+ sprintf(instr, "RR A,%s", str_r);
+}
+
+static void SLAA()
+{
+ sprintf(instr, "SLA A,%s", str_r);
+}
+
+static void SRAA()
+{
+ sprintf(instr, "SRA A,%s", str_r);
+}
+
+static void SLLA()
+{
+ sprintf(instr, "SLL A,%s", str_r);
+}
+
+static void SRLA()
+{
+ sprintf(instr, "SRL A,%s", str_r);
+}
+
+//=========================================================================
+
+//Secondary (REG) Instruction decode
+static void (*decode[256])() =
+{
+/*0*/ 0, 0, 0, LDi, PUSH, POP, CPL, NEG,
+ MULi, MULSi, DIVi, DIVSi, LINK, UNLK, BS1F, BS1B,
+/*1*/ DAA, 0, EXTZ, EXTS, PAA, 0, MIRR, 0,
+ 0, MULA, 0, 0, DJNZ, 0, 0, 0,
+/*2*/ ANDCFi, ORCFi, XORCFi, LDCFi, STCFi, 0, 0, 0,
+ ANDCFA, ORCFA, XORCFA, LDCFA, STCFA, 0, LDCcrr, LDCrcr,
+/*3*/ RES, SET, CHG, BIT, TSET, 0, 0, 0,
+ MINC1, MINC2, MINC4, 0, MDEC1, MDEC2, MDEC4, 0,
+/*4*/ MUL, MUL, MUL, MUL, MUL, MUL, MUL, MUL,
+ MULS, MULS, MULS, MULS, MULS, MULS, MULS, MULS,
+/*5*/ DIV, DIV, DIV, DIV, DIV, DIV, DIV, DIV,
+ DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS,
+/*6*/ INC, INC, INC, INC, INC, INC, INC, INC,
+ DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC,
+/*7*/ SCC, SCC, SCC, SCC, SCC, SCC, SCC, SCC,
+ SCC, SCC, SCC, SCC, SCC, SCC, SCC, SCC,
+/*8*/ ADD, ADD, ADD, ADD, ADD, ADD, ADD, ADD,
+ LDRr, LDRr, LDRr, LDRr, LDRr, LDRr, LDRr, LDRr,
+/*9*/ ADC, ADC, ADC, ADC, ADC, ADC, ADC, ADC,
+ LDrR, LDrR, LDrR, LDrR, LDrR, LDrR, LDrR, LDrR,
+/*A*/ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
+ LDr3, LDr3, LDr3, LDr3, LDr3, LDr3, LDr3, LDr3,
+/*B*/ SBC, SBC, SBC, SBC, SBC, SBC, SBC, SBC,
+ EX, EX, EX, EX, EX, EX, EX, EX,
+/*C*/ AND, AND, AND, AND, AND, AND, AND, AND,
+ ADDi, ADCi, SUBi, SBCi, ANDi, XORi, ORi, CPi,
+/*D*/ XOR, XOR, XOR, XOR, XOR, XOR, XOR, XOR,
+ CPr3, CPr3, CPr3, CPr3, CPr3, CPr3, CPr3, CPr3,
+/*E*/ OR, OR, OR, OR, OR, OR, OR, OR,
+ RLCi, RRCi, RLi, RRi, SLAi, SRAi, SLLi, SRLi,
+/*F*/ CP, CP, CP, CP, CP, CP, CP, CP,
+ RLCA, RRCA, RLA, RRA, SLAA, SRAA, SLLA, SRLA
+};
+
+//=============================================================================
+
+void TLCS900h_disassemble_reg(int opsize)
+{
+ second = get8_dis(); //Get the second opcode
+ size = opsize;
+
+ //Prepare 'Big R'
+ sprintf(str_R, "%s", gprName[second & 7][size]);
+
+ //Prepare 'little r'
+ if (brCode)
+ sprintf(str_r, "%s", extra);
+ else
+ sprintf(str_r, "%s", gprName[first & 7][opsize]);
+
+ if (decode[second])
+ (*decode[second])();
+ else
+ sprintf(instr, "unknown reg instr. %02X", second);
+}
+};
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_src.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_src.cpp
new file mode 100644
index 0000000000..27e42d5035
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_disassemble_src.cpp
@@ -0,0 +1,507 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_disassemble_src.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Better disassembly of MUL/MULS/DIV/DIVS - operand size is shown.
+
+//---------------------------------------------------------------------------
+*/
+
+//=========================================================================
+
+#include "../neopop.h"
+#include "TLCS900h_disassemble.h"
+#include "TLCS900h_registers.h"
+#include "TLCS900h_interpret.h"
+
+//=========================================================================
+
+namespace TLCS900H
+{
+
+static void PUSH()
+{
+ sprintf(instr, "PUSH (%s)", extra);
+}
+
+static void RLD()
+{
+ sprintf(instr, "RLD A,(%s)", extra);
+}
+
+static void RRD()
+{
+ sprintf(instr, "RRD A,(%s)", extra);
+}
+
+static void LDI()
+{
+ if ((first & 0xF) == 3)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDI.b (XDE+),(XHL+)"); break;
+ case 1: sprintf(instr, "LDI.w (XDE+),(XHL+)"); break;
+ }
+ }
+
+ if ((first & 0xF) == 5)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDI.b (XIX+),(XIY+)"); break;
+ case 1: sprintf(instr, "LDI.w (XIX+),(XIY+)"); break;
+ }
+ }
+}
+
+static void LDIR()
+{
+ if ((first & 0xF) == 3)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDIR.b (XDE+),(XHL+)"); break;
+ case 1: sprintf(instr, "LDIR.w (XDE+),(XHL+)"); break;
+ }
+ }
+
+ if ((first & 0xF) == 5)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDIR.b (XIX+),(XIY+)"); break;
+ case 1: sprintf(instr, "LDIR.w (XIX+),(XIY+)"); break;
+ }
+ }
+}
+
+static void LDD()
+{
+ if ((first & 0xF) == 3)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDD.b (XDE-),(XHL-)"); break;
+ case 1: sprintf(instr, "LDD.w (XDE-),(XHL-)"); break;
+ }
+ }
+
+ if ((first & 0xF) == 5)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDD.b (XIX-),(XIY-)"); break;
+ case 1: sprintf(instr, "LDD.w (XIX-),(XIY-)"); break;
+ }
+ }
+}
+
+static void LDDR()
+{
+ if ((first & 0xF) == 3)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDDR.b (XDE-),(XHL-)"); break;
+ case 1: sprintf(instr, "LDDR.w (XDE-),(XHL-)"); break;
+ }
+ }
+
+ if ((first & 0xF) == 5)
+ {
+ switch(size)
+ {
+ case 0: sprintf(instr, "LDDR.b (XIX-),(XIY-)"); break;
+ case 1: sprintf(instr, "LDDR.w (XIX-),(XIY-)"); break;
+ }
+ }
+}
+
+static void CPI()
+{
+ sprintf(instr, "CPI");
+}
+
+static void CPIR()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "CPIR.b A,(%s+)", gprName[first & 7][2]); break;
+ case 1: sprintf(instr, "CPIR.w WA,(%s+)", gprName[first & 7][2]); break;
+ }
+}
+
+static void CPD()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "CPD.b A,(%s+)", gprName[first & 7][2]); break;
+ case 1: sprintf(instr, "CPD.w WA,(%s+)", gprName[first & 7][2]); break;
+ }
+}
+
+static void CPDR()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "CPDR.b A,(%s+)", gprName[first & 7][2]); break;
+ case 1: sprintf(instr, "CPDR.w WA,(%s+)", gprName[first & 7][2]); break;
+ }
+}
+
+static void LD16m()
+{
+ sprintf(instr, "LD (0x%04X),(%s)", get16_dis(), extra);
+}
+
+static void LD()
+{
+ sprintf(instr, "LD %s,(%s)", str_R, extra);
+}
+
+static void EX()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "EX.b (%s),%s", extra, str_R); break;
+ case 1: sprintf(instr, "EX.w (%s),%s", extra, str_R); break;
+ }
+
+}
+
+static void ADDi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "ADD (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "ADD (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void ADCi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "ADC (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "ADC (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void SUBi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "SUB (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "SUB (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void SBCi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "SBC (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "SBC (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void ANDi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "AND (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "AND (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void XORi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "XOR (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "XOR (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void ORi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "OR (%s), 0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "OR (%s), 0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void CPi()
+{
+ switch(size)
+ {
+ case 0: sprintf(instr, "CP (%s),0x%02X", extra, get8_dis()); break;
+ case 1: sprintf(instr, "CP (%s),0x%04X", extra, get16_dis()); break;
+ }
+}
+
+static void MUL()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "MUL.b (%s),(%s)",str_R, extra); break;
+ case 1: sprintf(instr, "MUL.w (%s),(%s)",str_R, extra); break;
+ }
+}
+
+static void MULS()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "MULS.b (%s),(%s)",str_R, extra); break;
+ case 1: sprintf(instr, "MULS.w (%s),(%s)",str_R, extra); break;
+ }
+}
+
+static void DIV()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIV.b (%s),(%s)",str_R, extra); break;
+ case 1: sprintf(instr, "DIV.w (%s),(%s)",str_R, extra); break;
+ }
+}
+
+static void DIVS()
+{
+ get_RR_Name();
+ switch(size)
+ {
+ case 0: sprintf(instr, "DIVS.b (%s),(%s)",str_R, extra); break;
+ case 1: sprintf(instr, "DIVS.w (%s),(%s)",str_R, extra); break;
+ }
+}
+
+static void INC()
+{
+ uint8 val = (second & 7);
+ if (val == 0)
+ val = 8;
+
+ sprintf(instr, "INC %d,(%s)", val, extra);
+}
+
+static void DEC()
+{
+ uint8 val = (second & 7);
+ if (val == 0)
+ val = 8;
+
+ sprintf(instr, "DEC %d,(%s)", val, extra);
+}
+
+static void RLC()
+{
+ sprintf(instr, "RLC (%s)", extra);
+}
+
+static void RRC()
+{
+ sprintf(instr, "RRC (%s)", extra);
+}
+
+static void RL()
+{
+ sprintf(instr, "RL (%s)", extra);
+}
+
+static void RR()
+{
+ sprintf(instr, "RR (%s)", extra);
+}
+
+static void SLA()
+{
+ sprintf(instr, "SLA (%s)", extra);
+}
+
+static void SRA()
+{
+ sprintf(instr, "SRA (%s)", extra);
+}
+
+static void SLL()
+{
+ sprintf(instr, "SLL (%s)", extra);
+}
+
+static void SRL()
+{
+ sprintf(instr, "SRL (%s)", extra);
+}
+
+static void ADDRm()
+{
+ sprintf(instr, "ADD %s,(%s)", str_R, extra);
+}
+
+static void ADDmR()
+{
+ sprintf(instr, "ADD (%s),%s", extra, str_R);
+}
+
+static void ADCRm()
+{
+ sprintf(instr, "ADC %s,(%s)", str_R, extra);
+}
+
+static void ADCmR()
+{
+ sprintf(instr, "ADC (%s),%s", extra, str_R);
+}
+
+static void SUBRm()
+{
+ sprintf(instr, "SUB %s,(%s)", str_R, extra);
+}
+
+static void SUBmR()
+{
+ sprintf(instr, "SUB (%s),%s", extra, str_R);
+}
+
+static void SBCRm()
+{
+ sprintf(instr, "SBC %s,(%s)", str_R, extra);
+}
+
+static void SBCmR()
+{
+ sprintf(instr, "SBC (%s),%s", extra, str_R);
+}
+
+static void ANDmR()
+{
+ sprintf(instr, "AND (%s),%s", extra, str_R);
+}
+
+static void ANDRm()
+{
+ sprintf(instr, "AND %s,(%s)", str_R, extra);
+}
+
+static void XORmR()
+{
+ sprintf(instr, "XOR (%s),%s", extra, str_R);
+}
+
+static void XORRm()
+{
+ sprintf(instr, "XOR %s,(%s)", str_R, extra);
+}
+
+static void ORmR()
+{
+ sprintf(instr, "OR (%s),%s", extra, str_R);
+}
+
+static void ORRm()
+{
+ sprintf(instr, "OR %s,(%s)", str_R, extra);
+}
+
+static void CPmR()
+{
+ sprintf(instr, "CP (%s),%s", extra, str_R);
+}
+
+static void CPRm()
+{
+ sprintf(instr, "CP %s,(%s)", str_R, extra);
+}
+
+//=========================================================================
+
+//Secondary (SRC) Instruction decode
+static void (*decode[256])() =
+{
+/*0*/ 0, 0, 0, 0, PUSH, 0, RLD, RRD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*1*/ LDI, LDIR, LDD, LDDR, CPI, CPIR, CPD, CPDR,
+ 0, LD16m, 0, 0, 0, 0, 0, 0,
+/*2*/ LD, LD, LD, LD, LD, LD, LD, LD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*3*/ EX, EX, EX, EX, EX, EX, EX, EX,
+ ADDi, ADCi, SUBi, SBCi, ANDi, XORi, ORi, CPi,
+/*4*/ MUL, MUL, MUL, MUL, MUL, MUL, MUL, MUL,
+ MULS, MULS, MULS, MULS, MULS, MULS, MULS, MULS,
+/*5*/ DIV, DIV, DIV, DIV, DIV, DIV, DIV, DIV,
+ DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS, DIVS,
+/*6*/ INC, INC, INC, INC, INC, INC, INC, INC,
+ DEC, DEC, DEC, DEC, DEC, DEC, DEC, DEC,
+/*7*/ 0, 0, 0, 0, 0, 0, 0, 0,
+ RLC, RRC, RL, RR, SLA, SRA, SLL, SRL,
+/*8*/ ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm, ADDRm,
+ ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR, ADDmR,
+/*9*/ ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm, ADCRm,
+ ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR, ADCmR,
+/*A*/ SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm, SUBRm,
+ SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR, SUBmR,
+/*B*/ SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm, SBCRm,
+ SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR, SBCmR,
+/*C*/ ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm, ANDRm,
+ ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR, ANDmR,
+/*D*/ XORRm, XORRm, XORRm, XORRm, XORRm, XORRm, XORRm, XORRm,
+ XORmR, XORmR, XORmR, XORmR, XORmR, XORmR, XORmR, XORmR,
+/*E*/ ORRm, ORRm, ORRm, ORRm, ORRm, ORRm, ORRm, ORRm,
+ ORmR, ORmR, ORmR, ORmR, ORmR, ORmR, ORmR, ORmR,
+/*F*/ CPRm, CPRm, CPRm, CPRm, CPRm, CPRm, CPRm, CPRm,
+ CPmR, CPmR, CPmR, CPmR, CPmR, CPmR, CPmR, CPmR
+};
+
+//=============================================================================
+
+void TLCS900h_disassemble_src(int opsize)
+{
+ second = get8_dis(); //Get the second opcode
+ size = opsize;
+
+ //Prepare 'Big R'
+ sprintf(str_R, "%s", gprName[second & 7][size]);
+
+ if (decode[second])
+ (*decode[second])();
+ else
+ sprintf(instr, "unknown src instr. %02X", second);
+}
+};
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_interpret.cpp
new file mode 100644
index 0000000000..275e799b86
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret.cpp
@@ -0,0 +1,975 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+26 JUL 2002 - neopop_uk
+=======================================
+- Fixed a nasty bug that only affects [src]"EX (mem), XWA",
+ it was executing "EX F,F'" instead - Very bad!
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Added generic DIV and DIVS functions
+
+30 AUG 2002 - neopop_uk
+=======================================
+- Fixed detection of R32+d16 addressing mode.
+
+02 SEP 2002 - neopop_uk
+=======================================
+- Added the undocumented type 0x13 R32 address mode.
+
+09 SEP 2002 - neopop_uk
+=======================================
+- Extra cycles for addressing modes.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_registers.h"
+#include "../interrupt.h"
+#include "../mem.h"
+#include "../bios.h"
+#include "TLCS900h_interpret.h"
+#include "TLCS900h_interpret_single.h"
+#include "TLCS900h_interpret_src.h"
+#include "TLCS900h_interpret_dst.h"
+#include "TLCS900h_interpret_reg.h"
+
+namespace TLCS900H
+{
+
+static void DUMMY_instruction_error(const char* vaMessage,...)
+{
+
+
+}
+
+void (*instruction_error)(const char* vaMessage,...) = DUMMY_instruction_error;
+
+//=========================================================================
+
+uint32 mem; //Result of addressing mode
+int size; //operand size, 0 = Byte, 1 = Word, 2 = Long
+
+uint8 first; //The first byte
+uint8 R; //big R
+uint8 second; //The second opcode
+
+bool brCode; //Register code used?
+uint8 rCode; //The code
+
+int32 cycles; //How many state changes?
+int32 cycles_extra; //How many extra state changes?
+
+//=========================================================================
+
+uint16 fetch16(void)
+{
+ uint16 a = loadW(pc);
+ pc += 2;
+ return a;
+}
+
+uint32 fetch24(void)
+{
+ uint32 b, a = loadW(pc);
+ pc += 2;
+ b = loadB(pc++);
+ return (b << 16) | a;
+}
+
+uint32 fetch32(void)
+{
+ uint32 a = loadL(pc);
+ pc += 4;
+ return a;
+}
+
+//=============================================================================
+
+void parityB(uint8 value)
+{
+ uint8 count = 0, i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (value & 1) count++;
+ value >>= 1;
+ }
+
+ // if (count & 1) == FALSE, means even, thus SET
+ SETFLAG_V((count & 1) == 0);
+}
+
+void parityW(uint16 value)
+{
+ uint8 count = 0, i;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (value & 1) count++;
+ value >>= 1;
+ }
+
+ // if (count & 1) == FALSE, means even, thus SET
+ SETFLAG_V((count & 1) == 0);
+}
+
+//=========================================================================
+
+void push8(uint8 data) { REGXSP -= 1; storeB(REGXSP, data);}
+void push16(uint16 data) { REGXSP -= 2; storeW(REGXSP, data);}
+void push32(uint32 data) { REGXSP -= 4; storeL(REGXSP, data);}
+
+uint8 pop8(void) { uint8 temp = loadB(REGXSP); REGXSP += 1; return temp;}
+uint16 pop16(void) { uint16 temp = loadW(REGXSP); REGXSP += 2; return temp;}
+uint32 pop32(void) { uint32 temp = loadL(REGXSP); REGXSP += 4; return temp;}
+
+//=============================================================================
+
+uint16 generic_DIV_B(uint16 val, uint8 div)
+{
+ if (div == 0)
+ {
+ SETFLAG_V1
+ return (val << 8) | ((val >> 8) ^ 0xFF);
+ }
+ else
+ {
+ uint16 quo = val / (uint16)div;
+ uint16 rem = val % (uint16)div;
+ if (quo > 0xFF) SETFLAG_V1 else SETFLAG_V0
+ return (quo & 0xFF) | ((rem & 0xFF) << 8);
+ }
+}
+
+uint32 generic_DIV_W(uint32 val, uint16 div)
+{
+ if (div == 0)
+ {
+ SETFLAG_V1
+ return (val << 16) | ((val >> 16) ^ 0xFFFF);
+ }
+ else
+ {
+ uint32 quo = val / (uint32)div;
+ uint32 rem = val % (uint32)div;
+ if (quo > 0xFFFF) SETFLAG_V1 else SETFLAG_V0
+ return (quo & 0xFFFF) | ((rem & 0xFFFF) << 16);
+ }
+}
+
+//=============================================================================
+
+uint16 generic_DIVS_B(int16 val, int8 div)
+{
+ if (div == 0)
+ {
+ SETFLAG_V1
+ return (val << 8) | ((val >> 8) ^ 0xFF);
+ }
+ else
+ {
+ int16 quo = val / (int16)div;
+ int16 rem = val % (int16)div;
+ if (quo > 0xFF) SETFLAG_V1 else SETFLAG_V0
+ return (quo & 0xFF) | ((rem & 0xFF) << 8);
+ }
+}
+
+uint32 generic_DIVS_W(int32 val, int16 div)
+{
+ if (div == 0)
+ {
+ SETFLAG_V1
+ return (val << 16) | ((val >> 16) ^ 0xFFFF);
+ }
+ else
+ {
+ int32 quo = val / (int32)div;
+ int32 rem = val % (int32)div;
+ if (quo > 0xFFFF) SETFLAG_V1 else SETFLAG_V0
+ return (quo & 0xFFFF) | ((rem & 0xFFFF) << 16);
+ }
+}
+
+//=============================================================================
+
+uint8 generic_ADD_B(uint8 dst, uint8 src)
+{
+ uint8 half = (dst & 0xF) + (src & 0xF);
+ uint32 resultC = (uint32)dst + (uint32)src;
+ uint8 result = (uint8)(resultC & 0xFF);
+
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int8)dst >= 0) && ((int8)src >= 0) && ((int8)result < 0)) ||
+ (((int8)dst < 0) && ((int8)src < 0) && ((int8)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFF);
+
+ return result;
+}
+
+uint16 generic_ADD_W(uint16 dst, uint16 src)
+{
+ uint16 half = (dst & 0xF) + (src & 0xF);
+ uint32 resultC = (uint32)dst + (uint32)src;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int16)dst >= 0) && ((int16)src >= 0) && ((int16)result < 0)) ||
+ (((int16)dst < 0) && ((int16)src < 0) && ((int16)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFFFF);
+
+ return result;
+}
+
+uint32 generic_ADD_L(uint32 dst, uint32 src)
+{
+ uint64 resultC = (uint64)dst + (uint64)src;
+ uint32 result = (uint32)(resultC & 0xFFFFFFFF);
+
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+
+ if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) ||
+ (((int32)dst < 0) && ((int32)src < 0) && ((int32)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFFFFFFFF);
+
+ return result;
+}
+
+//=============================================================================
+
+uint8 generic_ADC_B(uint8 dst, uint8 src)
+{
+ uint8 half = (dst & 0xF) + (src & 0xF) + FLAG_C;
+ uint32 resultC = (uint32)dst + (uint32)src + (uint32)FLAG_C;
+ uint8 result = (uint8)(resultC & 0xFF);
+
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int8)dst >= 0) && ((int8)src >= 0) && ((int8)result < 0)) ||
+ (((int8)dst < 0) && ((int8)src < 0) && ((int8)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFF);
+
+ return result;
+}
+
+uint16 generic_ADC_W(uint16 dst, uint16 src)
+{
+ uint16 half = (dst & 0xF) + (src & 0xF) + FLAG_C;
+ uint32 resultC = (uint32)dst + (uint32)src + (uint32)FLAG_C;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int16)dst >= 0) && ((int16)src >= 0) && ((int16)result < 0)) ||
+ (((int16)dst < 0) && ((int16)src < 0) && ((int16)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFFFF);
+
+ return result;
+}
+
+uint32 generic_ADC_L(uint32 dst, uint32 src)
+{
+ uint64 resultC = (uint64)dst + (uint64)src + (uint64)FLAG_C;
+ uint32 result = (uint32)(resultC & 0xFFFFFFFF);
+
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+
+ if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) ||
+ (((int32)dst < 0) && ((int32)src < 0) && ((int32)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N0;
+ SETFLAG_C(resultC > 0xFFFFFFFF);
+
+ return result;
+}
+
+//=============================================================================
+
+uint8 generic_SUB_B(uint8 dst, uint8 src)
+{
+ uint8 half = (dst & 0xF) - (src & 0xF);
+ uint32 resultC = (uint32)dst - (uint32)src;
+ uint8 result = (uint8)(resultC & 0xFF);
+
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int8)dst >= 0) && ((int8)src < 0) && ((int8)result < 0)) ||
+ (((int8)dst < 0) && ((int8)src >= 0) && ((int8)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFF);
+
+ return result;
+}
+
+uint16 generic_SUB_W(uint16 dst, uint16 src)
+{
+ uint16 half = (dst & 0xF) - (src & 0xF);
+ uint32 resultC = (uint32)dst - (uint32)src;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int16)dst >= 0) && ((int16)src < 0) && ((int16)result < 0)) ||
+ (((int16)dst < 0) && ((int16)src >= 0) && ((int16)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFFFF);
+
+ return result;
+}
+
+uint32 generic_SUB_L(uint32 dst, uint32 src)
+{
+ uint64 resultC = (uint64)dst - (uint64)src;
+ uint32 result = (uint32)(resultC & 0xFFFFFFFF);
+
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+
+ if ((((int32)dst >= 0) && ((int32)src < 0) && ((int32)result < 0)) ||
+ (((int32)dst < 0) && ((int32)src >= 0) && ((int32)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFFFFFFFF);
+
+ return result;
+}
+
+//=============================================================================
+
+uint8 generic_SBC_B(uint8 dst, uint8 src)
+{
+ uint8 half = (dst & 0xF) - (src & 0xF) - FLAG_C;
+ uint32 resultC = (uint32)dst - (uint32)src - (uint32)FLAG_C;
+ uint8 result = (uint8)(resultC & 0xFF);
+
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int8)dst >= 0) && ((int8)src < 0) && ((int8)result < 0)) ||
+ (((int8)dst < 0) && ((int8)src >= 0) && ((int8)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFF);
+
+ return result;
+}
+
+uint16 generic_SBC_W(uint16 dst, uint16 src)
+{
+ uint16 half = (dst & 0xF) - (src & 0xF) - FLAG_C;
+ uint32 resultC = (uint32)dst - (uint32)src - (uint32)FLAG_C;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if ((((int16)dst >= 0) && ((int16)src < 0) && ((int16)result < 0)) ||
+ (((int16)dst < 0) && ((int16)src >= 0) && ((int16)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFFFF);
+
+ return result;
+}
+
+uint32 generic_SBC_L(uint32 dst, uint32 src)
+{
+ uint64 resultC = (uint64)dst - (uint64)src - (uint64)FLAG_C;
+ uint32 result = (uint32)(resultC & 0xFFFFFFFF);
+
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+
+ if ((((int32)dst >= 0) && ((int32)src < 0) && ((int32)result < 0)) ||
+ (((int32)dst < 0) && ((int32)src >= 0) && ((int32)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_N1;
+ SETFLAG_C(resultC > 0xFFFFFFFF);
+
+ return result;
+}
+
+//=============================================================================
+
+bool conditionCode(int cc)
+{
+ switch(cc)
+ {
+ case 0: return 0; //(F)
+ case 1: if (FLAG_S ^ FLAG_V) return 1; else return 0; //(LT)
+ case 2: if (FLAG_Z | (FLAG_S ^ FLAG_V)) return 1; else return 0; //(LE)
+ case 3: if (FLAG_C | FLAG_Z) return 1; else return 0; //(ULE)
+ case 4: if (FLAG_V) return 1; else return 0; //(OV)
+ case 5: if (FLAG_S) return 1; else return 0; //(MI)
+ case 6: if (FLAG_Z) return 1; else return 0; //(Z)
+ case 7: if (FLAG_C) return 1; else return 0; //(C)
+ case 8: return 1; //always True
+ case 9: if (FLAG_S ^ FLAG_V) return 0; else return 1; //(GE)
+ case 10:if (FLAG_Z | (FLAG_S ^ FLAG_V)) return 0; else return 1; //(GT)
+ case 11:if (FLAG_C | FLAG_Z) return 0; else return 1; //(UGT)
+ case 12:if (FLAG_V) return 0; else return 1; //(NOV)
+ case 13:if (FLAG_S) return 0; else return 1; //(PL)
+ case 14:if (FLAG_Z) return 0; else return 1; //(NZ)
+ case 15:if (FLAG_C) return 0; else return 1; //(NC)
+ }
+
+#ifdef NEOPOP_DEBUG
+ system_debug_message("Unknown Condition Code %d", cc);
+#endif
+ return FALSE;
+}
+
+//=============================================================================
+
+uint8 get_rr_Target(void)
+{
+ uint8 target = 0x80;
+
+ if (size == 0 && first == 0xC7)
+ return rCode;
+
+ //Create a regCode
+ switch(first & 7)
+ {
+ case 0: if (size == 1) target = 0xE0; break;
+ case 1:
+ if (size == 0) target = 0xE0;
+ if (size == 1) target = 0xE4;
+ break;
+ case 2: if (size == 1) target = 0xE8; break;
+ case 3:
+ if (size == 0) target = 0xE4;
+ if (size == 1) target = 0xEC;
+ break;
+ case 4: if (size == 1) target = 0xF0; break;
+ case 5:
+ if (size == 0) target = 0xE8;
+ if (size == 1) target = 0xF4;
+ break;
+ case 6: if (size == 1) target = 0xF8; break;
+ case 7:
+ if (size == 0) target = 0xEC;
+ if (size == 1) target = 0xFC;
+ break;
+ }
+
+ return target;
+}
+
+uint8 get_RR_Target(void)
+{
+ uint8 target = 0x80;
+
+ //Create a regCode
+ switch(second & 7)
+ {
+ case 0: if (size == 1) target = 0xE0; break;
+ case 1:
+ if (size == 0) target = 0xE0;
+ if (size == 1) target = 0xE4;
+ break;
+ case 2: if (size == 1) target = 0xE8; break;
+ case 3:
+ if (size == 0) target = 0xE4;
+ if (size == 1) target = 0xEC;
+ break;
+ case 4: if (size == 1) target = 0xF0; break;
+ case 5:
+ if (size == 0) target = 0xE8;
+ if (size == 1) target = 0xF4;
+ break;
+ case 6: if (size == 1) target = 0xF8; break;
+ case 7:
+ if (size == 0) target = 0xEC;
+ if (size == 1) target = 0xFC;
+ break;
+ }
+
+ return target;
+}
+
+//=========================================================================
+
+static void ExXWA() {mem = regL(0);}
+static void ExXBC() {mem = regL(1);}
+static void ExXDE() {mem = regL(2);}
+static void ExXHL() {mem = regL(3);}
+static void ExXIX() {mem = regL(4);}
+static void ExXIY() {mem = regL(5);}
+static void ExXIZ() {mem = regL(6);}
+static void ExXSP() {mem = regL(7);}
+
+static void ExXWAd() {mem = regL(0) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXBCd() {mem = regL(1) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXDEd() {mem = regL(2) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXHLd() {mem = regL(3) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXIXd() {mem = regL(4) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXIYd() {mem = regL(5) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXIZd() {mem = regL(6) + (int8)FETCH8; cycles_extra = 2;}
+static void ExXSPd() {mem = regL(7) + (int8)FETCH8; cycles_extra = 2;}
+
+static void Ex8() {mem = FETCH8; cycles_extra = 2;}
+static void Ex16() {mem = fetch16(); cycles_extra = 2;}
+static void Ex24() {mem = fetch24(); cycles_extra = 3;}
+
+static void ExR32()
+{
+ uint8 data = FETCH8;
+
+ if (data == 0x03)
+ {
+ uint8 rIndex, r32;
+ r32 = FETCH8; //r32
+ rIndex = FETCH8; //r8
+ mem = rCodeL(r32) + (int8)rCodeB(rIndex);
+ cycles_extra = 8;
+ return;
+ }
+
+ if (data == 0x07)
+ {
+ uint8 rIndex, r32;
+ r32 = FETCH8; //r32
+ rIndex = FETCH8; //r16
+ mem = rCodeL(r32) + (int16)rCodeW(rIndex);
+ cycles_extra = 8;
+ return;
+ }
+
+ //Undocumented mode!
+ if (data == 0x13)
+ {
+ mem = pc + (int16)fetch16();
+ cycles_extra = 8; //Unconfirmed... doesn't make much difference
+ return;
+ }
+
+ cycles_extra = 5;
+
+ if ((data & 3) == 1)
+ mem = rCodeL(data) + (int16)fetch16();
+ else
+ mem = rCodeL(data);
+}
+
+static void ExDec()
+{
+ uint8 data = FETCH8;
+ uint8 r32 = data & 0xFC;
+
+ cycles_extra = 3;
+
+ switch(data & 3)
+ {
+ case 0: rCodeL(r32) -= 1; mem = rCodeL(r32); break;
+ case 1: rCodeL(r32) -= 2; mem = rCodeL(r32); break;
+ case 2: rCodeL(r32) -= 4; mem = rCodeL(r32); break;
+ }
+}
+
+static void ExInc()
+{
+ uint8 data = FETCH8;
+ uint8 r32 = data & 0xFC;
+
+ cycles_extra = 3;
+
+ switch(data & 3)
+ {
+ case 0: mem = rCodeL(r32); rCodeL(r32) += 1; break;
+ case 1: mem = rCodeL(r32); rCodeL(r32) += 2; break;
+ case 2: mem = rCodeL(r32); rCodeL(r32) += 4; break;
+ }
+}
+
+static void ExRC()
+{
+ brCode = TRUE;
+ rCode = FETCH8;
+ cycles_extra = 1;
+}
+
+//=========================================================================
+
+//Address Mode & Register Code
+static void (*decodeExtra[256])() =
+{
+/*0*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*1*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*2*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*3*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*4*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*5*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*6*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*7*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+/*8*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*9*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*A*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*B*/ ExXWA, ExXBC, ExXDE, ExXHL, ExXIX, ExXIY, ExXIZ, ExXSP,
+ ExXWAd, ExXBCd, ExXDEd, ExXHLd, ExXIXd, ExXIYd, ExXIZd, ExXSPd,
+/*C*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*D*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*E*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, ExRC,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+/*F*/ Ex8, Ex16, Ex24, ExR32, ExDec, ExInc, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+//=========================================================================
+
+static void e(void)
+{
+ instruction_error("Unknown instruction %02X", first);
+}
+
+static void es(void)
+{
+ //instruction_error("Unknown [src] instruction %02X", second);
+}
+
+static void ed(void)
+{
+ //instruction_error("Unknown [dst] instruction %02X", second);
+}
+
+static void er(void)
+{
+ //instruction_error("Unknown [reg] instruction %02X", second);
+}
+
+//=========================================================================
+
+//Secondary (SRC) Instruction decode
+static void (*srcDecode[256])() =
+{
+/*0*/ es, es, es, es, srcPUSH, es, srcRLD, srcRRD,
+ es, es, es, es, es, es, es, es,
+/*1*/ srcLDI, srcLDIR, srcLDD, srcLDDR, srcCPI, srcCPIR, srcCPD, srcCPDR,
+ es, srcLD16m, es, es, es, es, es, es,
+/*2*/ srcLD, srcLD, srcLD, srcLD, srcLD, srcLD, srcLD, srcLD,
+ es, es, es, es, es, es, es, es,
+/*3*/ srcEX, srcEX, srcEX, srcEX, srcEX, srcEX, srcEX, srcEX,
+ srcADDi, srcADCi, srcSUBi, srcSBCi, srcANDi, srcXORi, srcORi, srcCPi,
+/*4*/ srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL, srcMUL,
+ srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS, srcMULS,
+/*5*/ srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV, srcDIV,
+ srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS, srcDIVS,
+/*6*/ srcINC, srcINC, srcINC, srcINC, srcINC, srcINC, srcINC, srcINC,
+ srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC, srcDEC,
+/*7*/ es, es, es, es, es, es, es, es,
+ srcRLC, srcRRC, srcRL, srcRR, srcSLA, srcSRA, srcSLL, srcSRL,
+/*8*/ srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm, srcADDRm,
+ srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR, srcADDmR,
+/*9*/ srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm, srcADCRm,
+ srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR, srcADCmR,
+/*A*/ srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm, srcSUBRm,
+ srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR, srcSUBmR,
+/*B*/ srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm, srcSBCRm,
+ srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR, srcSBCmR,
+/*C*/ srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm, srcANDRm,
+ srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR, srcANDmR,
+/*D*/ srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm, srcXORRm,
+ srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR, srcXORmR,
+/*E*/ srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm, srcORRm,
+ srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR, srcORmR,
+/*F*/ srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm, srcCPRm,
+ srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR, srcCPmR
+};
+
+//Secondary (DST) Instruction decode
+static void (*dstDecode[256])() =
+{
+/*0*/ dstLDBi, ed, dstLDWi, ed, dstPOPB, ed, dstPOPW, ed,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*1*/ ed, ed, ed, ed, dstLDBm16, ed, dstLDWm16, ed,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*2*/ dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW, dstLDAW,
+ dstANDCFA, dstORCFA, dstXORCFA, dstLDCFA, dstSTCFA, ed, ed, ed,
+/*3*/ dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL, dstLDAL,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*4*/ dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR, dstLDBR,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*5*/ dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR, dstLDWR,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*6*/ dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR, dstLDLR,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*7*/ ed, ed, ed, ed, ed, ed, ed, ed,
+ ed, ed, ed, ed, ed, ed, ed, ed,
+/*8*/ dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF, dstANDCF,
+ dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF, dstORCF,
+/*9*/ dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF, dstXORCF,
+ dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF, dstLDCF,
+/*A*/ dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF, dstSTCF,
+ dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET, dstTSET,
+/*B*/ dstRES, dstRES, dstRES, dstRES, dstRES, dstRES, dstRES, dstRES,
+ dstSET, dstSET, dstSET, dstSET, dstSET, dstSET, dstSET, dstSET,
+/*C*/ dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG, dstCHG,
+ dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT, dstBIT,
+/*D*/ dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP,
+ dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP, dstJP,
+/*E*/ dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL,
+ dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL, dstCALL,
+/*F*/ dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET,
+ dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET, dstRET
+};
+
+//Secondary (REG) Instruction decode
+static void (*regDecode[256])() =
+{
+/*0*/ er, er, er, regLDi, regPUSH, regPOP, regCPL, regNEG,
+ regMULi, regMULSi, regDIVi, regDIVSi, regLINK, regUNLK, regBS1F, regBS1B,
+/*1*/ regDAA, er, regEXTZ, regEXTS, regPAA, er, regMIRR, er,
+ er, regMULA, er, er, regDJNZ, er, er, er,
+/*2*/ regANDCFi, regORCFi, regXORCFi, regLDCFi, regSTCFi, er, er, er,
+ regANDCFA, regORCFA, regXORCFA, regLDCFA, regSTCFA, er, regLDCcrr, regLDCrcr,
+/*3*/ regRES, regSET, regCHG, regBIT, regTSET, er, er, er,
+ regMINC1, regMINC2, regMINC4, er, regMDEC1, regMDEC2, regMDEC4, er,
+/*4*/ regMUL, regMUL, regMUL, regMUL, regMUL, regMUL, regMUL, regMUL,
+ regMULS, regMULS, regMULS, regMULS, regMULS, regMULS, regMULS, regMULS,
+/*5*/ regDIV, regDIV, regDIV, regDIV, regDIV, regDIV, regDIV, regDIV,
+ regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS, regDIVS,
+/*6*/ regINC, regINC, regINC, regINC, regINC, regINC, regINC, regINC,
+ regDEC, regDEC, regDEC, regDEC, regDEC, regDEC, regDEC, regDEC,
+/*7*/ regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC,
+ regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC, regSCC,
+/*8*/ regADD, regADD, regADD, regADD, regADD, regADD, regADD, regADD,
+ regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr, regLDRr,
+/*9*/ regADC, regADC, regADC, regADC, regADC, regADC, regADC, regADC,
+ regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR, regLDrR,
+/*A*/ regSUB, regSUB, regSUB, regSUB, regSUB, regSUB, regSUB, regSUB,
+ regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3, regLDr3,
+/*B*/ regSBC, regSBC, regSBC, regSBC, regSBC, regSBC, regSBC, regSBC,
+ regEX, regEX, regEX, regEX, regEX, regEX, regEX, regEX,
+/*C*/ regAND, regAND, regAND, regAND, regAND, regAND, regAND, regAND,
+ regADDi, regADCi, regSUBi, regSBCi, regANDi, regXORi, regORi, regCPi,
+/*D*/ regXOR, regXOR, regXOR, regXOR, regXOR, regXOR, regXOR, regXOR,
+ regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3, regCPr3,
+/*E*/ regOR, regOR, regOR, regOR, regOR, regOR, regOR, regOR,
+ regRLCi, regRRCi, regRLi, regRRi, regSLAi, regSRAi, regSLLi, regSRLi,
+/*F*/ regCP, regCP, regCP, regCP, regCP, regCP, regCP, regCP,
+ regRLCA, regRRCA, regRLA, regRRA, regSLAA, regSRAA, regSLLA, regSRLA
+};
+
+//=========================================================================
+
+static void src_B()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 0; //Byte Size
+
+ (*srcDecode[second])(); //Call
+}
+
+static void src_W()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 1; //Word Size
+
+ (*srcDecode[second])(); //Call
+}
+
+static void src_L()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 2; //Long Size
+
+ (*srcDecode[second])(); //Call
+}
+
+static void dst()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+
+ (*dstDecode[second])(); //Call
+}
+
+static uint8 rCodeConversionB[8] = { 0xE1, 0xE0, 0xE5, 0xE4, 0xE9, 0xE8, 0xED, 0xEC };
+static uint8 rCodeConversionW[8] = { 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC };
+static uint8 rCodeConversionL[8] = { 0xE0, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC };
+
+static void reg_B()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 0; //Byte Size
+
+ if (brCode == FALSE)
+ {
+ brCode = TRUE;
+ rCode = rCodeConversionB[first & 7];
+ }
+
+ (*regDecode[second])(); //Call
+}
+
+static void reg_W()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 1; //Word Size
+
+ if (brCode == FALSE)
+ {
+ brCode = TRUE;
+ rCode = rCodeConversionW[first & 7];
+ }
+
+ (*regDecode[second])(); //Call
+}
+
+static void reg_L()
+{
+ second = FETCH8; //Get the second opcode
+ R = second & 7;
+ size = 2; //Long Size
+
+ if (brCode == FALSE)
+ {
+ brCode = TRUE;
+ rCode = rCodeConversionL[first & 7];
+ }
+
+ (*regDecode[second])(); //Call
+}
+
+//=============================================================================
+
+//Primary Instruction decode
+static void (*decode[256])() =
+{
+/*0*/ sngNOP, sngNORMAL, sngPUSHSR, sngPOPSR, sngMAX, sngHALT, sngEI, sngRETI,
+ sngLD8_8, sngPUSH8, sngLD8_16, sngPUSH16, sngINCF, sngDECF, sngRET, sngRETD,
+/*1*/ sngRCF, sngSCF, sngCCF, sngZCF, sngPUSHA, sngPOPA, sngEX, sngLDF,
+ sngPUSHF, sngPOPF, sngJP16, sngJP24, sngCALL16, sngCALL24, sngCALR, iBIOSHLE,
+/*2*/ sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB, sngLDB,
+ sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW, sngPUSHW,
+/*3*/ sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW, sngLDW,
+ sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL, sngPUSHL,
+/*4*/ sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL, sngLDL,
+ sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW, sngPOPW,
+/*5*/ e, e, e, e, e, e, e, e,
+ sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL, sngPOPL,
+/*6*/ sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR,
+ sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR, sngJR,
+/*7*/ sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL,
+ sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL, sngJRL,
+/*8*/ src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B,
+ src_B, src_B, src_B, src_B, src_B, src_B, src_B, src_B,
+/*9*/ src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W,
+ src_W, src_W, src_W, src_W, src_W, src_W, src_W, src_W,
+/*A*/ src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L,
+ src_L, src_L, src_L, src_L, src_L, src_L, src_L, src_L,
+/*B*/ dst, dst, dst, dst, dst, dst, dst, dst,
+ dst, dst, dst, dst, dst, dst, dst, dst,
+/*C*/ src_B, src_B, src_B, src_B, src_B, src_B, e, reg_B,
+ reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B, reg_B,
+/*D*/ src_W, src_W, src_W, src_W, src_W, src_W, e, reg_W,
+ reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W, reg_W,
+/*E*/ src_L, src_L, src_L, src_L, src_L, src_L, e, reg_L,
+ reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L, reg_L,
+/*F*/ dst, dst, dst, dst, dst, dst, e, sngLDX,
+ sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI, sngSWI
+};
+
+//=============================================================================
+
+int32 TLCS900h_interpret(void)
+{
+ brCode = FALSE;
+
+ first = FETCH8; //Get the first byte
+
+ //Is any extra data used by this instruction?
+ cycles_extra = 0;
+ if (decodeExtra[first])
+ (*decodeExtra[first])();
+
+ (*decode[first])(); //Decode
+
+ return cycles + cycles_extra;
+}
+
+};
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret.h b/waterbox/ngp/TLCS-900h/TLCS900h_interpret.h
new file mode 100644
index 0000000000..056b58521e
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret.h
@@ -0,0 +1,137 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+21 JUL 2002 - neopop_uk
+=======================================
+- Added the 'instruction_error' function declaration here.
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Removed CYCLE_WARNING as it is now obsolete.
+- Added generic DIV prototypes.
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_INTERPRET__
+#define __TLCS900H_INTERPRET__
+namespace TLCS900H
+{
+
+//=============================================================================
+
+//Interprets a single instruction from 'pc',
+//pc is incremented to the start of the next instruction.
+//Returns the number of cycles taken for this instruction
+int32 TLCS900h_interpret(void);
+
+//=============================================================================
+
+extern uint32 mem;
+extern int size;
+extern uint8 first; //First byte
+extern uint8 second; //Second byte
+extern uint8 R; //(second & 7)
+extern uint8 rCode;
+extern int32 cycles;
+extern bool brCode;
+
+//=============================================================================
+
+extern void (*instruction_error)(const char* vaMessage,...);
+
+//=============================================================================
+
+#define FETCH8 loadB(pc++)
+
+uint16 fetch16(void);
+uint32 fetch24(void);
+uint32 fetch32(void);
+
+//=============================================================================
+
+void parityB(uint8 value);
+void parityW(uint16 value);
+
+//=============================================================================
+
+void push8(uint8 data);
+void push16(uint16 data);
+void push32(uint32 data);
+
+uint8 pop8(void);
+uint16 pop16(void);
+uint32 pop32(void);
+
+//=============================================================================
+
+//DIV ===============
+uint16 generic_DIV_B(uint16 val, uint8 div);
+uint32 generic_DIV_W(uint32 val, uint16 div);
+
+//DIVS ===============
+uint16 generic_DIVS_B(int16 val, int8 div);
+uint32 generic_DIVS_W(int32 val, int16 div);
+
+//ADD ===============
+uint8 generic_ADD_B(uint8 dst, uint8 src);
+uint16 generic_ADD_W(uint16 dst, uint16 src);
+uint32 generic_ADD_L(uint32 dst, uint32 src);
+
+//ADC ===============
+uint8 generic_ADC_B(uint8 dst, uint8 src);
+uint16 generic_ADC_W(uint16 dst, uint16 src);
+uint32 generic_ADC_L(uint32 dst, uint32 src);
+
+//SUB ===============
+uint8 generic_SUB_B(uint8 dst, uint8 src);
+uint16 generic_SUB_W(uint16 dst, uint16 src);
+uint32 generic_SUB_L(uint32 dst, uint32 src);
+
+//SBC ===============
+uint8 generic_SBC_B(uint8 dst, uint8 src);
+uint16 generic_SBC_W(uint16 dst, uint16 src);
+uint32 generic_SBC_L(uint32 dst, uint32 src);
+
+//=============================================================================
+
+//Confirms a condition code check
+bool conditionCode(int cc);
+
+//=============================================================================
+
+//Translate an rr or RR value for MUL/MULS/DIV/DIVS
+uint8 get_rr_Target(void);
+uint8 get_RR_Target(void);
+
+};
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.cpp
new file mode 100644
index 0000000000..e59b3d554c
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.cpp
@@ -0,0 +1,315 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_dst.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+22 JUL 2002 - neopop_uk
+=======================================
+- Added ANDCF,ORCF and XORCF in # and A modes. These were being used
+ by one of the obscure pachinko "games".
+
+23 JUL 2002 - neopop_uk
+=======================================
+- Added cycle count for TSET.
+
+16 AUG 2002 - neopop_uk
+=======================================
+- Replaced 'second & 7' with 'R', clearer, faster - and for some reason
+ more accurate... oh well!
+
+21 AUG 2002 - neopop_uk
+=======================================
+- Added TSET.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_interpret.h"
+#include "TLCS900h_registers.h"
+#include "../mem.h"
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+//===== LD (mem),#
+void dstLDBi()
+{
+ storeB(mem, FETCH8);
+ cycles = 5;
+}
+
+//===== LD (mem),#
+void dstLDWi()
+{
+ storeW(mem, fetch16());
+ cycles = 6;
+}
+
+//===== POP (mem)
+void dstPOPB()
+{
+ storeB(mem, pop8());
+ cycles = 6;
+}
+
+//===== POP (mem)
+void dstPOPW()
+{
+ storeW(mem, pop16());
+ cycles = 6;
+}
+
+//===== LD (mem),(nn)
+void dstLDBm16()
+{
+ storeB(mem, loadB(fetch16()));
+ cycles = 8;
+}
+
+//===== LD (mem),(nn)
+void dstLDWm16()
+{
+ storeW(mem, loadW(fetch16()));
+ cycles = 8;
+}
+
+//===== LDA R,mem
+void dstLDAW()
+{
+ regW(R) = (uint16)mem;
+ cycles = 4;
+}
+
+//===== LDA R,mem
+void dstLDAL()
+{
+ regL(R) = (uint32)mem;
+ cycles = 4;
+}
+
+//===== ANDCF A,(mem)
+void dstANDCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(mbit & FLAG_C);
+ cycles = 8;
+}
+
+//===== ORCF A,(mem)
+void dstORCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(mbit | FLAG_C);
+ cycles = 8;
+}
+
+//===== XORCF A,(mem)
+void dstXORCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(mbit ^ FLAG_C);
+ cycles = 8;
+}
+
+//===== LDCF A,(mem)
+void dstLDCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint8 mask = (1 << bit);
+ if (bit < 8) SETFLAG_C(loadB(mem) & mask);
+ cycles = 8;
+}
+
+//===== STCF A,(mem)
+void dstSTCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint8 cmask = ~(1 << bit);
+ uint8 set = FLAG_C << bit;
+ if (bit < 8) storeB(mem, (loadB(mem) & cmask) | set);
+ cycles = 8;
+}
+
+//===== LD (mem),R
+void dstLDBR()
+{
+ storeB(mem, regB(R));
+ cycles = 4;
+}
+
+//===== LD (mem),R
+void dstLDWR()
+{
+ storeW(mem, regW(R));
+ cycles = 4;
+}
+
+//===== LD (mem),R
+void dstLDLR()
+{
+ storeL(mem, regL(R));
+ cycles = 6;
+}
+
+//===== ANDCF #3,(mem)
+void dstANDCF()
+{
+ uint8 bit = R;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ SETFLAG_C(mbit & FLAG_C);
+ cycles = 8;
+}
+
+//===== ORCF #3,(mem)
+void dstORCF()
+{
+ uint8 bit = R;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ SETFLAG_C(mbit | FLAG_C);
+ cycles = 8;
+}
+
+//===== XORCF #3,(mem)
+void dstXORCF()
+{
+ uint8 bit = R;
+ uint8 mbit = (loadB(mem) >> bit) & 1;
+ SETFLAG_C(mbit ^ FLAG_C);
+ cycles = 8;
+}
+
+//===== LDCF #3,(mem)
+void dstLDCF()
+{
+ uint8 bit = R;
+ uint32 mask = (1 << bit);
+ SETFLAG_C(loadB(mem) & mask);
+ cycles = 8;
+}
+
+//===== STCF #3,(mem)
+void dstSTCF()
+{
+ uint8 bit = R;
+ uint8 cmask = ~(1 << bit);
+ uint8 set = FLAG_C << bit;
+ storeB(mem, (loadB(mem) & cmask) | set);
+ cycles = 8;
+}
+
+//===== TSET #3,(mem)
+void dstTSET()
+{
+ SETFLAG_Z(! (loadB(mem) & (1 << R)) );
+ storeB(mem, loadB(mem) | (1 << R));
+
+ SETFLAG_H1
+ SETFLAG_N0
+ cycles = 10;
+}
+
+//===== RES #3,(mem)
+void dstRES()
+{
+ storeB(mem, loadB(mem) & (~(1 << R)));
+ cycles = 8;
+}
+
+//===== SET #3,(mem)
+void dstSET()
+{
+ storeB(mem, loadB(mem) | (1 << R));
+ cycles = 8;
+}
+
+//===== CHG #3,(mem)
+void dstCHG()
+{
+ storeB(mem, loadB(mem) ^ (1 << R));
+ cycles = 8;
+}
+
+//===== BIT #3,(mem)
+void dstBIT()
+{
+ SETFLAG_Z(! (loadB(mem) & (1 << R)) );
+ SETFLAG_H1;
+ SETFLAG_N0;
+ cycles = 8;
+}
+
+//===== JP cc,mem
+void dstJP()
+{
+ if (conditionCode(second & 0xF))
+ {
+ pc = mem;
+ cycles = 9;
+ }
+ else
+ {
+ cycles = 6;
+ }
+}
+
+//===== CALL cc,mem
+void dstCALL()
+{
+ if (conditionCode(second & 0xF))
+ {
+ push32(pc);
+ pc = mem;
+ cycles = 12;
+ }
+ else
+ {
+ cycles = 6;
+ }
+}
+
+//===== RET cc
+void dstRET()
+{
+ if (conditionCode(second & 0xF))
+ {
+ pc = pop32();
+ cycles = 12;
+ }
+ else
+ {
+ cycles = 6;
+ }
+}
+};
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.h b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.h
new file mode 100644
index 0000000000..2a8a579ff7
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.h
@@ -0,0 +1,132 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_dst.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_DST__
+#define __TLCS900H_DST__
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+//===== LD (mem),#
+void dstLDBi(void);
+
+//===== LD (mem),#
+void dstLDWi(void);
+
+//===== POP (mem)
+void dstPOPB(void);
+
+//===== POP (mem)
+void dstPOPW(void);
+
+//===== LD (mem),(nn)
+void dstLDBm16(void);
+
+//===== LD (mem),(nn)
+void dstLDWm16(void);
+
+//===== LDA R,mem
+void dstLDAW(void);
+
+//===== LDA R,mem
+void dstLDAL(void);
+
+//===== ANDCF A,(mem)
+void dstANDCFA(void);
+
+//===== ORCF A,(mem)
+void dstORCFA(void);
+
+//===== XORCF A,(mem)
+void dstXORCFA(void);
+
+//===== LDCF A,(mem)
+void dstLDCFA(void);
+
+//===== STCF A,(mem)
+void dstSTCFA(void);
+
+//===== LD (mem),R
+void dstLDBR(void);
+
+//===== LD (mem),R
+void dstLDWR(void);
+
+//===== LD (mem),R
+void dstLDLR(void);
+
+//===== ANDCF #3,(mem)
+void dstANDCF(void);
+
+//===== ORCF #3,(mem)
+void dstORCF(void);
+
+//===== XORCF #3,(mem)
+void dstXORCF(void);
+
+//===== LDCF #3,(mem)
+void dstLDCF(void);
+
+//===== STCF #3,(mem)
+void dstSTCF(void);
+
+//===== TSET #3,(mem)
+void dstTSET(void);
+
+//===== RES #3,(mem)
+void dstRES(void);
+
+//===== SET #3,(mem)
+void dstSET(void);
+
+//===== CHG #3,(mem)
+void dstCHG(void);
+
+//===== BIT #3,(mem)
+void dstBIT(void);
+
+//===== JP cc,mem
+void dstJP(void);
+
+//===== CALL cc,mem
+void dstCALL(void);
+
+//===== RET cc
+void dstRET(void);
+
+};
+
+//=========================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.cpp
new file mode 100644
index 0000000000..4d928edb70
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.cpp
@@ -0,0 +1,2187 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_reg.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+22 JUL 2002 - neopop_uk
+=======================================
+- Added ANDCF,ORCF and XORCF in A mode and improved the remaining ones.
+
+22 JUL 2002 - neopop_uk
+=======================================
+- Added LINK and UNLK to fix "Rockman Battle and Fighters"
+
+23 JUL 2002 - neopop_uk
+=======================================
+- Added MIRR to fix "Card Fighters 2"
+- Added cycle counts for TSET.
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Converted DIV/DIVS to use the generic function
+
+16 AUG 2002 - neopop_uk
+=======================================
+- Removed all of the 'second & 7' with R as it's pre-calculated anyway.
+- Fixed V flag emulation of INC/DEC, fixes "Cotton" menus
+- Fixed MINC4
+
+21 AUG 2002 - neopop_uk
+=======================================
+- Added TSET and MULA, both untested.
+
+04 SEP 2002 - neopop_uk
+=======================================
+- Fixed GCC compatibility.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_interpret.h"
+#include "TLCS900h_registers.h"
+#include "../mem.h"
+#include "../dma.h"
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+//===== LD r,#
+void regLDi()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = FETCH8; cycles = 4; break;
+ case 1: rCodeW(rCode) = fetch16(); cycles = 4; break;
+ case 2: rCodeL(rCode) = fetch32(); cycles = 6; break;
+ }
+}
+
+//===== PUSH r
+void regPUSH()
+{
+ switch(size)
+ {
+ case 0: push8(rCodeB(rCode)); cycles = 5;break;
+ case 1: push16(rCodeW(rCode)); cycles = 5;break;
+ case 2: push32(rCodeL(rCode)); cycles = 7;break;
+ }
+}
+
+//===== POP r
+void regPOP()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = pop8(); cycles = 6;break;
+ case 1: rCodeW(rCode) = pop16(); cycles = 6;break;
+ case 2: rCodeL(rCode) = pop32(); cycles = 8;break;
+ }
+}
+
+//===== CPL r
+void regCPL()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = ~ rCodeB(rCode); break;
+ case 1: rCodeW(rCode) = ~ rCodeW(rCode); break;
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N1;
+ cycles = 4;
+}
+
+//===== NEG r
+void regNEG()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = generic_SUB_B(0, rCodeB(rCode)); break;
+ case 1: rCodeW(rCode) = generic_SUB_W(0, rCodeW(rCode)); break;
+ }
+ cycles = 5;
+}
+
+//===== MUL rr,#
+void regMULi()
+{
+ uint8 target = get_rr_Target();
+ if (target == 0x80)
+ {
+#ifdef NEOPOP_DEBUG
+ instruction_error("reg: MULi bad \'rr\' dst code");
+#endif
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (rCodeW(target) & 0xFF) * FETCH8;
+ cycles = 18; break;
+ case 1: rCodeL(target) = (rCodeL(target) & 0xFFFF) * fetch16();
+ cycles = 26; break;
+ }
+}
+
+//===== MULS rr,#
+void regMULSi()
+{
+ uint8 target = get_rr_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: MULSi bad \'rr\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (int8)(rCodeW(target) & 0xFF) * (int8)FETCH8;
+ cycles = 18; break;
+ case 1: rCodeL(target) = (int16)(rCodeL(target) & 0xFFFF) * (int16)fetch16();
+ cycles = 26; break;
+ }
+}
+
+//===== DIV rr,#
+void regDIVi()
+{
+ uint8 target = get_rr_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: DIVi bad \'rr\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIV_B(rCodeW(target), FETCH8);
+ cycles = 22;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIV_W(rCodeL(target), fetch16());
+ cycles = 30;
+ break; }
+ }
+}
+
+//===== DIVS rr,#
+void regDIVSi()
+{
+ uint8 target = get_rr_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: DIVSi bad \'rr\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIVS_B(rCodeW(target), FETCH8);
+ cycles = 24;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIVS_W(rCodeL(target), fetch16());
+ cycles = 32;
+ break; }
+ }
+}
+
+//===== LINK r,dd
+void regLINK()
+{
+ int16 d = (int16)fetch16();
+ push32(rCodeL(rCode));
+ rCodeL(rCode) = REGXSP;
+ REGXSP += d;
+ cycles = 10;
+}
+
+//===== UNLK r
+void regUNLK()
+{
+ REGXSP = rCodeL(rCode);
+ rCodeL(rCode) = pop32();
+ cycles = 8;
+}
+
+//===== BS1F A,r
+void regBS1F()
+{
+ uint16 data = rCodeW(rCode), mask = 0x0001;
+ uint8 i;
+
+ SETFLAG_V0;
+ for (i = 0; i < 15; i++)
+ {
+ if (data & mask)
+ {
+ REGA = i;
+ return;
+ }
+
+ mask <<= 1;
+ }
+
+ SETFLAG_V1;
+ cycles = 4;
+}
+
+//===== BS1B A,r
+void regBS1B()
+{
+ uint16 data = rCodeW(rCode), mask = 0x8000;
+ uint8 i;
+
+ SETFLAG_V0;
+ for (i = 0; i < 15; i++)
+ {
+ if (data & mask)
+ {
+ REGA = 15 - i;
+ return;
+ }
+
+ mask >>= 1;
+ }
+
+ SETFLAG_V1;
+ cycles = 4;
+}
+
+//===== DAA r
+void regDAA()
+{
+ uint16 resultC;
+ uint8 src = rCodeB(rCode), result, added = 0, half;
+ bool setC = FALSE;
+
+ uint8 upper4 = (src & 0xF0);
+ uint8 lower4 = (src & 0x0F);
+
+ if (FLAG_C) // {C = 1}
+ {
+ if (FLAG_H) // {H = 1}
+ {
+ setC = TRUE;
+ added = 0x66;
+ }
+ else // {H = 0}
+ {
+ if (lower4 < 0x0a) { added = 0x60; }
+ else { added = 0x66; }
+ setC = TRUE;
+ }
+ }
+ else // {C = 0}
+ {
+ if (FLAG_H) // {H = 1}
+ {
+ if (src < 0x9A) { added = 0x06; }
+ else { added = 0x66; }
+ }
+ else // {H = 0}
+ {
+ if ((upper4 < 0x90) && (lower4 > 0x9)) { added = 0x06; }
+ else if ((upper4 > 0x80) && (lower4 > 0x9)) { added = 0x66; }
+ else if ((upper4 > 0x90) && (lower4 < 0xa)) { added = 0x60; }
+ }
+ }
+
+ if (FLAG_N)
+ {
+ resultC = (uint16)src - (uint16)added;
+ half = (src & 0xF) - (added & 0xF);
+ }
+ else
+ {
+ resultC = (uint16)src + (uint16)added;
+ half = (src & 0xF) + (added & 0xF);
+ }
+
+ result = (uint8)(resultC & 0xFF);
+
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+
+ if (FLAG_N) SETFLAG_C(result > src || setC)
+ else SETFLAG_C(result < src || setC)
+
+ parityB(result);
+ rCodeB(rCode) = result;
+ cycles = 6;
+}
+
+//===== EXTZ r
+void regEXTZ()
+{
+ switch(size)
+ {
+ case 1: rCodeW(rCode) &= 0xFF; break;
+ case 2: rCodeL(rCode) &= 0xFFFF; break;
+ }
+
+ cycles = 4;
+}
+
+//===== EXTS r
+void regEXTS()
+{
+ switch(size)
+ {
+ case 1: if (rCodeW(rCode) & 0x0080)
+ { rCodeW(rCode) |= 0xFF00; } else
+ { rCodeW(rCode) &= 0x00FF; }
+ break;
+
+ case 2: if (rCodeL(rCode) & 0x00008000)
+ { rCodeL(rCode) |= 0xFFFF0000; } else
+ { rCodeL(rCode) &= 0x0000FFFF; }
+ break;
+ }
+
+ cycles = 5;
+}
+
+//===== PAA r
+void regPAA()
+{
+ switch(size)
+ {
+ case 1: if (rCodeW(rCode) & 0x1) rCodeW(rCode)++; break;
+ case 2: if (rCodeL(rCode) & 0x1) rCodeL(rCode)++; break;
+ }
+ cycles = 4;
+}
+
+//===== MIRR r
+void regMIRR()
+{
+ uint16 src = rCodeW(rCode), dst = 0, bit;
+
+ //Undocumented - see p165 of CPU .PDF
+ //Seems to mirror bits completely, ie. 1234 -> 4321
+
+ for (bit = 0; bit < 16; bit++)
+ if (src & (1 << bit))
+ dst |= (1 << (15 - bit));
+
+ rCodeW(rCode) = dst;
+ cycles = 4;
+}
+
+//===== MULA rr
+void regMULA()
+{
+ uint32 src = (int16)loadW(regL(2/*XDE*/)) * (int16)loadW(regL(3/*XHL*/));
+ uint32 dst = rCodeL(rCode);
+ uint32 result = dst + src;
+
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+
+ if ((((int32)dst >= 0) && ((int32)src >= 0) && ((int32)result < 0)) ||
+ (((int32)dst < 0) && ((int32)src < 0) && ((int32)result >= 0)))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ cycles = 31;
+}
+
+//===== DJNZ r,d
+void regDJNZ()
+{
+ int8 offset = FETCH8;
+
+ cycles = 7;
+
+ switch(size)
+ {
+ case 0:
+ rCodeB(rCode) --;
+ if (rCodeB(rCode) != 0)
+ {
+ cycles = 11;
+ pc = pc + offset;
+ }
+ break;
+
+ case 1:
+ rCodeW(rCode) --;
+ if (rCodeW(rCode) != 0)
+ {
+ cycles = 11;
+ pc = pc + offset;
+ }
+ break;
+ }
+}
+
+//===== ANDCF #,r
+void regANDCFi()
+{
+ uint8 data, bit = FETCH8 & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C & data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C & data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== ORCF #,r
+void regORCFi()
+{
+ uint8 data, bit = FETCH8 & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C | data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C | data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== XORCF #,r
+void regXORCFi()
+{
+ uint8 data, bit = FETCH8 & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C ^ data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C ^ data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== LDCF #,r
+void regLDCFi()
+{
+ uint8 bit = FETCH8 & 0xF;
+ switch(size)
+ {
+ case 0: { uint8 mask = (1 << bit);
+ if (bit < 8)
+ SETFLAG_C(rCodeB(rCode) & mask);
+ break; }
+
+
+ case 1: { uint16 mask = (1 << bit);
+ SETFLAG_C(rCodeW(rCode) & mask);
+ break; }
+ }
+
+ cycles = 4;
+}
+
+//===== STCF #,r
+void regSTCFi()
+{
+ uint8 bit = FETCH8 & 0xF;
+ switch(size)
+ {
+ case 0: { uint8 cmask = ~(1 << bit);
+ uint8 set = FLAG_C << bit;
+ if (bit < 8) rCodeB(rCode) = (rCodeB(rCode) & cmask) | set;
+ break; }
+
+ case 1: { uint16 cmask = ~(1 << bit);
+ uint16 set = FLAG_C << bit;
+ rCodeW(rCode) = (rCodeW(rCode) & cmask) | set;
+ break; }
+ }
+
+ cycles = 4;
+}
+
+//===== ANDCF A,r
+void regANDCFA()
+{
+ uint8 data, bit = REGA & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C & data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C & data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== ORCF A,r
+void regORCFA()
+{
+ uint8 data, bit = REGA & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C | data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C | data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== XORCF A,r
+void regXORCFA()
+{
+ uint8 data, bit = REGA & 0xF;
+ switch(size)
+ {
+ case 0: { data = (rCodeB(rCode) >> bit) & 1;
+ if (bit < 8) SETFLAG_C(FLAG_C ^ data);
+ break; }
+
+ case 1: { data = (rCodeW(rCode) >> bit) & 1;
+ SETFLAG_C(FLAG_C ^ data);
+ break; }
+ }
+ cycles = 4;
+}
+
+//===== LDCF A,r
+void regLDCFA()
+{
+ uint8 bit = REGA & 0xF;
+ uint32 mask = (1 << bit);
+
+ switch(size)
+ {
+ case 0: if (bit < 8) SETFLAG_C(rCodeB(rCode) & mask); break;
+ case 1: SETFLAG_C(rCodeW(rCode) & mask); break;
+ }
+
+ cycles = 4;
+}
+
+//===== STCF A,r
+void regSTCFA()
+{
+ switch(size)
+ {
+ case 0: { uint8 bit = REGA & 0xF;
+ uint8 cmask = ~(1 << bit);
+ uint8 set = FLAG_C << bit;
+ if (bit < 8) rCodeB(rCode) = (rCodeB(rCode) & cmask) | set;
+ break; }
+
+ case 1: { uint8 bit = REGA & 0xF;
+ uint16 cmask = ~(1 << bit);
+ uint16 set = FLAG_C << bit;
+ rCodeW(rCode) = (rCodeW(rCode) & cmask) | set;
+ break; }
+ }
+
+ cycles = 4;
+}
+
+//===== LDC cr,r
+void regLDCcrr()
+{
+ uint8 cr = FETCH8;
+
+ switch(size)
+ {
+ case 0: dmaStoreB(cr, rCodeB(rCode)); break;
+ case 1: dmaStoreW(cr, rCodeW(rCode)); break;
+ case 2: dmaStoreL(cr, rCodeL(rCode)); break;
+ }
+
+ cycles = 8;
+}
+
+//===== LDC r,cr
+void regLDCrcr()
+{
+ uint8 cr = FETCH8;
+
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = dmaLoadB(cr); break;
+ case 1: rCodeW(rCode) = dmaLoadW(cr); break;
+ case 2: rCodeL(rCode) = dmaLoadL(cr); break;
+ }
+
+ cycles = 8;
+}
+
+//===== RES #,r
+void regRES()
+{
+ uint8 b = FETCH8 & 0xF;
+
+ switch(size)
+ {
+ case 0: rCodeB(rCode) &= ~(uint8)(1 << b); break;
+ case 1: rCodeW(rCode) &= ~(uint16)(1 << b); break;
+ }
+
+ cycles = 4;
+}
+
+//===== SET #,r
+void regSET()
+{
+ uint8 b = FETCH8 & 0xF;
+
+ switch(size)
+ {
+ case 0: rCodeB(rCode) |= (1 << b); break;
+ case 1: rCodeW(rCode) |= (1 << b); break;
+ }
+
+ cycles = 4;
+}
+
+//===== CHG #,r
+void regCHG()
+{
+ uint8 b = FETCH8 & 0xF;
+
+ switch(size)
+ {
+ case 0: rCodeB(rCode) ^= (1 << b); break;
+ case 1: rCodeW(rCode) ^= (1 << b); break;
+ }
+
+ cycles = 4;
+}
+
+//===== BIT #,r
+void regBIT()
+{
+ uint8 b = FETCH8 & 0xF;
+
+ switch(size)
+ {
+ case 0: SETFLAG_Z(! (rCodeB(rCode) & (1 << b)) ); break;
+ case 1: SETFLAG_Z(! (rCodeW(rCode) & (1 << b)) ); break;
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ cycles = 4;
+}
+
+//===== TSET #,r
+void regTSET()
+{
+ uint8 b = FETCH8 & 0xF;
+
+ switch(size)
+ {
+ case 0: SETFLAG_Z(! (rCodeB(rCode) & (1 << b)) );
+ rCodeB(rCode) |= (1 << b);
+ break;
+
+ case 1: SETFLAG_Z(! (rCodeW(rCode) & (1 << b)) );
+ rCodeW(rCode) |= (1 << b);
+ break;
+ }
+
+ SETFLAG_H1
+ SETFLAG_N0
+ cycles = 6;
+}
+
+//===== MINC1 #,r
+void regMINC1()
+{
+ uint16 num = fetch16() + 1;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == (num - 1))
+ rCodeW(rCode) -= (num - 1);
+ else
+ rCodeW(rCode) += 1;
+ }
+
+ cycles = 8;
+}
+
+//===== MINC2 #,r
+void regMINC2()
+{
+ uint16 num = fetch16() + 2;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == (num - 2))
+ rCodeW(rCode) -= (num - 2);
+ else
+ rCodeW(rCode) += 2;
+ }
+
+ cycles = 8;
+}
+
+//===== MINC4 #,r
+void regMINC4()
+{
+ uint16 num = fetch16() + 4;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == (num - 4))
+ rCodeW(rCode) -= (num - 4);
+ else
+ rCodeW(rCode) += 4;
+ }
+
+ cycles = 8;
+}
+
+//===== MDEC1 #,r
+void regMDEC1()
+{
+ uint16 num = fetch16() + 1;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == 0)
+ rCodeW(rCode) += (num - 1);
+ else
+ rCodeW(rCode) -= 1;
+ }
+
+ cycles = 7;
+}
+
+//===== MDEC2 #,r
+void regMDEC2()
+{
+ uint16 num = fetch16() + 2;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == 0)
+ rCodeW(rCode) += (num - 2);
+ else
+ rCodeW(rCode) -= 2;
+ }
+
+ cycles = 7;
+}
+
+//===== MDEC4 #,r
+void regMDEC4()
+{
+ uint16 num = fetch16() + 4;
+
+ if (size == 1)
+ {
+ if ((rCodeW(rCode) % num) == 0)
+ rCodeW(rCode) += (num - 4);
+ else
+ rCodeW(rCode) -= 4;
+ }
+
+ cycles = 7;
+}
+
+//===== MUL RR,r
+void regMUL()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: MUL bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (rCodeW(target) & 0xFF) * rCodeB(rCode);
+ cycles = 18; break;
+ case 1: rCodeL(target) = (rCodeL(target) & 0xFFFF) * rCodeW(rCode);
+ cycles = 26; break;
+ }
+}
+
+//===== MULS RR,r
+void regMULS()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: MUL bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (int8)(rCodeW(target) & 0xFF) * (int8)rCodeB(rCode);
+ cycles = 18; break;
+ case 1: rCodeL(target) = (int16)(rCodeL(target) & 0xFFFF) * (int16)rCodeW(rCode);
+ cycles = 26; break;
+ }
+}
+
+//===== DIV RR,r
+void regDIV()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: DIV bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIV_B(rCodeW(target), rCodeB(rCode));
+ cycles = 22;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIV_W(rCodeL(target), rCodeW(rCode));
+ cycles = 30;
+ break; }
+ }
+}
+
+//===== DIVS RR,r
+void regDIVS()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("reg: DIVS bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIVS_B(rCodeW(target), rCodeB(rCode));
+ cycles = 24;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIVS_W(rCodeL(target), rCodeW(rCode));
+ cycles = 32;
+ break; }
+ }
+}
+
+//===== INC #3,r
+void regINC()
+{
+ uint8 val = R;
+ if (val == 0)
+ val = 8;
+
+ switch(size)
+ {
+ case 0: { uint8 dst = rCodeB(rCode);
+ uint8 half = (dst & 0xF) + val;
+ uint32 resultC = dst + val;
+ uint8 result = (uint8)(resultC & 0xFF);
+ SETFLAG_S(result & 0x80);
+
+ if (((int8)dst >= 0) && ((int8)result < 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_H(half > 0xF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_N0;
+ rCodeB(rCode) = result;
+ break; }
+
+ case 1: { rCodeW(rCode) += val; break; }
+
+ case 2: { rCodeL(rCode) += val; break; }
+ }
+
+ cycles = 4;
+}
+
+//===== DEC #3,r
+void regDEC()
+{
+ uint8 val = R;
+ if (val == 0)
+ val = 8;
+
+ switch(size)
+ {
+ case 0: { uint8 dst = rCodeB(rCode);
+ uint8 half = (dst & 0xF) - val;
+ uint32 resultC = dst - val;
+ uint8 result = (uint8)(resultC & 0xFF);
+ SETFLAG_S(result & 0x80);
+
+ if (((int8)dst < 0) && ((int8)result >= 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ SETFLAG_H(half > 0xF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_N1;
+ rCodeB(rCode) = result;
+ cycles = 4;
+ break; }
+
+ case 1: { rCodeW(rCode) -= val; cycles = 4; break; }
+
+ case 2: { rCodeL(rCode) -= val; cycles = 5; break; }
+ }
+}
+
+//===== SCC cc,r
+void regSCC()
+{
+ uint32 result;
+
+ if (conditionCode(second & 0xF))
+ result = 1;
+ else
+ result = 0;
+
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = (uint8)result; break;
+ case 1: rCodeW(rCode) = (uint16)result; break;
+ }
+
+ cycles = 6;
+}
+
+//===== LD R,r
+void regLDRr()
+{
+ switch(size)
+ {
+ case 0: regB(R) = rCodeB(rCode); break;
+ case 1: regW(R) = rCodeW(rCode); break;
+ case 2: regL(R) = rCodeL(rCode); break;
+ }
+
+ cycles = 4;
+}
+
+//===== LD r,R
+void regLDrR()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = regB(R); break;
+ case 1: rCodeW(rCode) = regW(R); break;
+ case 2: rCodeL(rCode) = regL(R); break;
+ }
+
+ cycles = 4;
+}
+
+//===== ADD R,r
+void regADD()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_ADD_B(regB(R), rCodeB(rCode)); cycles = 4; break;
+ case 1: regW(R) = generic_ADD_W(regW(R), rCodeW(rCode)); cycles = 4; break;
+ case 2: regL(R) = generic_ADD_L(regL(R), rCodeL(rCode)); cycles = 7; break;
+ }
+}
+
+//===== ADC R,r
+void regADC()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_ADC_B(regB(R), rCodeB(rCode)); cycles = 4; break;
+ case 1: regW(R) = generic_ADC_W(regW(R), rCodeW(rCode)); cycles = 4; break;
+ case 2: regL(R) = generic_ADC_L(regL(R), rCodeL(rCode)); cycles = 7; break;
+ }
+}
+
+//===== SUB R,r
+void regSUB()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_SUB_B(regB(R), rCodeB(rCode)); cycles = 4; break;
+ case 1: regW(R) = generic_SUB_W(regW(R), rCodeW(rCode)); cycles = 4; break;
+ case 2: regL(R) = generic_SUB_L(regL(R), rCodeL(rCode)); cycles = 7; break;
+ }
+}
+
+//===== SBC R,r
+void regSBC()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_SBC_B(regB(R), rCodeB(rCode)); cycles = 4; break;
+ case 1: regW(R) = generic_SBC_W(regW(R), rCodeW(rCode)); cycles = 4; break;
+ case 2: regL(R) = generic_SBC_L(regL(R), rCodeL(rCode)); cycles = 7; break;
+ }
+}
+
+//===== LD r,#3
+void regLDr3()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = R; break;
+ case 1: rCodeW(rCode) = R; break;
+ case 2: rCodeL(rCode) = R; break;
+ }
+
+ cycles = 4;
+}
+
+//===== EX R,r
+void regEX()
+{
+ switch(size)
+ {
+ case 0: { uint8 temp = regB(R); regB(R) = rCodeB(rCode); rCodeB(rCode) = temp; break;}
+ case 1: { uint16 temp = regW(R); regW(R) = rCodeW(rCode); rCodeW(rCode) = temp; break;}
+ case 2: { uint32 temp = regL(R); regL(R) = rCodeL(rCode); rCodeL(rCode) = temp; break;}
+ }
+
+ cycles = 5;
+}
+
+//===== ADD r,#
+void regADDi()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = generic_ADD_B(rCodeB(rCode), FETCH8); cycles = 4;break;
+ case 1: rCodeW(rCode) = generic_ADD_W(rCodeW(rCode), fetch16()); cycles = 4;break;
+ case 2: rCodeL(rCode) = generic_ADD_L(rCodeL(rCode), fetch32()); cycles = 7;break;
+ }
+}
+
+//===== ADC r,#
+void regADCi()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = generic_ADC_B(rCodeB(rCode), FETCH8); cycles = 4;break;
+ case 1: rCodeW(rCode) = generic_ADC_W(rCodeW(rCode), fetch16()); cycles = 4;break;
+ case 2: rCodeL(rCode) = generic_ADC_L(rCodeL(rCode), fetch32()); cycles = 7;break;
+ }
+}
+
+//===== SUB r,#
+void regSUBi()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = generic_SUB_B(rCodeB(rCode), FETCH8); cycles = 4;break;
+ case 1: rCodeW(rCode) = generic_SUB_W(rCodeW(rCode), fetch16()); cycles = 4;break;
+ case 2: rCodeL(rCode) = generic_SUB_L(rCodeL(rCode), fetch32()); cycles = 7;break;
+ }
+}
+
+//===== SBC r,#
+void regSBCi()
+{
+ switch(size)
+ {
+ case 0: rCodeB(rCode) = generic_SBC_B(rCodeB(rCode), FETCH8); cycles = 4;break;
+ case 1: rCodeW(rCode) = generic_SBC_W(rCodeW(rCode), fetch16()); cycles = 4;break;
+ case 2: rCodeL(rCode) = generic_SBC_L(rCodeL(rCode), fetch32()); cycles = 7;break;
+ }
+}
+
+//===== CP r,#
+void regCPi()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(rCodeB(rCode), FETCH8); cycles = 4;break;
+ case 1: generic_SUB_W(rCodeW(rCode), fetch16());cycles = 4; break;
+ case 2: generic_SUB_L(rCodeL(rCode), fetch32());cycles = 7; break;
+ }
+}
+
+//===== AND r,#
+void regANDi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = rCodeB(rCode) & FETCH8;
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = rCodeW(rCode) & fetch16();
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = rCodeL(rCode) & fetch32();
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== OR r,#
+void regORi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = rCodeB(rCode) | FETCH8;
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ rCodeB(rCode) = result;
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = rCodeW(rCode) | fetch16();
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ rCodeW(rCode) = result;
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = rCodeL(rCode) | fetch32();
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ rCodeL(rCode) = result;
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== XOR r,#
+void regXORi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = rCodeB(rCode) ^ FETCH8;
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ rCodeB(rCode) = result;
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = rCodeW(rCode) ^ fetch16();
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ rCodeW(rCode) = result;
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = rCodeL(rCode) ^ fetch32();
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ rCodeL(rCode) = result;
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== AND R,r
+void regAND()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) & rCodeB(rCode);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ regB(R) = result;
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) & rCodeW(rCode);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ regW(R) = result;
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) & rCodeL(rCode);
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ regL(R) = result;
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== OR R,r
+void regOR()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) | rCodeB(rCode);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ regB(R) = result;
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) | rCodeW(rCode);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ regW(R) = result;
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) | rCodeL(rCode);
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ regL(R) = result;
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== XOR R,r
+void regXOR()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) ^ rCodeB(rCode);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ regB(R) = result;
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) ^ rCodeW(rCode);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ regW(R) = result;
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) ^ rCodeL(rCode);
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ regL(R) = result;
+ cycles = 7;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== CP r,#3
+void regCPr3()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(rCodeB(rCode), R); break;
+ case 1: generic_SUB_W(rCodeW(rCode), R); break;
+ }
+
+ cycles = 4;
+}
+
+//===== CP R,r
+void regCP()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(regB(R), rCodeB(rCode));cycles = 4; break;
+ case 1: generic_SUB_W(regW(R), rCodeW(rCode));cycles = 4; break;
+ case 2: generic_SUB_L(regL(R), rCodeL(rCode));cycles = 7; break;
+ }
+}
+
+//===== RLC #,r
+void regRLCi()
+{
+ int i;
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeB(rCode) & 0x80);
+ rCodeB(rCode) <<= 1;
+ if (FLAG_C) rCodeB(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeB(rCode) & 0x80);
+ SETFLAG_Z(rCodeB(rCode) == 0);
+ parityB(rCodeB(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 1: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeW(rCode) & 0x8000);
+ rCodeW(rCode) <<= 1;
+ if (FLAG_C) rCodeW(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeW(rCode) & 0x8000);
+ SETFLAG_Z(rCodeW(rCode) == 0);
+ parityW(rCodeW(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 2: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeL(rCode) & 0x80000000);
+ rCodeL(rCode) <<= 1;
+ if (FLAG_C) rCodeL(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeL(rCode) & 0x80000000);
+ SETFLAG_Z(rCodeL(rCode) == 0);
+ cycles = 8 + (2*sa);
+ break;
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RRC #,r
+void regRRCi()
+{
+ int i;
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeB(rCode) & 1);
+ rCodeB(rCode) >>= 1;
+ if (FLAG_C) rCodeB(rCode) |= 0x80;
+ }
+ SETFLAG_S(rCodeB(rCode) & 0x80);
+ SETFLAG_Z(rCodeB(rCode) == 0);
+ parityB(rCodeB(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 1: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeW(rCode) & 1);
+ rCodeW(rCode) >>= 1;
+ if (FLAG_C) rCodeW(rCode) |= 0x8000;
+ }
+ SETFLAG_S(rCodeW(rCode) & 0x8000);
+ SETFLAG_Z(rCodeW(rCode) == 0);
+ parityW(rCodeW(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 2: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeL(rCode) & 1);
+ rCodeL(rCode) >>= 1;
+ if (FLAG_C) rCodeL(rCode) |= 0x80000000;
+ }
+ SETFLAG_S(rCodeL(rCode) & 0x80000000);
+ SETFLAG_Z(rCodeL(rCode) == 0);
+ cycles = 8 + (2*sa);
+ break;
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RL #,r
+void regRLi()
+{
+ int i;
+ bool tempC;
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: { uint8 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeB(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeB(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + (2*sa);
+ break; }
+
+ case 1: { uint16 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeW(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeW(rCode) = result;
+ }
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + (2*sa);
+ break; }
+
+ case 2: { uint32 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeL(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeL(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ cycles = 8 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RR #,r
+void regRRi()
+{
+ int i;
+ bool tempC;
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: { uint8 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeB(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x80;
+ rCodeB(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeW(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x8000;
+ rCodeW(rCode) = result;
+ }
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityW(result);
+ break; }
+
+ case 2: { uint32 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeL(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x80000000;
+ rCodeL(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ cycles = 8 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SLA #,r
+void regSLAi()
+{
+ int8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { int8 result, data = (int8)rCodeB(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { int16 result, data = (int16)rCodeW(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { int32 result, data = (int32)rCodeL(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SRA #,r
+void regSRAi()
+{
+ int8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { int8 data = (int8)rCodeB(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { int16 data = (int16)rCodeW(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { int32 data = (int32)rCodeL(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SLL #,r
+void regSLLi()
+{
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { uint8 result, data = rCodeB(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { uint16 result, data = rCodeW(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { uint32 result, data = rCodeL(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SRL #,r
+void regSRLi()
+{
+ uint8 sa = FETCH8 & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { uint8 data = rCodeB(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { uint16 data = rCodeW(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { uint32 data = rCodeL(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RLC A,r
+void regRLCA()
+{
+ int i;
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeB(rCode) & 0x80);
+ rCodeB(rCode) <<= 1;
+ if (FLAG_C) rCodeB(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeB(rCode) & 0x80);
+ SETFLAG_Z(rCodeB(rCode) == 0);
+ cycles = 6 + (2*sa);
+ parityB(rCodeB(rCode));
+ break;
+
+ case 1: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeW(rCode) & 0x8000);
+ rCodeW(rCode) <<= 1;
+ if (FLAG_C) rCodeW(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeW(rCode) & 0x8000);
+ SETFLAG_Z(rCodeW(rCode) == 0);
+ cycles = 6 + (2*sa);
+ parityW(rCodeW(rCode));
+ break;
+
+ case 2: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeL(rCode) & 0x80000000);
+ rCodeL(rCode) <<= 1;
+ if (FLAG_C) rCodeL(rCode) |= 1;
+ }
+ SETFLAG_S(rCodeL(rCode) & 0x80000000);
+ SETFLAG_Z(rCodeL(rCode) == 0);
+ cycles = 8 + (2*sa);
+ break;
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RRC A,r
+void regRRCA()
+{
+ int i;
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeB(rCode) & 1);
+ rCodeB(rCode) >>= 1;
+ if (FLAG_C) rCodeB(rCode) |= 0x80;
+ }
+ SETFLAG_S(rCodeB(rCode) & 0x80);
+ SETFLAG_Z(rCodeB(rCode) == 0);
+ parityB(rCodeB(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 1: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeW(rCode) & 1);
+ rCodeW(rCode) >>= 1;
+ if (FLAG_C) rCodeW(rCode) |= 0x8000;
+ }
+ SETFLAG_S(rCodeW(rCode) & 0x8000);
+ SETFLAG_Z(rCodeW(rCode) == 0);
+ parityW(rCodeW(rCode));
+ cycles = 6 + (2*sa);
+ break;
+
+ case 2: for (i = 0; i < sa; i++)
+ {
+ SETFLAG_C(rCodeL(rCode) & 1);
+ rCodeL(rCode) >>= 1;
+ if (FLAG_C) rCodeL(rCode) |= 0x80000000;
+ }
+ SETFLAG_S(rCodeL(rCode) & 0x80000000);
+ SETFLAG_Z(rCodeL(rCode) == 0);
+ cycles = 8 + (2*sa);
+ break;
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RL A,r
+void regRLA()
+{
+ int i;
+ bool tempC;
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: { uint8 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeB(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeB(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeW(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeW(rCode) = result;
+ }
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityW(result);
+ break; }
+
+ case 2: { uint32 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeL(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ if (tempC) result |= 1;
+ rCodeL(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ cycles = 8 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== RR A,r
+void regRRA()
+{
+ int i;
+ bool tempC;
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+
+ switch(size)
+ {
+ case 0: { uint8 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeB(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x80;
+ rCodeB(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeW(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x8000;
+ rCodeW(rCode) = result;
+ }
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ cycles = 6 + (2*sa);
+ parityW(result);
+ break; }
+
+ case 2: { uint32 result;
+ for (i = 0; i < sa; i++)
+ {
+ result = rCodeL(rCode);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x01);
+ result >>= 1;
+ if (tempC) result |= 0x80000000;
+ rCodeL(rCode) = result;
+ }
+ SETFLAG_S(result & 0x80000000);
+ SETFLAG_Z(result == 0);
+ cycles = 8 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SLA A,r
+void regSLAA()
+{
+ int8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { int8 result, data = (int8)rCodeB(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { int16 result, data = (int16)rCodeW(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { int32 result, data = (int32)rCodeL(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SRA A,r
+void regSRAA()
+{
+ int8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { int8 data = (int8)rCodeB(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { int16 data = (int16)rCodeW(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { int32 data = (int32)rCodeL(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SLL A,r
+void regSLLA()
+{
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { uint8 result, data = rCodeB(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { uint16 result, data = rCodeW(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { uint32 result, data = rCodeL(rCode);
+ result = (data << sa);
+ SETFLAG_C(result & 0x80000000);
+ result <<= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== SRL A,r
+void regSRLA()
+{
+ uint8 sa = REGA & 0xF;
+ if (sa == 0) sa = 16;
+ sa--;
+
+ switch(size)
+ {
+ case 0: { uint8 data = rCodeB(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80);
+ rCodeB(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 1: { uint16 data = rCodeW(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x8000);
+ rCodeW(rCode) = result;
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 6 + 2 + (2*sa);
+ break; }
+
+ case 2: { uint32 data = rCodeL(rCode), result;
+ result = (data >> sa);
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ SETFLAG_S(result & 0x80000000);
+ rCodeL(rCode) = result;
+ SETFLAG_Z(result == 0);
+ cycles = 8 + 2 + (2*sa);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+};
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.h b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.h
new file mode 100644
index 0000000000..1895c8dc62
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.h
@@ -0,0 +1,305 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_reg.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_REG__
+#define __TLCS900H_REG__
+//=========================================================================
+
+namespace TLCS900H
+{
+
+//===== LD r,#
+void regLDi(void);
+
+//===== PUSH r
+void regPUSH(void);
+
+//===== POP r
+void regPOP(void);
+
+//===== CPL r
+void regCPL(void);
+
+//===== NEG r
+void regNEG(void);
+
+//===== MUL rr,#
+void regMULi(void);
+
+//===== MULS rr,#
+void regMULSi(void);
+
+//===== DIV rr,#
+void regDIVi(void);
+
+//===== DIVS rr,#
+void regDIVSi(void);
+
+//===== LINK r,dd
+void regLINK(void);
+
+//===== UNLK r
+void regUNLK(void);
+
+//===== BS1F A,r
+void regBS1F(void);
+
+//===== BS1B A,r
+void regBS1B(void);
+
+//===== DAA r
+void regDAA(void);
+
+//===== EXTZ r
+void regEXTZ(void);
+
+//===== EXTS r
+void regEXTS(void);
+
+//===== PAA r
+void regPAA(void);
+
+//===== MIRR r
+void regMIRR(void);
+
+//===== MULA r
+void regMULA(void);
+
+//===== DJNZ r,d
+void regDJNZ(void);
+
+//===== ANDCF #,r
+void regANDCFi(void);
+
+//===== ORCF #,r
+void regORCFi(void);
+
+//===== XORCF #,r
+void regXORCFi(void);
+
+//===== LDCF #,r
+void regLDCFi(void);
+
+//===== STCF #,r
+void regSTCFi(void);
+
+//===== ANDCF A,r
+void regANDCFA(void);
+
+//===== ORCF A,r
+void regORCFA(void);
+
+//===== XORCF A,r
+void regXORCFA(void);
+
+//===== LDCF A,r
+void regLDCFA(void);
+
+//===== STCF A,r
+void regSTCFA(void);
+
+//===== LDC cr,r
+void regLDCcrr(void);
+
+//===== LDC r,cr
+void regLDCrcr(void);
+
+//===== RES #,r
+void regRES(void);
+
+//===== SET #,r
+void regSET(void);
+
+//===== CHG #,r
+void regCHG(void);
+
+//===== BIT #,r
+void regBIT(void);
+
+//===== TSET #,r
+void regTSET(void);
+
+//===== MINC1 #,r
+void regMINC1(void);
+
+//===== MINC2 #,r
+void regMINC2(void);
+
+//===== MINC4 #,r
+void regMINC4(void);
+
+//===== MDEC1 #,r
+void regMDEC1(void);
+
+//===== MDEC2 #,r
+void regMDEC2(void);
+
+//===== MDEC4 #,r
+void regMDEC4(void);
+
+//===== MUL RR,r
+void regMUL(void);
+
+//===== MULS RR,r
+void regMULS(void);
+
+//===== DIV RR,r
+void regDIV(void);
+
+//===== DIVS RR,r
+void regDIVS(void);
+
+//===== INC #3,r
+void regINC(void);
+
+//===== DEC #3,r
+void regDEC(void);
+
+//===== SCC cc,r
+void regSCC(void);
+
+//===== LD R,r
+void regLDRr(void);
+
+//===== LD r,R
+void regLDrR(void);
+
+//===== ADD R,r
+void regADD(void);
+
+//===== ADC R,r
+void regADC(void);
+
+//===== SUB R,r
+void regSUB(void);
+
+//===== SBC R,r
+void regSBC(void);
+
+//===== LD r,#3
+void regLDr3(void);
+
+//===== EX R,r
+void regEX(void);
+
+//===== ADD r,#
+void regADDi(void);
+
+//===== ADC r,#
+void regADCi(void);
+
+//===== SUB r,#
+void regSUBi(void);
+
+//===== SBC r,#
+void regSBCi(void);
+
+//===== CP r,#
+void regCPi(void);
+
+//===== AND r,#
+void regANDi(void);
+
+//===== OR r,#
+void regORi(void);
+
+//===== XOR r,#
+void regXORi(void);
+
+//===== AND R,r
+void regAND(void);
+
+//===== OR R,r
+void regOR(void);
+
+//===== XOR R,r
+void regXOR(void);
+
+//===== CP r,#3
+void regCPr3(void);
+
+//===== CP R,r
+void regCP(void);
+
+//===== RLC #,r
+void regRLCi(void);
+
+//===== RRC #,r
+void regRRCi(void);
+
+//===== RL #,r
+void regRLi(void);
+
+//===== RR #,r
+void regRRi(void);
+
+//===== SLA #,r
+void regSLAi(void);
+
+//===== SRA #,r
+void regSRAi(void);
+
+//===== SLL #,r
+void regSLLi(void);
+
+//===== SRL #,r
+void regSRLi(void);
+
+//===== RLC A,r
+void regRLCA(void);
+
+//===== RRC A,r
+void regRRCA(void);
+
+//===== RL A,r
+void regRLA(void);
+
+//===== RR A,r
+void regRRA(void);
+
+//===== SLA A,r
+void regSLAA(void);
+
+//===== SRA A,r
+void regSRAA(void);
+
+//===== SLL A,r
+void regSLLA(void);
+
+//===== SRL A,r
+void regSRLA(void);
+
+};
+
+//=========================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.cpp
new file mode 100644
index 0000000000..96422b249f
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.cpp
@@ -0,0 +1,428 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_single.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+22 JUL 2002 - neopop_uk
+=======================================
+- Removed setting the register file pointer to 3 in the SWI instruction
+ This has fixed "Metal Slug 2" and flash saving in many games.
+
+26 JUL 2002 - neopop_uk
+=======================================
+- Prefixed all instruction functions with "sng" to avoid a repeat of the
+ the 'EX' fiasco.
+
+30 JUL 2002 - neopop_uk
+=======================================
+- Um... SWI doesn't cause a problem if IFF is set to 3... why did
+"Metal Slug 2" start working???
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_interpret.h"
+#include "TLCS900h_registers.h"
+#include "../mem.h"
+#include "../interrupt.h"
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+//===== NOP
+void sngNOP()
+{
+ cycles = 2;
+}
+
+//===== NORMAL
+void sngNORMAL()
+{
+ //Not supported
+ cycles = 4;
+}
+
+//===== PUSH SR
+void sngPUSHSR()
+{
+ push16(sr);
+ cycles = 4;
+}
+
+//===== POP SR
+void sngPOPSR()
+{
+ sr = pop16(); changedSP();
+ cycles = 6;
+}
+
+//===== MAX
+void sngMAX()
+{
+ //Not supported
+ cycles = 4;
+}
+
+//===== HALT
+void sngHALT()
+{
+ MDFN_printf("CPU halt requested and ignored.\nPlease send me a saved state.");
+ cycles = 8;
+}
+
+//===== EI #3
+void sngEI()
+{
+ setStatusIFF(FETCH8);
+ int_check_pending();
+ cycles = 5;
+}
+
+//===== RETI
+void sngRETI()
+{
+ uint16 temp = pop16();
+ pc = pop32();
+ sr = temp; changedSP();
+ cycles = 12;
+}
+
+//===== LD (n), n
+void sngLD8_8()
+{
+ uint8 dst = FETCH8;
+ uint8 src = FETCH8;
+ storeB(dst, src);
+ cycles = 5;
+}
+
+//===== PUSH n
+void sngPUSH8()
+{
+ uint8 data = FETCH8;
+ push8(data);
+ cycles = 4;
+}
+
+//===== LD (n), nn
+void sngLD8_16()
+{
+ uint8 dst = FETCH8;
+ uint16 src = fetch16();
+ storeW(dst, src);
+ cycles = 6;
+}
+
+//===== PUSH nn
+void sngPUSH16()
+{
+ push16(fetch16());
+ cycles = 5;
+}
+
+//===== INCF
+void sngINCF()
+{
+ setStatusRFP(((sr & 0x300) >> 8) + 1);
+ cycles = 2;
+}
+
+//===== DECF
+void sngDECF()
+{
+ setStatusRFP(((sr & 0x300) >> 8) - 1);
+ cycles = 2;
+}
+
+//===== RET condition
+void sngRET()
+{
+ pc = pop32();
+ cycles = 9;
+}
+
+//===== RETD dd
+void sngRETD()
+{
+ int16 d = (int16)fetch16();
+ pc = pop32();
+ REGXSP += d;
+ cycles = 9;
+}
+
+//===== RCF
+void sngRCF()
+{
+ SETFLAG_N0;
+ SETFLAG_V0;
+ SETFLAG_C0;
+ cycles = 2;
+}
+
+//===== SCF
+void sngSCF()
+{
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C1;
+ cycles = 2;
+}
+
+//===== CCF
+void sngCCF()
+{
+ SETFLAG_N0;
+ SETFLAG_C(!FLAG_C);
+ cycles = 2;
+}
+
+//===== ZCF
+void sngZCF()
+{
+ SETFLAG_N0;
+ SETFLAG_C(!FLAG_Z);
+ cycles = 2;
+}
+
+//===== PUSH A
+void sngPUSHA()
+{
+ push8(REGA);
+ cycles = 3;
+}
+
+//===== POP A
+void sngPOPA()
+{
+ REGA = pop8();
+ cycles = 4;
+}
+
+//===== EX F,F'
+void sngEX()
+{
+ uint8 f = sr & 0xFF;
+ sr = (sr & 0xFF00) | f_dash;
+ f_dash = f;
+ cycles = 2;
+}
+
+//===== LDF #3
+void sngLDF()
+{
+ setStatusRFP(FETCH8);
+ cycles = 2;
+}
+
+//===== PUSH F
+void sngPUSHF()
+{
+ push8(sr & 0xFF);
+ cycles = 3;
+}
+
+//===== POP F
+void sngPOPF()
+{
+ sr = (sr & 0xFF00) | pop8();
+ cycles = 4;
+}
+
+//===== JP nn
+void sngJP16()
+{
+ pc = fetch16();
+ cycles = 7;
+}
+
+//===== JP nnn
+void sngJP24()
+{
+ pc = fetch24();
+ cycles = 7;
+}
+
+//===== CALL #16
+void sngCALL16()
+{
+ uint32 target = fetch16();
+ push32(pc);
+ pc = target;
+ cycles = 12;
+}
+
+//===== CALL #24
+void sngCALL24()
+{
+ uint32 target = fetch24();
+ push32(pc);
+ pc = target;
+ cycles = 12;
+}
+
+//===== CALR $+3+d16
+void sngCALR()
+{
+ int16 displacement = (int16)fetch16();
+ uint32 target = pc + displacement;
+ push32(pc);
+ pc = target;
+ cycles = 12;
+}
+
+//===== LD R, n
+void sngLDB()
+{
+ regB(first & 7) = FETCH8;
+ cycles = 2;
+}
+
+//===== PUSH RR
+void sngPUSHW()
+{
+ push16(regW(first & 7));
+ cycles = 3;
+}
+
+//===== LD RR, nn
+void sngLDW()
+{
+ regW(first & 7) = fetch16();
+ cycles = 3;
+}
+
+//===== PUSH XRR
+void sngPUSHL()
+{
+ push32(regL(first & 7));
+ cycles = 5;
+}
+
+//===== LD XRR, nnnn
+void sngLDL()
+{
+ regL(first & 7) = fetch32();
+ cycles = 5;
+}
+
+//===== POP RR
+void sngPOPW()
+{
+ regW(first & 7) = pop16();
+ cycles = 4;
+}
+
+//===== POP XRR
+void sngPOPL()
+{
+ regL(first & 7) = pop32();
+ cycles = 6;
+}
+
+//===== JR cc,PC + d
+void sngJR()
+{
+ if (conditionCode(first & 0xF))
+ {
+ int8 displacement = (int8)FETCH8;
+
+ cycles = 8;
+ pc += displacement;
+ }
+ else
+ {
+ cycles = 4;
+ FETCH8;
+ }
+}
+
+//===== JR cc,PC + dd
+void sngJRL()
+{
+ if (conditionCode(first & 0xF))
+ {
+ int16 displacement = (int16)fetch16();
+ cycles = 8;
+ pc += displacement;
+ }
+ else
+ {
+ cycles = 4;
+ fetch16();
+ }
+}
+
+//===== LDX dst,src
+void sngLDX()
+{
+ uint8 dst, src;
+
+ FETCH8; //00
+ dst = FETCH8; //#8
+ FETCH8; //00
+ src = FETCH8; //#
+ FETCH8; //00
+
+ storeB(dst, src);
+ cycles = 9;
+}
+
+//===== SWI num
+void sngSWI()
+{
+ cycles = 16;
+
+ //printf("SWI: %02x\n", first & 0x7);
+ switch(first & 7)
+ {
+ //System Call
+ case 1: push32(pc);
+ pc = loadL(0xFFFE00 + ((rCodeB(0x31) & 0x1F) << 2));
+ break;
+
+ case 3: interrupt(0); //SWI 3
+ break;
+
+ case 4: interrupt(1); //SWI 4
+ break;
+
+ case 5: interrupt(2); //SWI 5
+ break;
+
+ case 6: interrupt(3); //SWI 6
+ break;
+
+ default: instruction_error("SWI %d is not valid.", first & 7);
+ break;
+ }
+}
+};
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.h b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.h
new file mode 100644
index 0000000000..f34d758493
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.h
@@ -0,0 +1,170 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_single.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_SINGLE__
+#define __TLCS900H_SINGLE__
+//=========================================================================
+
+namespace TLCS900H
+{
+
+//===== NOP
+void sngNOP(void);
+
+//===== NORMAL
+void sngNORMAL(void);
+
+//===== PUSH SR
+void sngPUSHSR(void);
+
+//===== POP SR
+void sngPOPSR(void);
+
+//===== MAX
+void sngMAX(void);
+
+//===== HALT
+void sngHALT(void);
+
+//===== EI #3
+void sngEI(void);
+
+//===== RETI
+void sngRETI(void);
+
+//===== LD (n), n
+void sngLD8_8(void);
+
+//===== PUSH n
+void sngPUSH8(void);
+
+//===== LD (n), nn
+void sngLD8_16(void);
+
+//===== PUSH nn
+void sngPUSH16(void);
+
+//===== INCF
+void sngINCF(void);
+
+//===== DECF
+void sngDECF(void);
+
+//===== RET condition
+void sngRET(void);
+
+//===== RETD dd
+void sngRETD(void);
+
+//===== RCF
+void sngRCF(void);
+
+//===== SCF
+void sngSCF(void);
+
+//===== CCF
+void sngCCF(void);
+
+//===== ZCF
+void sngZCF(void);
+
+//===== PUSH A
+void sngPUSHA(void);
+
+//===== POP A
+void sngPOPA(void);
+
+//===== EX F,F'
+void sngEX(void);
+
+//===== LDF #3
+void sngLDF(void);
+
+//===== PUSH F
+void sngPUSHF(void);
+
+//===== POP F
+void sngPOPF(void);
+
+//===== JP nn
+void sngJP16(void);
+
+//===== JP nnn
+void sngJP24(void);
+
+//===== CALL #16
+void sngCALL16(void);
+
+//===== CALL #24
+void sngCALL24(void);
+
+//===== CALR $+3+d16
+void sngCALR(void);
+
+//===== LD R, n
+void sngLDB(void);
+
+//===== PUSH RR
+void sngPUSHW(void);
+
+//===== LD RR, nn
+void sngLDW(void);
+
+//===== PUSH XRR
+void sngPUSHL(void);
+
+//===== LD XRR, nnnn
+void sngLDL(void);
+
+//===== POP RR
+void sngPOPW(void);
+
+//===== POP XRR
+void sngPOPL(void);
+
+//===== JR cc,PC + d
+void sngJR(void);
+
+//===== JR cc,PC + dd
+void sngJRL(void);
+
+//===== LDX dst,src
+void sngLDX(void);
+
+//===== SWI num
+void sngSWI(void);
+
+};
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.cpp
new file mode 100644
index 0000000000..9e16ea5590
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.cpp
@@ -0,0 +1,1266 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_src.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+24 JUL 2002 - neopop_uk
+=======================================
+- Fixed S flag in "RRC (mem)"
+
+25 JUL 2002 - neopop_uk
+=======================================
+- Removed unneeded Long mode from EX.
+
+28 JUL 2002 - neopop_uk
+=======================================
+- Improved the LDIR/LDDR/CPIR/CPDR instructions so that they
+ finish with the correct register settings, even if there is
+ a memory error.
+- Converted DIV/DIVS to use the generic function
+
+16 AUG 2002 - neopop_uk
+=======================================
+- Replaced 'second & 7' with 'R', clearer, faster - and for some reason
+ more accurate... oh well!
+- Fixed V flag emulation of INC/DEC, fixes "Cotton" menus
+
+21 AUG 2002 - neopop_uk
+=======================================
+- Fixed "RR (mem)" - It was actually the [REG] version that hadn't been
+ changed to use memory accesses!
+
+30 AUG 2002 - neopop_uk
+=======================================
+- Fixed "DIV RR,(mem)" in long mode, wrong operand size.
+
+04 SEP 2002 - neopop_uk
+=======================================
+- Fixed GCC compatibility.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "TLCS900h_interpret.h"
+#include "TLCS900h_registers.h"
+#include "../mem.h"
+
+namespace TLCS900H
+{
+
+//=========================================================================
+
+//===== PUSH (mem)
+void srcPUSH()
+{
+ switch(size)
+ {
+ case 0: push8(loadB(mem)); break;
+ case 1: push16(loadW(mem)); break;
+ }
+ cycles = 7;
+}
+
+//===== RLD A,(mem)
+void srcRLD()
+{
+ uint8 al = REGA & 0xF, m, mh, ml;
+
+ m = loadB(mem);
+ mh = (m & 0xF0) >> 4;
+ ml = (m & 0x0F) << 4;
+
+ REGA = (REGA & 0xF0) | mh;
+ storeB(mem, ml | al);
+
+ SETFLAG_S(REGA & 0x80);
+ SETFLAG_Z(REGA == 0);
+ SETFLAG_H0
+ SETFLAG_N0
+ parityB(REGA);
+
+ cycles = 12;
+}
+
+//===== RRD A,(mem)
+void srcRRD()
+{
+ uint8 al = (REGA & 0xF) << 4, m, mh, ml;
+
+ m = loadB(mem);
+ mh = (m & 0xF0) >> 4;
+ ml = m & 0x0F;
+
+ REGA = (REGA & 0xF0) | ml;
+ storeB(mem, al | mh);
+
+ SETFLAG_S(REGA & 0x80);
+ SETFLAG_Z(REGA == 0);
+ SETFLAG_H0
+ SETFLAG_N0
+ parityB(REGA);
+
+ cycles = 12;
+}
+
+//===== LDI
+void srcLDI()
+{
+ uint8 dst = 2/*XDE*/, src = 3/*XHL*/;
+ if ((first & 0xF) == 5) { dst = 4/*XIX*/; src = 5/*XIY*/; }
+
+ switch(size)
+ {
+ case 0:
+ storeB(regL(dst), loadB(regL(src)));
+ regL(dst) += 1;
+ regL(src) += 1;
+ break;
+
+ case 1:
+ storeW(regL(dst), loadW(regL(src)));
+ regL(dst) += 2;
+ regL(src) += 2;
+ break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ cycles = 10;
+}
+
+//===== LDIR
+void srcLDIR()
+{
+ uint8 dst = 2/*XDE*/, src = 3/*XHL*/;
+ if ((first & 0xF) == 5) { dst = 4/*XIX*/; src = 5/*XIY*/; }
+
+ cycles = 10;
+
+ do
+ {
+ switch(size)
+ {
+ case 0: if (debug_abort_memory == FALSE)
+ storeB(regL(dst), loadB(regL(src)));
+ regL(dst) += 1;
+ regL(src) += 1;
+ break;
+
+ case 1: if (debug_abort_memory == FALSE)
+ storeW(regL(dst), loadW(regL(src)));
+ regL(dst) += 2;
+ regL(src) += 2;
+ break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles += 14;
+ }
+ while (FLAG_V);
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== LDD
+void srcLDD()
+{
+ uint8 dst = 2/*XDE*/, src = 3/*XHL*/;
+ if ((first & 0xF) == 5) { dst = 4/*XIX*/; src = 5/*XIY*/; }
+
+ switch(size)
+ {
+ case 0:
+ storeB(regL(dst), loadB(regL(src)));
+ regL(dst) -= 1;
+ regL(src) -= 1;
+ break;
+
+ case 1:
+ storeW(regL(dst), loadW(regL(src)));
+ regL(dst) -= 2;
+ regL(src) -= 2;
+ break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ cycles = 10;
+}
+
+//===== LDDR
+void srcLDDR()
+{
+ uint8 dst = 2/*XDE*/, src = 3/*XHL*/;
+ if ((first & 0xF) == 5) { dst = 4/*XIX*/; src = 5/*XIY*/; }
+
+ cycles = 10;
+
+ do
+ {
+ switch(size)
+ {
+ case 0:
+ if (debug_abort_memory == FALSE)
+ storeB(regL(dst), loadB(regL(src)));
+ regL(dst) -= 1;
+ regL(src) -= 1;
+ break;
+
+ case 1:
+ if (debug_abort_memory == FALSE)
+ storeW(regL(dst), loadW(regL(src)));
+ regL(dst) -= 2;
+ regL(src) -= 2;
+ break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles += 14;
+ }
+ while (FLAG_V);
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+}
+
+//===== CPI
+void srcCPI()
+{
+ uint8 R = first & 7;
+
+ switch(size)
+ {
+ case 0: generic_SUB_B(REGA, loadB(regL(R)));
+ regL(R) ++; break;
+
+ case 1: generic_SUB_W(REGWA, loadW(regL(R)));
+ regL(R) += 2; break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles = 8;
+}
+
+//===== CPIR
+void srcCPIR()
+{
+ uint8 R = first & 7;
+
+ cycles = 10;
+
+ do
+ {
+ switch(size)
+ {
+ case 0: if (debug_abort_memory == FALSE)
+ generic_SUB_B(REGA, loadB(regL(R)));
+ regL(R) ++; break;
+
+ case 1: if (debug_abort_memory == FALSE)
+ generic_SUB_W(REGWA, loadW(regL(R)));
+ regL(R) += 2; break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles += 14;
+ }
+ while (FLAG_V && (FLAG_Z == FALSE));
+}
+
+//===== CPD
+void srcCPD()
+{
+ uint8 R = first & 7;
+
+ switch(size)
+ {
+ case 0: generic_SUB_B(REGA, loadB(regL(R)));
+ regL(R) --; break;
+
+ case 1: generic_SUB_W(REGWA, loadW(regL(R)));
+ regL(R) -= 2; break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles = 8;
+}
+
+//===== CPDR
+void srcCPDR()
+{
+ uint8 R = first & 7;
+
+ cycles = 10;
+
+ do
+ {
+ switch(size)
+ {
+ case 0: if (debug_abort_memory == FALSE)
+ generic_SUB_B(REGA, loadB(regL(R)));
+ regL(R) -= 1; break;
+
+ case 1: if (debug_abort_memory == FALSE)
+ generic_SUB_W(REGWA, loadW(regL(R)));
+ regL(R) -= 2; break;
+ }
+
+ REGBC --;
+ SETFLAG_V(REGBC);
+
+ cycles += 14;
+ }
+ while (FLAG_V && (FLAG_Z == FALSE));
+}
+
+//===== LD (nn),(mem)
+void srcLD16m()
+{
+ switch(size)
+ {
+ case 0: storeB(fetch16(), loadB(mem)); break;
+ case 1: storeW(fetch16(), loadW(mem)); break;
+ }
+
+ cycles = 8;
+}
+
+//===== LD R,(mem)
+void srcLD()
+{
+ switch(size)
+ {
+ case 0: regB(R) = loadB(mem); cycles = 4; break;
+ case 1: regW(R) = loadW(mem); cycles = 4; break;
+ case 2: regL(R) = loadL(mem); cycles = 6; break;
+ }
+}
+
+//===== EX (mem),R
+void srcEX()
+{
+ switch(size)
+ {
+ case 0: { uint8 temp = regB(R);
+ regB(R) = loadB(mem);
+ storeB(mem, temp); break; }
+
+ case 1: { uint16 temp = regW(R);
+ regW(R) = loadW(mem);
+ storeW(mem, temp); break; }
+ }
+
+ cycles = 6;
+}
+
+//===== ADD (mem),#
+void srcADDi()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_ADD_B(loadB(mem), FETCH8)); cycles = 7;break;
+ case 1: storeW(mem, generic_ADD_W(loadW(mem), fetch16())); cycles = 8;break;
+ }
+}
+
+//===== ADC (mem),#
+void srcADCi()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_ADC_B(loadB(mem), FETCH8)); cycles = 7;break;
+ case 1: storeW(mem, generic_ADC_W(loadW(mem), fetch16())); cycles = 8;break;
+ }
+}
+
+//===== SUB (mem),#
+void srcSUBi()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_SUB_B(loadB(mem), FETCH8)); cycles = 7;break;
+ case 1: storeW(mem, generic_SUB_W(loadW(mem), fetch16())); cycles = 8;break;
+ }
+}
+
+//===== SBC (mem),#
+void srcSBCi()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_SBC_B(loadB(mem), FETCH8)); cycles = 7;break;
+ case 1: storeW(mem, generic_SBC_W(loadW(mem), fetch16())); cycles = 8;break;
+ }
+}
+
+//===== AND (mem),#
+void srcANDi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem) & FETCH8;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 7;
+ break; }
+
+ case 1: { uint16 result = loadW(mem) & fetch16();
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 8;
+ break; }
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== OR (mem),#
+void srcORi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem) | FETCH8;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 7;
+ break; }
+
+ case 1: { uint16 result = loadW(mem) | fetch16();
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 8;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== XOR (mem),#
+void srcXORi()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem) ^ FETCH8;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ cycles = 7;
+ break; }
+
+ case 1: { uint16 result = loadW(mem) ^ fetch16();
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ cycles = 8;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== CP (mem),#
+void srcCPi()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(loadB(mem), FETCH8); break;
+ case 1: generic_SUB_W(loadW(mem), fetch16()); break;
+ }
+
+ cycles = 6;
+}
+
+//===== MUL RR,(mem)
+void srcMUL()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("src: MUL bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (rCodeW(target) & 0xFF) * loadB(mem);
+ cycles = 18; break;
+ case 1: rCodeL(target) = (rCodeL(target) & 0xFFFF) * loadW(mem);
+ cycles = 26; break;
+ }
+}
+
+//===== MULS RR,(mem)
+void srcMULS()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("src: MUL bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: rCodeW(target) = (int8)(rCodeW(target) & 0xFF) * (int8)loadB(mem);
+ cycles = 18; break;
+ case 1: rCodeL(target) = (int16)(rCodeL(target) & 0xFFFF) * (int16)loadW(mem);
+ cycles = 26; break;
+ }
+}
+
+//===== DIV RR,(mem)
+void srcDIV()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("src: DIV bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIV_B(rCodeW(target), loadB(mem));
+ cycles = 22;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIV_W(rCodeL(target), loadW(mem));
+ cycles = 30;
+ break; }
+ }
+}
+
+//===== DIVS RR,(mem)
+void srcDIVS()
+{
+ uint8 target = get_RR_Target();
+ if (target == 0x80)
+ {
+ instruction_error("src: DIVS bad \'RR\' dst code");
+ return;
+ }
+
+ switch(size)
+ {
+ case 0: { rCodeW(target) = generic_DIVS_B(rCodeW(target), loadB(mem));
+ cycles = 24;
+ break; }
+
+ case 1: { rCodeL(target) = generic_DIVS_W(rCodeL(target), loadW(mem));
+ cycles = 32;
+ break; }
+ }
+}
+
+//===== INC #3,(mem)
+void srcINC()
+{
+ uint8 val = R;
+ if (val == 0)
+ val = 8;
+
+ switch(size)
+ {
+ case 0: { uint8 dst = loadB(mem);
+ uint32 resultC = dst + val;
+ uint8 half = (dst & 0xF) + val;
+ uint8 result = (uint8)(resultC & 0xFF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_N0;
+
+ if (((int8)dst >= 0) && ((int8)result < 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ storeB(mem, result);
+ break; }
+
+ case 1: { uint16 dst = loadW(mem);
+ uint32 resultC = dst + val;
+ uint8 half = (dst & 0xF) + val;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_N0;
+
+ if (((int16)dst >= 0) && ((int16)result < 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ storeW(mem, result);
+ break; }
+ }
+
+ cycles = 6;
+}
+
+//===== DEC #3,(mem)
+void srcDEC()
+{
+ uint8 val = R;
+ if (val == 0)
+ val = 8;
+
+ switch(size)
+ {
+ case 0: { uint8 dst = loadB(mem);
+ uint32 resultC = dst - val;
+ uint8 half = (dst & 0xF) - val;
+ uint8 result = (uint8)(resultC & 0xFF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_N1;
+
+ if (((int8)dst < 0) && ((int8)result >= 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ storeB(mem, result);
+ break; }
+
+ case 1: { uint16 dst = loadW(mem);
+ uint32 resultC = dst - val;
+ uint8 half = (dst & 0xF) - val;
+ uint16 result = (uint16)(resultC & 0xFFFF);
+ SETFLAG_Z(result == 0);
+ SETFLAG_H(half > 0xF);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_N1;
+
+ if (((int16)dst < 0) && ((int16)result >= 0))
+ {SETFLAG_V1} else {SETFLAG_V0}
+
+ storeW(mem, result);
+ break; }
+ }
+
+ cycles = 6;
+}
+
+//===== RLC (mem)
+void srcRLC()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem);
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ if (FLAG_C) result |= 1;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result = loadW(mem);
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ if (FLAG_C) result |= 1;
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== RRC (mem)
+void srcRRC()
+{
+ switch(size)
+ {
+ case 0: { uint8 data = loadB(mem), result;
+ SETFLAG_C(data & 1);
+ result = data >> 1;
+ if (FLAG_C) result |= 0x80;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 data = loadW(mem), result;
+ SETFLAG_C(data & 1);
+ result = data >> 1;
+ if (FLAG_C) result |= 0x8000;
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== RL (mem)
+void srcRL()
+{
+ bool tempC;
+
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x80);
+ result <<= 1;
+ if (tempC) result |= 1;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result = loadW(mem);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 0x8000);
+ result <<= 1;
+ if (tempC) result |= 1;
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ cycles = 8;
+}
+
+//===== RR (mem)
+void srcRR()
+{
+ bool tempC;
+
+ switch(size)
+ {
+ case 0: { uint8 result = loadB(mem);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ if (tempC) result |= 0x80;
+ storeB(mem, result);
+ SETFLAG_S(result & 0x80);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result = loadW(mem);
+ tempC = FLAG_C;
+ SETFLAG_C(result & 1);
+ result >>= 1;
+ if (tempC) result |= 0x8000;
+ storeW(mem, result);
+ SETFLAG_S(result & 0x8000);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ cycles = 8;
+}
+
+//===== SLA (mem)
+void srcSLA()
+{
+ switch(size)
+ {
+ case 0: { uint8 result, data = loadB(mem);
+ SETFLAG_C(data & 0x80);
+ result = ((int8)data << 1);
+ SETFLAG_S(result & 0x80);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result, data = loadW(mem);
+ SETFLAG_C(data & 0x8000);
+ result = ((int16)data << 1);
+ SETFLAG_S(result & 0x8000);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== SRA (mem)
+void srcSRA()
+{
+ switch(size)
+ {
+ case 0: { uint8 result, data = loadB(mem);
+ SETFLAG_C(data & 0x1);
+ result = ((int8)data >> 1);
+ SETFLAG_S(result & 0x80);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result, data = loadW(mem);
+ SETFLAG_C(data & 0x1);
+ result = ((int16)data >> 1);
+ SETFLAG_S(result & 0x8000);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== SLL (mem)
+void srcSLL()
+{
+ switch(size)
+ {
+ case 0: { uint8 result, data = loadB(mem);
+ SETFLAG_C(data & 0x80);
+ result = (data << 1);
+ SETFLAG_S(result & 0x80);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result, data = loadW(mem);
+ SETFLAG_C(data & 0x8000);
+ result = (data << 1);
+ SETFLAG_S(result & 0x8000);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== SRL (mem)
+void srcSRL()
+{
+ switch(size)
+ {
+ case 0: { uint8 result, data = loadB(mem);
+ SETFLAG_C(data & 0x01);
+ result = (data >> 1);
+ SETFLAG_S(result & 0x80);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ parityB(result);
+ break; }
+
+ case 1: { uint16 result, data = loadW(mem);
+ SETFLAG_C(data & 0x0001);
+ result = (data >> 1);
+ SETFLAG_S(result & 0x8000);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ parityW(result);
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+
+ cycles = 8;
+}
+
+//===== ADD R,(mem)
+void srcADDRm()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_ADD_B(regB(R), loadB(mem)); cycles = 4;break;
+ case 1: regW(R) = generic_ADD_W(regW(R), loadW(mem)); cycles = 4;break;
+ case 2: regL(R) = generic_ADD_L(regL(R), loadL(mem)); cycles = 6;break;
+ }
+}
+
+//===== ADD (mem),R
+void srcADDmR()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_ADD_B(loadB(mem), regB(R))); cycles = 6;break;
+ case 1: storeW(mem, generic_ADD_W(loadW(mem), regW(R))); cycles = 6;break;
+ case 2: storeL(mem, generic_ADD_L(loadL(mem), regL(R))); cycles = 10;break;
+ }
+}
+
+//===== ADC R,(mem)
+void srcADCRm()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_ADC_B(regB(R), loadB(mem)); cycles = 4;break;
+ case 1: regW(R) = generic_ADC_W(regW(R), loadW(mem)); cycles = 4;break;
+ case 2: regL(R) = generic_ADC_L(regL(R), loadL(mem)); cycles = 6;break;
+ }
+}
+
+//===== ADC (mem),R
+void srcADCmR()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_ADC_B(loadB(mem), regB(R))); cycles = 6;break;
+ case 1: storeW(mem, generic_ADC_W(loadW(mem), regW(R))); cycles = 6;break;
+ case 2: storeL(mem, generic_ADC_L(loadL(mem), regL(R))); cycles = 10;break;
+ }
+}
+
+//===== SUB R,(mem)
+void srcSUBRm()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_SUB_B(regB(R), loadB(mem)); cycles = 4;break;
+ case 1: regW(R) = generic_SUB_W(regW(R), loadW(mem)); cycles = 4;break;
+ case 2: regL(R) = generic_SUB_L(regL(R), loadL(mem)); cycles = 6;break;
+ }
+}
+
+//===== SUB (mem),R
+void srcSUBmR()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_SUB_B(loadB(mem), regB(R))); cycles = 6;break;
+ case 1: storeW(mem, generic_SUB_W(loadW(mem), regW(R))); cycles = 6;break;
+ case 2: storeL(mem, generic_SUB_L(loadL(mem), regL(R))); cycles = 10;break;
+ }
+}
+
+//===== SBC R,(mem)
+void srcSBCRm()
+{
+ switch(size)
+ {
+ case 0: regB(R) = generic_SBC_B(regB(R), loadB(mem)); cycles = 4;break;
+ case 1: regW(R) = generic_SBC_W(regW(R), loadW(mem)); cycles = 4;break;
+ case 2: regL(R) = generic_SBC_L(regL(R), loadL(mem)); cycles = 6;break;
+ }
+}
+
+//===== SBC (mem),R
+void srcSBCmR()
+{
+ switch(size)
+ {
+ case 0: storeB(mem, generic_SBC_B(loadB(mem), regB(R))); cycles = 6;break;
+ case 1: storeW(mem, generic_SBC_W(loadW(mem), regW(R))); cycles = 6;break;
+ case 2: storeL(mem, generic_SBC_L(loadL(mem), regL(R))); cycles = 10;break;
+ }
+}
+
+//===== AND R,(mem)
+void srcANDRm()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) & loadB(mem);
+ regB(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) & loadW(mem);
+ regW(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) & loadL(mem);
+ regL(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 6;
+ break; }
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== AND (mem),R
+void srcANDmR()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) & loadB(mem);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 6;
+ break; }
+
+ case 1: { uint16 result = regW(R) & loadW(mem);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 6;
+ break; }
+
+ case 2: { uint32 result = regL(R) & loadL(mem);
+ storeL(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 10;
+ break; }
+ }
+
+ SETFLAG_H1;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== XOR R,(mem)
+void srcXORRm()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) ^ loadB(mem);
+ regB(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) ^ loadW(mem);
+ regW(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) ^ loadL(mem);
+ regL(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 6;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== XOR (mem),R
+void srcXORmR()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) ^ loadB(mem);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 6;
+ break; }
+
+ case 1: { uint16 result = regW(R) ^ loadW(mem);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 6;
+ break; }
+
+ case 2: { uint32 result = regL(R) ^ loadL(mem);
+ storeL(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 10;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== OR R,(mem)
+void srcORRm()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) | loadB(mem);
+ regB(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 4;
+ break; }
+
+ case 1: { uint16 result = regW(R) | loadW(mem);
+ regW(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 4;
+ break; }
+
+ case 2: { uint32 result = regL(R) | loadL(mem);
+ regL(R) = result;
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 6;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== OR (mem),R
+void srcORmR()
+{
+ switch(size)
+ {
+ case 0: { uint8 result = regB(R) | loadB(mem);
+ storeB(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80);
+ parityB(result);
+ cycles = 6;
+ break; }
+
+ case 1: { uint16 result = regW(R) | loadW(mem);
+ storeW(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x8000);
+ parityW(result);
+ cycles = 6;
+ break; }
+
+ case 2: { uint32 result = regL(R) | loadL(mem);
+ storeL(mem, result);
+ SETFLAG_Z(result == 0);
+ SETFLAG_S(result & 0x80000000);
+ cycles = 10;
+ break; }
+ }
+
+ SETFLAG_H0;
+ SETFLAG_N0;
+ SETFLAG_C0;
+}
+
+//===== CP R,(mem)
+void srcCPRm()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(regB(R), loadB(mem)); cycles = 4; break;
+ case 1: generic_SUB_W(regW(R), loadW(mem)); cycles = 4; break;
+ case 2: generic_SUB_L(regL(R), loadL(mem)); cycles = 6; break;
+ }
+}
+
+//===== CP (mem),R
+void srcCPmR()
+{
+ switch(size)
+ {
+ case 0: generic_SUB_B(loadB(mem), regB(R)); break;
+ case 1: generic_SUB_W(loadW(mem), regW(R)); break;
+ case 2: generic_SUB_L(loadL(mem), regL(R)); break;
+ }
+
+ cycles = 6;
+}
+};
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.h b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.h
new file mode 100644
index 0000000000..a89e775df8
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.h
@@ -0,0 +1,200 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_interpret_src.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_SRC__
+#define __TLCS900H_SRC__
+//=========================================================================
+namespace TLCS900H
+{
+
+
+//===== PUSH (mem)
+void srcPUSH(void);
+
+//===== RLD A,(mem)
+void srcRLD(void);
+
+//===== RRD A,(mem)
+void srcRRD(void);
+
+//===== LDI
+void srcLDI(void);
+
+//===== LDIR
+void srcLDIR(void);
+
+//===== LDD
+void srcLDD(void);
+
+//===== LDDR
+void srcLDDR(void);
+
+//===== CPI
+void srcCPI(void);
+
+//===== CPIR
+void srcCPIR(void);
+
+//===== CPD
+void srcCPD(void);
+
+//===== CPDR
+void srcCPDR(void);
+
+//===== LD (nn),(mem)
+void srcLD16m(void);
+
+//===== LD R,(mem)
+void srcLD(void);
+
+//===== EX (mem),R
+void srcEX(void);
+
+//===== ADD (mem),#
+void srcADDi(void);
+
+//===== ADC (mem),#
+void srcADCi(void);
+
+//===== SUB (mem),#
+void srcSUBi(void);
+
+//===== SBC (mem),#
+void srcSBCi(void);
+
+//===== AND (mem),#
+void srcANDi(void);
+
+//===== OR (mem),#
+void srcORi(void);
+
+//===== XOR (mem),#
+void srcXORi(void);
+
+//===== CP (mem),#
+void srcCPi(void);
+
+//===== MUL RR,(mem)
+void srcMUL(void);
+
+//===== MULS RR,(mem)
+void srcMULS(void);
+
+//===== DIV RR,(mem)
+void srcDIV(void);
+
+//===== DIVS RR,(mem)
+void srcDIVS(void);
+
+//===== INC #3,(mem)
+void srcINC(void);
+
+//===== DEC #3,(mem)
+void srcDEC(void);
+
+//===== RLC (mem)
+void srcRLC(void);
+
+//===== RRC (mem)
+void srcRRC(void);
+
+//===== RL (mem)
+void srcRL(void);
+
+//===== RR (mem)
+void srcRR(void);
+
+//===== SLA (mem)
+void srcSLA(void);
+
+//===== SRA (mem)
+void srcSRA(void);
+
+//===== SLL (mem)
+void srcSLL(void);
+
+//===== SRL (mem)
+void srcSRL(void);
+
+//===== ADD R,(mem)
+void srcADDRm(void);
+
+//===== ADD (mem),R
+void srcADDmR(void);
+
+//===== ADC R,(mem)
+void srcADCRm(void);
+
+//===== ADC (mem),R
+void srcADCmR(void);
+
+//===== SUB R,(mem)
+void srcSUBRm(void);
+
+//===== SUB (mem),R
+void srcSUBmR(void);
+
+//===== SBC R,(mem)
+void srcSBCRm(void);
+
+//===== SBC (mem),R
+void srcSBCmR(void);
+
+//===== AND R,(mem)
+void srcANDRm(void);
+
+//===== AND (mem),R
+void srcANDmR(void);
+
+//===== XOR R,(mem)
+void srcXORRm(void);
+
+//===== XOR (mem),R
+void srcXORmR(void);
+
+//===== OR R,(mem)
+void srcORRm(void);
+
+//===== OR (mem),R
+void srcORmR(void);
+
+//===== CP R,(mem)
+void srcCPRm(void);
+
+//===== CP (mem),R
+void srcCPmR(void);
+
+};
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers.cpp b/waterbox/ngp/TLCS-900h/TLCS900h_registers.cpp
new file mode 100644
index 0000000000..d17e4a2a31
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers.cpp
@@ -0,0 +1,208 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+10 AUG 2002 - neopop_uk
+=======================================
+- Moved default PC setup to the 'reset_registers' function.
+
+//---------------------------------------------------------------------------
+*/
+
+#include "../neopop.h"
+#include "../interrupt.h"
+#include "TLCS900h_registers.h"
+
+namespace TLCS900H
+{
+
+#ifdef MSB_FIRST
+#define BYTE0 3
+#define BYTE1 2
+#define BYTE2 1
+#define BYTE3 0
+#define WORD0 2
+#define WORD1 0
+#else
+#define BYTE0 0
+#define BYTE1 1
+#define BYTE2 2
+#define BYTE3 3
+#define WORD0 0
+#define WORD1 2
+#endif
+
+//=============================================================================
+
+uint32 pc, gprBank[4][4], gpr[4];
+uint16 sr;
+uint8 f_dash;
+
+//=============================================================================
+
+//Bank Data
+uint8* gprMapB[4][8] =
+{
+ #include "TLCS900h_registers_mapB.h"
+};
+
+uint16* gprMapW[4][8] =
+{
+ #include "TLCS900h_registers_mapW.h"
+};
+
+uint32* gprMapL[4][8] =
+{
+ #include "TLCS900h_registers_mapL.h"
+};
+
+//=============================================================================
+
+uint32 rErr;
+
+uint8* regCodeMapB[4][256] =
+{
+ {
+ #include "TLCS900h_registers_mapCodeB0.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeB1.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeB2.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeB3.h"
+ }
+};
+
+uint16* regCodeMapW[4][128] =
+{
+ {
+ #include "TLCS900h_registers_mapCodeW0.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeW1.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeW2.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeW3.h"
+ }
+};
+
+uint32* regCodeMapL[4][64] =
+{
+ {
+ #include "TLCS900h_registers_mapCodeL0.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeL1.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeL2.h"
+ },
+
+ {
+ #include "TLCS900h_registers_mapCodeL3.h"
+ }
+};
+
+//=============================================================================
+
+uint8 statusIFF(void)
+{
+ uint8 iff = (sr & 0x7000) >> 12;
+
+ if (iff == 1)
+ return 0;
+ else
+ return iff;
+}
+
+void setStatusIFF(uint8 iff)
+{
+ sr = (sr & 0x8FFF) | ((iff & 0x7) << 12);
+}
+
+//=============================================================================
+
+uint8 statusRFP;
+
+void setStatusRFP(uint8 rfp)
+{
+ sr = (sr & 0xF8FF) | ((rfp & 0x3) << 8);
+ changedSP();
+}
+
+void changedSP(void)
+{
+ //Store global RFP for optimisation.
+ statusRFP = ((sr & 0x300) >> 8);
+ int_check_pending();
+}
+
+//=============================================================================
+
+void reset_registers(void)
+{
+ memset(gprBank, 0, sizeof(gprBank));
+ memset(gpr, 0, sizeof(gpr));
+
+ if (ngpc_rom.data)
+ pc = MDFN_de32lsb(rom_header->startPC) & 0xFFFFFF;
+ else
+ pc = 0xFFFFFE;
+
+ sr = 0xF800; // = %11111000???????? (?) are undefined in the manual)
+ changedSP();
+
+ f_dash = 00;
+
+ rErr = RERR_VALUE;
+
+ gpr[0] = 0xff23c3;
+ gpr[1] = 0xff23df;
+ gpr[2] = 0x006480;
+ REGXSP = 0x00006C00; //Confirmed from BIOS,
+ //immediately changes value from default of 0x100
+}
+
+};
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers.h
new file mode 100644
index 0000000000..b343cf8f43
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers.h
@@ -0,0 +1,126 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+21 AUG 2002 - neopop_uk
+=======================================
+- Fixed potential precidence problems in regX and rCodeX by using ()'s
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __TLCS900H_REGISTERS__
+#define __TLCS900H_REGISTERS__
+//=============================================================================
+
+namespace TLCS900H
+{
+
+void reset_registers(void);
+void dump_registers_TLCS900h(void);
+
+//The value read by bad rCodes, leave 0, improves "Gals Fighters"
+#define RERR_VALUE 0
+
+//=============================================================================
+
+extern uint32 pc;
+extern uint16 sr;
+extern uint8 f_dash;
+
+extern uint32 gprBank[4][4], gpr[4];
+
+extern uint32 rErr;
+
+extern uint8 statusRFP;
+
+//GPR Access
+extern uint8* gprMapB[4][8];
+extern uint16* gprMapW[4][8];
+extern uint32* gprMapL[4][8];
+
+#define regB(x) (*(gprMapB[statusRFP][(x)]))
+#define regW(x) (*(gprMapW[statusRFP][(x)]))
+#define regL(x) (*(gprMapL[statusRFP][(x)]))
+
+//Reg.Code Access
+extern uint8* regCodeMapB[4][256];
+extern uint16* regCodeMapW[4][128];
+extern uint32* regCodeMapL[4][64];
+
+#define rCodeB(r) (*(regCodeMapB[statusRFP][(r)]))
+#define rCodeW(r) (*(regCodeMapW[statusRFP][(r) >> 1]))
+#define rCodeL(r) (*(regCodeMapL[statusRFP][(r) >> 2]))
+
+//Common Registers
+#define REGA (regB(1))
+#define REGWA (regW(0))
+#define REGBC (regW(1))
+#define REGXSP (gpr[3])
+
+//=============================================================================
+
+uint8 statusIFF(void);
+void setStatusIFF(uint8 iff);
+
+void setStatusRFP(uint8 rfp);
+void changedSP(void);
+
+#define FLAG_S ((sr & 0x0080) >> 7)
+#define FLAG_Z ((sr & 0x0040) >> 6)
+#define FLAG_H ((sr & 0x0010) >> 4)
+#define FLAG_V ((sr & 0x0004) >> 2)
+#define FLAG_N ((sr & 0x0002) >> 1)
+#define FLAG_C (sr & 1)
+
+#define SETFLAG_S(s) { uint16 sr1 = sr & 0xFF7F; if (s) sr1 |= 0x0080; sr = sr1; }
+#define SETFLAG_Z(z) { uint16 sr1 = sr & 0xFFBF; if (z) sr1 |= 0x0040; sr = sr1; }
+#define SETFLAG_H(h) { uint16 sr1 = sr & 0xFFEF; if (h) sr1 |= 0x0010; sr = sr1; }
+#define SETFLAG_V(v) { uint16 sr1 = sr & 0xFFFB; if (v) sr1 |= 0x0004; sr = sr1; }
+#define SETFLAG_N(n) { uint16 sr1 = sr & 0xFFFD; if (n) sr1 |= 0x0002; sr = sr1; }
+#define SETFLAG_C(c) { uint16 sr1 = sr & 0xFFFE; if (c) sr1 |= 0x0001; sr = sr1; }
+
+#define SETFLAG_S0 { sr &= 0xFF7F; }
+#define SETFLAG_Z0 { sr &= 0xFFBF; }
+#define SETFLAG_H0 { sr &= 0xFFEF; }
+#define SETFLAG_V0 { sr &= 0xFFFB; }
+#define SETFLAG_N0 { sr &= 0xFFFD; }
+#define SETFLAG_C0 { sr &= 0xFFFE; }
+
+#define SETFLAG_S1 { sr |= 0x0080; }
+#define SETFLAG_Z1 { sr |= 0x0040; }
+#define SETFLAG_H1 { sr |= 0x0010; }
+#define SETFLAG_V1 { sr |= 0x0004; }
+#define SETFLAG_N1 { sr |= 0x0002; }
+#define SETFLAG_C1 { sr |= 0x0001; }
+
+};
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapB.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapB.h
new file mode 100644
index 0000000000..f6688f88bd
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapB.h
@@ -0,0 +1,83 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapB.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //Bank 0
+ {
+ (uint8*)&(gprBank[0][0]) + BYTE1,
+ (uint8*)&(gprBank[0][0]) + BYTE0,
+ (uint8*)&(gprBank[0][1]) + BYTE1,
+ (uint8*)&(gprBank[0][1]) + BYTE0,
+ (uint8*)&(gprBank[0][2]) + BYTE1,
+ (uint8*)&(gprBank[0][2]) + BYTE0,
+ (uint8*)&(gprBank[0][3]) + BYTE1,
+ (uint8*)&(gprBank[0][3]) + BYTE0,
+ },
+
+ //Bank 1
+ {
+ (uint8*)&(gprBank[1][0]) + BYTE1,
+ (uint8*)&(gprBank[1][0]) + BYTE0,
+ (uint8*)&(gprBank[1][1]) + BYTE1,
+ (uint8*)&(gprBank[1][1]) + BYTE0,
+ (uint8*)&(gprBank[1][2]) + BYTE1,
+ (uint8*)&(gprBank[1][2]) + BYTE0,
+ (uint8*)&(gprBank[1][3]) + BYTE1,
+ (uint8*)&(gprBank[1][3]) + BYTE0,
+ },
+
+ //Bank 2
+ {
+ (uint8*)&(gprBank[2][0]) + BYTE1,
+ (uint8*)&(gprBank[2][0]) + BYTE0,
+ (uint8*)&(gprBank[2][1]) + BYTE1,
+ (uint8*)&(gprBank[2][1]) + BYTE0,
+ (uint8*)&(gprBank[2][2]) + BYTE1,
+ (uint8*)&(gprBank[2][2]) + BYTE0,
+ (uint8*)&(gprBank[2][3]) + BYTE1,
+ (uint8*)&(gprBank[2][3]) + BYTE0,
+ },
+
+ //Bank 3
+ {
+ (uint8*)&(gprBank[3][0]) + BYTE1,
+ (uint8*)&(gprBank[3][0]) + BYTE0,
+ (uint8*)&(gprBank[3][1]) + BYTE1,
+ (uint8*)&(gprBank[3][1]) + BYTE0,
+ (uint8*)&(gprBank[3][2]) + BYTE1,
+ (uint8*)&(gprBank[3][2]) + BYTE0,
+ (uint8*)&(gprBank[3][3]) + BYTE1,
+ (uint8*)&(gprBank[3][3]) + BYTE0,
+ }
+
+//=============================================================================
+
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB0.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB0.h
new file mode 100644
index 0000000000..8b76446da5
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB0.h
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeB0.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1, //BANK 0
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1, //BANK 1
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1, //BANK 2
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ ((uint8*)&gprBank[3][0]) + BYTE0,((uint8*)&gprBank[3][0]) + BYTE1, //BANK 3
+ ((uint8*)&gprBank[3][0]) + BYTE2, ((uint8*)&gprBank[3][0]) + BYTE3,
+ ((uint8*)&gprBank[3][1]) + BYTE0,((uint8*)&gprBank[3][1]) + BYTE1,
+ ((uint8*)&gprBank[3][1]) + BYTE2, ((uint8*)&gprBank[3][1]) + BYTE3,
+ ((uint8*)&gprBank[3][2]) + BYTE0,((uint8*)&gprBank[3][2]) + BYTE1,
+ ((uint8*)&gprBank[3][2]) + BYTE2, ((uint8*)&gprBank[3][2]) + BYTE3,
+ ((uint8*)&gprBank[3][3]) + BYTE0,((uint8*)&gprBank[3][3]) + BYTE1,
+ ((uint8*)&gprBank[3][3]) + BYTE2, ((uint8*)&gprBank[3][3]) + BYTE3,
+
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+
+ //Previous Bank
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,
+
+ //Current Bank
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1,
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ ((uint8*)&gpr[0]) + BYTE0, ((uint8*)&gpr[0]) + BYTE1,
+ ((uint8*)&gpr[0]) + BYTE2, ((uint8*)&gpr[0]) + BYTE3,
+ ((uint8*)&gpr[1]) + BYTE0, ((uint8*)&gpr[1]) + BYTE1,
+ ((uint8*)&gpr[1]) + BYTE2, ((uint8*)&gpr[1]) + BYTE3,
+ ((uint8*)&gpr[2]) + BYTE0, ((uint8*)&gpr[2]) + BYTE1,
+ ((uint8*)&gpr[2]) + BYTE2, ((uint8*)&gpr[2]) + BYTE3,
+ ((uint8*)&gpr[3]) + BYTE0, ((uint8*)&gpr[3]) + BYTE1,
+ ((uint8*)&gpr[3]) + BYTE2, ((uint8*)&gpr[3]) + BYTE3
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB1.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB1.h
new file mode 100644
index 0000000000..d9f7868bf5
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB1.h
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeB1.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1, //BANK 0
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1, //BANK 1
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1, //BANK 2
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ ((uint8*)&gprBank[3][0]) + BYTE0,((uint8*)&gprBank[3][0]) + BYTE1, //BANK 3
+ ((uint8*)&gprBank[3][0]) + BYTE2, ((uint8*)&gprBank[3][0]) + BYTE3,
+ ((uint8*)&gprBank[3][1]) + BYTE0,((uint8*)&gprBank[3][1]) + BYTE1,
+ ((uint8*)&gprBank[3][1]) + BYTE2, ((uint8*)&gprBank[3][1]) + BYTE3,
+ ((uint8*)&gprBank[3][2]) + BYTE0,((uint8*)&gprBank[3][2]) + BYTE1,
+ ((uint8*)&gprBank[3][2]) + BYTE2, ((uint8*)&gprBank[3][2]) + BYTE3,
+ ((uint8*)&gprBank[3][3]) + BYTE0,((uint8*)&gprBank[3][3]) + BYTE1,
+ ((uint8*)&gprBank[3][3]) + BYTE2, ((uint8*)&gprBank[3][3]) + BYTE3,
+
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+
+ //Previous Bank
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1,
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ //Current Bank
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1,
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ ((uint8*)&gpr[0]) + BYTE0, ((uint8*)&gpr[0]) + BYTE1,
+ ((uint8*)&gpr[0]) + BYTE2, ((uint8*)&gpr[0]) + BYTE3,
+ ((uint8*)&gpr[1]) + BYTE0, ((uint8*)&gpr[1]) + BYTE1,
+ ((uint8*)&gpr[1]) + BYTE2, ((uint8*)&gpr[1]) + BYTE3,
+ ((uint8*)&gpr[2]) + BYTE0, ((uint8*)&gpr[2]) + BYTE1,
+ ((uint8*)&gpr[2]) + BYTE2, ((uint8*)&gpr[2]) + BYTE3,
+ ((uint8*)&gpr[3]) + BYTE0, ((uint8*)&gpr[3]) + BYTE1,
+ ((uint8*)&gpr[3]) + BYTE2, ((uint8*)&gpr[3]) + BYTE3
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB2.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB2.h
new file mode 100644
index 0000000000..036604be22
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB2.h
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeB2.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1, //BANK 0
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1, //BANK 1
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1, //BANK 2
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ ((uint8*)&gprBank[3][0]) + BYTE0,((uint8*)&gprBank[3][0]) + BYTE1, //BANK 3
+ ((uint8*)&gprBank[3][0]) + BYTE2, ((uint8*)&gprBank[3][0]) + BYTE3,
+ ((uint8*)&gprBank[3][1]) + BYTE0,((uint8*)&gprBank[3][1]) + BYTE1,
+ ((uint8*)&gprBank[3][1]) + BYTE2, ((uint8*)&gprBank[3][1]) + BYTE3,
+ ((uint8*)&gprBank[3][2]) + BYTE0,((uint8*)&gprBank[3][2]) + BYTE1,
+ ((uint8*)&gprBank[3][2]) + BYTE2, ((uint8*)&gprBank[3][2]) + BYTE3,
+ ((uint8*)&gprBank[3][3]) + BYTE0,((uint8*)&gprBank[3][3]) + BYTE1,
+ ((uint8*)&gprBank[3][3]) + BYTE2, ((uint8*)&gprBank[3][3]) + BYTE3,
+
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+
+ //Previous Bank
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1,
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ //Current Bank
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1,
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ ((uint8*)&gpr[0]) + BYTE0, ((uint8*)&gpr[0]) + BYTE1,
+ ((uint8*)&gpr[0]) + BYTE2, ((uint8*)&gpr[0]) + BYTE3,
+ ((uint8*)&gpr[1]) + BYTE0, ((uint8*)&gpr[1]) + BYTE1,
+ ((uint8*)&gpr[1]) + BYTE2, ((uint8*)&gpr[1]) + BYTE3,
+ ((uint8*)&gpr[2]) + BYTE0, ((uint8*)&gpr[2]) + BYTE1,
+ ((uint8*)&gpr[2]) + BYTE2, ((uint8*)&gpr[2]) + BYTE3,
+ ((uint8*)&gpr[3]) + BYTE0, ((uint8*)&gpr[3]) + BYTE1,
+ ((uint8*)&gpr[3]) + BYTE2, ((uint8*)&gpr[3]) + BYTE3
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB3.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB3.h
new file mode 100644
index 0000000000..b3e1fd77fb
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB3.h
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeB3.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ ((uint8*)&gprBank[0][0]) + BYTE0,((uint8*)&gprBank[0][0]) + BYTE1, //BANK 0
+ ((uint8*)&gprBank[0][0]) + BYTE2, ((uint8*)&gprBank[0][0]) + BYTE3,
+ ((uint8*)&gprBank[0][1]) + BYTE0,((uint8*)&gprBank[0][1]) + BYTE1,
+ ((uint8*)&gprBank[0][1]) + BYTE2, ((uint8*)&gprBank[0][1]) + BYTE3,
+ ((uint8*)&gprBank[0][2]) + BYTE0,((uint8*)&gprBank[0][2]) + BYTE1,
+ ((uint8*)&gprBank[0][2]) + BYTE2, ((uint8*)&gprBank[0][2]) + BYTE3,
+ ((uint8*)&gprBank[0][3]) + BYTE0,((uint8*)&gprBank[0][3]) + BYTE1,
+ ((uint8*)&gprBank[0][3]) + BYTE2, ((uint8*)&gprBank[0][3]) + BYTE3,
+
+ ((uint8*)&gprBank[1][0]) + BYTE0,((uint8*)&gprBank[1][0]) + BYTE1, //BANK 1
+ ((uint8*)&gprBank[1][0]) + BYTE2, ((uint8*)&gprBank[1][0]) + BYTE3,
+ ((uint8*)&gprBank[1][1]) + BYTE0,((uint8*)&gprBank[1][1]) + BYTE1,
+ ((uint8*)&gprBank[1][1]) + BYTE2, ((uint8*)&gprBank[1][1]) + BYTE3,
+ ((uint8*)&gprBank[1][2]) + BYTE0,((uint8*)&gprBank[1][2]) + BYTE1,
+ ((uint8*)&gprBank[1][2]) + BYTE2, ((uint8*)&gprBank[1][2]) + BYTE3,
+ ((uint8*)&gprBank[1][3]) + BYTE0,((uint8*)&gprBank[1][3]) + BYTE1,
+ ((uint8*)&gprBank[1][3]) + BYTE2, ((uint8*)&gprBank[1][3]) + BYTE3,
+
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1, //BANK 2
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ ((uint8*)&gprBank[3][0]) + BYTE0,((uint8*)&gprBank[3][0]) + BYTE1, //BANK 3
+ ((uint8*)&gprBank[3][0]) + BYTE2, ((uint8*)&gprBank[3][0]) + BYTE3,
+ ((uint8*)&gprBank[3][1]) + BYTE0,((uint8*)&gprBank[3][1]) + BYTE1,
+ ((uint8*)&gprBank[3][1]) + BYTE2, ((uint8*)&gprBank[3][1]) + BYTE3,
+ ((uint8*)&gprBank[3][2]) + BYTE0,((uint8*)&gprBank[3][2]) + BYTE1,
+ ((uint8*)&gprBank[3][2]) + BYTE2, ((uint8*)&gprBank[3][2]) + BYTE3,
+ ((uint8*)&gprBank[3][3]) + BYTE0,((uint8*)&gprBank[3][3]) + BYTE1,
+ ((uint8*)&gprBank[3][3]) + BYTE2, ((uint8*)&gprBank[3][3]) + BYTE3,
+
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+ (uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,(uint8*)&rErr,
+
+ //Previous Bank
+ ((uint8*)&gprBank[2][0]) + BYTE0,((uint8*)&gprBank[2][0]) + BYTE1,
+ ((uint8*)&gprBank[2][0]) + BYTE2, ((uint8*)&gprBank[2][0]) + BYTE3,
+ ((uint8*)&gprBank[2][1]) + BYTE0,((uint8*)&gprBank[2][1]) + BYTE1,
+ ((uint8*)&gprBank[2][1]) + BYTE2, ((uint8*)&gprBank[2][1]) + BYTE3,
+ ((uint8*)&gprBank[2][2]) + BYTE0,((uint8*)&gprBank[2][2]) + BYTE1,
+ ((uint8*)&gprBank[2][2]) + BYTE2, ((uint8*)&gprBank[2][2]) + BYTE3,
+ ((uint8*)&gprBank[2][3]) + BYTE0,((uint8*)&gprBank[2][3]) + BYTE1,
+ ((uint8*)&gprBank[2][3]) + BYTE2, ((uint8*)&gprBank[2][3]) + BYTE3,
+
+ //Current Bank
+ ((uint8*)&gprBank[3][0]) + BYTE0,((uint8*)&gprBank[3][0]) + BYTE1,
+ ((uint8*)&gprBank[3][0]) + BYTE2, ((uint8*)&gprBank[3][0]) + BYTE3,
+ ((uint8*)&gprBank[3][1]) + BYTE0,((uint8*)&gprBank[3][1]) + BYTE1,
+ ((uint8*)&gprBank[3][1]) + BYTE2, ((uint8*)&gprBank[3][1]) + BYTE3,
+ ((uint8*)&gprBank[3][2]) + BYTE0,((uint8*)&gprBank[3][2]) + BYTE1,
+ ((uint8*)&gprBank[3][2]) + BYTE2, ((uint8*)&gprBank[3][2]) + BYTE3,
+ ((uint8*)&gprBank[3][3]) + BYTE0,((uint8*)&gprBank[3][3]) + BYTE1,
+ ((uint8*)&gprBank[3][3]) + BYTE2, ((uint8*)&gprBank[3][3]) + BYTE3,
+
+ ((uint8*)&gpr[0]) + BYTE0, ((uint8*)&gpr[0]) + BYTE1,
+ ((uint8*)&gpr[0]) + BYTE2, ((uint8*)&gpr[0]) + BYTE3,
+ ((uint8*)&gpr[1]) + BYTE0, ((uint8*)&gpr[1]) + BYTE1,
+ ((uint8*)&gpr[1]) + BYTE2, ((uint8*)&gpr[1]) + BYTE3,
+ ((uint8*)&gpr[2]) + BYTE0, ((uint8*)&gpr[2]) + BYTE1,
+ ((uint8*)&gpr[2]) + BYTE2, ((uint8*)&gpr[2]) + BYTE3,
+ ((uint8*)&gpr[3]) + BYTE0, ((uint8*)&gpr[3]) + BYTE1,
+ ((uint8*)&gpr[3]) + BYTE2, ((uint8*)&gpr[3]) + BYTE3
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL0.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL0.h
new file mode 100644
index 0000000000..6897182d51
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL0.h
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeL0.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ //BANK 1
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ //BANK 2
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ //BANK 3
+ &(gprBank[3][0]), &(gprBank[3][1]), &(gprBank[3][2]), &(gprBank[3][3]),
+
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,
+
+ //Previous Bank
+ &rErr,&rErr,&rErr,&rErr,
+
+ //Current Bank
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ &(gpr[0]), &(gpr[1]), &(gpr[2]), &(gpr[3])
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL1.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL1.h
new file mode 100644
index 0000000000..6099806d63
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL1.h
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeL1.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ //BANK 1
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ //BANK 2
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ //BANK 3
+ &(gprBank[3][0]), &(gprBank[3][1]), &(gprBank[3][2]), &(gprBank[3][3]),
+
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,
+
+ //Previous Bank
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ //Current Bank
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ &(gpr[0]), &(gpr[1]), &(gpr[2]), &(gpr[3])
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL2.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL2.h
new file mode 100644
index 0000000000..57492049bf
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL2.h
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeL2.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ //BANK 1
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ //BANK 2
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ //BANK 3
+ &(gprBank[3][0]), &(gprBank[3][1]), &(gprBank[3][2]), &(gprBank[3][3]),
+
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,
+
+ //Previous Bank
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ //Current Bank
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ &(gpr[0]), &(gpr[1]), &(gpr[2]), &(gpr[3])
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL3.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL3.h
new file mode 100644
index 0000000000..aa597cadba
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL3.h
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeL3.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ &(gprBank[0][0]), &(gprBank[0][1]), &(gprBank[0][2]), &(gprBank[0][3]),
+
+ //BANK 1
+ &(gprBank[1][0]), &(gprBank[1][1]), &(gprBank[1][2]), &(gprBank[1][3]),
+
+ //BANK 2
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ //BANK 3
+ &(gprBank[3][0]), &(gprBank[3][1]), &(gprBank[3][2]), &(gprBank[3][3]),
+
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,&rErr,
+ &rErr,&rErr,&rErr,&rErr,
+
+ //Previous Bank
+ &(gprBank[2][0]), &(gprBank[2][1]), &(gprBank[2][2]), &(gprBank[2][3]),
+
+ //Current Bank
+ &(gprBank[3][0]), &(gprBank[3][1]), &(gprBank[3][2]), &(gprBank[3][3]),
+
+ &(gpr[0]), &(gpr[1]), &(gpr[2]), &(gpr[3])
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW0.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW0.h
new file mode 100644
index 0000000000..ba9fb6954d
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW0.h
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeW0.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ //BANK 1
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ //BANK 2
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ //BANK 3
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0), (uint16*)(((uint8*)&gprBank[3][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0), (uint16*)(((uint8*)&gprBank[3][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0), (uint16*)(((uint8*)&gprBank[3][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0), (uint16*)(((uint8*)&gprBank[3][3]) + WORD1),
+
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+
+ //Previous Bank
+ (uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,
+
+ //Current Bank
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ (uint16*)((uint8*)&(gpr[0]) + WORD0), (uint16*)((uint8*)&(gpr[0]) + WORD1),
+ (uint16*)((uint8*)&(gpr[1]) + WORD0), (uint16*)((uint8*)&(gpr[1]) + WORD1),
+ (uint16*)((uint8*)&(gpr[2]) + WORD0), (uint16*)((uint8*)&(gpr[2]) + WORD1),
+ (uint16*)((uint8*)&(gpr[3]) + WORD0), (uint16*)((uint8*)&(gpr[3]) + WORD1),
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW1.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW1.h
new file mode 100644
index 0000000000..fa7f93f1d9
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW1.h
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeW1.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ //BANK 1
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ //BANK 2
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ //BANK 3
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0), (uint16*)(((uint8*)&gprBank[3][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0), (uint16*)(((uint8*)&gprBank[3][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0), (uint16*)(((uint8*)&gprBank[3][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0), (uint16*)(((uint8*)&gprBank[3][3]) + WORD1),
+
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+
+ //Previous Bank
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ //Current Bank
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ (uint16*)((uint8*)&(gpr[0]) + WORD0), (uint16*)((uint8*)&(gpr[0]) + WORD1),
+ (uint16*)((uint8*)&(gpr[1]) + WORD0), (uint16*)((uint8*)&(gpr[1]) + WORD1),
+ (uint16*)((uint8*)&(gpr[2]) + WORD0), (uint16*)((uint8*)&(gpr[2]) + WORD1),
+ (uint16*)((uint8*)&(gpr[3]) + WORD0), (uint16*)((uint8*)&(gpr[3]) + WORD1),
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW2.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW2.h
new file mode 100644
index 0000000000..805c605598
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW2.h
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeW2.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ //BANK 1
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ //BANK 2
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ //BANK 3
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0), (uint16*)(((uint8*)&gprBank[3][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0), (uint16*)(((uint8*)&gprBank[3][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0), (uint16*)(((uint8*)&gprBank[3][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0), (uint16*)(((uint8*)&gprBank[3][3]) + WORD1),
+
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+
+ //Previous Bank
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ //Current Bank
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ (uint16*)((uint8*)&(gpr[0]) + WORD0), (uint16*)((uint8*)&(gpr[0]) + WORD1),
+ (uint16*)((uint8*)&(gpr[1]) + WORD0), (uint16*)((uint8*)&(gpr[1]) + WORD1),
+ (uint16*)((uint8*)&(gpr[2]) + WORD0), (uint16*)((uint8*)&(gpr[2]) + WORD1),
+ (uint16*)((uint8*)&(gpr[3]) + WORD0), (uint16*)((uint8*)&(gpr[3]) + WORD1),
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW3.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW3.h
new file mode 100644
index 0000000000..a1f431766e
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW3.h
@@ -0,0 +1,94 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapCodeW3.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //BANK 0
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0), (uint16*)(((uint8*)&gprBank[0][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0), (uint16*)(((uint8*)&gprBank[0][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0), (uint16*)(((uint8*)&gprBank[0][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0), (uint16*)(((uint8*)&gprBank[0][3]) + WORD1),
+
+ //BANK 1
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0), (uint16*)(((uint8*)&gprBank[1][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0), (uint16*)(((uint8*)&gprBank[1][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0), (uint16*)(((uint8*)&gprBank[1][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0), (uint16*)(((uint8*)&gprBank[1][3]) + WORD1),
+
+ //BANK 2
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ //BANK 3
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0), (uint16*)(((uint8*)&gprBank[3][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0), (uint16*)(((uint8*)&gprBank[3][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0), (uint16*)(((uint8*)&gprBank[3][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0), (uint16*)(((uint8*)&gprBank[3][3]) + WORD1),
+
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+ (uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,(uint16*)&rErr,
+
+ //Previous Bank
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0), (uint16*)(((uint8*)&gprBank[2][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0), (uint16*)(((uint8*)&gprBank[2][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0), (uint16*)(((uint8*)&gprBank[2][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0), (uint16*)(((uint8*)&gprBank[2][3]) + WORD1),
+
+ //Current Bank
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0), (uint16*)(((uint8*)&gprBank[3][0]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0), (uint16*)(((uint8*)&gprBank[3][1]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0), (uint16*)(((uint8*)&gprBank[3][2]) + WORD1),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0), (uint16*)(((uint8*)&gprBank[3][3]) + WORD1),
+
+ (uint16*)((uint8*)&(gpr[0]) + WORD0), (uint16*)((uint8*)&(gpr[0]) + WORD1),
+ (uint16*)((uint8*)&(gpr[1]) + WORD0), (uint16*)((uint8*)&(gpr[1]) + WORD1),
+ (uint16*)((uint8*)&(gpr[2]) + WORD0), (uint16*)((uint8*)&(gpr[2]) + WORD1),
+ (uint16*)((uint8*)&(gpr[3]) + WORD0), (uint16*)((uint8*)&(gpr[3]) + WORD1),
+
+//=============================================================================
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapL.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapL.h
new file mode 100644
index 0000000000..102a9f0436
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapL.h
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapL.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //Bank 0
+ {
+ (uint32*)&(gprBank[0][0]),
+ (uint32*)&(gprBank[0][1]),
+ (uint32*)&(gprBank[0][2]),
+ (uint32*)&(gprBank[0][3]),
+ (uint32*)&(gpr[0]),
+ (uint32*)&(gpr[1]),
+ (uint32*)&(gpr[2]),
+ (uint32*)&(gpr[3]),
+ },
+
+ //Bank 1
+ {
+ (uint32*)&(gprBank[1][0]),
+ (uint32*)&(gprBank[1][1]),
+ (uint32*)&(gprBank[1][2]),
+ (uint32*)&(gprBank[1][3]),
+ (uint32*)&(gpr[0]),
+ (uint32*)&(gpr[1]),
+ (uint32*)&(gpr[2]),
+ (uint32*)&(gpr[3]),
+ },
+
+ //Bank 2
+ {
+ (uint32*)&(gprBank[2][0]),
+ (uint32*)&(gprBank[2][1]),
+ (uint32*)&(gprBank[2][2]),
+ (uint32*)&(gprBank[2][3]),
+ (uint32*)&(gpr[0]),
+ (uint32*)&(gpr[1]),
+ (uint32*)&(gpr[2]),
+ (uint32*)&(gpr[3]),
+ },
+
+ //Bank 3
+ {
+ (uint32*)&(gprBank[3][0]),
+ (uint32*)&(gprBank[3][1]),
+ (uint32*)&(gprBank[3][2]),
+ (uint32*)&(gprBank[3][3]),
+ (uint32*)&(gpr[0]),
+ (uint32*)&(gpr[1]),
+ (uint32*)&(gpr[2]),
+ (uint32*)&(gpr[3]),
+ },
+
+//=============================================================================
+
+
diff --git a/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapW.h b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapW.h
new file mode 100644
index 0000000000..0cd86877d5
--- /dev/null
+++ b/waterbox/ngp/TLCS-900h/TLCS900h_registers_mapW.h
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ TLCS900h_registers_mapW.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+//---------------------------------------------------------------------------
+*/
+
+ //Bank 0
+ {
+ (uint16*)(((uint8*)&gprBank[0][0]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[0][1]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[0][2]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[0][3]) + WORD0),
+ (uint16*)(((uint8*)&gpr[0]) + WORD0),
+ (uint16*)(((uint8*)&gpr[1]) + WORD0),
+ (uint16*)(((uint8*)&gpr[2]) + WORD0),
+ (uint16*)(((uint8*)&gpr[3]) + WORD0),
+ },
+
+ //Bank 1
+ {
+ (uint16*)(((uint8*)&gprBank[1][0]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[1][1]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[1][2]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[1][3]) + WORD0),
+ (uint16*)(((uint8*)&gpr[0]) + WORD0),
+ (uint16*)(((uint8*)&gpr[1]) + WORD0),
+ (uint16*)(((uint8*)&gpr[2]) + WORD0),
+ (uint16*)(((uint8*)&gpr[3]) + WORD0),
+ },
+
+ //Bank 2
+ {
+ (uint16*)(((uint8*)&gprBank[2][0]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[2][1]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[2][2]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[2][3]) + WORD0),
+ (uint16*)(((uint8*)&gpr[0]) + WORD0),
+ (uint16*)(((uint8*)&gpr[1]) + WORD0),
+ (uint16*)(((uint8*)&gpr[2]) + WORD0),
+ (uint16*)(((uint8*)&gpr[3]) + WORD0),
+ },
+
+ //Bank 3
+ {
+ (uint16*)(((uint8*)&gprBank[3][0]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[3][1]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[3][2]) + WORD0),
+ (uint16*)(((uint8*)&gprBank[3][3]) + WORD0),
+ (uint16*)(((uint8*)&gpr[0]) + WORD0),
+ (uint16*)(((uint8*)&gpr[1]) + WORD0),
+ (uint16*)(((uint8*)&gpr[2]) + WORD0),
+ (uint16*)(((uint8*)&gpr[3]) + WORD0),
+ },
+
+//=============================================================================
+
+
diff --git a/waterbox/ngp/Z80_interface.cpp b/waterbox/ngp/Z80_interface.cpp
new file mode 100644
index 0000000000..ef47a9f3e1
--- /dev/null
+++ b/waterbox/ngp/Z80_interface.cpp
@@ -0,0 +1,139 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "mem.h"
+#include "sound.h"
+#include "Z80_interface.h"
+#include "interrupt.h"
+#include "dma.h"
+
+namespace MDFN_IEN_NGP
+{
+
+static uint8 CommByte;
+static bool Z80Enabled;
+
+uint8 Z80_ReadComm(void)
+{
+ return (CommByte);
+}
+
+void Z80_WriteComm(uint8 data)
+{
+ CommByte = data;
+}
+
+static uint8 NGP_z80_readbyte(uint16 address)
+{
+ if (address <= 0xFFF)
+ return loadB(0x7000 + address);
+
+ if (address == 0x8000)
+ {
+ return CommByte;
+ }
+ return 0;
+}
+
+//=============================================================================
+
+static void NGP_z80_writebyte(uint16 address, uint8 value)
+{
+ if (address <= 0x0FFF)
+ {
+ storeB(0x7000 + address, value);
+ return;
+ }
+
+ if (address == 0x8000)
+ {
+ CommByte = value;
+ return;
+ }
+
+ if (address == 0x4001)
+ {
+ Write_SoundChipLeft(value);
+ return;
+ }
+ if (address == 0x4000)
+ {
+ Write_SoundChipRight(value);
+ return;
+ }
+
+ if (address == 0xC000)
+ {
+ TestIntHDMA(6, 0x0C);
+ }
+}
+
+//=============================================================================
+
+static void NGP_z80_writeport(uint16 port, uint8 value)
+{
+ //printf("Portout: %04x %02x\n", port, value);
+ z80_set_interrupt(0);
+}
+
+static uint8 NGP_z80_readport(uint16 port)
+{
+ //printf("Portin: %04x\n", port);
+ return 0;
+}
+
+void Z80_nmi(void)
+{
+ z80_nmi();
+}
+
+void Z80_irq(void)
+{
+ z80_set_interrupt(1);
+}
+
+void Z80_reset(void)
+{
+ Z80Enabled = 0;
+
+ z80_writebyte = NGP_z80_writebyte;
+ z80_readbyte = NGP_z80_readbyte;
+ z80_writeport = NGP_z80_writeport;
+ z80_readport = NGP_z80_readport;
+
+ z80_init();
+ z80_reset();
+}
+
+void Z80_SetEnable(bool set)
+{
+ Z80Enabled = set;
+ if (!set)
+ z80_reset();
+}
+
+bool Z80_IsEnabled(void)
+{
+ return (Z80Enabled);
+}
+
+int Z80_RunOP(void)
+{
+ if (!Z80Enabled)
+ return (-1);
+
+ return (z80_do_opcode());
+}
+}
diff --git a/waterbox/ngp/Z80_interface.h b/waterbox/ngp/Z80_interface.h
new file mode 100644
index 0000000000..e3cc8baa74
--- /dev/null
+++ b/waterbox/ngp/Z80_interface.h
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __Z80_CONTROL__
+#define __Z80_CONTROL__
+//=============================================================================
+
+#include "z80-fuse/z80.h"
+
+namespace MDFN_IEN_NGP
+{
+
+uint8 Z80_ReadComm(void);
+void Z80_WriteComm(uint8 data);
+
+void Z80_reset(void); // z80 reset
+
+void Z80_irq(void); // Cause an interrupt
+void Z80_nmi(void); // Cause an NMI
+void Z80_SetEnable(bool set);
+bool Z80_IsEnabled(void);
+int Z80_RunOP(void);
+
+}
+
+#endif
diff --git a/waterbox/ngp/bios.cpp b/waterbox/ngp/bios.cpp
new file mode 100644
index 0000000000..8a91c7f490
--- /dev/null
+++ b/waterbox/ngp/bios.cpp
@@ -0,0 +1,241 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "Z80_interface.h"
+#include "gfx.h"
+#include "mem.h"
+#include "interrupt.h"
+#include "sound.h"
+#include "dma.h"
+#include "bios.h"
+
+namespace MDFN_IEN_NGP
+{
+
+//=============================================================================
+
+uint8 ngpc_bios[0x10000]; //Holds bios program data
+
+//=============================================================================
+
+void reset(void)
+{
+ NGPGfx->power();
+ Z80_reset();
+ reset_int();
+ reset_timers();
+
+ reset_memory();
+ BIOSHLE_Reset();
+ reset_registers(); // TLCS900H registers
+ reset_dma();
+}
+
+//=============================================================================
+
+static const uint8 font[0x800] = {
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
+ 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
+ 0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x20,0x30,0x38,0x3C,0x38,0x30,0x20,0x00,0x04,0x0C,0x1C,0x3C,0x1C,0x0C,0x04,0x00,
+ 0x00,0x00,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x00,0x00,
+ 0x20,0x3C,0x08,0x3C,0x28,0x7E,0x08,0x00,0x3C,0x24,0x3C,0x24,0x3C,0x24,0x24,0x00,
+ 0x3C,0x24,0x24,0x3C,0x24,0x24,0x3C,0x00,0x10,0x10,0x54,0x54,0x10,0x28,0xC6,0x00,
+ 0x10,0x12,0xD4,0x58,0x54,0x92,0x10,0x00,0x10,0x10,0x7C,0x10,0x38,0x54,0x92,0x00,
+ 0x10,0x28,0x7C,0x92,0x38,0x54,0xFE,0x00,0x10,0x10,0x10,0x7C,0x10,0x10,0xFE,0x00,
+ 0x7F,0xFF,0xE0,0xFF,0x7F,0x01,0xFF,0xFF,0xDC,0xDE,0x1F,0x9F,0xDF,0xDD,0xDC,0x9C,
+ 0x3B,0x3B,0x3B,0xBB,0xFB,0xFB,0xFB,0x7B,0x8F,0x9E,0xBC,0xF8,0xF8,0xBC,0x9E,0x8F,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x08,0x10,0x00,0x18,0x00,
+ 0x6C,0x6C,0x24,0x48,0x00,0x00,0x00,0x00,0x14,0x14,0xFE,0x28,0xFE,0x50,0x50,0x00,
+ 0x10,0x7C,0x90,0x7C,0x12,0xFC,0x10,0x00,0x42,0xA4,0xA8,0x54,0x2A,0x4A,0x84,0x00,
+ 0x30,0x48,0x38,0x62,0x94,0x88,0x76,0x00,0x18,0x18,0x08,0x10,0x00,0x00,0x00,0x00,
+ 0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00,
+ 0x10,0x92,0x54,0x38,0x38,0x54,0x92,0x00,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x00,
+ 0x00,0x00,0x00,0x30,0x30,0x10,0x20,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,
+ 0x3C,0x42,0x46,0x5A,0x62,0x42,0x3C,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x00,
+ 0x3C,0x42,0x42,0x0C,0x30,0x40,0x7E,0x00,0x3C,0x42,0x02,0x1C,0x02,0x42,0x3C,0x00,
+ 0x0C,0x14,0x24,0x44,0x7E,0x04,0x04,0x00,0x7E,0x40,0x7C,0x02,0x02,0x42,0x3C,0x00,
+ 0x3C,0x40,0x7C,0x42,0x42,0x42,0x3C,0x00,0x7E,0x02,0x04,0x08,0x08,0x10,0x10,0x00,
+ 0x3C,0x42,0x42,0x3C,0x42,0x42,0x3C,0x00,0x3C,0x42,0x42,0x42,0x3E,0x02,0x3C,0x00,
+ 0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x08,0x10,0x00,
+ 0x00,0x08,0x10,0x20,0x10,0x08,0x00,0x00,0x00,0x00,0x3C,0x00,0x3C,0x00,0x00,0x00,
+ 0x00,0x10,0x08,0x04,0x08,0x10,0x00,0x00,0x3C,0x62,0x62,0x0C,0x18,0x00,0x18,0x00,
+ 0x7C,0x82,0xBA,0xA2,0xBA,0x82,0x7C,0x00,0x10,0x28,0x28,0x44,0x7C,0x82,0x82,0x00,
+ 0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00,
+ 0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x7E,0x40,0x40,0x7E,0x40,0x40,0x7E,0x00,
+ 0x7E,0x40,0x40,0x7C,0x40,0x40,0x40,0x00,0x3C,0x42,0x80,0x9E,0x82,0x46,0x3A,0x00,
+ 0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,
+ 0x02,0x02,0x02,0x02,0x42,0x42,0x3C,0x00,0x42,0x44,0x48,0x50,0x68,0x44,0x42,0x00,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x82,0xC6,0xAA,0x92,0x82,0x82,0x82,0x00,
+ 0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x00,0x38,0x44,0x82,0x82,0x82,0x44,0x38,0x00,
+ 0x7C,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x38,0x44,0x82,0x82,0x8A,0x44,0x3A,0x00,
+ 0x7C,0x42,0x42,0x7C,0x48,0x44,0x42,0x00,0x3C,0x42,0x40,0x3C,0x02,0x42,0x3C,0x00,
+ 0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,
+ 0x82,0x82,0x44,0x44,0x28,0x28,0x10,0x00,0x82,0x92,0x92,0xAA,0xAA,0x44,0x44,0x00,
+ 0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x00,0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x00,
+ 0x7E,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x18,0x10,0x10,0x10,0x10,0x10,0x18,0x00,
+ 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x18,0x00,
+ 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,
+ 0x08,0x10,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x78,0x04,0x7C,0x84,0x84,0x7E,0x00,
+ 0x40,0x40,0x7C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x3C,0x42,0x40,0x42,0x3C,0x00,
+ 0x02,0x02,0x3E,0x42,0x42,0x42,0x3C,0x00,0x00,0x00,0x3C,0x42,0x7E,0x40,0x3E,0x00,
+ 0x0C,0x10,0x3E,0x10,0x10,0x10,0x10,0x00,0x00,0x3C,0x42,0x42,0x3E,0x02,0x7C,0x00,
+ 0x40,0x40,0x7C,0x42,0x42,0x42,0x42,0x00,0x18,0x18,0x00,0x08,0x08,0x08,0x08,0x00,
+ 0x06,0x06,0x00,0x02,0x42,0x42,0x3C,0x00,0x20,0x20,0x26,0x28,0x30,0x28,0x26,0x00,
+ 0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x80,0xEC,0x92,0x92,0x92,0x92,0x00,
+ 0x00,0x40,0x78,0x44,0x44,0x44,0x44,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x00,
+ 0x00,0x3C,0x42,0x42,0x7C,0x40,0x40,0x00,0x00,0x78,0x84,0x84,0x7C,0x04,0x06,0x00,
+ 0x00,0x00,0x5C,0x62,0x40,0x40,0x40,0x00,0x00,0x00,0x3E,0x40,0x3C,0x02,0x7C,0x00,
+ 0x00,0x10,0x7C,0x10,0x10,0x10,0x0E,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x3F,0x00,
+ 0x00,0x00,0x42,0x42,0x24,0x24,0x18,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x6C,0x00,
+ 0x00,0x00,0x42,0x24,0x18,0x24,0x42,0x00,0x00,0x00,0x42,0x42,0x3E,0x02,0x7C,0x00,
+ 0x00,0x00,0x7E,0x02,0x3C,0x40,0x7E,0x00,0x08,0x10,0x10,0x20,0x10,0x10,0x08,0x00,
+ 0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x00,0x20,0x10,0x10,0x08,0x10,0x10,0x20,0x00,
+ 0x00,0x00,0x60,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00,
+ 0x1E,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xF0,0x00,
+ 0x00,0x00,0x00,0x80,0x40,0x60,0x60,0x00,0x00,0x00,0x00,0x30,0x78,0x30,0x00,0x00,
+ 0x20,0xF8,0x26,0x78,0xD0,0x80,0x7C,0x00,0x00,0x10,0x3A,0x1C,0x36,0x5A,0x36,0x00,
+ 0x00,0x00,0x44,0x42,0x42,0x42,0x30,0x00,0x00,0x3C,0x00,0x3C,0x42,0x02,0x3C,0x00,
+ 0x00,0x3C,0x00,0x7C,0x08,0x38,0x66,0x00,0x00,0x14,0x72,0x1C,0x32,0x52,0x34,0x00,
+ 0x00,0x28,0x2C,0x3A,0x62,0x16,0x10,0x00,0x00,0x08,0x5C,0x6A,0x4A,0x0C,0x18,0x00,
+ 0x00,0x08,0x0C,0x38,0x4C,0x4A,0x38,0x00,0x00,0x00,0x00,0x1C,0x62,0x02,0x1C,0x00,
+ 0x00,0x00,0x80,0x7E,0x00,0x00,0x00,0x00,0x28,0xF2,0x3C,0x6A,0xAA,0xB6,0xEC,0x00,
+ 0x80,0x88,0x84,0x84,0x82,0x92,0x70,0x00,0x78,0x00,0x3C,0xC2,0x02,0x04,0x78,0x00,
+ 0x78,0x00,0xFC,0x08,0x30,0x50,0x9E,0x00,0x2C,0xF2,0x20,0x7C,0xA2,0xA2,0xE4,0x00,
+ 0x28,0xF4,0x2A,0x4A,0x4A,0x88,0xB0,0x00,0x20,0xFC,0x12,0xFC,0x08,0xC2,0x7C,0x00,
+ 0x04,0x18,0x60,0x80,0xC0,0x30,0x0E,0x00,0x84,0xBE,0x84,0x84,0x84,0x84,0x58,0x00,
+ 0x00,0x7C,0x02,0x00,0x80,0x82,0x7E,0x00,0x20,0xFE,0x10,0x78,0x8C,0xC0,0x7C,0x00,
+ 0x80,0x80,0x80,0x80,0x82,0x84,0x78,0x00,0x04,0xFE,0x3C,0x44,0x7C,0x04,0x78,0x00,
+ 0x44,0x5E,0xF4,0x44,0x48,0x40,0x3E,0x00,0x44,0x58,0xE0,0x3E,0xC0,0x40,0x3C,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x90,0x60,0x00,
+ 0x1E,0x10,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xF0,0x00,
+ 0x00,0x00,0x00,0x80,0x40,0x60,0x60,0x00,0x00,0x00,0x00,0x30,0x78,0x30,0x00,0x00,
+ 0x1E,0x62,0x1E,0x62,0x04,0x0C,0x30,0x00,0x00,0x00,0x1E,0x6A,0x0E,0x08,0x18,0x00,
+ 0x00,0x00,0x06,0x18,0x68,0x08,0x08,0x00,0x00,0x10,0x1C,0x72,0x42,0x04,0x38,0x00,
+ 0x00,0x00,0x0C,0x78,0x10,0x10,0x7E,0x00,0x00,0x08,0x08,0x7C,0x18,0x28,0x48,0x00,
+ 0x00,0x00,0x26,0x1A,0x72,0x10,0x08,0x00,0x00,0x00,0x0C,0x34,0x04,0x08,0x7E,0x00,
+ 0x00,0x00,0x78,0x04,0x3C,0x04,0x78,0x00,0x00,0x00,0x52,0x4A,0x22,0x04,0x38,0x00,
+ 0x00,0x00,0x80,0x7E,0x00,0x00,0x00,0x00,0x3C,0xC2,0x14,0x1C,0x10,0x30,0x60,0x00,
+ 0x02,0x0C,0x38,0xC8,0x08,0x08,0x08,0x00,0x60,0x3C,0xE2,0x82,0x82,0x04,0x38,0x00,
+ 0x00,0x1C,0x70,0x10,0x10,0x1C,0xE2,0x00,0x08,0xFE,0x18,0x38,0x68,0xC8,0x18,0x00,
+ 0x10,0x3E,0xD2,0x12,0x22,0x62,0xCC,0x00,0x20,0x3C,0xF0,0x1E,0xF0,0x08,0x08,0x00,
+ 0x10,0x3E,0x62,0xC2,0x04,0x0C,0x70,0x00,0x40,0x7E,0x44,0x84,0x84,0x08,0x30,0x00,
+ 0x3E,0xC2,0x02,0x02,0x02,0x02,0xFC,0x00,0x44,0x5E,0xE4,0x44,0x44,0x08,0xF0,0x00,
+ 0x60,0x12,0xC2,0x22,0x04,0x04,0xF8,0x00,0x3C,0xC6,0x0C,0x08,0x38,0x6C,0xC6,0x00,
+ 0x40,0x4E,0x72,0xC4,0x4C,0x40,0x3E,0x00,0x82,0x42,0x62,0x04,0x04,0x08,0x70,0x00,
+ 0x3C,0x42,0x72,0x8A,0x04,0x0C,0x70,0x00,0x0C,0xF8,0x10,0xFE,0x10,0x10,0x60,0x00,
+ 0x22,0xA2,0x92,0x42,0x04,0x08,0x70,0x00,0x3C,0x40,0x1E,0xE8,0x08,0x10,0x60,0x00,
+ 0x40,0x40,0x70,0x4C,0x42,0x40,0x40,0x00,0x08,0x3E,0xC8,0x08,0x08,0x18,0x70,0x00,
+ 0x00,0x1C,0x60,0x00,0x00,0x3C,0xC2,0x00,0x3C,0xC2,0x26,0x38,0x1C,0x36,0xE2,0x00,
+ 0x10,0x3C,0xC6,0x1C,0x38,0xD6,0x12,0x00,0x02,0x02,0x02,0x06,0x04,0x1C,0xF0,0x00,
+ 0x18,0x4C,0x44,0x46,0x42,0x82,0x82,0x00,0x80,0x86,0xBC,0xE0,0x80,0x80,0x7E,0x00,
+ 0x3C,0xC2,0x02,0x02,0x04,0x08,0x30,0x00,0x30,0x48,0x4C,0x84,0x86,0x02,0x02,0x00,
+ 0x10,0xFE,0x10,0x54,0x52,0x92,0x92,0x00,0x3C,0xC2,0x02,0x44,0x28,0x10,0x0C,0x00,
+ 0x70,0x0C,0x60,0x18,0xC4,0x30,0x0E,0x00,0x30,0x40,0x4C,0x84,0x8E,0xBA,0x62,0x00,
+ 0x04,0x04,0x64,0x18,0x0C,0x16,0xE2,0x00,0x1C,0xE0,0x3E,0xE0,0x20,0x20,0x1E,0x00,
+ 0x4E,0x52,0x62,0xE4,0x20,0x10,0x18,0x00,0x1C,0x64,0x04,0x08,0x08,0x10,0xFE,0x00,
+ 0x1C,0x62,0x02,0x3E,0x02,0x02,0x7C,0x00,0x3C,0xC0,0x3E,0xC2,0x02,0x04,0x78,0x00,
+ 0x44,0x42,0x42,0x42,0x22,0x04,0x78,0x00,0x50,0x50,0x52,0x52,0x52,0x54,0x88,0x00,
+ 0x80,0x80,0x82,0x82,0x84,0x88,0xF0,0x00,0x1C,0xE2,0x82,0x82,0x82,0x4C,0x74,0x00,
+ 0x3C,0xC2,0x82,0x82,0x02,0x04,0x38,0x00,0xC0,0x62,0x22,0x02,0x04,0x08,0xF0,0x00,
+ 0x00,0x00,0x00,0x00,0x0A,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x02,0x00,
+ 0x20,0xF8,0x40,0x5E,0x80,0xA0,0x9E,0x00,0x20,0xFE,0x40,0x7C,0xC2,0x86,0x3C,0x00,
+ 0x00,0x3C,0xC6,0x02,0x02,0x0C,0x38,0x00,0x0E,0xF8,0x10,0x20,0x20,0x10,0x0E,0x00,
+ 0x40,0x4C,0x30,0x40,0x80,0x80,0x7E,0x00,0x44,0xF2,0x4A,0x9C,0xA4,0xA6,0x3A,0x00,
+ 0x40,0x5C,0x82,0x80,0xA0,0xA0,0x9E,0x00,0x48,0x7C,0x52,0xB2,0xBE,0xAA,0x4C,0x00,
+ 0x20,0xFC,0x32,0x62,0xEE,0xAA,0x2C,0x00,0x38,0x54,0x92,0x92,0xB2,0xA2,0x4C,0x00,
+ 0x44,0x5E,0x84,0x9C,0xA4,0xA6,0x9C,0x00,0x28,0xEE,0x44,0x84,0x84,0x44,0x38,0x00,
+ 0x78,0x10,0x64,0x34,0x8A,0x8A,0x30,0x00,0x30,0x58,0x48,0x84,0x84,0x02,0x02,0x00,
+ 0xBC,0x88,0xBE,0x84,0xBC,0xA6,0x9C,0x00,0x68,0x1E,0x68,0x1E,0x78,0x8C,0x7A,0x00,
+ 0x70,0x14,0x7C,0x96,0x94,0x94,0x68,0x00,0x2C,0xF2,0x60,0xA0,0xA2,0xC2,0x7C,0x00,
+ 0x48,0x7C,0x6A,0xAA,0xB2,0xB2,0x6C,0x00,0x10,0xF8,0x20,0xF8,0x22,0x22,0x1C,0x00,
+ 0x48,0x5C,0x6A,0xC2,0x64,0x20,0x18,0x00,0x10,0xBC,0xD6,0xCA,0xAA,0x1C,0x70,0x00,
+ 0x10,0x1C,0x12,0x70,0x9C,0x92,0x70,0x00,0xE0,0x18,0x40,0x7C,0xC2,0x82,0x3C,0x00,
+ 0x44,0x42,0x82,0xA2,0x62,0x04,0x78,0x00,0x7C,0x38,0x7C,0xC2,0xBA,0x26,0x3C,0x00,
+ 0x48,0xD4,0x64,0x64,0xC4,0xC4,0x46,0x00,0x7C,0x30,0x7C,0xC2,0x82,0x06,0x3C,0x00,
+ 0x20,0xFC,0x32,0x62,0xE2,0xA2,0x2C,0x00,0x10,0x30,0x60,0x72,0xD2,0x92,0x9C,0x00,
+ 0x00,0x00,0x00,0x00,0x0A,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x02,0x05,0x02,0x00
+};
+
+bool bios_install(void)
+{
+ //=== Install the reverse engineered bios
+ int i;
+
+ uint32 vectable[] =
+ {
+ 0xFF27A2, //0 VECT_SHUTDOWN
+ 0xFF1030, //1 VECT_CLOCKGEARSET
+ 0xFF1440, //2 VECT_RTCGET
+ 0xFF12B4, //3 ?
+ 0xFF1222, //4 VECT_INTLVSET
+ 0xFF8D8A, //5 VECT_SYSFONTSET
+ 0xFF6FD8, //6 VECT_FLASHWRITE
+ 0xFF7042, //7 VECT_FLASHALLERS
+ 0xFF7082, //8 VECT_FLASHERS
+ 0xFF149B, //9 VECT_ALARMSET
+ 0xFF1033, //10 ?
+ 0xFF1487, //11 VECT_ALARMDOWNSET
+ 0xFF731F, //12 ?
+ 0xFF70CA, //13 VECT_FLASHPROTECT
+ 0xFF17C4, //14 VECT_GEMODESET
+ 0xFF1032, //15 ?
+
+ 0xFF2BBD, //0x10 VECT_COMINIT
+ 0xFF2C0C, //0x11 VECT_COMSENDSTART
+ 0xFF2C44, //0x12 VECT_COMRECIVESTART
+ 0xFF2C86, //0x13 VECT_COMCREATEDATA
+ 0xFF2CB4, //0x14 VECT_COMGETDATA
+ 0xFF2D27, //0x15 VECT_COMONRTS
+ 0xFF2D33, //0x16 VECT_COMOFFRTS
+ 0xFF2D3A, //0x17 VECT_COMSENDSTATUS
+ 0xFF2D4E, //0x18 VECT_COMRECIVESTATUS
+ 0xFF2D6C, //0x19 VECT_COMCREATEBUFDATA
+ 0xFF2D85, //0x1a VECT_COMGETBUFDATA
+ };
+
+ //System Call Table, install iBIOSHLE instructions
+ for (i = 0; i <= 0x1A; i++)
+ {
+ MDFN_en32lsb(&ngpc_bios[0xFE00 + (i * 4)], vectable[i]);
+ ngpc_bios[vectable[i] & 0xFFFF] = 0x1F; //iBIOSHLE
+ }
+
+ //System Font
+ memcpy(ngpc_bios + 0x8DCF, font, 0x800);
+
+ //Default Interrupt handler
+ ngpc_bios[0x23DF] = 0x07; //RETI
+
+ // ==========
+
+ //Install a Quick and Dirty Bios
+ ngpc_bios[0xFFFE] = 0x68; // - JR 0xFFFFFE (Infinite loop!)
+ ngpc_bios[0xFFFF] = 0xFE;
+
+ return TRUE; //Success
+}
+
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/bios.h b/waterbox/ngp/bios.h
new file mode 100644
index 0000000000..4c6c7a2b8d
--- /dev/null
+++ b/waterbox/ngp/bios.h
@@ -0,0 +1,55 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ bios.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+18 AUG 2002 - neopop_uk
+=======================================
+- Moved reset() and biosInstall() to neopop.h
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __NEOPOP_BIOS__
+#define __NEOPOP_BIOS__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+extern uint8 ngpc_bios[0x10000];
+
+void iBIOSHLE(void);
+
+void biosDecode(int function);
+void BIOSHLE_Reset(void);
+}
+
+//=============================================================================
+#endif
+
diff --git a/waterbox/ngp/biosHLE.cpp b/waterbox/ngp/biosHLE.cpp
new file mode 100644
index 0000000000..7c097fcb23
--- /dev/null
+++ b/waterbox/ngp/biosHLE.cpp
@@ -0,0 +1,629 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "bios.h"
+#include "mem.h"
+#include "flash.h"
+#include "dma.h"
+#include "interrupt.h"
+
+namespace MDFN_IEN_NGP
+{
+
+static uint8 CacheIntPrio[0xB]; // Iinterrupt prio registers at 0x0070-0x007a don't have priority readable.
+ // This should probably be stored in BIOS work RAM somewhere instead of a separate array, but I don't know where!
+
+void BIOSHLE_Reset(void)
+{
+ memset(CacheIntPrio, 0, sizeof(CacheIntPrio));
+ CacheIntPrio[0] = 0x02;
+ CacheIntPrio[1] = 0x32;
+
+ for (int x = 0; x < 0xB; x++)
+ storeB(0x70 + x, CacheIntPrio[x]);
+}
+
+/* This is the custom HLE instruction. I considered it was the fastest and
+most streamlined way of intercepting a bios call. The operation performed
+is dependant on the current program counter. */
+
+void iBIOSHLE(void)
+{
+ //Only works within the bios
+ if ((pc & 0xFF0000) != 0xFF0000)
+ return;
+
+ pc--; //Compensate for processing this instruction.
+
+ cycles = 8; //TODO: Correct cycle counts (or approx?)
+
+ //if(pc != 0xff1222)
+ //printf("SPOON: %08x\n", pc);
+
+ switch (pc & 0xffffff)
+ {
+
+ //default: printf("SPOON: %08x\n", pc); break;
+ //VECT_SHUTDOWN
+ case 0xFF27A2:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ if (a != 0xBAADC0DE)
+ system_debug_message("VECT_SHUTDOWN: called before %06X", a);
+ push32(a);
+ }
+
+ system_debug_stop();
+#endif
+ {
+ //Cheap bit of code to stop the message appearing repeatedly.
+ uint32 a = pop32();
+ if (a != 0xBAADC0DE)
+ MDFN_printf("IDS_POWER");
+ push32(0xBAADC0DE); //Sure is!
+ }
+
+ return; //Don't pop a return address, stay here
+
+ //VECT_CLOCKGEARSET
+ case 0xFF1030:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_CLOCKGEARSET: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //MDFN_printf("%d\n", rCodeB(0x35));
+ //TODO
+ // if (rCodeB(0x35) > 0)
+ // system_message("Unsupported clock gear %d set\nPlease inform the author", rCodeB(0x35));
+
+ break;
+
+ //VECT_RTCGET
+ case 0xFF1440:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_RTCGET: called before %06X", a);
+ push32(a);
+ }
+#endif
+
+ if (rCodeL(0x3C) < 0xC000)
+ {
+ //Copy data from hardware area
+ storeB(rCodeL(0x3C) + 0, loadB(0x91));
+ storeB(rCodeL(0x3C) + 1, loadB(0x92));
+ storeB(rCodeL(0x3C) + 2, loadB(0x93));
+ storeB(rCodeL(0x3C) + 3, loadB(0x94));
+ storeB(rCodeL(0x3C) + 4, loadB(0x95));
+ storeB(rCodeL(0x3C) + 5, loadB(0x96));
+ storeB(rCodeL(0x3C) + 6, loadB(0x97));
+ }
+
+ break;
+
+ //?
+ //case 0xFF12B4:
+ // break;
+
+ //VECT_INTLVSET
+ case 0xFF1222:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_INTLVSET: called before %06X", a);
+ push32(a);
+ }
+#endif
+
+ {
+
+ uint8 level = rCodeB(0x35); //RB3
+ uint8 interrupt = rCodeB(0x34); //RC3
+
+ // 0 - Interrupt from RTC alarm
+ // 1 - Interrupt from the Z80 CPU
+ // 2 - Interrupt from the 8 bit timer 0
+ // 3 - Interrupt from the 8 bit timer 1
+ // 4 - Interrupt from the 8 bit timer 2
+ // 5 - Interrupt from the 8 bit timer 3
+ // 6 - End of transfer interrupt from DMA channel 0
+ // 7 - End of transfer interrupt from DMA channel 1
+ // 8 - End of transfer interrupt from DMA channel 2
+ // 9 - End of transfer interrupt from DMA channel 3
+
+ switch (interrupt)
+ {
+ case 0x00:
+ CacheIntPrio[0x0] = (CacheIntPrio[0x0] & 0xf0) | (level & 0x07);
+ storeB(0x70, CacheIntPrio[0x0]);
+ break;
+
+ case 0x01:
+ CacheIntPrio[0x1] = (CacheIntPrio[0x1] & 0x0f) | ((level & 0x07) << 4);
+ storeB(0x71, CacheIntPrio[0x1]);
+ break;
+
+ case 0x02:
+ CacheIntPrio[0x3] = (CacheIntPrio[0x3] & 0xf0) | (level & 0x07);
+ storeB(0x73, CacheIntPrio[0x3]);
+ break;
+
+ case 0x03:
+ CacheIntPrio[0x3] = (CacheIntPrio[0x3] & 0x0f) | ((level & 0x07) << 4);
+ storeB(0x73, CacheIntPrio[0x3]);
+ break;
+
+ case 0x04:
+ CacheIntPrio[0x4] = (CacheIntPrio[0x4] & 0xf0) | (level & 0x07);
+ storeB(0x74, CacheIntPrio[0x4]);
+ break;
+
+ case 0x05:
+ CacheIntPrio[0x4] = (CacheIntPrio[0x4] & 0x0f) | ((level & 0x07) << 4);
+ storeB(0x74, CacheIntPrio[0x4]);
+ break;
+
+ case 0x06:
+ CacheIntPrio[0x9] = (CacheIntPrio[0x9] & 0xf0) | (level & 0x07);
+ storeB(0x79, CacheIntPrio[0x9]);
+ break;
+
+ case 0x07:
+ CacheIntPrio[0x9] = (CacheIntPrio[0x9] & 0x0f) | ((level & 0x07) << 4);
+ storeB(0x79, CacheIntPrio[0x9]);
+ break;
+
+ case 0x08:
+ CacheIntPrio[0xa] = (CacheIntPrio[0xa] & 0xf0) | (level & 0x07);
+ storeB(0x7a, CacheIntPrio[0xa]);
+ break;
+
+ case 0x09:
+ CacheIntPrio[0xa] = (CacheIntPrio[0xa] & 0x0f) | ((level & 0x07) << 4);
+ storeB(0x7a, CacheIntPrio[0xa]);
+ break;
+ default:
+ puts("DOH");
+ break;
+ }
+ }
+ break;
+
+ //VECT_SYSFONTSET
+ case 0xFF8D8A:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_SYSFONTSET: called before %06X", a);
+ push32(a);
+ }
+#endif
+ {
+ uint8 a, b, c, j;
+ uint16 i, dst = 0xA000;
+
+ b = rCodeB(0x30) >> 4;
+ a = rCodeB(0x30) & 3;
+
+ for (i = 0; i < 0x800; i++)
+ {
+ c = ngpc_bios[0x8DCF + i];
+
+ for (j = 0; j < 8; j++, c <<= 1)
+ {
+ uint16 data16;
+
+ data16 = loadW(dst);
+ data16 <<= 2;
+ storeW(dst, data16);
+
+ if (c & 0x80)
+ storeB(dst, loadB(dst) | a);
+ else
+ storeB(dst, loadB(dst) | b);
+ }
+
+ dst += 2;
+ }
+ }
+
+ break;
+
+ //VECT_FLASHWRITE
+ case 0xFF6FD8:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_FLASHWRITE: called before %06X", a);
+ push32(a);
+ }
+#endif
+ {
+ uint32 i, bank = 0x200000;
+
+ //Select HI rom?
+ if (rCodeB(0x30) == 1)
+ bank = 0x800000;
+
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ system_debug_message("VECT_FLASHWRITE: Copy %06X -> %06X, %d bytes",
+ rCodeL(0x3C), rCodeL(0x38) + bank, rCodeW(0x34) * 256);
+#endif
+
+ memory_flash_error = FALSE;
+ memory_unlock_flash_write = TRUE;
+ //Copy as 32 bit values for speed
+ for (i = 0; i < rCodeW(0x34) * 64ul; i++)
+ storeL(rCodeL(0x38) + bank + (i * 4), loadL(rCodeL(0x3C) + (i * 4)));
+ memory_unlock_flash_write = FALSE;
+
+ if (memory_flash_error)
+ {
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ system_debug_message("VECT_FLASHWRITE: Error");
+#endif
+ rCodeB(0x30) = 0xFF; //RA3 = SYS_FAILURE
+ }
+ else
+ {
+ uint32 address = rCodeL(0x38);
+ if (rCodeB(0x30) == 1)
+ address += 0x800000;
+ else
+ address += 0x200000;
+
+ //Save this data to an external file
+ flash_write(address, rCodeW(0x34) * 256);
+
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ }
+ }
+
+ break;
+
+ //VECT_FLASHALLERS
+ case 0xFF7042:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_FLASHALLERS: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //TODO
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ break;
+
+ //VECT_FLASHERS
+ case 0xFF7082:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_FLASHERS: called before %06X", a);
+ push32(a);
+ }
+#endif
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ system_debug_message("VECT_FLASHERS: bank %d, block %d (?)", rCodeB(0x30), rCodeB(0x35));
+#endif
+ //TODO
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ break;
+
+ //VECT_ALARMSET
+ case 0xFF149B:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_ALARMSET: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //TODO
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ break;
+
+ //?
+ //case 0xFF1033: break;
+
+ //VECT_ALARMDOWNSET
+ case 0xFF1487:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_ALARMDOWNSET: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //TODO
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ break;
+
+ //?
+ //case 0xFF731F: break;
+
+ //VECT_FLASHPROTECT
+ case 0xFF70CA:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_FLASHPROTECT: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //TODO
+ rCodeB(0x30) = 0; //RA3 = SYS_SUCCESS
+ break;
+
+ //VECT_GEMODESET
+ case 0xFF17C4:
+#ifdef NEOPOP_DEBUG
+ if (filter_bios)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_GEMODESET: called before %06X", a);
+ push32(a);
+ }
+#endif
+ //TODO
+ break;
+
+ //?
+ //case 0xFF1032: break;
+
+ //VECT_COMINIT
+ case 0xFF2BBD:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMINIT: called before %06X", a);
+ push32(a);
+ }
+#endif
+ // Nothing to do.
+ rCodeB(0x30) = 0; //RA3 = COM_BUF_OK
+ break;
+
+ //VECT_COMSENDSTART
+ case 0xFF2C0C:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMSENDSTART: called before %06X", a);
+ push32(a);
+ }
+#endif
+ // Nothing to do.
+ break;
+
+ //VECT_COMRECIVESTART
+ case 0xFF2C44:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMRECIVESTART: called before %06X", a);
+ push32(a);
+ }
+#endif
+ // Nothing to do.
+ break;
+
+ //VECT_COMCREATEDATA
+ case 0xFF2C86:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMCREATEDATA: called before %06X", a);
+ push32(a);
+ }
+#endif
+ {
+ //Write the byte
+ uint8 data = rCodeB(0x35);
+ system_comms_write(data);
+ }
+
+ //Restore $PC after BIOS-HLE instruction
+ pc = pop32();
+
+ TestIntHDMA(11, 0x18);
+
+ //Always COM_BUF_OK because the write call always succeeds.
+ rCodeB(0x30) = 0x0; //RA3 = COM_BUF_OK
+ return;
+
+ //VECT_COMGETDATA
+ case 0xFF2CB4:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMGETDATA: called before %06X", a);
+ push32(a);
+ }
+#endif
+ {
+ uint8 data;
+
+ if (system_comms_read(&data))
+ {
+ rCodeB(0x30) = 0; //COM_BUF_OK
+ rCodeB(0x35) = data;
+
+ pc = pop32();
+
+ //Comms. Read interrupt
+ storeB(0x50, data);
+ TestIntHDMA(12, 0x19);
+
+ return;
+ }
+ else
+ {
+ rCodeB(0x30) = 1; //COM_BUF_EMPTY
+ }
+ }
+
+ break;
+
+ //VECT_COMONRTS
+ case 0xFF2D27:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMONRTS: called before %06X", a);
+ push32(a);
+ }
+#endif
+ storeB(0xB2, 0);
+ break;
+
+ //VECT_COMOFFRTS
+ case 0xFF2D33:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMOFFRTS: called before %06X", a);
+ push32(a);
+ }
+#endif
+ storeB(0xB2, 1);
+ break;
+
+ //VECT_COMSENDSTATUS
+ case 0xFF2D3A:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMSENDSTATUS: called before %06X", a);
+ push32(a);
+ }
+#endif
+ // Nothing to do.
+ rCodeW(0x30) = 0; //Send Buffer Count, never any pending data!
+ break;
+
+ //VECT_COMRECIVESTATUS
+ case 0xFF2D4E:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMRECIVESTATUS: called before %06X", a);
+ push32(a);
+ }
+#endif
+
+ // Receive Buffer Count
+ rCodeW(0x30) = system_comms_read(NULL);
+
+ break;
+
+ //VECT_COMCREATEBUFDATA
+ case 0xFF2D6C:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMCREATEBUFDATA: called before %06X", a);
+ push32(a);
+ }
+#endif
+ pc = pop32();
+
+ while (rCodeB(0x35) > 0)
+ {
+ uint8 data;
+ data = loadB(rCodeL(0x3C));
+
+ //Write data from (XHL3++)
+ system_comms_write(data);
+ rCodeL(0x3C)++; //Next data
+
+ rCodeB(0x35)--; //RB3 = Count Left
+ }
+
+ TestIntHDMA(11, 0x18);
+ return;
+
+ //VECT_COMGETBUFDATA
+ case 0xFF2D85:
+#ifdef NEOPOP_DEBUG
+ if (filter_comms)
+ {
+ uint32 a = pop32();
+ system_debug_message("VECT_COMGETBUFDATA: called before %06X", a);
+ push32(a);
+ }
+#endif
+ {
+ pc = pop32();
+
+ while (rCodeB(0x35) > 0)
+ {
+ uint8 data;
+
+ if (system_comms_read(&data))
+ {
+ //Read data into (XHL3++)
+ storeB(rCodeL(0x3C), data);
+ rCodeL(0x3C)++; //Next data
+ rCodeB(0x35)--; //RB3 = Count Left
+
+ //Comms. Read interrupt
+ storeB(0x50, data);
+ TestIntHDMA(12, 0x19);
+ return;
+ }
+ else
+ break;
+ }
+ }
+
+ return;
+ }
+
+ //RET
+ pc = pop32();
+}
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/defs.h b/waterbox/ngp/defs.h
new file mode 100644
index 0000000000..294dd421ec
--- /dev/null
+++ b/waterbox/ngp/defs.h
@@ -0,0 +1,85 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+
+//#define MDFN_FASTCALL
+#define INLINE inline
+#define MDFN_COLD
+#define NO_INLINE
+//#define MDFN_ASSUME_ALIGNED(p, align) ((decltype(p))__builtin_assume_aligned((p), (align)))
+#define MDFN_ASSUME_ALIGNED(p, align) (p)
+#define trio_snprintf snprintf
+#define TRUE true
+#define FALSE false
+#ifndef __alignas_is_defined
+#define alignas(p)
+#endif
+
+struct MDFN_Surface
+{
+ uint32 *pixels;
+ int pitch32;
+};
+
+struct EmulateSpecStruct
+{
+ // Pitch(32-bit) must be equal to width and >= the "fb_width" specified in the MDFNGI struct for the emulated system.
+ // Height must be >= to the "fb_height" specified in the MDFNGI struct for the emulated system.
+ // The framebuffer pointed to by surface->pixels is written to by the system emulation code.
+ uint32 *pixels;
+
+ // Pointer to sound buffer, set by the driver code, that the emulation code should render sound to.
+ // Guaranteed to be at least 500ms in length, but emulation code really shouldn't exceed 40ms or so. Additionally, if emulation code
+ // generates >= 100ms,
+ // DEPRECATED: Emulation code may set this pointer to a sound buffer internal to the emulation module.
+ int16 *SoundBuf;
+
+ // Number of cycles that this frame consumed, using MDFNGI::MasterClock as a time base.
+ // Set by emulation code.
+ int64 MasterCycles;
+
+ // Maximum size of the sound buffer, in frames. Set by the driver code.
+ int32 SoundBufMaxSize;
+
+ // Number of frames currently in internal sound buffer. Set by the system emulation code, to be read by the driver code.
+ int32 SoundBufSize;
+
+ // true to skip rendering
+ int32 skip;
+
+ int32 Buttons;
+
+ // set by core, true if lagged
+ int32 Lagged;
+};
+
+#define MDFN_printf(...)
+#define MDFN_PrintError(...)
+#define require assert
+
+#include "endian.h"
+
+inline char* strdup(const char* p)
+{
+ char* ret = (char*)malloc(strlen(p) + 1);
+ if (ret)
+ strcpy(ret, p);
+ return ret;
+}
+
+#include
+#define EXPORT extern "C" ECL_EXPORT
diff --git a/waterbox/ngp/dma.cpp b/waterbox/ngp/dma.cpp
new file mode 100644
index 0000000000..c9e8277c9f
--- /dev/null
+++ b/waterbox/ngp/dma.cpp
@@ -0,0 +1,379 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ dma.c
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+25 JUL 2002 - neopop_uk
+=======================================
+- Removed incorrect quick-fix code and added new DMA_update functions
+ to process the dma values.
+- Fixed setting of C and M registers
+- Added source copy byte and word mode DMA, seems to be only ones used.
+
+26 JUL 2002 - neopop_uk
+=======================================
+- Added more DMA modes - "Kikouseki Unitron (J)" uses counter mode
+ and 4 byte memory to I/O transfer.
+- Added load *from* dma control register.
+
+30 JUL 2002 - neopop_uk
+=======================================
+- Made DMA_update more secure in it's ability to detect unknown DMA modes.
+- DMA mode and count are printed in decimal, for internal consistancy.
+
+01 AUG 2002 - neopop_uk
+=======================================
+- Re-written DMA_update for clarity, and added missing modes,
+ fixes "Super Real Mahjong"
+
+//---------------------------------------------------------------------------
+*/
+
+#include "neopop.h"
+#include "dma.h"
+#include "mem.h"
+#include "interrupt.h"
+
+namespace MDFN_IEN_NGP
+{
+
+//=============================================================================
+
+static uint32 dmaS[4], dmaD[4];
+static uint16 dmaC[4];
+static uint8 dmaM[4];
+
+//=============================================================================
+
+void reset_dma(void)
+{
+ memset(dmaS, 0, sizeof(dmaS));
+ memset(dmaD, 0, sizeof(dmaD));
+ memset(dmaC, 0, sizeof(dmaC));
+ memset(dmaM, 0, sizeof(dmaM));
+}
+
+//=============================================================================
+
+void DMA_update(int channel)
+{
+ uint8 mode = (dmaM[channel] & 0x1C) >> 2;
+ uint8 size = (dmaM[channel] & 0x03); //byte, word or long
+
+ // Correct?
+ if (dmaC[channel] == 0)
+ return;
+
+ switch (mode)
+ {
+ case 0: // Destination INC mode, I/O to Memory transfer
+ switch (size)
+ {
+ case 0:
+ storeB(dmaD[channel], loadB(dmaS[channel]));
+ dmaD[channel] += 1; //Byte increment
+ break;
+
+ case 1:
+ storeW(dmaD[channel], loadW(dmaS[channel]));
+ dmaD[channel] += 2; //Word increment
+ break;
+
+ case 2:
+ storeL(dmaD[channel], loadL(dmaS[channel]));
+ dmaD[channel] += 4; //Long increment
+ break;
+ }
+ break;
+
+ case 1: // Destination DEC mode, I/O to Memory transfer
+ switch (size)
+ {
+ case 0:
+ storeB(dmaD[channel], loadB(dmaS[channel]));
+ dmaD[channel] -= 1; //Byte decrement
+ break;
+
+ case 1:
+ storeW(dmaD[channel], loadW(dmaS[channel]));
+ dmaD[channel] -= 2; //Word decrement
+ break;
+
+ case 2:
+ storeL(dmaD[channel], loadL(dmaS[channel]));
+ dmaD[channel] -= 4; //Long decrement
+ break;
+ }
+ break;
+
+ case 2: // Source INC mode, Memory to I/O transfer
+ switch (size)
+ {
+ case 0:
+ storeB(dmaD[channel], loadB(dmaS[channel]));
+ dmaS[channel] += 1; //Byte increment
+ break;
+
+ case 1:
+ storeW(dmaD[channel], loadW(dmaS[channel]));
+ dmaS[channel] += 2; //Word increment
+ break;
+
+ case 2:
+ storeL(dmaD[channel], loadL(dmaS[channel]));
+ dmaS[channel] += 4; //Long increment
+ break;
+ }
+ break;
+
+ case 3: // Source DEC mode, Memory to I/O transfer
+ switch (size)
+ {
+ case 0:
+ storeB(dmaD[channel], loadB(dmaS[channel]));
+ dmaS[channel] -= 1; //Byte decrement
+ break;
+
+ case 1:
+ storeW(dmaD[channel], loadW(dmaS[channel]));
+ dmaS[channel] -= 2; //Word decrement
+ break;
+
+ case 2:
+ storeL(dmaD[channel], loadL(dmaS[channel]));
+ dmaS[channel] -= 4; //Long decrement
+ break;
+ }
+ break;
+
+ case 4: // Fixed Address Mode
+ switch (size)
+ {
+ case 0:
+ storeB(dmaD[channel], loadB(dmaS[channel]));
+ break;
+
+ case 1:
+ storeW(dmaD[channel], loadW(dmaS[channel]));
+ break;
+
+ case 2:
+ storeL(dmaD[channel], loadL(dmaS[channel]));
+ break;
+ }
+ break;
+
+ case 5: // Counter Mode
+ dmaS[channel]++;
+ break;
+
+ default:
+ MDFN_printf("Bad DMA mode %d\nPlease report this to the author.", dmaM[channel]);
+ return;
+ }
+
+ // Perform common counter decrement,
+ // vector clearing, and interrupt handling.
+
+ dmaC[channel]--;
+ if (dmaC[channel] == 0)
+ {
+ interrupt(14 + channel);
+ storeB(0x7C + channel, 0);
+ }
+}
+
+//=============================================================================
+
+void dmaStoreB(uint8 cr, uint8 data)
+{
+ switch (cr)
+ {
+ case 0x22:
+ dmaM[0] = data;
+ break;
+ case 0x26:
+ dmaM[1] = data;
+ break;
+ case 0x2A:
+ dmaM[2] = data;
+ break;
+ case 0x2E:
+ dmaM[3] = data;
+ break;
+
+ default:
+ MDFN_printf("dmaStoreB: Unknown register 0x%02X <- %02X\nPlease report this to the author.\n", cr, data);
+ break;
+ }
+}
+
+void dmaStoreW(uint8 cr, uint16 data)
+{
+ switch (cr)
+ {
+ case 0x20:
+ dmaC[0] = data;
+ break;
+ case 0x24:
+ dmaC[1] = data;
+ break;
+ case 0x28:
+ dmaC[2] = data;
+ break;
+ case 0x2C:
+ dmaC[3] = data;
+ break;
+
+ default:
+ MDFN_printf("dmaStoreW: Unknown register 0x%02X <- %04X\nPlease report this to the author.\n", cr, data);
+ break;
+ }
+}
+
+void dmaStoreL(uint8 cr, uint32 data)
+{
+ switch (cr)
+ {
+ case 0x00:
+ dmaS[0] = data;
+ break;
+ case 0x04:
+ dmaS[1] = data;
+ break;
+ case 0x08:
+ dmaS[2] = data;
+ break;
+ case 0x0C:
+ dmaS[3] = data;
+ break;
+
+ case 0x10:
+ dmaD[0] = data;
+ break;
+ case 0x14:
+ dmaD[1] = data;
+ break;
+ case 0x18:
+ dmaD[2] = data;
+ break;
+ case 0x1C:
+ dmaD[3] = data;
+ break;
+
+ default:
+ MDFN_printf("dmaStoreL: Unknown register 0x%02X <- %08X\nPlease report this to the author.\n", cr, data);
+ break;
+ }
+}
+
+//=============================================================================
+
+uint8 dmaLoadB(uint8 cr)
+{
+
+ switch (cr)
+ {
+ case 0x22:
+ return dmaM[0];
+ break;
+ case 0x26:
+ return dmaM[1];
+ break;
+ case 0x2A:
+ return dmaM[2];
+ break;
+ case 0x2E:
+ return dmaM[3];
+ break;
+
+ default:
+ MDFN_printf("dmaLoadB: Unknown register 0x%02X\nPlease report this to the author.", cr);
+ return 0;
+ }
+}
+
+uint16 dmaLoadW(uint8 cr)
+{
+ switch (cr)
+ {
+ case 0x20:
+ return dmaC[0];
+ break;
+ case 0x24:
+ return dmaC[1];
+ break;
+ case 0x28:
+ return dmaC[2];
+ break;
+ case 0x2C:
+ return dmaC[3];
+ break;
+
+ default:
+ MDFN_printf("dmaLoadW: Unknown register 0x%02X\nPlease report this to the author.", cr);
+ return 0;
+ }
+}
+
+uint32 dmaLoadL(uint8 cr)
+{
+ switch (cr)
+ {
+ case 0x00:
+ return dmaS[0];
+ break;
+ case 0x04:
+ return dmaS[1];
+ break;
+ case 0x08:
+ return dmaS[2];
+ break;
+ case 0x0C:
+ return dmaS[3];
+ break;
+
+ case 0x10:
+ return dmaD[0];
+ break;
+ case 0x14:
+ return dmaD[1];
+ break;
+ case 0x18:
+ return dmaD[2];
+ break;
+ case 0x1C:
+ return dmaD[3];
+ break;
+
+ default:
+ MDFN_printf("dmaLoadL: Unknown register 0x%02X\nPlease report this to the author.", cr);
+ return 0;
+ }
+}
+}
diff --git a/waterbox/ngp/dma.h b/waterbox/ngp/dma.h
new file mode 100644
index 0000000000..d09951d2cb
--- /dev/null
+++ b/waterbox/ngp/dma.h
@@ -0,0 +1,60 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+/*
+//---------------------------------------------------------------------------
+//=========================================================================
+
+ dma.h
+
+//=========================================================================
+//---------------------------------------------------------------------------
+
+ History of changes:
+ ===================
+
+20 JUL 2002 - neopop_uk
+=======================================
+- Cleaned and tidied up for the source release
+
+25 JUL 2002 - neopop_uk
+=======================================
+- Added function prototype for DMA_update
+
+//---------------------------------------------------------------------------
+*/
+
+#ifndef __NEOPOP_DMA__
+#define __NEOPOP_DMA__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+void reset_dma(void);
+
+void DMA_update(int channel);
+
+uint8 dmaLoadB(uint8 cr);
+uint16 dmaLoadW(uint8 cr);
+uint32 dmaLoadL(uint8 cr);
+
+void dmaStoreB(uint8 cr, uint8 data);
+void dmaStoreW(uint8 cr, uint16 data);
+void dmaStoreL(uint8 cr, uint32 data);
+
+}
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/endian.h b/waterbox/ngp/endian.h
new file mode 100644
index 0000000000..e78a0c577f
--- /dev/null
+++ b/waterbox/ngp/endian.h
@@ -0,0 +1,494 @@
+/******************************************************************************/
+/* Mednafen - Multi-system Emulator */
+/******************************************************************************/
+/* endian.h:
+** Copyright (C) 2006-2016 Mednafen Team
+**
+** 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.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __MDFN_ENDIAN_H
+#define __MDFN_ENDIAN_H
+
+void Endian_A16_Swap(void *src, uint32 nelements);
+void Endian_A32_Swap(void *src, uint32 nelements);
+void Endian_A64_Swap(void *src, uint32 nelements);
+
+void Endian_A16_NE_LE(void *src, uint32 nelements);
+void Endian_A32_NE_LE(void *src, uint32 nelements);
+void Endian_A64_NE_LE(void *src, uint32 nelements);
+
+void Endian_A16_NE_BE(void *src, uint32 nelements);
+void Endian_A32_NE_BE(void *src, uint32 nelements);
+void Endian_A64_NE_BE(void *src, uint32 nelements);
+
+void Endian_V_NE_LE(void* p, size_t len);
+void Endian_V_NE_BE(void* p, size_t len);
+
+//
+//
+//
+
+static INLINE uint32 BitsExtract(const uint8* ptr, const size_t bit_offset, const size_t bit_count)
+{
+ uint32 ret = 0;
+
+ for(size_t x = 0; x < bit_count; x++)
+ {
+ size_t co = bit_offset + x;
+ bool b = (ptr[co >> 3] >> (co & 7)) & 1;
+
+ ret |= (uint64)b << x;
+ }
+
+ return ret;
+}
+
+static INLINE void BitsIntract(uint8* ptr, const size_t bit_offset, const size_t bit_count, uint32 value)
+{
+ for(size_t x = 0; x < bit_count; x++)
+ {
+ size_t co = bit_offset + x;
+ bool b = (value >> x) & 1;
+ uint8 tmp = ptr[co >> 3];
+
+ tmp &= ~(1 << (co & 7));
+ tmp |= b << (co & 7);
+
+ ptr[co >> 3] = tmp;
+ }
+}
+
+/*
+ Regarding safety of calling MDFN_*sb on dynamically-allocated memory with new uint8[], see C++ standard 3.7.3.1(i.e. it should be
+ safe provided the offsets into the memory are aligned/multiples of the MDFN_*sb access type). malloc()'d and calloc()'d
+ memory should be safe as well.
+
+ Statically-allocated arrays/memory should be unioned with a big POD type or C++11 "alignas"'d. (May need to audit code to ensure
+ this is being done).
+*/
+
+static INLINE uint16 MDFN_bswap16(uint16 v)
+{
+ return (v << 8) | (v >> 8);
+}
+
+static INLINE uint32 MDFN_bswap32(uint32 v)
+{
+ return (v << 24) | ((v & 0xFF00) << 8) | ((v >> 8) & 0xFF00) | (v >> 24);
+}
+
+static INLINE uint64 MDFN_bswap64(uint64 v)
+{
+ return (v << 56) | (v >> 56) | ((v & 0xFF00) << 40) | ((v >> 40) & 0xFF00) | ((uint64)MDFN_bswap32(v >> 16) << 16);
+}
+
+#ifdef LSB_FIRST
+ #define MDFN_ENDIANH_IS_BIGENDIAN 0
+#else
+ #define MDFN_ENDIANH_IS_BIGENDIAN 1
+#endif
+
+//
+// X endian.
+//
+template
+static INLINE T MDFN_deXsb(const void* ptr)
+{
+ T tmp;
+
+ memcpy(&tmp, MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), sizeof(T));
+
+ if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
+ {
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
+
+ if(sizeof(T) == 8)
+ return MDFN_bswap64(tmp);
+ else if(sizeof(T) == 4)
+ return MDFN_bswap32(tmp);
+ else if(sizeof(T) == 2)
+ return MDFN_bswap16(tmp);
+ }
+
+ return tmp;
+}
+
+//
+// Native endian.
+//
+template
+static INLINE T MDFN_densb(const void* ptr)
+{
+ return MDFN_deXsb<-1, T, aligned>(ptr);
+}
+
+//
+// Little endian.
+//
+template
+static INLINE T MDFN_delsb(const void* ptr)
+{
+ return MDFN_deXsb<0, T, aligned>(ptr);
+}
+
+template
+static INLINE uint16 MDFN_de16lsb(const void* ptr)
+{
+ return MDFN_delsb(ptr);
+}
+
+static INLINE uint32 MDFN_de24lsb(const void* ptr)
+{
+ const uint8* ptr_u8 = (const uint8*)ptr;
+
+ return (ptr_u8[0] << 0) | (ptr_u8[1] << 8) | (ptr_u8[2] << 16);
+}
+
+template
+static INLINE uint32 MDFN_de32lsb(const void* ptr)
+{
+ return MDFN_delsb(ptr);
+}
+
+template
+static INLINE uint64 MDFN_de64lsb(const void* ptr)
+{
+ return MDFN_delsb(ptr);
+}
+
+//
+// Big endian.
+//
+template
+static INLINE T MDFN_demsb(const void* ptr)
+{
+ return MDFN_deXsb<1, T, aligned>(ptr);
+}
+
+template
+static INLINE uint16 MDFN_de16msb(const void* ptr)
+{
+ return MDFN_demsb(ptr);
+}
+
+static INLINE uint32 MDFN_de24msb(const void* ptr)
+{
+ const uint8* ptr_u8 = (const uint8*)ptr;
+
+ return (ptr_u8[0] << 16) | (ptr_u8[1] << 8) | (ptr_u8[2] << 0);
+}
+
+template
+static INLINE uint32 MDFN_de32msb(const void* ptr)
+{
+ return MDFN_demsb(ptr);
+}
+
+template
+static INLINE uint64 MDFN_de64msb(const void* ptr)
+{
+ return MDFN_demsb(ptr);
+}
+
+//
+//
+//
+//
+//
+//
+//
+//
+
+//
+// X endian.
+//
+template
+static INLINE void MDFN_enXsb(void* ptr, T value)
+{
+ T tmp = value;
+
+ if(isbigendian != -1 && isbigendian != MDFN_ENDIANH_IS_BIGENDIAN)
+ {
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Gummy penguins.");
+
+ if(sizeof(T) == 8)
+ tmp = MDFN_bswap64(value);
+ else if(sizeof(T) == 4)
+ tmp = MDFN_bswap32(value);
+ else if(sizeof(T) == 2)
+ tmp = MDFN_bswap16(value);
+ }
+
+ memcpy(MDFN_ASSUME_ALIGNED(ptr, (aligned ? sizeof(T) : 1)), &tmp, sizeof(T));
+}
+
+//
+// Native endian.
+//
+template
+static INLINE void MDFN_ennsb(void* ptr, T value)
+{
+ MDFN_enXsb<-1, T, aligned>(ptr, value);
+}
+
+//
+// Little endian.
+//
+template
+static INLINE void MDFN_enlsb(void* ptr, T value)
+{
+ MDFN_enXsb<0, T, aligned>(ptr, value);
+}
+
+template
+static INLINE void MDFN_en16lsb(void* ptr, uint16 value)
+{
+ MDFN_enlsb(ptr, value);
+}
+
+static INLINE void MDFN_en24lsb(void* ptr, uint32 value)
+{
+ uint8* ptr_u8 = (uint8*)ptr;
+
+ ptr_u8[0] = value >> 0;
+ ptr_u8[1] = value >> 8;
+ ptr_u8[2] = value >> 16;
+}
+
+template
+static INLINE void MDFN_en32lsb(void* ptr, uint32 value)
+{
+ MDFN_enlsb(ptr, value);
+}
+
+template
+static INLINE void MDFN_en64lsb(void* ptr, uint64 value)
+{
+ MDFN_enlsb(ptr, value);
+}
+
+
+//
+// Big endian.
+//
+template
+static INLINE void MDFN_enmsb(void* ptr, T value)
+{
+ MDFN_enXsb<1, T, aligned>(ptr, value);
+}
+
+template
+static INLINE void MDFN_en16msb(void* ptr, uint16 value)
+{
+ MDFN_enmsb(ptr, value);
+}
+
+static INLINE void MDFN_en24msb(void* ptr, uint32 value)
+{
+ uint8* ptr_u8 = (uint8*)ptr;
+
+ ptr_u8[0] = value >> 16;
+ ptr_u8[1] = value >> 8;
+ ptr_u8[2] = value >> 0;
+}
+
+template
+static INLINE void MDFN_en32msb(void* ptr, uint32 value)
+{
+ MDFN_enmsb(ptr, value);
+}
+
+template
+static INLINE void MDFN_en64msb(void* ptr, uint64 value)
+{
+ MDFN_enmsb(ptr, value);
+}
+
+
+//
+//
+//
+//
+//
+//
+
+template
+static INLINE uint8* ne16_ptr_be(BT* const base, const size_t byte_offset)
+{
+#ifdef MSB_FIRST
+ return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
+#else
+ return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min(2, sizeof(T)))));
+#endif
+}
+
+template
+static INLINE void ne16_wbo_be(uint16* const base, const size_t byte_offset, const T value)
+{
+ uint8* const ptr = ne16_ptr_be(base, byte_offset);
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
+
+ if(sizeof(T) == 4)
+ {
+ uint16* const ptr16 = (uint16*)ptr;
+
+ ptr16[0] = value >> 16;
+ ptr16[1] = value;
+ }
+ else
+ *(T*)ptr = value;
+}
+
+template
+static INLINE T ne16_rbo_be(const uint16* const base, const size_t byte_offset)
+{
+ uint8* const ptr = ne16_ptr_be(base, byte_offset);
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
+
+ if(sizeof(T) == 4)
+ {
+ uint16* const ptr16 = (uint16*)ptr;
+ T tmp;
+
+ tmp = ptr16[0] << 16;
+ tmp |= ptr16[1];
+
+ return tmp;
+ }
+ else
+ return *(T*)ptr;
+}
+
+template
+static INLINE void ne16_rwbo_be(uint16* const base, const size_t byte_offset, T* value)
+{
+ if(IsWrite)
+ ne16_wbo_be(base, byte_offset, *value);
+ else
+ *value = ne16_rbo_be(base, byte_offset);
+}
+
+//
+//
+//
+
+template
+static INLINE uint8* ne16_ptr_le(BT* const base, const size_t byte_offset)
+{
+#ifdef LSB_FIRST
+ return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
+#else
+ return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (2 - std::min(2, sizeof(T)))));
+#endif
+}
+
+template
+static INLINE void ne16_wbo_le(uint16* const base, const size_t byte_offset, const T value)
+{
+ uint8* const ptr = ne16_ptr_le(base, byte_offset);
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
+
+ if(sizeof(T) == 4)
+ {
+ uint16* const ptr16 = (uint16*)ptr;
+
+ ptr16[0] = value;
+ ptr16[1] = value >> 16;
+ }
+ else
+ *(T*)ptr = value;
+}
+
+template
+static INLINE T ne16_rbo_le(const uint16* const base, const size_t byte_offset)
+{
+ uint8* const ptr = ne16_ptr_le(base, byte_offset);
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
+
+ if(sizeof(T) == 4)
+ {
+ uint16* const ptr16 = (uint16*)ptr;
+ T tmp;
+
+ tmp = ptr16[0];
+ tmp |= ptr16[1] << 16;
+
+ return tmp;
+ }
+ else
+ return *(T*)ptr;
+}
+
+
+template
+static INLINE void ne16_rwbo_le(uint16* const base, const size_t byte_offset, T* value)
+{
+ if(IsWrite)
+ ne16_wbo_le(base, byte_offset, *value);
+ else
+ *value = ne16_rbo_le(base, byte_offset);
+}
+
+//
+//
+//
+template
+static INLINE uint8* ne64_ptr_be(uint64* const base, const size_t byte_offset)
+{
+#ifdef MSB_FIRST
+ return (uint8*)base + (byte_offset &~ (sizeof(T) - 1));
+#else
+ return (uint8*)base + (((byte_offset &~ (sizeof(T) - 1)) ^ (8 - sizeof(T))));
+#endif
+}
+
+template
+static INLINE void ne64_wbo_be(uint64* const base, const size_t byte_offset, const T value)
+{
+ uint8* const ptr = ne64_ptr_be(base, byte_offset);
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
+
+ memcpy(MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), &value, sizeof(T));
+}
+
+template
+static INLINE T ne64_rbo_be(uint64* const base, const size_t byte_offset)
+{
+ uint8* const ptr = ne64_ptr_be(base, byte_offset);
+ T ret;
+
+ static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, "Unsupported type size");
+
+ memcpy(&ret, MDFN_ASSUME_ALIGNED(ptr, sizeof(T)), sizeof(T));
+
+ return ret;
+}
+
+template
+static INLINE void ne64_rwbo_be(uint64* const base, const size_t byte_offset, T* value)
+{
+ if(IsWrite)
+ ne64_wbo_be(base, byte_offset, *value);
+ else
+ *value = ne64_rbo_be(base, byte_offset);
+}
+
+#endif
diff --git a/waterbox/ngp/flash.cpp b/waterbox/ngp/flash.cpp
new file mode 100644
index 0000000000..20c5da9bbb
--- /dev/null
+++ b/waterbox/ngp/flash.cpp
@@ -0,0 +1,318 @@
+/*
+ FIXME:
+ File format is not endian-safe.
+
+ Still possible for corrupt/malicious save game data to cause a crash, from blindly reading past the end of the buffer.
+*/
+
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "flash.h"
+#include "mem.h"
+
+#include
+
+namespace MDFN_IEN_NGP
+{
+
+//-----------------------------------------------------------------------------
+// Local Definitions
+//-----------------------------------------------------------------------------
+//This value is used to verify flash data - it is set to the
+//version number that the flash description was modified for.
+
+#define FLASH_VALID_ID 0x0053
+
+//Number of different flash blocks, this should be enough.
+
+#define FLASH_MAX_BLOCKS 256
+
+typedef struct
+{
+ //Flash Id
+ uint16 valid_flash_id; // = FLASH_VALID_ID
+
+ uint16 block_count; //Number of flash data blocks
+
+ uint32 total_file_length; // header + block[0 - block_count]
+
+} FlashFileHeader;
+
+typedef struct
+{
+ uint32 start_address; // 24 bit address
+ uint16 data_length; // length of following data
+
+ //Followed by data_length bytes of the actual data.
+
+} FlashFileBlockHeader;
+
+//-----------------------------------------------------------------------------
+// Local Data
+//-----------------------------------------------------------------------------
+static FlashFileBlockHeader blocks[FLASH_MAX_BLOCKS];
+static uint16 block_count;
+
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// optimise_blocks()
+//-----------------------------------------------------------------------------
+static void optimise_blocks(void)
+{
+ int i, j;
+
+ // Bubble Sort by address
+ for (i = 0; i < block_count - 1; i++)
+ {
+ for (j = i + 1; j < block_count; j++)
+ {
+ //Swap?
+ if (blocks[i].start_address > blocks[j].start_address)
+ {
+ uint32 temp32;
+ uint16 temp16;
+
+ temp32 = blocks[i].start_address;
+ blocks[i].start_address = blocks[j].start_address;
+ blocks[j].start_address = temp32;
+
+ temp16 = blocks[i].data_length;
+ blocks[i].data_length = blocks[j].data_length;
+ blocks[j].data_length = temp16;
+ }
+ }
+ }
+
+ //Join contiguous blocks
+ //Only advance 'i' if required, this will allow subsequent
+ //blocks to be compared to the newly expanded block.
+ for (i = 0; i < block_count - 1; /**/)
+ {
+ //Next block lies within (or borders) this one?
+ if (blocks[i + 1].start_address <=
+ (blocks[i].start_address + blocks[i].data_length))
+ {
+ //Extend the first block
+ blocks[i].data_length =
+ (uint16)((blocks[i + 1].start_address + blocks[i + 1].data_length) -
+ blocks[i].start_address);
+
+ //Remove the next one.
+ for (j = i + 2; j < block_count; j++)
+ {
+ blocks[j - 1].start_address = blocks[j].start_address;
+ blocks[j - 1].data_length = blocks[j].data_length;
+ }
+ block_count--;
+ }
+ else
+ {
+ i++; // Try the next block
+ }
+ }
+}
+
+static bool do_flash_read(const uint8 *flashdata)
+{
+ FlashFileHeader header;
+ const uint8 *fileptr;
+ uint16 i;
+ uint32 j;
+ bool PREV_memory_unlock_flash_write = memory_unlock_flash_write; // kludge, hack, FIXME
+
+ memcpy(&header, flashdata, sizeof(header));
+
+ if (header.block_count > FLASH_MAX_BLOCKS)
+ {
+ return false;
+ //throw MDFN_Error(0, _("FLASH header block_count(%u) > FLASH_MAX_BLOCKS!"), header.block_count);
+ }
+
+ //Read header
+ block_count = header.block_count;
+ fileptr = flashdata + sizeof(FlashFileHeader);
+
+ //Copy blocks
+ memory_unlock_flash_write = TRUE;
+ for (i = 0; i < block_count; i++)
+ {
+ FlashFileBlockHeader *current = (FlashFileBlockHeader *)fileptr;
+ fileptr += sizeof(FlashFileBlockHeader);
+
+ blocks[i].start_address = current->start_address;
+ blocks[i].data_length = current->data_length;
+
+ //Copy data
+ for (j = 0; j < blocks[i].data_length; j++)
+ {
+ storeB(blocks[i].start_address + j, *fileptr);
+ fileptr++;
+ }
+ }
+ memory_unlock_flash_write = PREV_memory_unlock_flash_write;
+
+ optimise_blocks(); //Optimise
+
+#if 0
+ //Output block list...
+ for (i = 0; i < block_count; i++)
+ printf("flash block: %06X, %d bytes\n",
+ blocks[i].start_address, blocks[i].data_length);
+#endif
+ return true;
+}
+
+bool FLASH_LoadNV(const uint8* data, uint32 size)
+{
+ FlashFileHeader header;
+ std::vector flashdata;
+
+ //Initialise the internal flash configuration
+ block_count = 0;
+
+ //Read flash buffer header
+ if (size < sizeof(FlashFileHeader))
+ return false;
+ memcpy((uint8 *)&header, data, sizeof(FlashFileHeader));
+
+ //Verify correct flash id
+ if (header.valid_flash_id != FLASH_VALID_ID)
+ {
+ return false;
+ //throw MDFN_Error(0, _("FLASH header ID is bad!"));
+ }
+
+ if (header.total_file_length < sizeof(FlashFileHeader) || header.total_file_length > 16384 * 1024)
+ {
+ return false;
+ //throw MDFN_Error(0, _("FLASH header total_file_length is bad!"));
+ }
+
+ if (size < sizeof(FlashFileHeader) + header.total_file_length)
+ return false;
+
+ flashdata.resize(header.total_file_length);
+ memcpy(&flashdata[0], data + sizeof(FlashFileHeader), flashdata.size());
+
+ if (!do_flash_read(&flashdata[0]))
+ return false;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// flash_write()
+//-----------------------------------------------------------------------------
+void flash_write(uint32 start_address, uint16 length)
+{
+ /*uint16 i;
+
+ //Now we need a new flash command before the next flash write will work!
+ memory_flash_command = FALSE;
+
+ // system_debug_message("flash write: %06X, %d bytes", start_address, length);
+
+ for (i = 0; i < block_count; i++)
+ {
+ //Got this block with enough bytes to cover it
+ if (blocks[i].start_address == start_address &&
+ blocks[i].data_length >= length)
+ {
+ return; //Nothing to do, block already registered.
+ }
+
+ //Got this block with but it's length is too short
+ if (blocks[i].start_address == start_address &&
+ blocks[i].data_length < length)
+ {
+ blocks[i].data_length = length; //Enlarge block updating.
+ return;
+ }
+ }
+
+ if (block_count >= FLASH_MAX_BLOCKS)
+ {
+ MDFN_PrintError(_("[FLASH] Block list overflow!"));
+ return;
+ }
+ else
+ {
+ // New block needs to be added
+ blocks[block_count].start_address = start_address;
+ blocks[block_count].data_length = length;
+ block_count++;
+ }*/
+}
+
+static void make_flash_commit(std::vector &flashdata)
+{
+ FlashFileHeader header;
+ uint8 *fileptr;
+
+ flashdata.clear();
+
+ //No flash data?
+ if (block_count == 0)
+ return;
+
+ //Optimise before writing
+ optimise_blocks();
+
+ //Build a header;
+ header.valid_flash_id = FLASH_VALID_ID;
+ header.block_count = block_count;
+ header.total_file_length = sizeof(FlashFileHeader);
+ for (int i = 0; i < block_count; i++)
+ {
+ header.total_file_length += sizeof(FlashFileBlockHeader);
+ header.total_file_length += blocks[i].data_length;
+ }
+
+ //Write the flash data
+ flashdata.resize(header.total_file_length);
+
+ //Copy header
+ memcpy(&flashdata[0], &header, sizeof(FlashFileHeader));
+ fileptr = &flashdata[0] + sizeof(FlashFileHeader);
+
+ //Copy blocks
+ for (int i = 0; i < block_count; i++)
+ {
+ memcpy(fileptr, &blocks[i], sizeof(FlashFileBlockHeader));
+ fileptr += sizeof(FlashFileBlockHeader);
+
+ //Copy data
+ for (uint32 j = 0; j < blocks[i].data_length; j++)
+ {
+ *fileptr = loadB(blocks[i].start_address + j);
+ fileptr++;
+ }
+ }
+}
+
+void FLASH_SaveNV(void (*callback)(const uint8* data, uint32 size))
+{
+ std::vector flashdata;
+
+ make_flash_commit(flashdata);
+
+ if (flashdata.size() > 0)
+ {
+ callback(&flashdata[0], flashdata.size());
+ }
+}
+}
diff --git a/waterbox/ngp/flash.h b/waterbox/ngp/flash.h
new file mode 100644
index 0000000000..eebe6d312c
--- /dev/null
+++ b/waterbox/ngp/flash.h
@@ -0,0 +1,30 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP_FLASH__
+#define __NEOPOP_FLASH__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+//Marks flash blocks for saving.
+void flash_write(uint32 start_address, uint16 length);
+
+bool FLASH_LoadNV(const uint8* data, uint32 size);
+void FLASH_SaveNV(void (*callback)(const uint8* data, uint32 size));
+}
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/gfx.cpp b/waterbox/ngp/gfx.cpp
new file mode 100644
index 0000000000..36380ddd40
--- /dev/null
+++ b/waterbox/ngp/gfx.cpp
@@ -0,0 +1,474 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "mem.h"
+#include "gfx.h"
+#include "interrupt.h"
+#include "dma.h"
+
+namespace MDFN_IEN_NGP
+{
+
+NGPGFX_CLASS::NGPGFX_CLASS(void)
+{
+ layer_enable_setting = 1 | 2 | 4;
+
+ for (int x = 0; x < 4096; x++)
+ {
+ int r = (x & 0xF) * 17;
+ int g = ((x >> 4) & 0xF) * 17;
+ int b = ((x >> 8) & 0xF) * 17;
+
+ ColorMap[x] = r | g << 8 | b << 16 | 0xff000000;
+ }
+}
+
+NGPGFX_CLASS::~NGPGFX_CLASS()
+{
+}
+
+void NGPGFX_CLASS::reset(void)
+{
+ memset(SPPLT, 0x7, sizeof(SPPLT));
+ memset(SCRP1PLT, 0x7, sizeof(SCRP1PLT));
+ memset(SCRP2PLT, 0x7, sizeof(SCRP2PLT));
+
+ raster_line = 0;
+ S1SO_H = 0;
+ S1SO_V = 0;
+ S2SO_H = 0;
+ S2SO_V = 0;
+ WBA_H = 0;
+ WBA_V = 0;
+
+ WSI_H = 0xFF;
+ WSI_V = 0xFF;
+
+ C_OVR = 0;
+ BLNK = 0;
+
+ PO_H = 0;
+ PO_V = 0;
+ P_F = 0;
+
+ BG_COL = 0x7;
+ CONTROL_2D = 0;
+ CONTROL_INT = 0;
+ SCREEN_PERIOD = 0xC6;
+ K2GE_MODE = 0;
+
+ delayed_settings();
+}
+
+void NGPGFX_CLASS::power(void)
+{
+ reset();
+
+ memset(ScrollVRAM, 0, sizeof(ScrollVRAM));
+ memset(CharacterRAM, 0, sizeof(CharacterRAM));
+ memset(SpriteVRAM, 0, sizeof(SpriteVRAM));
+ memset(SpriteVRAMColor, 0, sizeof(SpriteVRAMColor));
+ memset(ColorPaletteRAM, 0, sizeof(ColorPaletteRAM));
+}
+
+void NGPGFX_CLASS::delayed_settings(void)
+{
+ //Window dimensions
+ winx = WBA_H;
+ winy = WBA_V;
+ winw = WSI_H;
+ winh = WSI_V;
+
+ //Scroll Planes (Confirmed delayed)
+ scroll1x = S1SO_H;
+ scroll1y = S1SO_V;
+
+ scroll2x = S2SO_H;
+ scroll2y = S2SO_V;
+
+ //Sprite offset (Confirmed delayed)
+ scrollsprx = PO_H;
+ scrollspry = PO_V;
+
+ //Plane Priority (Confirmed delayed)
+ planeSwap = P_F & 0x80;
+
+ //Background colour register (Confirmed delayed)
+ bgc = BG_COL;
+
+ //2D Control register (Confirmed delayed)
+ oowc = CONTROL_2D & 7;
+ negative = CONTROL_2D & 0x80;
+}
+
+bool NGPGFX_CLASS::hint(void)
+{
+ //H_Int / Delayed settings
+ if ((raster_line < SCREEN_HEIGHT - 1 || raster_line == SCREEN_PERIOD))
+ {
+ delayed_settings(); //Get delayed settings
+
+ //Allowed?
+ if (CONTROL_INT & 0x40)
+ return (1);
+ }
+ return (0);
+}
+
+bool NGPGFX_CLASS::draw(MDFN_Surface *surface, bool skip)
+{
+ bool ret = 0;
+
+ //Draw the scanline
+ if (raster_line < SCREEN_HEIGHT && !skip)
+ {
+ if (!K2GE_MODE)
+ draw_scanline_colour(layer_enable_setting, raster_line);
+ else
+ draw_scanline_mono(layer_enable_setting, raster_line);
+
+ uint32 *dest = surface->pixels + surface->pitch32 * raster_line;
+ for (int x = 0; x < SCREEN_WIDTH; x++)
+ dest[x] = ColorMap[cfb_scanline[x] & 4095];
+ }
+ raster_line++;
+
+ //V_Int?
+ if (raster_line == SCREEN_HEIGHT)
+ {
+ BLNK = 1;
+ ret = 1;
+
+ if (CONTROL_INT & 0x80) // (statusIFF() <= 4
+ TestIntHDMA(5, 0x0B);
+ }
+
+ //End of V_Int
+ if (raster_line == SCREEN_PERIOD + 1) //Last scanline + 1
+ {
+ raster_line = 0;
+ C_OVR = 0;
+ BLNK = 0;
+ }
+
+ return (ret);
+}
+
+void NGPGFX_CLASS::SetLayerEnableMask(uint64 mask)
+{
+ layer_enable_setting = mask;
+}
+
+//extern uint32 ngpc_soundTS;
+void NGPGFX_CLASS::write8(uint32 address, uint8 data)
+{
+ //if(address >= 0x8032 && address <= 0x8035)
+ // printf("%08x %02x %d\n", address, data, ngpc_soundTS);
+
+ if (address >= 0x9000 && address <= 0x9fff)
+ ScrollVRAM[address - 0x9000] = data;
+ else if (address >= 0xa000 && address <= 0xbfff)
+ CharacterRAM[address - 0xa000] = data;
+ else if (address >= 0x8800 && address <= 0x88ff)
+ SpriteVRAM[address - 0x8800] = data;
+ else if (address >= 0x8c00 && address <= 0x8c3f)
+ SpriteVRAMColor[address - 0x8c00] = data & 0x0f;
+ else if (address >= 0x8200 && address <= 0x83ff)
+ ColorPaletteRAM[address - 0x8200] = data;
+ else
+ switch (address)
+ {
+ //default: printf("HuhW: %08x\n", address); break;
+
+ case 0x8000:
+ CONTROL_INT = data & 0xC0;
+ break;
+ case 0x8002:
+ WBA_H = data;
+ break;
+ case 0x8003:
+ WBA_V = data;
+ break;
+ case 0x8004:
+ WSI_H = data;
+ break;
+ case 0x8005:
+ WSI_V = data;
+ break;
+ case 0x8006:
+ SCREEN_PERIOD = data;
+ break;
+ case 0x8012:
+ CONTROL_2D = data & 0x87;
+ break;
+ case 0x8020:
+ PO_H = data;
+ break;
+ case 0x8021:
+ PO_V = data;
+ break;
+ case 0x8030:
+ P_F = data & 0x80;
+ break;
+ case 0x8032:
+ S1SO_H = data;
+ break;
+ case 0x8033:
+ S1SO_V = data;
+ break;
+ case 0x8034:
+ S2SO_H = data;
+ break;
+ case 0x8035:
+ S2SO_V = data;
+ break;
+
+ case 0x8101:
+ SPPLT[0] = data & 0x7;
+ break;
+ case 0x8102:
+ SPPLT[1] = data & 0x7;
+ break;
+ case 0x8103:
+ SPPLT[2] = data & 0x7;
+ break;
+
+ case 0x8105:
+ SPPLT[3] = data & 0x7;
+ break;
+ case 0x8106:
+ SPPLT[4] = data & 0x7;
+ break;
+ case 0x8107:
+ SPPLT[5] = data & 0x7;
+ break;
+
+ case 0x8109:
+ SCRP1PLT[0] = data & 0x7;
+ break;
+ case 0x810a:
+ SCRP1PLT[1] = data & 0x7;
+ break;
+ case 0x810b:
+ SCRP1PLT[2] = data & 0x7;
+ break;
+
+ case 0x810d:
+ SCRP1PLT[3] = data & 0x7;
+ break;
+ case 0x810e:
+ SCRP1PLT[4] = data & 0x7;
+ break;
+ case 0x810f:
+ SCRP1PLT[5] = data & 0x7;
+ break;
+
+ case 0x8111:
+ SCRP2PLT[0] = data & 0x7;
+ break;
+ case 0x8112:
+ SCRP2PLT[1] = data & 0x7;
+ break;
+ case 0x8113:
+ SCRP2PLT[2] = data & 0x7;
+ break;
+
+ case 0x8115:
+ SCRP2PLT[3] = data & 0x7;
+ break;
+ case 0x8116:
+ SCRP2PLT[4] = data & 0x7;
+ break;
+ case 0x8117:
+ SCRP2PLT[5] = data & 0x7;
+ break;
+
+ case 0x8118:
+ BG_COL = data & 0xC7;
+ break;
+
+ case 0x87e0:
+ if (data == 0x52)
+ {
+ puts("GEreset");
+ reset();
+ }
+ break;
+ case 0x87e2:
+ K2GE_MODE = data & 0x80;
+ break;
+ }
+}
+
+void NGPGFX_CLASS::write16(uint32 address, uint16 data)
+{
+ write8(address, data & 0xFF);
+ write8(address + 1, data >> 8);
+}
+
+#if 0
+namespace TLCS900H
+{
+ extern uint32 pc;
+};
+#endif
+
+uint8 NGPGFX_CLASS::read8(uint32 address)
+{
+#if 0
+ if(address >= 0x8200 && address <= 0xbfff)
+ {
+ printf("[GFX] Read8: %08x -- %08x\n", address, TLCS900H::pc);
+ if(pc == 0x0028dd3d) //21)
+ {
+ TLCS900H::pc = 0x28DD15;
+ for(int x = 0; x < 256; x++)
+ puts(TLCS900h_disassemble());
+
+ abort();
+ }
+ }
+#endif
+
+ if (address >= 0x9000 && address <= 0x9fff)
+ return (ScrollVRAM[address - 0x9000]);
+ else if (address >= 0xa000 && address <= 0xbfff)
+ return (CharacterRAM[address - 0xa000]);
+ else if (address >= 0x8800 && address <= 0x88ff)
+ return (SpriteVRAM[address - 0x8800]);
+ else if (address >= 0x8c00 && address <= 0x8c3f)
+ return (SpriteVRAMColor[address - 0x8c00]);
+ else if (address >= 0x8200 && address <= 0x83ff)
+ return (ColorPaletteRAM[address - 0x8200]);
+ else
+ switch (address)
+ {
+ //default: printf("Huh: %08x\n", address); break;
+ case 0x8000:
+ return (CONTROL_INT);
+ case 0x8002:
+ return (WBA_H);
+ case 0x8003:
+ return (WBA_V);
+ case 0x8004:
+ return (WSI_H);
+ case 0x8005:
+ return (WSI_V);
+ case 0x8006:
+ return (SCREEN_PERIOD);
+
+ case 0x8008:
+ return ((uint8)((abs(TIMER_HINT_RATE - (int)timer_hint)) >> 2)); //RAS.H read (Simulated horizontal raster position)
+ case 0x8009:
+ return (raster_line);
+ case 0x8010:
+ return ((C_OVR ? 0x80 : 0x00) | (BLNK ? 0x40 : 0x00));
+ case 0x8012:
+ return (CONTROL_2D);
+ case 0x8020:
+ return (PO_H);
+ case 0x8021:
+ return (PO_V);
+ case 0x8030:
+ return (P_F);
+ case 0x8032:
+ return (S1SO_H);
+ case 0x8033:
+ return (S1SO_V);
+ case 0x8034:
+ return (S2SO_H);
+ case 0x8035:
+ return (S2SO_V);
+
+ case 0x8101:
+ return (SPPLT[0]);
+ break;
+ case 0x8102:
+ return (SPPLT[1]);
+ break;
+ case 0x8103:
+ return (SPPLT[2]);
+ break;
+
+ case 0x8105:
+ return (SPPLT[3]);
+ break;
+ case 0x8106:
+ return (SPPLT[4]);
+ break;
+ case 0x8107:
+ return (SPPLT[5]);
+ break;
+
+ case 0x8108:
+ return (SCRP1PLT[0]);
+ break;
+ case 0x8109:
+ return (SCRP1PLT[1]);
+ break;
+ case 0x810a:
+ return (SCRP1PLT[2]);
+ break;
+
+ case 0x810d:
+ return (SCRP1PLT[3]);
+ break;
+ case 0x810e:
+ return (SCRP1PLT[4]);
+ break;
+ case 0x810f:
+ return (SCRP1PLT[5]);
+ break;
+
+ case 0x8111:
+ return (SCRP2PLT[0]);
+ break;
+ case 0x8112:
+ return (SCRP2PLT[1]);
+ break;
+ case 0x8113:
+ return (SCRP2PLT[2]);
+ break;
+
+ case 0x8115:
+ return (SCRP2PLT[3]);
+ break;
+ case 0x8116:
+ return (SCRP2PLT[4]);
+ break;
+ case 0x8117:
+ return (SCRP2PLT[5]);
+ break;
+
+ case 0x8118:
+ return (BG_COL);
+
+ case 0x87e2:
+ return (K2GE_MODE);
+ }
+
+ return (0);
+}
+
+uint16 NGPGFX_CLASS::read16(uint32 address)
+{
+ uint16 ret;
+
+ ret = read8(address);
+ ret |= read8(address + 1) << 8;
+
+ return (ret);
+}
+}
diff --git a/waterbox/ngp/gfx.h b/waterbox/ngp/gfx.h
new file mode 100644
index 0000000000..aac7a9deab
--- /dev/null
+++ b/waterbox/ngp/gfx.h
@@ -0,0 +1,105 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP_GFX__
+#define __NEOPOP_GFX__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+#define ZDEPTH_BACK_SPRITE 2
+#define ZDEPTH_BACKGROUND_SCROLL 3
+#define ZDEPTH_MIDDLE_SPRITE 4
+#define ZDEPTH_FOREGROUND_SCROLL 5
+#define ZDEPTH_FRONT_SPRITE 6
+
+class NGPGFX_CLASS
+{
+ public:
+ NGPGFX_CLASS()
+ MDFN_COLD;
+ ~NGPGFX_CLASS() MDFN_COLD;
+
+ void write8(uint32 address, uint8 data);
+ void write16(uint32 address, uint16 data);
+
+ uint8 read8(uint32 address);
+ uint16 read16(uint32 address);
+
+ void SetLayerEnableMask(uint64 mask);
+
+ bool draw(MDFN_Surface *surface, bool skip);
+ bool hint(void);
+
+ void power(void);
+
+ private:
+ // TODO: Alignment for faster memset
+ uint8 zbuffer[256]; // __attribute__ ((aligned (8))); //Line z-buffer
+ uint16 cfb_scanline[256]; // __attribute__ ((aligned (8)));
+
+ uint8 winx, winw;
+ uint8 winy, winh;
+ uint8 scroll1x, scroll1y;
+ uint8 scroll2x, scroll2y;
+ uint8 scrollsprx, scrollspry;
+ uint8 planeSwap;
+ uint8 bgc, oowc, negative;
+
+ void reset(void);
+ void delayed_settings(void);
+
+ void draw_scanline_colour(int, int);
+ void drawColourPattern(uint8 screenx, uint16 tile, uint8 tiley, uint16 mirror,
+ uint16 *palette_ptr, uint8 pal, uint8 depth);
+ void draw_colour_scroll1(uint8 depth, int ngpc_scanline);
+ void draw_colour_scroll2(uint8 depth, int ngpc_scanline);
+
+ void draw_scanline_mono(int, int);
+ void MonoPlot(uint8 x, uint8 *palette_ptr, uint16 pal_hi, uint8 index, uint8 depth);
+ void drawMonoPattern(uint8 screenx, uint16 tile, uint8 tiley, uint16 mirror,
+ uint8 *palette_ptr, uint16 pal, uint8 depth);
+ void draw_mono_scroll1(uint8 depth, int ngpc_scanline);
+ void draw_mono_scroll2(uint8 depth, int ngpc_scanline);
+
+ uint8 ScrollVRAM[4096]; // 9000-9fff
+ uint8 CharacterRAM[8192]; // a000-bfff
+ uint8 SpriteVRAM[256]; // 8800-88ff
+ uint8 SpriteVRAMColor[0x40]; // 8C00-8C3F
+ uint8 ColorPaletteRAM[0x200]; // 8200-83ff
+
+ uint8 SPPLT[6];
+ uint8 SCRP1PLT[6];
+ uint8 SCRP2PLT[6];
+
+ uint8 raster_line;
+ uint8 S1SO_H, S1SO_V, S2SO_H, S2SO_V;
+ uint8 WBA_H, WBA_V, WSI_H, WSI_V;
+ bool C_OVR, BLNK;
+ uint8 PO_H, PO_V;
+ uint8 P_F;
+ uint8 BG_COL;
+ uint8 CONTROL_2D;
+ uint8 CONTROL_INT;
+ uint8 SCREEN_PERIOD;
+ uint8 K2GE_MODE;
+
+ uint32 ColorMap[4096];
+
+ int layer_enable_setting;
+};
+}
+
+#endif
diff --git a/waterbox/ngp/gfx_scanline_colour.cpp b/waterbox/ngp/gfx_scanline_colour.cpp
new file mode 100644
index 0000000000..272f1491c5
--- /dev/null
+++ b/waterbox/ngp/gfx_scanline_colour.cpp
@@ -0,0 +1,270 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "mem.h"
+#include "gfx.h"
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+static const unsigned char mirrored[] = {
+ 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
+ 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0,
+ 0x04, 0x44, 0x84, 0xc4, 0x14, 0x54, 0x94, 0xd4,
+ 0x24, 0x64, 0xa4, 0xe4, 0x34, 0x74, 0xb4, 0xf4,
+ 0x08, 0x48, 0x88, 0xc8, 0x18, 0x58, 0x98, 0xd8,
+ 0x28, 0x68, 0xa8, 0xe8, 0x38, 0x78, 0xb8, 0xf8,
+ 0x0c, 0x4c, 0x8c, 0xcc, 0x1c, 0x5c, 0x9c, 0xdc,
+ 0x2c, 0x6c, 0xac, 0xec, 0x3c, 0x7c, 0xbc, 0xfc,
+ 0x01, 0x41, 0x81, 0xc1, 0x11, 0x51, 0x91, 0xd1,
+ 0x21, 0x61, 0xa1, 0xe1, 0x31, 0x71, 0xb1, 0xf1,
+ 0x05, 0x45, 0x85, 0xc5, 0x15, 0x55, 0x95, 0xd5,
+ 0x25, 0x65, 0xa5, 0xe5, 0x35, 0x75, 0xb5, 0xf5,
+ 0x09, 0x49, 0x89, 0xc9, 0x19, 0x59, 0x99, 0xd9,
+ 0x29, 0x69, 0xa9, 0xe9, 0x39, 0x79, 0xb9, 0xf9,
+ 0x0d, 0x4d, 0x8d, 0xcd, 0x1d, 0x5d, 0x9d, 0xdd,
+ 0x2d, 0x6d, 0xad, 0xed, 0x3d, 0x7d, 0xbd, 0xfd,
+ 0x02, 0x42, 0x82, 0xc2, 0x12, 0x52, 0x92, 0xd2,
+ 0x22, 0x62, 0xa2, 0xe2, 0x32, 0x72, 0xb2, 0xf2,
+ 0x06, 0x46, 0x86, 0xc6, 0x16, 0x56, 0x96, 0xd6,
+ 0x26, 0x66, 0xa6, 0xe6, 0x36, 0x76, 0xb6, 0xf6,
+ 0x0a, 0x4a, 0x8a, 0xca, 0x1a, 0x5a, 0x9a, 0xda,
+ 0x2a, 0x6a, 0xaa, 0xea, 0x3a, 0x7a, 0xba, 0xfa,
+ 0x0e, 0x4e, 0x8e, 0xce, 0x1e, 0x5e, 0x9e, 0xde,
+ 0x2e, 0x6e, 0xae, 0xee, 0x3e, 0x7e, 0xbe, 0xfe,
+ 0x03, 0x43, 0x83, 0xc3, 0x13, 0x53, 0x93, 0xd3,
+ 0x23, 0x63, 0xa3, 0xe3, 0x33, 0x73, 0xb3, 0xf3,
+ 0x07, 0x47, 0x87, 0xc7, 0x17, 0x57, 0x97, 0xd7,
+ 0x27, 0x67, 0xa7, 0xe7, 0x37, 0x77, 0xb7, 0xf7,
+ 0x0b, 0x4b, 0x8b, 0xcb, 0x1b, 0x5b, 0x9b, 0xdb,
+ 0x2b, 0x6b, 0xab, 0xeb, 0x3b, 0x7b, 0xbb, 0xfb,
+ 0x0f, 0x4f, 0x8f, 0xcf, 0x1f, 0x5f, 0x9f, 0xdf,
+ 0x2f, 0x6f, 0xaf, 0xef, 0x3f, 0x7f, 0xbf, 0xff
+};
+
+//=============================================================================
+
+
+void NGPGFX_CLASS::drawColourPattern(uint8 screenx, uint16 tile, uint8 tiley, uint16 mirror,
+ uint16* palette_ptr, uint8 pal, uint8 depth)
+{
+ int index, x, left, right, highmark, xx;
+ uint16 data16;
+
+ x = screenx;
+ if (x > 0xf8)
+ x -= 256;
+ if (x >= SCREEN_WIDTH)
+ return;
+
+ //Get the data for the "tiley'th" line of "tile".
+ index = MDFN_de16lsb(CharacterRAM + (tile * 16) + (tiley * 2));
+
+ //Horizontal Flip
+ if (mirror)
+ index = mirrored[(index & 0xff00)>>8] | (mirrored[(index & 0xff)] << 8);
+
+ palette_ptr += pal << 2;
+ left = max(max(x, winx), 0);
+ right = x+7;
+
+ highmark = min(winw+winx, SCREEN_WIDTH)-1;
+
+ if (right > highmark) {
+ index >>= (right - highmark)*2;
+ right = highmark;
+ }
+
+ for (xx=right; xx>=left; --xx,index>>=2) {
+ if (depth <= zbuffer[xx] || (index&3)==0)
+ continue;
+ zbuffer[xx] = depth;
+
+ //Get the colour of the pixel
+ data16 = MDFN_de16lsb(&palette_ptr[index&3]);
+
+ if (negative)
+ cfb_scanline[xx] = ~data16;
+ else
+ cfb_scanline[xx] = data16;
+ }
+}
+
+void NGPGFX_CLASS::draw_colour_scroll1(uint8 depth, int ngpc_scanline)
+{
+ uint8 tx, row, line;
+ uint16 data16;
+
+ line = ngpc_scanline + scroll1y;
+ row = line & 7; //Which row?
+
+ //Draw Foreground scroll plane (Scroll 1)
+ for (tx = 0; tx < 32; tx++)
+ {
+ data16 = MDFN_de16lsb(ScrollVRAM + ((tx + ((line >> 3) << 5)) << 1));
+
+ //Draw the line of the tile
+ drawColourPattern((tx << 3) - scroll1x, data16 & 0x01FF,
+ (data16 & 0x4000) ? (7 - row) : row, data16 & 0x8000, (uint16*)(ColorPaletteRAM + 0x0080),
+ (data16 & 0x1E00) >> 9, depth);
+ }
+}
+
+void NGPGFX_CLASS::draw_colour_scroll2(uint8 depth, int ngpc_scanline)
+{
+ uint8 tx, row, line;
+ uint16 data16;
+
+ line = ngpc_scanline + scroll2y;
+ row = line & 7; //Which row?
+
+ //Draw Background scroll plane (Scroll 2)
+ for (tx = 0; tx < 32; tx++)
+ {
+ data16 = MDFN_de16lsb(ScrollVRAM + 0x0800 + ((tx + ((line >> 3) << 5)) << 1));
+
+ //Draw the line of the tile
+ drawColourPattern((tx << 3) - scroll2x, data16 & 0x01FF,
+ (data16 & 0x4000) ? (7 - row) : row, data16 & 0x8000, (uint16*)(ColorPaletteRAM + 0x0100),
+ (data16 & 0x1E00) >> 9, depth);
+ }
+}
+
+void NGPGFX_CLASS::draw_scanline_colour(int layer_enable, int ngpc_scanline)
+{
+ int16 lastSpriteX;
+ int16 lastSpriteY;
+ int spr;
+ uint16 win_color;
+
+ memset(cfb_scanline, 0, SCREEN_WIDTH * sizeof(uint16));
+ memset(zbuffer, 0, SCREEN_WIDTH);
+
+ //Window colour
+ win_color = MDFN_de16lsb(ColorPaletteRAM + 0x01F0 + (oowc << 1));
+ if (negative) win_color = ~win_color;
+
+ //Top
+ if (ngpc_scanline < winy)
+ {
+ for (int x = 0; x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = win_color;
+ }
+ else
+ {
+ //Middle
+ if (ngpc_scanline < winy + winh)
+ {
+ for (int x = 0; x < min(winx, SCREEN_WIDTH); x++)
+ cfb_scanline[x] = win_color;
+
+ for (int x = min(winx + winw, SCREEN_WIDTH); x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = win_color;
+ }
+ else //Bottom
+ {
+ for (int x = 0; x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = win_color;
+ }
+ }
+
+ //Ignore above and below the window's top and bottom
+ if (ngpc_scanline >= winy && ngpc_scanline < winy + winh)
+ {
+ //Background colour Enabled? HACK: 01 AUG 2002 - Always on!
+ // if ((bgc & 0xC0) == 0x80)
+ {
+ win_color = MDFN_de16lsb(ColorPaletteRAM + 0x01E0 + ((bgc & 7) << 1));
+ }
+ // else win_color = 0;
+
+ if (negative) win_color = ~win_color;
+
+ //Draw background!
+ for (int x = winx; x < min(winx + winw, SCREEN_WIDTH); x++)
+ cfb_scanline[x] = win_color;
+
+ //Swap Front/Back scroll planes?
+ if (planeSwap)
+ {
+ if(layer_enable & 1)
+ draw_colour_scroll1(ZDEPTH_BACKGROUND_SCROLL, ngpc_scanline); //Swap
+ if(layer_enable & 2)
+ draw_colour_scroll2(ZDEPTH_FOREGROUND_SCROLL, ngpc_scanline);
+ }
+ else
+ {
+ if(layer_enable & 1)
+ draw_colour_scroll2(ZDEPTH_BACKGROUND_SCROLL, ngpc_scanline); //Normal
+ if(layer_enable & 2)
+ draw_colour_scroll1(ZDEPTH_FOREGROUND_SCROLL, ngpc_scanline);
+ }
+
+ //Draw Sprites
+ //Last sprite position, (defaults to top-left, sure?)
+ lastSpriteX = 0;
+ lastSpriteY = 0;
+
+ if(layer_enable & 4)
+ for (spr = 0; spr < 64; spr++)
+ {
+ uint8 priority, row;
+ uint8 sx = SpriteVRAM[(spr * 4) + 2]; //X position
+ uint8 sy = SpriteVRAM[(spr * 4) + 3]; //Y position
+ int16 x = sx;
+ int16 y = sy;
+ uint16 data16;
+
+ data16 = MDFN_de16lsb(SpriteVRAM + (spr * 4));
+ priority = (data16 & 0x1800) >> 11;
+
+ if (data16 & 0x0400) x = lastSpriteX + sx; //Horizontal chain?
+ if (data16 & 0x0200) y = lastSpriteY + sy; //Vertical chain?
+
+ //Store the position for chaining
+ lastSpriteX = x;
+ lastSpriteY = y;
+
+ //Visible?
+ if (priority == 0) continue;
+
+ //Scroll the sprite
+ x += scrollsprx;
+ y += scrollspry;
+
+ //Off-screen?
+ if (x > 248 && x < 256) x = x - 256; else x &= 0xFF;
+ if (y > 248 && y < 256) y = y - 256; else y &= 0xFF;
+
+ //In range?
+ if (ngpc_scanline >= y && ngpc_scanline <= y + 7)
+ {
+ row = (ngpc_scanline - y) & 7; //Which row?
+ drawColourPattern((uint8)x, data16 & 0x01FF,
+ (data16 & 0x4000) ? 7 - row : row, data16 & 0x8000,
+ (uint16*)ColorPaletteRAM, SpriteVRAMColor[spr] & 0xF, priority << 1);
+ }
+ }
+
+ //==========
+ }
+
+}
+
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/gfx_scanline_mono.cpp b/waterbox/ngp/gfx_scanline_mono.cpp
new file mode 100644
index 0000000000..549a0b8e71
--- /dev/null
+++ b/waterbox/ngp/gfx_scanline_mono.cpp
@@ -0,0 +1,253 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "mem.h"
+#include "gfx.h"
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+void NGPGFX_CLASS::MonoPlot(uint8 x, uint8* palette_ptr, uint16 pal_hi, uint8 index, uint8 depth)
+{
+ uint8 data8;
+
+ //Clip
+ if (index == 0 || x < winx || x >= (winw + winx) || x >= SCREEN_WIDTH)
+ return;
+
+ //Depth check, <= to stop later sprites overwriting pixels!
+ if (depth <= zbuffer[x]) return;
+ zbuffer[x] = depth;
+
+ //Get the colour of the pixel
+ if (pal_hi)
+ data8 = palette_ptr[3 + index - 1];
+ else
+ data8 = palette_ptr[0 + index - 1];
+
+ uint16 r = (data8 & 7) << 1;
+ uint16 g = (data8 & 7) << 5;
+ uint16 b = (data8 & 7) << 9;
+
+ if (negative)
+ cfb_scanline[x] = (r | g | b);
+ else
+ cfb_scanline[x] = ~(r | g | b);
+}
+
+void NGPGFX_CLASS::drawMonoPattern(uint8 screenx, uint16 tile, uint8 tiley, uint16 mirror,
+ uint8* palette_ptr, uint16 pal, uint8 depth)
+{
+ //Get the data for th e "tiley'th" line of "tile".
+ uint16 data = MDFN_de16lsb(CharacterRAM + (tile * 16) + (tiley * 2));
+
+ //Horizontal Flip
+ if (mirror)
+ {
+ MonoPlot(screenx + 7, palette_ptr, pal, (data & 0xC000) >> 0xE, depth);
+ MonoPlot(screenx + 6, palette_ptr, pal, (data & 0x3000) >> 0xC, depth);
+ MonoPlot(screenx + 5, palette_ptr, pal, (data & 0x0C00) >> 0xA, depth);
+ MonoPlot(screenx + 4, palette_ptr, pal, (data & 0x0300) >> 0x8, depth);
+ MonoPlot(screenx + 3, palette_ptr, pal, (data & 0x00C0) >> 0x6, depth);
+ MonoPlot(screenx + 2, palette_ptr, pal, (data & 0x0030) >> 0x4, depth);
+ MonoPlot(screenx + 1, palette_ptr, pal, (data & 0x000C) >> 0x2, depth);
+ MonoPlot(screenx + 0, palette_ptr, pal, (data & 0x0003) >> 0x0, depth);
+ }
+ else
+ //Normal
+ {
+ MonoPlot(screenx + 0, palette_ptr, pal, (data & 0xC000) >> 0xE, depth);
+ MonoPlot(screenx + 1, palette_ptr, pal, (data & 0x3000) >> 0xC, depth);
+ MonoPlot(screenx + 2, palette_ptr, pal, (data & 0x0C00) >> 0xA, depth);
+ MonoPlot(screenx + 3, palette_ptr, pal, (data & 0x0300) >> 0x8, depth);
+ MonoPlot(screenx + 4, palette_ptr, pal, (data & 0x00C0) >> 0x6, depth);
+ MonoPlot(screenx + 5, palette_ptr, pal, (data & 0x0030) >> 0x4, depth);
+ MonoPlot(screenx + 6, palette_ptr, pal, (data & 0x000C) >> 0x2, depth);
+ MonoPlot(screenx + 7, palette_ptr, pal, (data & 0x0003) >> 0x0, depth);
+ }
+}
+
+void NGPGFX_CLASS::draw_mono_scroll1(uint8 depth, int ngpc_scanline)
+{
+ uint8 tx, row, line;
+ uint16 data16;
+
+ line = ngpc_scanline + scroll1y;
+ row = line & 7; //Which row?
+
+ //Draw Foreground scroll plane (Scroll 1)
+ for (tx = 0; tx < 32; tx++)
+ {
+ data16 = MDFN_de16lsb(ScrollVRAM + ((tx + ((line >> 3) << 5)) << 1));
+
+ //Draw the line of the tile
+ drawMonoPattern((tx << 3) - scroll1x, data16 & 0x01FF,
+ (data16 & 0x4000) ? 7 - row : row, data16 & 0x8000, SCRP1PLT,
+ data16 & 0x2000, depth);
+ }
+}
+
+void NGPGFX_CLASS::draw_mono_scroll2(uint8 depth, int ngpc_scanline)
+{
+ uint8 tx, row, line;
+ uint16 data16;
+
+ line = ngpc_scanline + scroll2y;
+ row = line & 7; //Which row?
+
+ //Draw Background scroll plane (Scroll 2)
+ for (tx = 0; tx < 32; tx++)
+ {
+ data16 = MDFN_de16lsb(ScrollVRAM + 0x0800 + ((tx + ((line >> 3) << 5)) << 1));
+
+ //Draw the line of the tile
+ drawMonoPattern((tx << 3) - scroll2x, data16 & 0x01FF,
+ (data16 & 0x4000) ? 7 - row : row, data16 & 0x8000, SCRP2PLT,
+ data16 & 0x2000, depth);
+ }
+}
+
+void NGPGFX_CLASS::draw_scanline_mono(int layer_enable, int ngpc_scanline)
+{
+ int16 lastSpriteX;
+ int16 lastSpriteY;
+ int spr;
+ uint16 data16;
+
+ memset(cfb_scanline, 0, SCREEN_WIDTH * sizeof(uint16));
+ memset(zbuffer, 0, SCREEN_WIDTH);
+
+ //Window colour
+ uint16 r = (uint16)oowc << 1;
+ uint16 g = (uint16)oowc << 5;
+ uint16 b = (uint16)oowc << 9;
+
+ if (negative)
+ data16 = (r | g | b);
+ else
+ data16 = ~(r | g | b);
+
+ //Top
+ if (ngpc_scanline < winy)
+ {
+ for (int x = 0; x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = data16;
+ }
+ else
+ {
+ //Middle
+ if (ngpc_scanline < winy + winh)
+ {
+ for (int x = 0; x < min(winx, SCREEN_WIDTH); x++)
+ cfb_scanline[x] = data16;
+ for (int x = min(winx + winw, SCREEN_WIDTH); x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = data16;
+ }
+ else //Bottom
+ {
+ for (int x = 0; x < SCREEN_WIDTH; x++)
+ cfb_scanline[x] = data16;
+ }
+ }
+
+ //Ignore above and below the window's top and bottom
+ if (ngpc_scanline >= winy && ngpc_scanline < winy + winh)
+ {
+ //Background colour Enabled?
+ if ((bgc & 0xC0) == 0x80)
+ {
+ r = (uint16)(bgc & 7) << 1;
+ g = (uint16)(bgc & 7) << 5;
+ b = (uint16)(bgc & 7) << 9;
+ data16 = ~(r | g | b);
+ }
+ else data16 = 0x0FFF;
+
+ if (negative) data16 = ~data16;
+
+ //Draw background!
+ for (int x = winx; x < min(winx + winw, SCREEN_WIDTH); x++)
+ cfb_scanline[x] = data16;
+
+ //Swap Front/Back scroll planes?
+ if (planeSwap)
+ {
+ if(layer_enable & 1)
+ draw_mono_scroll1(ZDEPTH_BACKGROUND_SCROLL, ngpc_scanline); //Swap
+ if(layer_enable & 2)
+ draw_mono_scroll2(ZDEPTH_FOREGROUND_SCROLL, ngpc_scanline);
+ }
+ else
+ {
+ if(layer_enable & 1)
+ draw_mono_scroll2(ZDEPTH_BACKGROUND_SCROLL, ngpc_scanline); //Normal
+ if(layer_enable & 2)
+ draw_mono_scroll1(ZDEPTH_FOREGROUND_SCROLL, ngpc_scanline);
+ }
+
+ //Draw Sprites
+ //Last sprite position, (defaults to top-left, sure?)
+ lastSpriteX = 0;
+ lastSpriteY = 0;
+ if(layer_enable & 4)
+ for (spr = 0; spr < 64; spr++)
+ {
+ uint8 priority, row;
+ uint8 sx = SpriteVRAM[(spr * 4) + 2]; //X position
+ uint8 sy = SpriteVRAM[(spr * 4) + 3]; //Y position
+ int16 x = sx;
+ int16 y = sy;
+
+ data16 = MDFN_de16lsb(SpriteVRAM + (spr * 4));
+ priority = (data16 & 0x1800) >> 11;
+
+ if (data16 & 0x0400) x = lastSpriteX + sx; //Horizontal chain?
+ if (data16 & 0x0200) y = lastSpriteY + sy; //Vertical chain?
+
+ //Store the position for chaining
+ lastSpriteX = x;
+ lastSpriteY = y;
+
+ //Visible?
+ if (priority == 0) continue;
+
+ //Scroll the sprite
+ x += scrollsprx;
+ y += scrollspry;
+
+ //Off-screen?
+ if (x > 248 && x < 256) x = x - 256; else x &= 0xFF;
+ if (y > 248 && y < 256) y = y - 256; else y &= 0xFF;
+
+ //In range?
+ if (ngpc_scanline >= y && ngpc_scanline <= y + 7)
+ {
+ row = (ngpc_scanline - y) & 7; //Which row?
+ drawMonoPattern((uint8)x, data16 & 0x01FF,
+ (data16 & 0x4000) ? 7 - row : row, data16 & 0x8000,
+ SPPLT, data16 & 0x2000, priority << 1);
+ }
+ }
+
+ }
+
+ //==========
+}
+
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/interrupt.cpp b/waterbox/ngp/interrupt.cpp
new file mode 100644
index 0000000000..dc96bcf784
--- /dev/null
+++ b/waterbox/ngp/interrupt.cpp
@@ -0,0 +1,598 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "mem.h"
+#include "gfx.h"
+#include "interrupt.h"
+#include "Z80_interface.h"
+#include "dma.h"
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+uint32 timer_hint;
+static uint32 timer_clock[4];
+static uint8 timer[4]; //Up-counters
+static uint8 timer_threshold[4];
+
+static uint8 TRUN;
+static uint8 T01MOD, T23MOD;
+static uint8 TRDC;
+static uint8 TFFCR;
+static uint8 HDMAStartVector[4];
+
+static int32 ipending[24];
+static int32 IntPrio[0xB]; // 0070-007a
+static bool h_int, timer0, timer2;
+
+// The way interrupt processing is set up is still written towards BIOS HLE emulation, which assumes
+// that the interrupt handler will immediately call DI, clear the interrupt latch(so the interrupt won't happen again when interrupts are re-enabled),
+// and then call the game's interrupt handler.
+
+// We automatically clear the interrupt latch when the interrupt is accepted, and the interrupt latch is not checked every instruction,
+// but only when: an EI/DI, POP SR, or RETI instruction occurs; after a write to an interrupt priority register occurs; and when
+// a device sets the virual interrupt latch register, signaling it wants an interrupt.
+
+// FIXME in the future if we ever add real bios support?
+void interrupt(uint8 index)
+{
+ //printf("INT: %d\n", index);
+ push32(pc);
+ push16(sr);
+
+ //Up the IFF
+ if (((sr & 0x7000) >> 12) < 7)
+ setStatusIFF(((sr & 0x7000) >> 12) + 1);
+
+ //Access the interrupt vector table to find the jump destination
+ pc = loadL(0x6FB8 + index * 4);
+}
+
+void set_interrupt(uint8 index, bool set)
+{
+ assert(index < 24);
+
+ ipending[index] = set;
+ int_check_pending();
+}
+
+void int_check_pending(void)
+{
+ uint8 prio;
+ uint8 curIFF = statusIFF();
+
+ // Technically, the BIOS should clear the interrupt pending flag by writing with IxxC set to "0", but
+ // we'll actually need to implement a BIOS to do that!
+
+ prio = IntPrio[0x1] & 0x07; // INT4
+ if (ipending[5] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[5] = 0;
+ interrupt(5);
+ return;
+ }
+
+ prio = (IntPrio[0x1] & 0x70) >> 4; // INT5 (Z80)
+ if (ipending[6] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[6] = 0;
+ interrupt(6);
+ return;
+ }
+
+ prio = IntPrio[0x3] & 0x07; // INTT0
+ if (ipending[7] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[7] = 0;
+ interrupt(7);
+ return;
+ }
+
+ prio = (IntPrio[0x3] & 0x70) >> 4; // INTT1
+ if (ipending[8] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[8] = 0;
+ interrupt(8);
+ return;
+ }
+
+ prio = (IntPrio[0x4] & 0x07); // INTT2
+ if (ipending[9] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[9] = 0;
+ interrupt(9);
+ return;
+ }
+
+ prio = ((IntPrio[0x4] & 0x70) >> 4); // INTT3
+ if (ipending[10] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[10] = 0;
+ interrupt(10);
+ return;
+ }
+
+ prio = (IntPrio[0x7] & 0x07); // INTRX0
+ if (ipending[11] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[11] = 0;
+ interrupt(11);
+ return;
+ }
+
+ prio = ((IntPrio[0x7] & 0x70) >> 4); // INTTX0
+ if (ipending[12] && curIFF <= prio && prio && prio != 7)
+ {
+ ipending[12] = 0;
+ interrupt(12);
+ return;
+ }
+}
+
+void int_write8(uint32 address, uint8 data)
+{
+ switch (address)
+ {
+ case 0x71:
+ if (!(data & 0x08))
+ ipending[5] = 0;
+ if (!(data & 0x80))
+ ipending[6] = 0;
+ break;
+ case 0x73:
+ if (!(data & 0x08))
+ ipending[7] = 0;
+ if (!(data & 0x80))
+ ipending[8] = 0;
+ break;
+ case 0x74:
+ if (!(data & 0x08))
+ ipending[9] = 0;
+ if (!(data & 0x80))
+ ipending[10] = 0;
+ break;
+ case 0x77:
+ if (!(data & 0x08))
+ ipending[11] = 0;
+ if (!(data & 0x80))
+ ipending[12] = 0;
+ break;
+ case 0x7C:
+ HDMAStartVector[0] = data;
+ break;
+ case 0x7D:
+ HDMAStartVector[1] = data;
+ break;
+ case 0x7E:
+ HDMAStartVector[2] = data;
+ break;
+ case 0x7F:
+ HDMAStartVector[3] = data;
+ break;
+ }
+ if (address >= 0x70 && address <= 0x7A)
+ {
+ IntPrio[address - 0x70] = data;
+ int_check_pending();
+ }
+}
+
+uint8 int_read8(uint32 address)
+{
+ uint8 ret = 0;
+ switch (address)
+ {
+ case 0x71:
+ ret = ((ipending[5] ? 0x08 : 0x00) | (ipending[6] ? 0x80 : 0x00));
+ break;
+ case 0x73:
+ ret = ((ipending[7] ? 0x08 : 0x00) | (ipending[8] ? 0x80 : 0x00));
+ break;
+ case 0x74:
+ ret = ((ipending[9] ? 0x08 : 0x00) | (ipending[10] ? 0x80 : 0x00));
+ break;
+ case 0x77:
+ ret = ((ipending[11] ? 0x08 : 0x00) | (ipending[12] ? 0x80 : 0x00));
+ break;
+ }
+
+ return (ret);
+}
+
+void TestIntHDMA(int bios_num, int vec_num)
+{
+ bool WasDMA = 0;
+
+ if (HDMAStartVector[0] == vec_num)
+ {
+ WasDMA = 1;
+ DMA_update(0);
+ }
+ else
+ {
+ if (HDMAStartVector[1] == vec_num)
+ {
+ WasDMA = 1;
+ DMA_update(1);
+ }
+ else
+ {
+ if (HDMAStartVector[2] == vec_num)
+ {
+ WasDMA = 1;
+ DMA_update(2);
+ }
+ else
+ {
+ if (HDMAStartVector[3] == vec_num)
+ {
+ WasDMA = 1;
+ DMA_update(3);
+ }
+ }
+ }
+ }
+ if (!WasDMA)
+ set_interrupt(bios_num, TRUE);
+}
+
+extern int32 ngpc_soundTS;
+extern bool NGPFrameSkip;
+
+bool updateTimers(MDFN_Surface *surface, int cputicks)
+{
+ bool ret = 0;
+
+ ngpc_soundTS += cputicks;
+ //increment H-INT timer
+ timer_hint += cputicks;
+
+ //=======================
+
+ //End of scanline / Start of Next one
+ if (timer_hint >= TIMER_HINT_RATE)
+ {
+ uint8 data;
+
+ // ============= END OF CURRENT SCANLINE =============
+
+ h_int = NGPGfx->hint();
+ ret = NGPGfx->draw(surface, NGPFrameSkip);
+
+ // ============= START OF NEXT SCANLINE =============
+
+ timer_hint -= TIMER_HINT_RATE; //Start of next scanline
+
+ //Comms. Read interrupt
+ if ((COMMStatus & 1) == 0 && system_comms_poll(&data))
+ {
+ storeB(0x50, data);
+ TestIntHDMA(12, 0x19);
+ }
+ }
+
+ //=======================
+
+ //Tick the Clock Generator
+ timer_clock[0] += cputicks;
+ timer_clock[1] += cputicks;
+
+ timer0 = FALSE; //Clear the timer0 tick, for timer1 chain mode.
+
+ //=======================
+
+ //Run Timer 0 (TRUN)?
+ if ((TRUN & 0x01))
+ {
+ //T01MOD
+ switch (T01MOD & 0x03)
+ {
+ case 0:
+ if (h_int) //Horizontal interrupt trigger
+ {
+ timer[0]++;
+
+ timer_clock[0] = 0;
+ h_int = FALSE; // Stop h_int remaining active
+ }
+ break;
+
+ case 1:
+ while (timer_clock[0] >= TIMER_T1_RATE)
+ {
+ timer[0]++;
+ timer_clock[0] -= TIMER_T1_RATE;
+ }
+ break;
+
+ case 2:
+ while (timer_clock[0] >= TIMER_T4_RATE)
+ {
+ timer[0]++;
+ timer_clock[0] -= TIMER_T4_RATE;
+ }
+ break;
+
+ case 3:
+ while (timer_clock[0] >= TIMER_T16_RATE)
+ {
+ timer[0]++;
+ timer_clock[0] -= TIMER_T16_RATE;
+ }
+ break;
+ }
+
+ //Threshold check
+ if (timer_threshold[0] && timer[0] >= timer_threshold[0])
+ {
+ timer[0] = 0;
+ timer0 = TRUE;
+
+ TestIntHDMA(7, 0x10);
+ }
+ }
+
+ //=======================
+
+ //Run Timer 1 (TRUN)?
+ if ((TRUN & 0x02))
+ {
+ //T01MOD
+ switch ((T01MOD & 0x0C) >> 2)
+ {
+ case 0:
+ if (timer0) //Timer 0 chain mode.
+ {
+ timer[1] += timer0;
+ timer_clock[1] = 0;
+ }
+ break;
+
+ case 1:
+ while (timer_clock[1] >= TIMER_T1_RATE)
+ {
+ timer[1]++;
+ timer_clock[1] -= TIMER_T1_RATE;
+ }
+ break;
+
+ case 2:
+ while (timer_clock[1] >= TIMER_T16_RATE)
+ {
+ timer[1]++;
+ timer_clock[1] -= TIMER_T16_RATE;
+ }
+ break;
+
+ case 3:
+ while (timer_clock[1] >= TIMER_T256_RATE)
+ {
+ timer[1]++;
+ timer_clock[1] -= TIMER_T256_RATE;
+ }
+ break;
+ }
+
+ //Threshold check
+ if (timer_threshold[1] && timer[1] >= timer_threshold[1])
+ {
+ timer[1] = 0;
+
+ TestIntHDMA(8, 0x11);
+ }
+ }
+
+ //=======================
+
+ //Tick the Clock Generator
+ timer_clock[2] += cputicks;
+ timer_clock[3] += cputicks;
+
+ timer2 = FALSE; //Clear the timer2 tick, for timer3 chain mode.
+
+ //=======================
+
+ //Run Timer 2 (TRUN)?
+ if ((TRUN & 0x04))
+ {
+ //T23MOD
+ switch (T23MOD & 0x03)
+ {
+ case 0: // -
+ break;
+
+ case 1:
+ while (timer_clock[2] >= TIMER_T1_RATE / 2) // Kludge :(
+ {
+ timer[2]++;
+ timer_clock[2] -= TIMER_T1_RATE / 2;
+ }
+ break;
+
+ case 2:
+ while (timer_clock[2] >= TIMER_T4_RATE)
+ {
+ timer[2]++;
+ timer_clock[2] -= TIMER_T4_RATE;
+ }
+ break;
+
+ case 3:
+ while (timer_clock[2] >= TIMER_T16_RATE)
+ {
+ timer[2]++;
+ timer_clock[2] -= TIMER_T16_RATE;
+ }
+ break;
+ }
+
+ //Threshold check
+ if (timer_threshold[2] && timer[2] >= timer_threshold[2])
+ {
+ timer[2] = 0;
+ timer2 = TRUE;
+
+ TestIntHDMA(9, 0x12);
+ }
+ }
+
+ //=======================
+
+ //Run Timer 3 (TRUN)?
+ if ((TRUN & 0x08))
+ {
+ //T23MOD
+ switch ((T23MOD & 0x0C) >> 2)
+ {
+ case 0:
+ if (timer2) //Timer 2 chain mode.
+ {
+ timer[3] += timer2;
+ timer_clock[3] = 0;
+ }
+ break;
+
+ case 1:
+ while (timer_clock[3] >= TIMER_T1_RATE)
+ {
+ timer[3]++;
+ timer_clock[3] -= TIMER_T1_RATE;
+ }
+ break;
+
+ case 2:
+ while (timer_clock[3] >= TIMER_T16_RATE)
+ {
+ timer[3]++;
+ timer_clock[3] -= TIMER_T16_RATE;
+ }
+ break;
+
+ case 3:
+ while (timer_clock[3] >= TIMER_T256_RATE)
+ {
+ timer[3]++;
+ timer_clock[3] -= TIMER_T256_RATE;
+ }
+ break;
+ }
+
+ //Threshold check
+ if (timer_threshold[3] && timer[3] >= timer_threshold[3])
+ {
+ timer[3] = 0;
+
+ Z80_irq();
+ TestIntHDMA(10, 0x13);
+ }
+ }
+ return (ret);
+}
+
+void reset_timers(void)
+{
+ timer_hint = 0;
+
+ memset(timer, 0, sizeof(timer));
+ memset(timer_clock, 0, sizeof(timer_clock));
+ memset(timer_threshold, 0, sizeof(timer_threshold));
+
+ timer0 = FALSE;
+ timer2 = FALSE;
+}
+
+void reset_int(void)
+{
+ TRUN = 0;
+ T01MOD = 0;
+ T23MOD = 0;
+ TRDC = 0;
+ TFFCR = 0;
+
+ memset(HDMAStartVector, 0, sizeof(HDMAStartVector));
+ memset(ipending, 0, sizeof(ipending));
+ memset(IntPrio, 0, sizeof(IntPrio));
+
+ h_int = FALSE;
+}
+
+void timer_write8(uint32 address, uint8 data)
+{
+ switch (address)
+ {
+ case 0x20:
+ TRUN = data;
+ if ((TRUN & 0x01) == 0)
+ timer[0] = 0;
+ if ((TRUN & 0x02) == 0)
+ timer[1] = 0;
+ if ((TRUN & 0x04) == 0)
+ timer[2] = 0;
+ if ((TRUN & 0x08) == 0)
+ timer[3] = 0;
+ break;
+ case 0x22:
+ timer_threshold[0] = data;
+ break;
+ case 0x23:
+ timer_threshold[1] = data;
+ break;
+ case 0x24:
+ T01MOD = data;
+ break;
+ case 0x25:
+ TFFCR = data & 0x33;
+ break;
+ case 0x26:
+ timer_threshold[2] = data;
+ break;
+ case 0x27:
+ timer_threshold[3] = data;
+ break;
+ case 0x28:
+ T23MOD = data;
+ break;
+ case 0x29:
+ TRDC = data & 0x3;
+ break;
+ }
+}
+
+uint8 timer_read8(uint32 address)
+{
+ uint8 ret = 0;
+
+ switch (address)
+ {
+ //default: printf("Baaaad: %08x\n", address); break;
+ // Cool boarders is stupid and tries to read from a write-only register >_<
+ // Returning 4 makes the game run ok, so 4 it is!
+ default:
+ ret = 0x4;
+ break;
+ case 0x20:
+ ret = TRUN;
+ break;
+ case 0x29:
+ ret = TRDC;
+ break;
+ }
+
+ //printf("UNK B R: %08x\n", address);
+ return (ret);
+}
+}
diff --git a/waterbox/ngp/interrupt.h b/waterbox/ngp/interrupt.h
new file mode 100644
index 0000000000..a82510d4cd
--- /dev/null
+++ b/waterbox/ngp/interrupt.h
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP_INTERRUPT__
+#define __NEOPOP_INTERRUPT__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+void interrupt(uint8 index);
+
+#define TIMER_HINT_RATE 515 //CPU Ticks between horizontal interrupts
+
+#define TIMER_BASE_RATE 32 //1 //ticks
+
+#define TIMER_T1_RATE (8 * TIMER_BASE_RATE)
+#define TIMER_T4_RATE (32 * TIMER_BASE_RATE)
+#define TIMER_T16_RATE (128 * TIMER_BASE_RATE)
+#define TIMER_T256_RATE (2048 * TIMER_BASE_RATE)
+
+void reset_timers(void);
+void reset_int(void);
+
+//Call this after each instruction
+bool updateTimers(MDFN_Surface *surface, int cputicks);
+
+//H-INT Timer
+extern uint32 timer_hint;
+
+void timer_write8(uint32 address, uint8 data);
+uint8 timer_read8(uint32 address);
+
+
+// Set this value to fix problems with glitching extra lines.
+extern bool gfx_hack;
+
+
+void int_write8(uint32 address, uint8 data);
+uint8 int_read8(uint32 address);
+void int_check_pending(void);
+void TestIntHDMA(int bios_num, int vec_num);
+}
+
+//=============================================================================
+#endif
+
+
+
+
diff --git a/waterbox/ngp/mem.cpp b/waterbox/ngp/mem.cpp
new file mode 100644
index 0000000000..82ab5c7a87
--- /dev/null
+++ b/waterbox/ngp/mem.cpp
@@ -0,0 +1,673 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "Z80_interface.h"
+#include "bios.h"
+#include "gfx.h"
+#include "mem.h"
+#include "interrupt.h"
+#include "sound.h"
+#include "flash.h"
+#include "rtc.h"
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+extern uint8 settings_language;
+
+//Hack way of returning good Flash status.
+bool FlashStatusEnable = FALSE;
+static uint32 FlashStatus;
+
+uint8 CPUExRAM[16384];
+
+bool debug_abort_memory = FALSE;
+bool debug_mask_memory_error_messages = FALSE;
+
+bool memory_unlock_flash_write = FALSE;
+bool memory_flash_error = FALSE;
+bool memory_flash_command = FALSE;
+
+uint8 SC0BUF; // Serial channel 0 buffer.
+uint8 COMMStatus;
+
+// In very very very rare conditions(like on embedded platforms with no virtual memory and very limited RAM and
+// malloc happens to return a pointer aligned to a 64KiB boundary), a FastReadMap entry may be NULL even if
+// it points to valid data when it's added to the address of the read, but
+// if this happens, it will only make the emulator slightly slower.
+static uint8 *FastReadMap[256], *FastReadMapReal[256];
+
+void SetFRM(void) // Call this function after rom is loaded
+{
+ for (unsigned int x = 0; x < 256; x++)
+ FastReadMapReal[x] = NULL;
+
+ for (unsigned int x = 0x20; x <= 0x3f; x++)
+ {
+ if (ngpc_rom.length > (x * 65536 + 65535 - 0x20000))
+ FastReadMapReal[x] = &ngpc_rom.data[x * 65536 - 0x200000] - x * 65536;
+ }
+
+ for (unsigned int x = 0x80; x <= 0x9f; x++)
+ {
+ if (ngpc_rom.length > (x * 65536 + 65535 - 0x80000))
+ FastReadMapReal[x] = &ngpc_rom.data[x * 65536 - 0x800000] - x * 65536;
+ }
+}
+
+void RecacheFRM(void)
+{
+ for (int x = 0; x < 256; x++)
+ FastReadMap[x] = FlashStatusEnable ? NULL : FastReadMapReal[x];
+}
+
+static void *translate_address_read(uint32 address)
+{
+ address &= 0xFFFFFF;
+
+ //Get Flash status?
+ if (FlashStatusEnable)
+ {
+ if ((address >= ROM_START && address <= ROM_END) || (address >= HIROM_START && address <= HIROM_END))
+ {
+ FlashStatusEnable = FALSE;
+ RecacheFRM();
+ if (address == 0x220000 || address == 0x230000)
+ {
+ FlashStatus = 0xFFFFFFFF;
+ return &FlashStatus;
+ }
+ }
+ }
+
+ //ROM (LOW)
+ if (address >= ROM_START && address <= ROM_END)
+ {
+ if (address < ROM_START + ngpc_rom.length)
+ return ngpc_rom.data + (address - ROM_START);
+ else
+ return NULL;
+ }
+
+ //ROM (HIGH)
+ if (address >= HIROM_START && address <= HIROM_END)
+ {
+ if (address < HIROM_START + (ngpc_rom.length - 0x200000))
+ return ngpc_rom.data + 0x200000 + (address - HIROM_START);
+ else
+ return NULL;
+ }
+
+ // ===================================
+
+ //BIOS Access?
+ if ((address & 0xFF0000) == 0xFF0000)
+ {
+ return ngpc_bios + (address & 0xFFFF); // BIOS ROM
+ }
+ return NULL;
+}
+
+//=============================================================================
+
+static void *translate_address_write(uint32 address)
+{
+ address &= 0xFFFFFF;
+
+ if (memory_unlock_flash_write)
+ {
+ //ROM (LOW)
+ if (address >= ROM_START && address <= ROM_END)
+ {
+ if (address < ROM_START + ngpc_rom.length)
+ return ngpc_rom.data + (address - ROM_START);
+ else
+ return NULL;
+ }
+
+ //ROM (HIGH)
+ if (address >= HIROM_START && address <= HIROM_END)
+ {
+ if (address < HIROM_START + (ngpc_rom.length - 0x200000))
+ return ngpc_rom.data + 0x200000 + (address - HIROM_START);
+ else
+ return NULL;
+ }
+ }
+ else
+ {
+ //ROM (LOW)
+ if (address >= ROM_START && address <= ROM_END)
+ {
+ //Ignore Flash commands
+ if (address == 0x202AAA || address == 0x205555)
+ {
+ // system_debug_message("%06X: Enable Flash command from %06X", pc, address);
+ memory_flash_command = TRUE;
+ return NULL;
+ }
+
+ //Set Flash status reading?
+ if (address == 0x220000 || address == 0x230000)
+ {
+ // system_debug_message("%06X: Flash status read from %06X", pc, address);
+ FlashStatusEnable = TRUE;
+ RecacheFRM();
+ return NULL;
+ }
+
+ if (memory_flash_command)
+ {
+ //Write the 256byte block around the flash data
+ flash_write(address & 0xFFFF00, 256);
+
+ //Need to issue a new command before writing will work again.
+ memory_flash_command = FALSE;
+
+ // system_debug_message("%06X: Direct Flash write to %06X", pc, address & 0xFFFF00);
+ // system_debug_stop();
+
+ //Write to the rom itself.
+ if (address < ROM_START + ngpc_rom.length)
+ return ngpc_rom.data + (address - ROM_START);
+ }
+ }
+ }
+
+ // ===================================
+ return NULL;
+}
+
+/* WARNING: 32-bit loads and stores apparently DON'T have to be 4-byte-aligned(so we must +2 instead of |2). */
+/* Treat all 32-bit operations as two 16-bit operations */
+uint8 loadB(uint32 address)
+{
+ address &= 0xFFFFFF;
+
+ if (FastReadMap[address >> 16])
+ return (FastReadMap[address >> 16][address]);
+
+ uint8 *ptr = (uint8 *)translate_address_read(address);
+
+ if (ptr)
+ return *ptr;
+
+ if (address >= 0x8000 && address <= 0xbfff)
+ return (NGPGfx->read8(address));
+ if (address >= 0x4000 && address <= 0x7fff)
+ {
+ return (*(uint8 *)(CPUExRAM + address - 0x4000));
+ }
+
+ if (address >= 0x70 && address <= 0x7F)
+ {
+ return (int_read8(address));
+ }
+
+ if (address >= 0x90 && address <= 0x97)
+ {
+ return (rtc_read8(address));
+ }
+
+ if (address >= 0x20 && address <= 0x29)
+ {
+ return (timer_read8(address));
+ }
+
+ if (address == 0x50)
+ return (SC0BUF);
+
+ if (address == 0xBC)
+ return Z80_ReadComm();
+
+ //printf("UNK B R: %08x\n", address);
+
+ return (0);
+}
+
+uint16 loadW(uint32 address)
+{
+ address &= 0xFFFFFF;
+
+ if (address & 1)
+ {
+ uint16 ret;
+
+ ret = loadB(address);
+ ret |= loadB(address + 1) << 8;
+
+ return (ret);
+ }
+
+ if (FastReadMap[address >> 16])
+ return (MDFN_de16lsb(&FastReadMap[address >> 16][address]));
+
+ uint16 *ptr = (uint16 *)translate_address_read(address);
+ if (ptr)
+ return MDFN_de16lsb(ptr);
+
+ if (address >= 0x8000 && address <= 0xbfff)
+ return (NGPGfx->read16(address));
+
+ if (address >= 0x4000 && address <= 0x7fff)
+ {
+ return (MDFN_de16lsb(CPUExRAM + address - 0x4000));
+ }
+ if (address == 0x50)
+ return (SC0BUF);
+
+ if (address >= 0x70 && address <= 0x7F)
+ {
+ uint16 ret;
+
+ ret = int_read8(address);
+ ret |= int_read8(address + 1) << 8;
+
+ return (ret);
+ }
+
+ if (address >= 0x90 && address <= 0x97)
+ {
+ uint16 ret;
+
+ ret = rtc_read8(address);
+ ret |= rtc_read8(address + 1) << 8;
+
+ return (ret);
+ }
+
+ if (address >= 0x20 && address <= 0x29)
+ {
+ uint16 ret;
+
+ ret = timer_read8(address);
+ ret |= timer_read8(address + 1) << 8;
+
+ return (ret);
+ }
+
+ if (address == 0xBC)
+ return Z80_ReadComm();
+
+ //printf("UNK W R: %08x\n", address);
+
+ return (0);
+}
+
+uint32 loadL(uint32 address)
+{
+ uint32 ret;
+
+ ret = loadW(address);
+ ret |= loadW(address + 2) << 16;
+
+ return (ret);
+}
+
+//=============================================================================
+
+void storeB(uint32 address, uint8 data)
+{
+ address &= 0xFFFFFF;
+
+ if (address >= 0x8000 && address <= 0xbfff)
+ {
+ NGPGfx->write8(address, data);
+ return;
+ }
+ if (address >= 0x4000 && address <= 0x7fff)
+ {
+ *(uint8 *)(CPUExRAM + address - 0x4000) = data;
+ return;
+ }
+ if (address >= 0x70 && address <= 0x7F)
+ {
+ int_write8(address, data);
+ return;
+ }
+ if (address >= 0x20 && address <= 0x29)
+ {
+ timer_write8(address, data);
+ return;
+ }
+
+ if (address == 0x50)
+ {
+ SC0BUF = data;
+ return;
+ }
+
+ if (address == 0x6f) // Watchdog timer
+ {
+ return;
+ }
+
+ if (address == 0xb2) // Comm?
+ {
+ COMMStatus = data & 1;
+ return;
+ }
+
+ if (address == 0xb9)
+ {
+ if (data == 0x55)
+ Z80_SetEnable(1);
+ else if (data == 0xAA)
+ Z80_SetEnable(0);
+ return;
+ }
+
+ if (address == 0xb8)
+ {
+ if (data == 0x55)
+ MDFNNGPCSOUND_SetEnable(1);
+ else if (data == 0xAA)
+ MDFNNGPCSOUND_SetEnable(0);
+ return;
+ }
+
+ if (address == 0xBA)
+ {
+ Z80_nmi();
+ return;
+ }
+
+ if (address == 0xBC)
+ {
+ Z80_WriteComm(data);
+ return;
+ }
+
+ if (address >= 0xa0 && address <= 0xA3)
+ {
+ if (!Z80_IsEnabled())
+ {
+ if (address == 0xA1)
+ Write_SoundChipLeft(data);
+ else if (address == 0xA0)
+ Write_SoundChipRight(data);
+ }
+ //DAC Write
+ if (address == 0xA2)
+ {
+ dac_write_left(data);
+ }
+ else if (address == 0xA3)
+ {
+ dac_write_right(data);
+ }
+ return;
+ }
+
+ //printf("%08x %02x\n", address, data);
+ uint8 *ptr = (uint8 *)translate_address_write(address);
+
+ //Write
+ if (ptr)
+ {
+ *ptr = data;
+ }
+ //else
+ // printf("ACK: %08x %02x\n", address, data);
+}
+
+void storeW(uint32 address, uint16 data)
+{
+ address &= 0xFFFFFF;
+
+ if (address & 1)
+ {
+ storeB(address + 0, data & 0xFF);
+ storeB(address + 1, data >> 8);
+ return;
+ }
+
+ if (address >= 0x8000 && address <= 0xbfff)
+ {
+ NGPGfx->write16(address, data);
+ return;
+ }
+ if (address >= 0x4000 && address <= 0x7fff)
+ {
+ MDFN_en16lsb(CPUExRAM + address - 0x4000, data);
+ return;
+ }
+ if (address >= 0x70 && address <= 0x7F)
+ {
+ int_write8(address, data & 0xFF);
+ int_write8(address + 1, data >> 8);
+ return;
+ }
+
+ if (address >= 0x20 && address <= 0x29)
+ {
+ timer_write8(address, data & 0xFF);
+ timer_write8(address + 1, data >> 8);
+ }
+
+ if (address == 0x50)
+ {
+ SC0BUF = data & 0xFF;
+ return;
+ }
+
+ if (address == 0x6e) // Watchdog timer(technically 0x6f)
+ {
+ return;
+ }
+
+ if (address == 0xb2) // Comm?
+ {
+ COMMStatus = data & 1;
+ return;
+ }
+
+ if (address == 0xb8)
+ {
+ if ((data & 0xFF00) == 0x5500)
+ Z80_SetEnable(1);
+ else if ((data & 0xFF00) == 0xAA00)
+ Z80_SetEnable(0);
+
+ if ((data & 0xFF) == 0x55)
+ MDFNNGPCSOUND_SetEnable(1);
+ else if ((data & 0xFF) == 0xAA)
+ MDFNNGPCSOUND_SetEnable(0);
+ return;
+ }
+
+ if (address == 0xBA)
+ {
+ Z80_nmi();
+ return;
+ }
+
+ if (address == 0xBC)
+ {
+ Z80_WriteComm(data);
+ return;
+ }
+
+ if (address >= 0xa0 && address <= 0xA3)
+ {
+ storeB(address, data & 0xFF);
+ storeB(address + 1, data >> 8);
+ return;
+ }
+
+ uint16 *ptr = (uint16 *)translate_address_write(address);
+
+ //Write
+ if (ptr)
+ {
+ MDFN_en16lsb(ptr, data);
+ }
+ //else
+ // printf("ACK16: %08x %04x\n", address, data);
+}
+
+void storeL(uint32 address, uint32 data)
+{
+ storeW(address, data & 0xFFFF);
+ storeW(address + 2, data >> 16);
+}
+
+//=============================================================================
+
+static const uint8 systemMemory[] =
+ {
+ // 0x00 // 0x08
+ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0xFF, 0xFF,
+ // 0x10 // 0x18
+ 0x34, 0x3C, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x3F, 0xFF, 0x2D, 0x01, 0xFF, 0xFF, 0x03, 0xB2,
+ // 0x20 // 0x28
+ 0x80, 0x00, 0x01, 0x90, 0x03, 0xB0, 0x90, 0x62, 0x05, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x4C, 0x4C,
+ // 0x30 // 0x38
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0xFF, 0x80, 0x7F,
+ // 0x40 // 0x48
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0x50 // 0x58
+ 0x00, 0x20, 0x69, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ // 0x60 // 0x68
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x03, 0x03, 0x02, 0x00, 0x00, 0x4E,
+ // 0x70 // 0x78
+ 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0x80 // 0x88
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0x90 // 0x98
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xA0 // 0xA8
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xB0 // 0xB8
+ 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xC0 // 0xC8
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xD0 // 0xD8
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xE0 // 0xE8
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // 0xF0 // 0xF8
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+//=============================================================================
+
+void reset_memory(void)
+{
+ unsigned int i;
+
+ FlashStatusEnable = FALSE;
+ RecacheFRM();
+
+ memory_flash_command = FALSE;
+
+ //=============================================================================
+ //000000 -> 000100 CPU Internal RAM (Timers/DMA/Z80)
+ //=====================================================
+
+ for (i = 0; i < sizeof(systemMemory); i++)
+ storeB(i, systemMemory[i]);
+
+ //=============================================================================
+ //006C00 -> 006FFF BIOS Workspace
+ //==================================
+
+ storeL(0x6C00, MDFN_de32lsb(rom_header->startPC)); //Start
+
+ storeW(0x6C04, MDFN_de16lsb(rom_header->catalog));
+ storeW(0x6E82, MDFN_de16lsb(rom_header->catalog));
+
+ storeB(0x6C06, rom_header->subCatalog);
+ storeB(0x6E84, rom_header->subCatalog);
+
+ for (i = 0; i < 12; i++)
+ storeB(0x6c08 + i, ngpc_rom.data[0x24 + i]);
+
+ storeB(0x6C58, 0x01);
+
+ //32MBit cart?
+ if (ngpc_rom.length > 0x200000)
+ storeB(0x6C59, 0x01);
+ else
+ storeB(0x6C59, 0x00);
+
+ storeB(0x6C55, 1); //Commercial game
+
+ storeB(0x6F80, 0xFF); //Lots of battery power!
+ storeB(0x6F81, 0x03);
+
+ storeB(0x6F84, 0x40); // "Power On" startup
+ storeB(0x6F85, 0x00); // No shutdown request
+ storeB(0x6F86, 0x00); // No user answer (?)
+
+ //Language: 0 = Japanese, 1 = English
+ storeB(0x6F87, settings_language);
+
+ //Color Mode Selection: 0x00 = B&W, 0x10 = Colour
+ storeB(0x6F91, rom_header->mode);
+ storeB(0x6F95, rom_header->mode);
+
+ //Interrupt table
+ for (i = 0; i < 0x12; i++)
+ storeL(0x6FB8 + i * 4, 0x00FF23DF);
+
+ //=============================================================================
+ //008000 -> 00BFFF Video RAM
+ //=============================
+
+ storeB(0x8000, 0xC0); // Both interrupts allowed
+
+ //Hardware window
+ storeB(0x8002, 0x00);
+ storeB(0x8003, 0x00);
+ storeB(0x8004, 0xFF);
+ storeB(0x8005, 0xFF);
+
+ storeB(0x8006, 0xc6); // Frame Rate Register
+
+ storeB(0x8012, 0x00); // NEG / OOWC setting.
+
+ storeB(0x8118, 0x80); // BGC on!
+
+ storeB(0x83E0, 0xFF); // Default background colour
+ storeB(0x83E1, 0x0F);
+
+ storeB(0x83F0, 0xFF); // Default window colour
+ storeB(0x83F1, 0x0F);
+
+ storeB(0x8400, 0xFF); // LED on
+ storeB(0x8402, 0x80); // Flash cycle = 1.3s
+
+ storeB(0x87E2, loadB(0x6F95) ? 0x00 : 0x80);
+
+ //
+ // Metal Slug - 2nd Mission oddly relies on a specific character RAM pattern.
+ //
+ {
+ static const uint8 char_data[64] = {
+ 255, 63, 255, 255, 0, 252, 255, 255, 255, 63, 3, 0, 255, 255, 255, 255,
+ 240, 243, 252, 243, 255, 3, 255, 195, 255, 243, 243, 243, 240, 243, 240, 195,
+ 207, 15, 207, 15, 207, 15, 207, 207, 207, 255, 207, 255, 207, 255, 207, 63,
+ 255, 192, 252, 195, 240, 207, 192, 255, 192, 255, 240, 207, 252, 195, 255, 192};
+
+ for (i = 0; i < 64; i++)
+ {
+ storeB(0xA1C0 + i, char_data[i]);
+ }
+ }
+}
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/mem.h b/waterbox/ngp/mem.h
new file mode 100644
index 0000000000..c467354d2c
--- /dev/null
+++ b/waterbox/ngp/mem.h
@@ -0,0 +1,61 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP_MEM__
+#define __NEOPOP_MEM__
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+#define ROM_START 0x200000
+#define ROM_END 0x3FFFFF
+
+#define HIROM_START 0x800000
+#define HIROM_END 0x9FFFFF
+
+#define BIOS_START 0xFF0000
+#define BIOS_END 0xFFFFFF
+
+void reset_memory(void);
+
+void dump_memory(uint32 start, uint32 length);
+
+extern bool debug_abort_memory;
+extern bool debug_mask_memory_error_messages;
+
+extern bool memory_unlock_flash_write;
+extern bool memory_flash_error;
+extern bool memory_flash_command;
+
+extern bool FlashStatusEnable;
+extern uint8 COMMStatus;
+
+//=============================================================================
+
+uint8 loadB(uint32 address);
+uint16 loadW(uint32 address);
+uint32 loadL(uint32 address);
+
+void storeB(uint32 address, uint8 data);
+void storeW(uint32 address, uint16 data);
+void storeL(uint32 address, uint32 data);
+
+void SetFRM(void);
+void RecacheFRM(void);
+
+}
+
+//=============================================================================
+#endif
diff --git a/waterbox/ngp/neopop.cpp b/waterbox/ngp/neopop.cpp
new file mode 100644
index 0000000000..81a0fff569
--- /dev/null
+++ b/waterbox/ngp/neopop.cpp
@@ -0,0 +1,268 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+
+#include "Z80_interface.h"
+#include "interrupt.h"
+#include "mem.h"
+#include "gfx.h"
+#include "sound.h"
+#include "dma.h"
+#include "bios.h"
+#include "flash.h"
+
+#include
+
+namespace MDFN_IEN_NGP
+{
+
+extern uint8 CPUExRAM[16384];
+
+NGPGFX_CLASS *NGPGfx = NULL;
+
+COLOURMODE system_colour = COLOURMODE_AUTO;
+
+uint8 NGPJoyLatch;
+uint8 settings_language;
+time_t frontend_time;
+
+bool system_comms_read(uint8 *buffer)
+{
+ return (0);
+}
+
+bool system_comms_poll(uint8 *buffer)
+{
+ return (0);
+}
+
+void system_comms_write(uint8 data)
+{
+ return;
+}
+
+void instruction_error(char *vaMessage, ...)
+{
+ /*char message[1000];
+ va_list vl;
+
+ va_start(vl, vaMessage);
+ vsprintf(message, vaMessage, vl);
+ va_end(vl);
+
+ MDFN_printf("[PC %06X] %s\n", pc, message);*/
+}
+
+bool NGPFrameSkip;
+int32 ngpc_soundTS = 0;
+//static int32 main_timeaccum;
+static int32 z80_runtime;
+
+static void Emulate(EmulateSpecStruct *espec)
+{
+ bool MeowMeow = 0;
+ MDFN_Surface surface;
+ surface.pixels = espec->pixels;
+ surface.pitch32 = 160;
+
+ storeB(0x6f82, espec->Buttons);
+
+ ngpc_soundTS = 0;
+ NGPFrameSkip = espec->skip;
+
+ do
+ {
+ int32 timetime = (uint8)TLCS900h_interpret(); // This is sooo not right, but it's replicating the old behavior(which is necessary
+ // now since I've fixed the TLCS900h core and other places not to truncate cycle counts
+ // internally to 8-bits). Switch to the #if 0'd block of code once we fix cycle counts in the
+ // TLCS900h core(they're all sorts of messed up), and investigate if certain long
+ // instructions are interruptable(by interrupts) and later resumable, RE Rockman Battle
+ // & Fighters voice sample playback.
+
+ //if(timetime > 255)
+ // printf("%d\n", timetime);
+
+ // Note: Don't call updateTimers with a time/tick/cycle/whatever count greater than 255.
+ MeowMeow |= updateTimers(&surface, timetime);
+
+ z80_runtime += timetime;
+
+ while (z80_runtime > 0)
+ {
+ int z80rantime = Z80_RunOP();
+
+ if (z80rantime < 0) // Z80 inactive, so take up all run time!
+ {
+ z80_runtime = 0;
+ break;
+ }
+
+ z80_runtime -= z80rantime << 1;
+ }
+ } while (!MeowMeow);
+
+ espec->MasterCycles = ngpc_soundTS;
+ espec->SoundBufSize = MDFNNGPCSOUND_Flush(espec->SoundBuf, espec->SoundBufMaxSize);
+}
+
+static MDFN_COLD bool Load(const uint8* romdata, int32 romlength)
+{
+ const uint64 fp_size = romlength;
+
+ if (fp_size > 1024 * 1024 * 8) // 4MiB maximum ROM size, 2* to be a little tolerant of garbage.
+ return false;
+ //throw MDFN_Error(0, _("NGP/NGPC ROM image is too large."));
+
+ ngpc_rom.length = fp_size;
+ ngpc_rom.data = new uint8[ngpc_rom.length];
+ memcpy(ngpc_rom.data, romdata, romlength);
+
+ rom_loaded();
+ //if (!FLASH_LoadNV())
+ // return false;
+
+ //MDFNMP_Init(1024, 1024 * 1024 * 16 / 1024);
+
+ NGPGfx = new NGPGFX_CLASS();
+
+ //MDFNGameInfo->fps = (uint32)((uint64)6144000 * 65536 * 256 / 515 / 198); // 3072000 * 2 * 10000 / 515 / 198
+
+ MDFNNGPCSOUND_Init();
+
+ //MDFNMP_AddRAM(16384, 0x4000, CPUExRAM);
+
+ SetFRM(); // Set up fast read memory mapping
+
+ bios_install();
+
+ //main_timeaccum = 0;
+ z80_runtime = 0;
+
+ reset();
+
+ MDFNNGPC_SetSoundRate(44100);
+ return true;
+}
+
+/*static void DoSimpleCommand(int cmd)
+{
+ switch (cmd)
+ {
+ case MDFN_MSC_POWER:
+ case MDFN_MSC_RESET:
+ reset();
+ break;
+ }
+}*/
+
+/*static const IDIISG IDII =
+ {
+ {"up", "UP ↑", 0, IDIT_BUTTON, "down"},
+ {"down", "DOWN ↓", 1, IDIT_BUTTON, "up"},
+ {"left", "LEFT ←", 2, IDIT_BUTTON, "right"},
+ {"right", "RIGHT →", 3, IDIT_BUTTON, "left"},
+ {"a", "A", 5, IDIT_BUTTON_CAN_RAPID, NULL},
+ {"b", "B", 6, IDIT_BUTTON_CAN_RAPID, NULL},
+ {"option", "OPTION", 4, IDIT_BUTTON, NULL},
+};*/
+
+/*static const FileExtensionSpecStruct KnownExtensions[] =
+ {
+ {".ngp", gettext_noop("Neo Geo Pocket ROM Image")},
+ {".ngc", gettext_noop("Neo Geo Pocket Color ROM Image")},
+ {NULL, NULL}};
+}*/
+}
+using namespace MDFN_IEN_NGP;
+
+
+
+/*MDFNGI EmulatedNGP =
+ {
+ "ngp",
+ "Neo Geo Pocket (Color)",
+ KnownExtensions,
+ MODPRIO_INTERNAL_HIGH,
+ NULL,
+ PortInfo,
+ Load,
+ TestMagic,
+ NULL,
+ NULL,
+ CloseGame,
+
+ SetLayerEnableMask,
+ "Background Scroll\0Foreground Scroll\0Sprites\0",
+
+ NULL,
+ NULL,
+
+ NULL,
+ 0,
+
+ CheatInfo_Empty,
+
+ false,
+ StateAction,
+ Emulate,
+ NULL,
+ SetInput,
+ NULL,
+ DoSimpleCommand,
+ NULL,
+ NGPSettings,
+ MDFN_MASTERCLOCK_FIXED(6144000),
+ 0,
+
+ false, // Multires possible?
+
+ 160, // lcm_width
+ 152, // lcm_height
+ NULL, // Dummy
+
+ 160, // Nominal width
+ 152, // Nominal height
+
+ 160, // Framebuffer width
+ 152, // Framebuffer height
+
+ 2, // Number of output sound channels
+};*/
+
+int main(void)
+{
+ return 0;
+}
+
+EXPORT int LoadSystem(const uint8* rom, int romlength, int language)
+{
+ settings_language = language;
+ return Load(rom, romlength);
+}
+
+EXPORT void SetLayers(int enable) // 1, 2, 4 bg,fg,sprites
+{
+ NGPGfx->SetLayerEnableMask(enable);
+}
+
+EXPORT void FrameAdvance(EmulateSpecStruct *espec)
+{
+ Emulate(espec);
+}
+
+EXPORT void HardReset()
+{
+ reset();
+}
diff --git a/waterbox/ngp/neopop.h b/waterbox/ngp/neopop.h
new file mode 100644
index 0000000000..18ab2723da
--- /dev/null
+++ b/waterbox/ngp/neopop.h
@@ -0,0 +1,178 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP__
+#define __NEOPOP__
+//=============================================================================
+
+#include "defs.h"
+
+#include
+#include
+#include
+#include
+
+#include "TLCS-900h/TLCS900h_disassemble.h"
+#include "TLCS-900h/TLCS900h_interpret_dst.h"
+#include "TLCS-900h/TLCS900h_interpret.h"
+#include "TLCS-900h/TLCS900h_interpret_reg.h"
+#include "TLCS-900h/TLCS900h_interpret_single.h"
+#include "TLCS-900h/TLCS900h_interpret_src.h"
+#include "TLCS-900h/TLCS900h_registers.h"
+
+
+// I put the TLCS900h code in its own namespace, so it doesn't
+// pollute the global namespace with all of its CARAZZZY short-named global variables.
+// (I'm too lazy to clean up and turn it into an object :b)
+using namespace TLCS900H;
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+//===========================
+// GCC specific
+//===========================
+
+#ifndef max
+#define max(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+//COLOURMODE
+typedef enum
+{
+ COLOURMODE_GREYSCALE,
+ COLOURMODE_COLOUR,
+ COLOURMODE_AUTO
+}
+COLOURMODE;
+
+//RomInfo
+typedef struct
+{
+ uint8* data; //Pointer to the rom data
+ uint8 *orig_data; // Original data(without flash writes during emulation; necessary for save states)
+
+ uint32 length; //Length of the rom
+
+ uint8 name[16]; //Null terminated string, holding the Game name
+}
+RomInfo;
+
+//RomHeader
+typedef struct
+{
+ uint8 licence[28]; // 0x00 - 0x1B
+ uint8 startPC[4]; // 0x1C - 0x1F
+ uint8 catalog[2]; // 0x20 - 0x21
+ uint8 subCatalog; // 0x22
+ uint8 mode; // 0x23
+ uint8 name[12]; // 0x24 - 0x2F
+
+ uint8 reserved1[4]; // 0x30 - 0x33
+ uint8 reserved2[4]; // 0x34 - 0x37
+ uint8 reserved3[4]; // 0x38 - 0x3B
+ uint8 reserved4[4]; // 0x3C - 0x3F
+} __attribute__((__packed__)) RomHeader;
+
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Core <--> System-Main Interface
+//-----------------------------------------------------------------------------
+
+ void reset(void);
+
+/* Fill the bios rom area with a bios. call once at program start */
+ bool bios_install(void);
+
+ extern RomInfo ngpc_rom;
+
+ extern RomHeader* rom_header;
+
+/*! Emulate a single instruction with correct TLCS900h:Z80 timing */
+
+ void emulate(void);
+
+/*! Call this function when a rom has just been loaded, it will perform
+ the system independent actions required. */
+
+ void rom_loaded(void);
+
+/*! Tidy up the rom and free the resources used. */
+
+ void rom_unload(void);
+
+ //=========================================
+
+/*! Used to generate a critical message for the user. After the message
+ has been displayed, the function should return. The message is not
+ necessarily a fatal error. */
+
+ void system_message(char* vaMessage,...);
+
+//-----------------------------------------------------------------------------
+// Core <--> System-Graphics Interface
+//-----------------------------------------------------------------------------
+
+ // Physical screen dimensions
+#define SCREEN_WIDTH 160
+#define SCREEN_HEIGHT 152
+
+ extern COLOURMODE system_colour;
+
+
+//-----------------------------------------------------------------------------
+// Core <--> System-IO Interface
+//-----------------------------------------------------------------------------
+
+/*! Reads a byte from the other system. If no data is available or no
+ high-level communications have been established, then return FALSE.
+ If buffer is NULL, then no data is read, only status is returned */
+
+ bool system_comms_read(uint8* buffer);
+
+
+/*! Peeks at any data from the other system. If no data is available or
+ no high-level communications have been established, then return FALSE.
+ If buffer is NULL, then no data is read, only status is returned */
+
+ bool system_comms_poll(uint8* buffer);
+
+
+/*! Writes a byte from the other system. This function should block until
+ the data is written. USE RELIABLE COMMS! Data cannot be re-requested. */
+
+ void system_comms_write(uint8 data);
+
+void int_redo_icache(void);
+
+}
+
+#include "gfx.h"
+
+namespace MDFN_IEN_NGP
+{
+extern NGPGFX_CLASS *NGPGfx;
+extern uint8 NGPJoyLatch;
+}
+
+using namespace MDFN_IEN_NGP;
+
+#endif
diff --git a/waterbox/ngp/rom.cpp b/waterbox/ngp/rom.cpp
new file mode 100644
index 0000000000..b209f1e0e1
--- /dev/null
+++ b/waterbox/ngp/rom.cpp
@@ -0,0 +1,136 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include "flash.h"
+#include "interrupt.h"
+
+//=============================================================================
+
+namespace MDFN_IEN_NGP
+{
+
+RomInfo ngpc_rom;
+RomHeader* rom_header;
+
+#define MATCH_CATALOG(c, s) (MDFN_de16lsb(rom_header->catalog) == (c) && rom_header->subCatalog == (s))
+
+//=============================================================================
+static void rom_hack(void)
+{
+ //=============================
+ // SPECIFIC ROM HACKS !
+ //=============================
+
+ //"Neo-Neo! V1.0 (PD)"
+ if (MATCH_CATALOG(0, 16))
+ {
+ ngpc_rom.data[0x23] = 0x10; // Fix rom header
+
+ MDFN_printf("HACK: \"Neo-Neo! V1.0 (PD)\"\n");
+ }
+
+ //"Cool Cool Jam SAMPLE (U)"
+ if (MATCH_CATALOG(4660, 161))
+ {
+ ngpc_rom.data[0x23] = 0x10; // Fix rom header
+
+ MDFN_printf("HACK: \"Cool Cool Jam SAMPLE (U)\"\n");
+ }
+
+ //"Dokodemo Mahjong (J)"
+ if (MATCH_CATALOG(51, 33))
+ {
+ ngpc_rom.data[0x23] = 0x00; // Fix rom header
+
+ MDFN_printf("HACK: \"Dokodemo Mahjong (J)\"\n");
+ }
+}
+
+//=============================================================================
+
+static void rom_display_header(void)
+{
+ MDFN_printf(_("Name: %s\n"), ngpc_rom.name);
+ MDFN_printf(_("System: "));
+
+ if(rom_header->mode & 0x10)
+ MDFN_printf(_("Color"));
+ else
+ MDFN_printf(_("Greyscale"));
+
+ MDFN_printf("\n");
+
+ MDFN_printf(_("Catalog: %u (sub %u)\n"),
+ MDFN_de16lsb(rom_header->catalog),
+ rom_header->subCatalog);
+
+ //Starting PC
+ MDFN_printf(_("Starting PC: 0x%06X\n"), MDFN_de32lsb(rom_header->startPC) & 0xFFFFFF);
+}
+
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// rom_loaded()
+//-----------------------------------------------------------------------------
+void rom_loaded(void)
+{
+ //Extract the header
+ rom_header = (RomHeader*)(ngpc_rom.data);
+
+ //Rom Name
+ for(int i = 0; i < 12; i++)
+ {
+ if (rom_header->name[i] >= 32 && rom_header->name[i] < 128)
+ ngpc_rom.name[i] = rom_header->name[i];
+ else
+ ngpc_rom.name[i] = ' ';
+ }
+ ngpc_rom.name[12] = 0;
+
+ rom_hack(); //Apply a hack if required!
+
+ rom_display_header();
+
+ ngpc_rom.orig_data = new uint8[ngpc_rom.length];
+ memcpy(ngpc_rom.orig_data, ngpc_rom.data, ngpc_rom.length);
+}
+
+//-----------------------------------------------------------------------------
+// rom_unload()
+//-----------------------------------------------------------------------------
+void rom_unload(void)
+{
+ if(ngpc_rom.data)
+ {
+ delete[] ngpc_rom.data;
+ ngpc_rom.data = NULL;
+ ngpc_rom.length = 0;
+ rom_header = 0;
+
+ for(int i = 0; i < 16; i++)
+ ngpc_rom.name[i] = 0;
+ }
+
+ if(ngpc_rom.orig_data)
+ {
+ delete[] ngpc_rom.orig_data;
+ ngpc_rom.orig_data = NULL;
+ }
+}
+
+}
+
+//=============================================================================
diff --git a/waterbox/ngp/rtc.cpp b/waterbox/ngp/rtc.cpp
new file mode 100644
index 0000000000..b4deb6f28d
--- /dev/null
+++ b/waterbox/ngp/rtc.cpp
@@ -0,0 +1,70 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#include "neopop.h"
+#include
+
+namespace MDFN_IEN_NGP
+{
+
+extern time_t frontend_time;
+
+static uint8 rtc_latch[7];
+
+static void update_rtc_latch(void)
+{
+ uint8 low, high;
+
+ //Get the system time
+ const struct tm* localTime = gmtime(&frontend_time);
+
+ low = localTime->tm_year - 100;
+ high = low; //Years
+ rtc_latch[0x00] = ((high / 10) << 4) | (low % 10);
+
+ low = localTime->tm_mon + 1;
+ high = low; //Months
+ rtc_latch[0x01] = ((high / 10) << 4) | (low % 10);
+
+ low = localTime->tm_mday;
+ high = low; //Days
+ rtc_latch[0x02] = ((high / 10) << 4) | (low % 10);
+
+ low = localTime->tm_hour;
+ high = low; //Hours
+ rtc_latch[0x03] = ((high / 10) << 4) | (low % 10);
+
+ low = localTime->tm_min;
+ high = low; //Minutes
+ rtc_latch[0x04] = ((high / 10) << 4) | (low % 10);
+
+ low = localTime->tm_sec;
+ high = low; //Seconds
+ rtc_latch[0x05] = ((high / 10) << 4) | (low % 10);
+
+ rtc_latch[0x06] = ((rtc_latch[0x00] % 4) << 4) | (localTime->tm_wday & 0x0F);
+}
+
+uint8 rtc_read8(uint32 address)
+{
+ if (address >= 0x0091 && address <= 0x0097)
+ {
+ if (address == 0x0091)
+ update_rtc_latch();
+
+ return (rtc_latch[address - 0x0091]);
+ }
+ return (0);
+}
+}
diff --git a/waterbox/ngp/rtc.h b/waterbox/ngp/rtc.h
new file mode 100644
index 0000000000..871dd29959
--- /dev/null
+++ b/waterbox/ngp/rtc.h
@@ -0,0 +1,11 @@
+#ifndef __NGP_RTC_H
+#define __NGP_RTC_H
+
+namespace MDFN_IEN_NGP
+{
+
+uint8 rtc_read8(uint32 address);
+
+}
+
+#endif
diff --git a/waterbox/ngp/sound.cpp b/waterbox/ngp/sound.cpp
new file mode 100644
index 0000000000..d14dd248f8
--- /dev/null
+++ b/waterbox/ngp/sound.cpp
@@ -0,0 +1,114 @@
+/* Mednafen - Multi-system Emulator
+ *
+ * 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
+ */
+
+#include "neopop.h"
+#include "sound.h"
+
+#include "sound/Blip_Buffer.h"
+#include "T6W28_Apu.h"
+#include "sound/Stereo_Buffer.h"
+
+namespace MDFN_IEN_NGP
+{
+
+static T6W28_Apu apu;
+
+static Stereo_Buffer st_buf;
+
+static uint8 LastDACLeft = 0, LastDACRight = 0;
+static uint8 CurrentDACLeft = 0, CurrentDACRight = 0;
+
+typedef Blip_Synth Synth;
+static Synth synth;
+extern int32 ngpc_soundTS;
+static bool schipenable = 0;
+
+void MDFNNGPCSOUND_SetEnable(bool set)
+{
+ schipenable = set;
+ if (!set)
+ apu.reset();
+}
+
+void Write_SoundChipLeft(uint8 data)
+{
+ if (schipenable)
+ apu.write_data_left(ngpc_soundTS >> 1, data);
+}
+
+void Write_SoundChipRight(uint8 data)
+{
+ if (schipenable)
+ apu.write_data_right(ngpc_soundTS >> 1, data);
+}
+
+void dac_write_left(uint8 data)
+{
+ CurrentDACLeft = data;
+
+ synth.offset_inline(ngpc_soundTS >> 1, CurrentDACLeft - LastDACLeft, st_buf.left());
+
+ LastDACLeft = data;
+}
+
+void dac_write_right(uint8 data)
+{
+ CurrentDACRight = data;
+
+ synth.offset_inline(ngpc_soundTS >> 1, CurrentDACRight - LastDACRight, st_buf.right());
+
+ LastDACRight = data;
+}
+
+int32 MDFNNGPCSOUND_Flush(int16 *SoundBuf, const int32 MaxSoundFrames)
+{
+ int32 FrameCount = 0;
+
+ apu.end_frame(ngpc_soundTS >> 1);
+
+ st_buf.end_frame(ngpc_soundTS >> 1);
+
+ if (SoundBuf)
+ FrameCount = st_buf.read_samples(SoundBuf, MaxSoundFrames * 2) / 2;
+ else
+ st_buf.clear();
+
+ return (FrameCount);
+}
+
+static void RedoVolume(void)
+{
+ apu.output(st_buf.center(), st_buf.left(), st_buf.right());
+ apu.volume(0.30);
+ synth.volume(0.40);
+}
+
+void MDFNNGPCSOUND_Init(void)
+{
+ MDFNNGPC_SetSoundRate(0);
+ st_buf.clock_rate((long)(3072000));
+
+ RedoVolume();
+ st_buf.bass_freq(20);
+}
+
+bool MDFNNGPC_SetSoundRate(uint32 rate)
+{
+ st_buf.set_sample_rate(rate ? rate : 44100, 60);
+ return (TRUE);
+}
+}
diff --git a/waterbox/ngp/sound.h b/waterbox/ngp/sound.h
new file mode 100644
index 0000000000..bde71033c5
--- /dev/null
+++ b/waterbox/ngp/sound.h
@@ -0,0 +1,34 @@
+//---------------------------------------------------------------------------
+// NEOPOP : Emulator as in Dreamland
+//
+// Copyright (c) 2001-2002 by neopop_uk
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// 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. See also the license.txt file for
+// additional informations.
+//---------------------------------------------------------------------------
+
+#ifndef __NEOPOP_SOUND__
+#define __NEOPOP_SOUND__
+
+namespace MDFN_IEN_NGP
+{
+
+void Write_SoundChipLeft(uint8 data);
+void Write_SoundChipRight(uint8 data);
+
+void dac_write_left(uint8);
+void dac_write_right(uint8);
+
+int32 MDFNNGPCSOUND_Flush(int16 *SoundBuf, const int32 MaxSoundFrames);
+void MDFNNGPCSOUND_Init(void) MDFN_COLD;
+bool MDFNNGPC_SetSoundRate(uint32 rate);
+void MDFNNGPCSOUND_SetEnable(bool set);
+
+}
+
+#endif
diff --git a/waterbox/ngp/sound/Blip_Buffer.cpp b/waterbox/ngp/sound/Blip_Buffer.cpp
new file mode 100644
index 0000000000..f04a1fc599
--- /dev/null
+++ b/waterbox/ngp/sound/Blip_Buffer.cpp
@@ -0,0 +1,457 @@
+// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+
+#include "Blip_Buffer.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+ #include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
+
+Blip_Buffer::Blip_Buffer()
+{
+ factor_ = (blip_u64)ULLONG_MAX;
+ offset_ = 0;
+ buffer_ = 0;
+ buffer_size_ = 0;
+ sample_rate_ = 0;
+ reader_accum_ = 0;
+ bass_shift_ = 0;
+ clock_rate_ = 0;
+ bass_freq_ = 16;
+ length_ = 0;
+
+ // assumptions code makes about implementation-defined features
+ #ifndef NDEBUG
+ // right shift of negative value preserves sign
+ buf_t_ i = -0x7FFFFFFE;
+ assert( (i >> 1) == -0x3FFFFFFF );
+
+ // casting to short truncates to 16 bits and sign-extends
+ i = 0x18000;
+ assert( (short) i == -0x8000 );
+ #endif
+}
+
+Blip_Buffer::~Blip_Buffer()
+{
+ if ( buffer_size_ != silent_buf_size )
+ free( buffer_ );
+}
+
+Silent_Blip_Buffer::Silent_Blip_Buffer()
+{
+ factor_ = 0;
+ buffer_ = buf;
+ buffer_size_ = silent_buf_size;
+ memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
+}
+
+void Blip_Buffer::clear( int entire_buffer )
+{
+ offset_ = 0;
+ reader_accum_ = 0;
+ modified_ = 0;
+ if ( buffer_ )
+ {
+ long count = (entire_buffer ? buffer_size_ : samples_avail());
+ memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
+ }
+}
+
+Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
+{
+ if ( buffer_size_ == silent_buf_size )
+ {
+ assert( 0 );
+ return "Internal (tried to resize Silent_Blip_Buffer)";
+ }
+
+ // start with maximum length that resampled time can represent
+ blip_s64 new_size = (ULLONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
+
+ // simple safety check, since code elsewhere may not be safe for sizes approaching (2 ^ 31).
+ if(new_size > ((1LL << 30) - 1))
+ new_size = (1LL << 30) - 1;
+
+ if ( msec != blip_max_length )
+ {
+ blip_s64 s = ((blip_s64)new_rate * (msec + 1) + 999) / 1000;
+ if ( s < new_size )
+ new_size = s;
+ else
+ assert( 0 ); // fails if requested buffer length exceeds limit
+ }
+
+ if ( buffer_size_ != new_size )
+ {
+ void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
+ if ( !p )
+ return "Out of memory";
+
+ //if(new_size > buffer_size_)
+ // memset(buffer_ + buffer_size_, 0, (new_size + blip_buffer_extra_) * sizeof *buffer_
+
+ buffer_ = (buf_t_*) p;
+ }
+
+ buffer_size_ = new_size;
+ assert( buffer_size_ != silent_buf_size );
+
+ // update things based on the sample rate
+ sample_rate_ = new_rate;
+ length_ = new_size * 1000 / new_rate - 1;
+ if ( msec )
+ assert( length_ == msec ); // ensure length is same as that passed in
+ if ( clock_rate_ )
+ clock_rate( clock_rate_ );
+ bass_freq( bass_freq_ );
+
+ clear();
+
+ return 0; // success
+}
+
+blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
+{
+ double ratio = (double) sample_rate_ / rate;
+ blip_s64 factor = (blip_s64) floor( ratio * (1LL << BLIP_BUFFER_ACCURACY) + 0.5 );
+ assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
+ return (blip_resampled_time_t) factor;
+}
+
+void Blip_Buffer::bass_freq( int freq )
+{
+ bass_freq_ = freq;
+ int shift = 31;
+ if ( freq > 0 )
+ {
+ shift = 13;
+ long f = (freq << 16) / sample_rate_;
+ while ( (f >>= 1) && --shift ) { }
+ }
+ bass_shift_ = shift;
+ //printf("%d\n", bass_shift_);
+}
+
+void Blip_Buffer::end_frame( blip_time_t t )
+{
+ offset_ += t * factor_;
+ assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
+}
+
+void Blip_Buffer::remove_silence( long count )
+{
+ assert( count <= samples_avail() ); // tried to remove more samples than available
+ offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+}
+
+long Blip_Buffer::count_samples( blip_time_t t ) const
+{
+ unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
+ unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
+ return (long) (last_sample - first_sample);
+}
+
+blip_time_t Blip_Buffer::count_clocks( long count ) const
+{
+ if ( !factor_ )
+ {
+ assert( 0 ); // sample rate and clock rates must be set first
+ return 0;
+ }
+
+ if ( count > buffer_size_ )
+ count = buffer_size_;
+ blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+ return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
+}
+
+void Blip_Buffer::remove_samples( long count )
+{
+ if ( count )
+ {
+ remove_silence( count );
+
+ // copy remaining samples to beginning and clear old samples
+ long remain = samples_avail() + blip_buffer_extra_;
+ memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
+ memset( buffer_ + remain, 0, count * sizeof *buffer_ );
+ }
+}
+
+// Blip_Synth_
+
+Blip_Synth_Fast_::Blip_Synth_Fast_()
+{
+ buf = 0;
+ last_amp = 0;
+ delta_factor = 0;
+}
+
+void Blip_Synth_Fast_::volume_unit( double new_unit )
+{
+ delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
+}
+
+#if !BLIP_BUFFER_FAST
+
+Blip_Synth_::Blip_Synth_( short* p, int w ) :
+ impulses( p ),
+ width( w )
+{
+ volume_unit_ = 0.0;
+ kernel_unit = 0;
+ buf = 0;
+ last_amp = 0;
+ delta_factor = 0;
+}
+
+#undef PI
+#define PI 3.1415926535897932384626433832795029
+
+static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
+{
+ if ( cutoff >= 0.999 )
+ cutoff = 0.999;
+
+ if ( treble < -300.0 )
+ treble = -300.0;
+ if ( treble > 5.0 )
+ treble = 5.0;
+
+ double const maxh = 4096.0;
+ double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
+ double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
+ double const to_angle = PI / 2 / maxh / oversample;
+ for ( int i = 0; i < count; i++ )
+ {
+ double angle = ((i - count) * 2 + 1) * to_angle;
+ double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
+ double cos_nc_angle = cos( maxh * cutoff * angle );
+ double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
+ double cos_angle = cos( angle );
+
+ c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
+ double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
+ double b = 2.0 - cos_angle - cos_angle;
+ double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
+
+ out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
+ }
+}
+
+void blip_eq_t::generate( float* out, int count ) const
+{
+ // lower cutoff freq for narrow kernels with their wider transition band
+ // (8 points->1.49, 16 points->1.15)
+ double oversample = blip_res * 2.25 / count + 0.85;
+ double half_rate = sample_rate * 0.5;
+ if ( cutoff_freq )
+ oversample = half_rate / cutoff_freq;
+ double cutoff = rolloff_freq * oversample / half_rate;
+
+ gen_sinc( out, count, blip_res * oversample, treble, cutoff );
+
+ // apply (half of) hamming window
+ double to_fraction = PI / (count - 1);
+ for ( int i = count; i--; )
+ out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
+}
+
+void Blip_Synth_::adjust_impulse()
+{
+ // sum pairs for each phase and add error correction to end of first half
+ int const size = impulses_size();
+ for ( int p = blip_res; p-- >= blip_res / 2; )
+ {
+ int p2 = blip_res - 2 - p;
+ long error = kernel_unit;
+ for ( int i = 1; i < size; i += blip_res )
+ {
+ error -= impulses [i + p ];
+ error -= impulses [i + p2];
+ }
+ if ( p == p2 )
+ error /= 2; // phase = 0.5 impulse uses same half for both sides
+ impulses [size - blip_res + p] += (short) error;
+ //printf( "error: %ld\n", error );
+ }
+
+ //for ( int i = blip_res; i--; printf( "\n" ) )
+ // for ( int j = 0; j < width / 2; j++ )
+ // printf( "%5ld,", impulses [j * blip_res + i + 1] );
+}
+
+void Blip_Synth_::treble_eq( blip_eq_t const& eq )
+{
+ float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
+
+ int const half_size = blip_res / 2 * (width - 1);
+ eq.generate( &fimpulse [blip_res], half_size );
+
+ int i;
+
+ // need mirror slightly past center for calculation
+ for ( i = blip_res; i--; )
+ fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
+
+ // starts at 0
+ for ( i = 0; i < blip_res; i++ )
+ fimpulse [i] = 0.0f;
+
+ // find rescale factor
+ double total = 0.0;
+ for ( i = 0; i < half_size; i++ )
+ total += fimpulse [blip_res + i];
+
+ //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
+ //double const base_unit = 37888.0; // allows treble to +5 dB
+ double const base_unit = 32768.0; // necessary for blip_unscaled to work
+ double rescale = base_unit / 2 / total;
+ kernel_unit = (long) base_unit;
+
+ // integrate, first difference, rescale, convert to int
+ double sum = 0.0;
+ double next = 0.0;
+ int const impulses_size_local = this->impulses_size();
+ for ( i = 0; i < impulses_size_local; i++ )
+ {
+ impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
+ sum += fimpulse [i];
+ next += fimpulse [i + blip_res];
+ }
+ adjust_impulse();
+
+ // volume might require rescaling
+ double vol = volume_unit_;
+ if ( vol )
+ {
+ volume_unit_ = 0.0;
+ volume_unit( vol );
+ }
+}
+
+void Blip_Synth_::volume_unit( double new_unit )
+{
+ if ( new_unit != volume_unit_ )
+ {
+ // use default eq if it hasn't been set yet
+ if ( !kernel_unit )
+ treble_eq( -8.0 );
+
+ volume_unit_ = new_unit;
+ double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
+
+ if ( factor > 0.0 )
+ {
+ int shift = 0;
+
+ // if unit is really small, might need to attenuate kernel
+ while ( factor < 2.0 )
+ {
+ shift++;
+ factor *= 2.0;
+ }
+
+ if ( shift )
+ {
+ kernel_unit >>= shift;
+ assert( kernel_unit > 0 ); // fails if volume unit is too low
+
+ // keep values positive to avoid round-towards-zero of sign-preserving
+ // right shift for negative values
+ long offset = 0x8000 + (1 << (shift - 1));
+ long offset2 = 0x8000 >> shift;
+ for ( int i = impulses_size(); i--; )
+ impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
+ adjust_impulse();
+ }
+ }
+ delta_factor = (int) floor( factor + 0.5 );
+ //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
+ }
+}
+#endif
+
+long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
+{
+ long count = samples_avail();
+ if ( count > max_samples )
+ count = max_samples;
+
+ if ( count )
+ {
+ int const bass = BLIP_READER_BASS( *this );
+ BLIP_READER_BEGIN( reader, *this );
+
+ if ( !stereo )
+ {
+ for ( blip_long n = count; n; --n )
+ {
+ blip_long s = BLIP_READER_READ( reader );
+ if ( (blip_sample_t) s != s )
+ s = 0x7FFF - (s >> 24);
+ *out++ = (blip_sample_t) s;
+ BLIP_READER_NEXT( reader, bass );
+ }
+ }
+ else
+ {
+ for ( blip_long n = count; n; --n )
+ {
+ blip_long s = BLIP_READER_READ( reader );
+ if ( (blip_sample_t) s != s )
+ s = 0x7FFF - (s >> 24);
+ *out = (blip_sample_t) s;
+ out += 2;
+ BLIP_READER_NEXT( reader, bass );
+ }
+ }
+ BLIP_READER_END( reader, *this );
+
+ remove_samples( count );
+ }
+ return count;
+}
+
+void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
+{
+ if ( buffer_size_ == silent_buf_size )
+ {
+ assert( 0 );
+ return;
+ }
+
+ buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
+
+ int const sample_shift = blip_sample_bits - 16;
+ int prev = 0;
+ while ( count-- )
+ {
+ blip_long s = (blip_long) *in++ << sample_shift;
+ *out += s - prev;
+ prev = s;
+ ++out;
+ }
+ *out -= prev;
+}
+
diff --git a/waterbox/ngp/sound/Blip_Buffer.h b/waterbox/ngp/sound/Blip_Buffer.h
new file mode 100644
index 0000000000..a8e90ee053
--- /dev/null
+++ b/waterbox/ngp/sound/Blip_Buffer.h
@@ -0,0 +1,498 @@
+// Band-limited sound synthesis buffer
+// Various changes and hacks for use in Mednafen.
+
+#ifdef __GNUC__
+ #define blip_inline inline __attribute__((always_inline))
+#else
+ #define blip_inline inline
+#endif
+
+#include
+#include
+
+// Blip_Buffer 0.4.1
+#ifndef BLIP_BUFFER_H
+#define BLIP_BUFFER_H
+
+// Internal
+typedef int32_t blip_long;
+typedef uint32_t blip_ulong;
+typedef int64_t blip_s64;
+typedef uint64_t blip_u64;
+
+// Time unit at source clock rate
+typedef blip_long blip_time_t;
+
+// Output samples are 16-bit signed, with a range of -32768 to 32767
+typedef short blip_sample_t;
+enum { blip_sample_max = 32767 };
+
+class Blip_Buffer {
+public:
+ typedef const char* blargg_err_t;
+
+ // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
+ // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
+ // isn't enough memory, returns error without affecting current buffer setup.
+ blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
+
+ // Set number of source time units per second
+ void clock_rate( long );
+
+ // End current time frame of specified duration and make its samples available
+ // (along with any still-unread samples) for reading with read_samples(). Begins
+ // a new time frame at the end of the current frame.
+ void end_frame( blip_time_t time );
+
+ // Read at most 'max_samples' out of buffer into 'dest', removing them from from
+ // the buffer. Returns number of samples actually read and removed. If stereo is
+ // true, increments 'dest' one extra time after writing each sample, to allow
+ // easy interleving of two channels into a stereo output buffer.
+ long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
+
+// Additional optional features
+
+ // Current output sample rate
+ long sample_rate() const;
+
+ // Length of buffer, in milliseconds
+ int length() const;
+
+ // Number of source time units per second
+ long clock_rate() const;
+
+ // Set frequency high-pass filter frequency, where higher values reduce bass more
+ void bass_freq( int frequency );
+
+ // Number of samples delay from synthesis to samples read out
+ int output_latency() const;
+
+ // Remove all available samples and clear buffer to silence. If 'entire_buffer' is
+ // false, just clears out any samples waiting rather than the entire buffer.
+ void clear( int entire_buffer = 1 );
+
+ // Number of samples available for reading with read_samples()
+ long samples_avail() const;
+
+ // Remove 'count' samples from those waiting to be read
+ void remove_samples( long count );
+
+// Experimental features
+
+ // Count number of clocks needed until 'count' samples will be available.
+ // If buffer can't even hold 'count' samples, returns number of clocks until
+ // buffer becomes full.
+ blip_time_t count_clocks( long count ) const;
+
+ // Number of raw samples that can be mixed within frame of specified duration.
+ long count_samples( blip_time_t duration ) const;
+
+ // Mix 'count' samples from 'buf' into buffer.
+ void mix_samples( blip_sample_t const* buf, long count );
+
+ // not documented yet
+ void set_modified() { modified_ = 1; }
+ int clear_modified() { int b = modified_; modified_ = 0; return b; }
+ typedef blip_u64 blip_resampled_time_t;
+ void remove_silence( long count );
+ blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
+ blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
+ blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
+public:
+ Blip_Buffer();
+ ~Blip_Buffer();
+
+ // Deprecated
+ typedef blip_resampled_time_t resampled_time_t;
+ blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
+ blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
+private:
+ // noncopyable
+ Blip_Buffer( const Blip_Buffer& );
+ Blip_Buffer& operator = ( const Blip_Buffer& );
+public:
+ typedef blip_time_t buf_t_;
+ blip_u64 factor_;
+ blip_resampled_time_t offset_;
+ buf_t_* buffer_;
+ blip_long buffer_size_;
+ blip_long reader_accum_;
+ int bass_shift_;
+private:
+ long sample_rate_;
+ long clock_rate_;
+ int bass_freq_;
+ int length_;
+ int modified_;
+ friend class Blip_Reader;
+};
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#define BLIP_BUFFER_ACCURACY 32
+#define BLIP_PHASE_BITS 8
+
+// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
+// but reduce maximum buffer size.
+//#ifndef BLIP_BUFFER_ACCURACY
+// #define BLIP_BUFFER_ACCURACY 16
+//#endif
+
+// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
+// noticeable broadband noise when synthesizing high frequency square waves.
+// Affects size of Blip_Synth objects since they store the waveform directly.
+//#ifndef BLIP_PHASE_BITS
+// #if BLIP_BUFFER_FAST
+// #define BLIP_PHASE_BITS 8
+// #else
+// #define BLIP_PHASE_BITS 6
+// #endif
+//#endif
+
+ // Internal
+ typedef blip_u64 blip_resampled_time_t;
+ int const blip_widest_impulse_ = 16;
+ int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
+ int const blip_res = 1 << BLIP_PHASE_BITS;
+ class blip_eq_t;
+
+ class Blip_Synth_Fast_ {
+ public:
+ Blip_Buffer* buf;
+ int last_amp;
+ int delta_factor;
+
+ void volume_unit( double );
+ Blip_Synth_Fast_();
+ void treble_eq( blip_eq_t const& ) { }
+ };
+
+ class Blip_Synth_ {
+ public:
+ Blip_Buffer* buf;
+ int last_amp;
+ int delta_factor;
+
+ void volume_unit( double );
+ Blip_Synth_( short* impulses, int width );
+ void treble_eq( blip_eq_t const& );
+ private:
+ double volume_unit_;
+ short* const impulses;
+ int const width;
+ blip_long kernel_unit;
+ int impulses_size() const { return blip_res / 2 * width + 1; }
+ void adjust_impulse();
+ };
+
+// Quality level. Start with blip_good_quality.
+const int blip_med_quality = 8;
+const int blip_good_quality = 12;
+const int blip_high_quality = 16;
+
+// Range specifies the greatest expected change in amplitude. Calculate it
+// by finding the difference between the maximum and minimum expected
+// amplitudes (max - min).
+template
+class Blip_Synth {
+public:
+ // Set overall volume of waveform
+ void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
+
+ // Configure low-pass filter (see blip_buffer.txt)
+ void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
+
+ // Get/set Blip_Buffer used for output
+ Blip_Buffer* output() const { return impl.buf; }
+ void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
+
+ // Update amplitude of waveform at given time. Using this requires a separate
+ // Blip_Synth for each waveform.
+ void update( blip_time_t time, int amplitude );
+
+// Low-level interface
+
+ // Add an amplitude transition of specified delta, optionally into specified buffer
+ // rather than the one set with output(). Delta can be positive or negative.
+ // The actual change in amplitude is delta * (volume / range)
+ void offset( blip_time_t, int delta, Blip_Buffer* ) const;
+ void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
+
+ // Works directly in terms of fractional output samples. Contact author for more info.
+ void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
+
+ // Same as offset(), except code is inlined for higher performance
+ void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
+ offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
+ }
+ void offset_inline( blip_time_t t, int delta ) const {
+ offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
+ }
+
+private:
+#if BLIP_BUFFER_FAST
+ Blip_Synth_Fast_ impl;
+#else
+ Blip_Synth_ impl;
+ typedef short imp_t;
+ imp_t impulses [blip_res * (quality / 2) + 1];
+public:
+ Blip_Synth() : impl( impulses, quality ) { }
+#endif
+};
+
+// Low-pass equalization parameters
+class blip_eq_t {
+public:
+ // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
+ // treble, small positive values (0 to 5.0) increase treble.
+ blip_eq_t( double treble_db = 0 );
+
+ // See blip_buffer.txt
+ blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
+
+private:
+ double treble;
+ long rolloff_freq;
+ long sample_rate;
+ long cutoff_freq;
+ void generate( float* out, int count ) const;
+ friend class Blip_Synth_;
+};
+
+int const blip_sample_bits = 30;
+
+// Dummy Blip_Buffer to direct sound output to, for easy muting without
+// having to stop sound code.
+class Silent_Blip_Buffer : public Blip_Buffer {
+ buf_t_ buf [blip_buffer_extra_ + 1];
+public:
+ // The following cannot be used (an assertion will fail if attempted):
+ blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
+ blip_time_t count_clocks( long count ) const;
+ void mix_samples( blip_sample_t const* buf, long count );
+
+ Silent_Blip_Buffer();
+};
+
+ #if defined (__GNUC__) || _MSC_VER >= 1100
+ #define BLIP_RESTRICT __restrict
+ #else
+ #define BLIP_RESTRICT
+ #endif
+
+// Optimized reading from Blip_Buffer, for use in custom sample output
+
+// Begin reading from buffer. Name should be unique to the current block.
+#define BLIP_READER_BEGIN( name, blip_buffer ) \
+ const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
+ blip_long name##_reader_accum = (blip_buffer).reader_accum_
+
+// Get value to pass to BLIP_READER_NEXT()
+#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
+
+// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
+// code at the cost of having no bass control
+int const blip_reader_default_bass = 9;
+
+// Current sample
+#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
+
+// Current raw sample in full internal resolution
+#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
+
+// Advance to next sample
+#define BLIP_READER_NEXT( name, bass ) \
+ (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
+
+// End reading samples from buffer. The number of samples read must now be removed
+// using Blip_Buffer::remove_samples().
+#define BLIP_READER_END( name, blip_buffer ) \
+ (void) ((blip_buffer).reader_accum_ = name##_reader_accum)
+
+
+// Compatibility with older version
+const long blip_unscaled = 65535;
+const int blip_low_quality = blip_med_quality;
+const int blip_best_quality = blip_high_quality;
+
+// Deprecated; use BLIP_READER macros as follows:
+// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
+// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
+// r.read() -> BLIP_READER_READ( r )
+// r.read_raw() -> BLIP_READER_READ_RAW( r )
+// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
+// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
+// r.end( buf ) -> BLIP_READER_END( r, buf )
+class Blip_Reader {
+public:
+ int begin( Blip_Buffer& );
+ blip_long read() const { return accum >> (blip_sample_bits - 16); }
+ blip_long read_raw() const { return accum; }
+ void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
+ void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
+
+private:
+ const Blip_Buffer::buf_t_* buf;
+ blip_long accum;
+};
+
+// End of public interface
+
+#include
+
+template
+blip_inline void Blip_Synth::offset_resampled( blip_resampled_time_t time,
+ int delta, Blip_Buffer* blip_buf ) const
+{
+ // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
+ // need for a longer buffer as set by set_sample_rate().
+ assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
+ delta *= impl.delta_factor;
+ blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
+ int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
+
+#if BLIP_BUFFER_FAST
+ blip_long left = buf [0] + delta;
+
+ // Kind of crappy, but doing shift after multiply results in overflow.
+ // Alternate way of delaying multiply by delta_factor results in worse
+ // sub-sample resolution.
+ blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
+ left -= right;
+ right += buf [1];
+
+ buf [0] = left;
+ buf [1] = right;
+#else
+
+ int const fwd = (blip_widest_impulse_ - quality) / 2;
+ int const rev = fwd + quality - 2;
+ int const mid = quality / 2 - 1;
+
+ imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
+
+ #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
+ defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
+
+ // straight forward implementation resulted in better code on GCC for x86
+
+ #define ADD_IMP( out, in ) \
+ buf [out] += (blip_long) imp [blip_res * (in)] * delta
+
+ #define BLIP_FWD( i ) {\
+ ADD_IMP( fwd + i, i );\
+ ADD_IMP( fwd + 1 + i, i + 1 );\
+ }
+ #define BLIP_REV( r ) {\
+ ADD_IMP( rev - r, r + 1 );\
+ ADD_IMP( rev + 1 - r, r );\
+ }
+
+ BLIP_FWD( 0 )
+ if ( quality > 8 ) BLIP_FWD( 2 )
+ if ( quality > 12 ) BLIP_FWD( 4 )
+ {
+ ADD_IMP( fwd + mid - 1, mid - 1 );
+ ADD_IMP( fwd + mid , mid );
+ imp = impulses + phase;
+ }
+ if ( quality > 12 ) BLIP_REV( 6 )
+ if ( quality > 8 ) BLIP_REV( 4 )
+ BLIP_REV( 2 )
+
+ ADD_IMP( rev , 1 );
+ ADD_IMP( rev + 1, 0 );
+
+ #else
+
+ // for RISC processors, help compiler by reading ahead of writes
+
+ #define BLIP_FWD( i ) {\
+ blip_long t0 = i0 * delta + buf [fwd + i];\
+ blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
+ i0 = imp [blip_res * (i + 2)];\
+ buf [fwd + i] = t0;\
+ buf [fwd + 1 + i] = t1;\
+ }
+ #define BLIP_REV( r ) {\
+ blip_long t0 = i0 * delta + buf [rev - r];\
+ blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
+ i0 = imp [blip_res * (r - 1)];\
+ buf [rev - r] = t0;\
+ buf [rev + 1 - r] = t1;\
+ }
+
+ blip_long i0 = *imp;
+ BLIP_FWD( 0 )
+ if ( quality > 8 ) BLIP_FWD( 2 )
+ if ( quality > 12 ) BLIP_FWD( 4 )
+ {
+ blip_long t0 = i0 * delta + buf [fwd + mid - 1];
+ blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
+ imp = impulses + phase;
+ i0 = imp [blip_res * mid];
+ buf [fwd + mid - 1] = t0;
+ buf [fwd + mid ] = t1;
+ }
+ if ( quality > 12 ) BLIP_REV( 6 )
+ if ( quality > 8 ) BLIP_REV( 4 )
+ BLIP_REV( 2 )
+
+ blip_long t0 = i0 * delta + buf [rev ];
+ blip_long t1 = *imp * delta + buf [rev + 1];
+ buf [rev ] = t0;
+ buf [rev + 1] = t1;
+ #endif
+
+#endif
+}
+
+#undef BLIP_FWD
+#undef BLIP_REV
+
+template
+#if BLIP_BUFFER_FAST
+ blip_inline
+#endif
+void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
+{
+ offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
+}
+
+template
+#if BLIP_BUFFER_FAST
+ blip_inline
+#endif
+void Blip_Synth::update( blip_time_t t, int amp )
+{
+ int delta = amp - impl.last_amp;
+ impl.last_amp = amp;
+ offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
+}
+
+blip_inline blip_eq_t::blip_eq_t( double t ) :
+ treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
+blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
+ treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
+
+blip_inline int Blip_Buffer::length() const { return length_; }
+blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
+blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
+blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
+blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
+blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
+
+blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
+{
+ buf = blip_buf.buffer_;
+ accum = blip_buf.reader_accum_;
+ return blip_buf.bass_shift_;
+}
+
+int const blip_max_length = 0;
+int const blip_default_length = 250;
+
+#endif
diff --git a/waterbox/ngp/sound/Stereo_Buffer.cpp b/waterbox/ngp/sound/Stereo_Buffer.cpp
new file mode 100644
index 0000000000..6e65464685
--- /dev/null
+++ b/waterbox/ngp/sound/Stereo_Buffer.cpp
@@ -0,0 +1,146 @@
+
+// Blip_Buffer 0.3.0. http://www.slack.net/~ant/nes-emu/
+
+#include "Stereo_Buffer.h"
+
+/* Library Copyright (C) 2004 Shay Green. Blip_Buffer 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.
+Stereo_Buffer 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 Stereo_Buffer; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+Stereo_Buffer::Stereo_Buffer() {
+ stereo_added = false;
+ was_stereo = false;
+}
+
+Stereo_Buffer::~Stereo_Buffer() {
+}
+
+bool Stereo_Buffer::set_sample_rate( long rate, int msec )
+{
+ for ( int i = 0; i < buf_count; i++ ) {
+ if ( bufs [i].set_sample_rate( rate, msec ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Stereo_Buffer::clock_rate( long rate )
+{
+ for ( int i = 0; i < buf_count; i++ )
+ bufs [i].clock_rate( rate );
+}
+
+void Stereo_Buffer::bass_freq( int bass )
+{
+ for ( unsigned i = 0; i < buf_count; i++ )
+ bufs [i].bass_freq( bass );
+}
+
+void Stereo_Buffer::clear()
+{
+ stereo_added = false;
+ was_stereo = false;
+ for ( int i = 0; i < buf_count; i++ )
+ bufs [i].clear();
+}
+
+void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo )
+{
+ for ( unsigned i = 0; i < buf_count; i++ )
+ {
+ bufs [i].end_frame( clock_count );
+ }
+ stereo_added |= stereo;
+}
+
+
+
+long Stereo_Buffer::read_samples( blip_sample_t* out, long max_samples )
+{
+ long count = bufs [0].samples_avail();
+ if ( count > max_samples / 2 )
+ count = max_samples / 2;
+ if ( count )
+ {
+ if ( stereo_added || was_stereo )
+ {
+ mix_stereo( out, count );
+
+ bufs [0].remove_samples( count );
+ bufs [1].remove_samples( count );
+ bufs [2].remove_samples( count );
+ }
+ else
+ {
+ mix_mono( out, count );
+
+ bufs [0].remove_samples( count );
+
+ bufs [1].remove_silence( count );
+ bufs [2].remove_silence( count );
+ }
+
+ // to do: this might miss opportunities for optimization
+ if ( !bufs [0].samples_avail() ) {
+ was_stereo = stereo_added;
+ stereo_added = false;
+ }
+ }
+
+ return count * 2;
+}
+
+void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count )
+{
+ Blip_Reader l_left;
+ Blip_Reader l_right;
+ Blip_Reader l_center;
+
+ l_left.begin( bufs [1] );
+ l_right.begin( bufs [2] );
+ int bass = l_center.begin( bufs [0] );
+
+ while ( count-- )
+ {
+ int c = l_center.read();
+ out [0] = c + l_left.read();
+ out [1] = c + l_right.read();
+ out += 2;
+
+ l_center.next( bass );
+ l_left.next( bass );
+ l_right.next( bass );
+ }
+
+ l_center.end( bufs [0] );
+ l_right.end( bufs [2] );
+ l_left.end( bufs [1] );
+}
+
+void Stereo_Buffer::mix_mono( blip_sample_t* out, long count )
+{
+ Blip_Reader in;
+ int bass = in.begin( bufs [0] );
+
+ while ( count-- )
+ {
+ int sample = in.read();
+ out [0] = sample;
+ out [1] = sample;
+ out += 2;
+ in.next( bass );
+ }
+
+ in.end( bufs [0] );
+}
+
diff --git a/waterbox/ngp/sound/Stereo_Buffer.h b/waterbox/ngp/sound/Stereo_Buffer.h
new file mode 100644
index 0000000000..3d907fac54
--- /dev/null
+++ b/waterbox/ngp/sound/Stereo_Buffer.h
@@ -0,0 +1,69 @@
+
+// Simple stereo Blip_Buffer for sound emulators whose oscillators output
+// either on the left only, center, or right only.
+
+// Blip_Buffer 0.3.0. Copyright (C) 2003-2004 Shay Green. GNU GPL license.
+
+#ifndef STEREO_BUFFER_H
+#define STEREO_BUFFER_H
+
+#include "Blip_Buffer.h"
+
+class Stereo_Buffer {
+public:
+ Stereo_Buffer();
+ ~Stereo_Buffer();
+
+ // Same as in Blip_Buffer (see Blip_Buffer.h)
+ bool set_sample_rate( long, int msec = 0 );
+ void clock_rate( long );
+ void bass_freq( int );
+ void clear();
+
+ // Buffers to output synthesis to
+ Blip_Buffer* left();
+ Blip_Buffer* center();
+ Blip_Buffer* right();
+
+ // Same as in Blip_Buffer. For more efficient operation, pass false
+ // for was_stereo if the left and right buffers had nothing added
+ // to them for this frame.
+ void end_frame( blip_time_t, bool was_stereo = true );
+
+ // Output is stereo with channels interleved, left before right. Counts
+ // are in samples, *not* pairs.
+ long samples_avail() const;
+ long read_samples( blip_sample_t*, long );
+
+private:
+ // noncopyable
+ Stereo_Buffer( const Stereo_Buffer& );
+ Stereo_Buffer& operator = ( const Stereo_Buffer& );
+
+ enum { buf_count = 3 };
+ Blip_Buffer bufs [buf_count];
+ bool stereo_added;
+ bool was_stereo;
+
+ void mix_stereo( blip_sample_t*, long );
+ void mix_mono( blip_sample_t*, long );
+};
+
+ inline Blip_Buffer* Stereo_Buffer::left() {
+ return &bufs [1];
+ }
+
+ inline Blip_Buffer* Stereo_Buffer::center() {
+ return &bufs [0];
+ }
+
+ inline Blip_Buffer* Stereo_Buffer::right() {
+ return &bufs [2];
+ }
+
+ inline long Stereo_Buffer::samples_avail() const {
+ return bufs [0].samples_avail();
+ }
+
+#endif
+
diff --git a/waterbox/ngp/z80-fuse/opcodes_base.c b/waterbox/ngp/z80-fuse/opcodes_base.c
new file mode 100644
index 0000000000..f56121db70
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/opcodes_base.c
@@ -0,0 +1,1123 @@
+/* opcodes_base.c: unshifted Z80 opcodes
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+/* NB: this file is autogenerated by 'z80.pl' from 'opcodes_base.dat',
+ and included in 'z80_ops.c' */
+
+ case 0x00: /* NOP */
+ break;
+ case 0x01: /* LD BC,nnnn */
+ C=Z80_RB_MACRO(PC++);
+ B=Z80_RB_MACRO(PC++);
+ break;
+ case 0x02: /* LD (BC),A */
+ Z80_WB_MACRO(BC,A);
+ break;
+ case 0x03: /* INC BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ BC++;
+ break;
+ case 0x04: /* INC B */
+ INC(B);
+ break;
+ case 0x05: /* DEC B */
+ DEC(B);
+ break;
+ case 0x06: /* LD B,nn */
+ B = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x07: /* RLCA */
+ A = ( A << 1 ) | ( A >> 7 );
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( A & ( FLAG_C | FLAG_3 | FLAG_5 ) );
+ break;
+ case 0x08: /* EX AF,AF' */
+ {
+ uint16 wordtemp = AF; AF = AF_; AF_ = wordtemp;
+ }
+ break;
+ case 0x09: /* ADD HL,BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(HL,BC);
+ break;
+ case 0x0a: /* LD A,(BC) */
+ A=Z80_RB_MACRO(BC);
+ break;
+ case 0x0b: /* DEC BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ BC--;
+ break;
+ case 0x0c: /* INC C */
+ INC(C);
+ break;
+ case 0x0d: /* DEC C */
+ DEC(C);
+ break;
+ case 0x0e: /* LD C,nn */
+ C = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x0f: /* RRCA */
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) | ( A & FLAG_C );
+ A = ( A >> 1) | ( A << 7 );
+ F |= ( A & ( FLAG_3 | FLAG_5 ) );
+ break;
+ case 0x10: /* DJNZ offset */
+ contend_read_no_mreq( IR, 1 );
+ B--;
+ if(B) {
+ JR();
+ } else {
+ contend_read( PC, 3 );
+ }
+ PC++;
+ break;
+ case 0x11: /* LD DE,nnnn */
+ E=Z80_RB_MACRO(PC++);
+ D=Z80_RB_MACRO(PC++);
+ break;
+ case 0x12: /* LD (DE),A */
+ Z80_WB_MACRO(DE,A);
+ break;
+ case 0x13: /* INC DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ DE++;
+ break;
+ case 0x14: /* INC D */
+ INC(D);
+ break;
+ case 0x15: /* DEC D */
+ DEC(D);
+ break;
+ case 0x16: /* LD D,nn */
+ D = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x17: /* RLA */
+ {
+ uint8 bytetemp = A;
+ A = ( A << 1 ) | ( F & FLAG_C );
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( A & ( FLAG_3 | FLAG_5 ) ) | ( bytetemp >> 7 );
+ }
+ break;
+ case 0x18: /* JR offset */
+ JR();
+ PC++;
+ break;
+ case 0x19: /* ADD HL,DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(HL,DE);
+ break;
+ case 0x1a: /* LD A,(DE) */
+ A=Z80_RB_MACRO(DE);
+ break;
+ case 0x1b: /* DEC DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ DE--;
+ break;
+ case 0x1c: /* INC E */
+ INC(E);
+ break;
+ case 0x1d: /* DEC E */
+ DEC(E);
+ break;
+ case 0x1e: /* LD E,nn */
+ E = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x1f: /* RRA */
+ {
+ uint8 bytetemp = A;
+ A = ( A >> 1 ) | ( F << 7 );
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( A & ( FLAG_3 | FLAG_5 ) ) | ( bytetemp & FLAG_C ) ;
+ }
+ break;
+ case 0x20: /* JR NZ,offset */
+ if( ! ( F & FLAG_Z ) ) {
+ JR();
+ } else {
+ contend_read( PC, 3 );
+ }
+ PC++;
+ break;
+ case 0x21: /* LD HL,nnnn */
+ L=Z80_RB_MACRO(PC++);
+ H=Z80_RB_MACRO(PC++);
+ break;
+ case 0x22: /* LD (nnnn),HL */
+ LD16_NNRR(L,H);
+ break;
+ case 0x23: /* INC HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ HL++;
+ break;
+ case 0x24: /* INC H */
+ INC(H);
+ break;
+ case 0x25: /* DEC H */
+ DEC(H);
+ break;
+ case 0x26: /* LD H,nn */
+ H = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x27: /* DAA */
+ {
+ uint8 add = 0, carry = ( F & FLAG_C );
+ if( ( F & FLAG_H ) || ( ( A & 0x0f ) > 9 ) ) add = 6;
+ if( carry || ( A > 0x99 ) ) add |= 0x60;
+ if( A > 0x99 ) carry = FLAG_C;
+ if( F & FLAG_N ) {
+ SUB(add);
+ } else {
+ ADD(add);
+ }
+ F = ( F & ~( FLAG_C | FLAG_P ) ) | carry | parity_table[A];
+ }
+ break;
+ case 0x28: /* JR Z,offset */
+ if( F & FLAG_Z ) {
+ JR();
+ } else {
+ contend_read( PC, 3 );
+ }
+ PC++;
+ break;
+ case 0x29: /* ADD HL,HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(HL,HL);
+ break;
+ case 0x2a: /* LD HL,(nnnn) */
+ LD16_RRNN(L,H);
+ break;
+ case 0x2b: /* DEC HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ HL--;
+ break;
+ case 0x2c: /* INC L */
+ INC(L);
+ break;
+ case 0x2d: /* DEC L */
+ DEC(L);
+ break;
+ case 0x2e: /* LD L,nn */
+ L = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x2f: /* CPL */
+ A ^= 0xff;
+ F = ( F & ( FLAG_C | FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( A & ( FLAG_3 | FLAG_5 ) ) | ( FLAG_N | FLAG_H );
+ break;
+ case 0x30: /* JR NC,offset */
+ if( ! ( F & FLAG_C ) ) {
+ JR();
+ } else {
+ contend_read( PC, 3 );
+ }
+ PC++;
+ break;
+ case 0x31: /* LD SP,nnnn */
+ SPL=Z80_RB_MACRO(PC++);
+ SPH=Z80_RB_MACRO(PC++);
+ break;
+ case 0x32: /* LD (nnnn),A */
+ {
+ uint16 wordtemp = Z80_RB_MACRO( PC++ );
+ wordtemp|=Z80_RB_MACRO(PC++) << 8;
+ Z80_WB_MACRO(wordtemp,A);
+ }
+ break;
+ case 0x33: /* INC SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SP++;
+ break;
+ case 0x34: /* INC (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ INC(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x35: /* DEC (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ DEC(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x36: /* LD (HL),nn */
+ Z80_WB_MACRO(HL,Z80_RB_MACRO(PC++));
+ break;
+ case 0x37: /* SCF */
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( A & ( FLAG_3 | FLAG_5 ) ) |
+ FLAG_C;
+ break;
+ case 0x38: /* JR C,offset */
+ if( F & FLAG_C ) {
+ JR();
+ } else {
+ contend_read( PC, 3 );
+ }
+ PC++;
+ break;
+ case 0x39: /* ADD HL,SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(HL,SP);
+ break;
+ case 0x3a: /* LD A,(nnnn) */
+ {
+ uint16 wordtemp;
+ wordtemp = Z80_RB_MACRO(PC++);
+ wordtemp|= ( Z80_RB_MACRO(PC++) << 8 );
+ A=Z80_RB_MACRO(wordtemp);
+ }
+ break;
+ case 0x3b: /* DEC SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SP--;
+ break;
+ case 0x3c: /* INC A */
+ INC(A);
+ break;
+ case 0x3d: /* DEC A */
+ DEC(A);
+ break;
+ case 0x3e: /* LD A,nn */
+ A = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x3f: /* CCF */
+ F = ( F & ( FLAG_P | FLAG_Z | FLAG_S ) ) |
+ ( ( F & FLAG_C ) ? FLAG_H : FLAG_C ) | ( A & ( FLAG_3 | FLAG_5 ) );
+ break;
+ case 0x40: /* LD B,B */
+ break;
+ case 0x41: /* LD B,C */
+ B=C;
+ break;
+ case 0x42: /* LD B,D */
+ B=D;
+ break;
+ case 0x43: /* LD B,E */
+ B=E;
+ break;
+ case 0x44: /* LD B,H */
+ B=H;
+ break;
+ case 0x45: /* LD B,L */
+ B=L;
+ break;
+ case 0x46: /* LD B,(HL) */
+ B=Z80_RB_MACRO(HL);
+ break;
+ case 0x47: /* LD B,A */
+ B=A;
+ break;
+ case 0x48: /* LD C,B */
+ C=B;
+ break;
+ case 0x49: /* LD C,C */
+ break;
+ case 0x4a: /* LD C,D */
+ C=D;
+ break;
+ case 0x4b: /* LD C,E */
+ C=E;
+ break;
+ case 0x4c: /* LD C,H */
+ C=H;
+ break;
+ case 0x4d: /* LD C,L */
+ C=L;
+ break;
+ case 0x4e: /* LD C,(HL) */
+ C=Z80_RB_MACRO(HL);
+ break;
+ case 0x4f: /* LD C,A */
+ C=A;
+ break;
+ case 0x50: /* LD D,B */
+ D=B;
+ break;
+ case 0x51: /* LD D,C */
+ D=C;
+ break;
+ case 0x52: /* LD D,D */
+ break;
+ case 0x53: /* LD D,E */
+ D=E;
+ break;
+ case 0x54: /* LD D,H */
+ D=H;
+ break;
+ case 0x55: /* LD D,L */
+ D=L;
+ break;
+ case 0x56: /* LD D,(HL) */
+ D=Z80_RB_MACRO(HL);
+ break;
+ case 0x57: /* LD D,A */
+ D=A;
+ break;
+ case 0x58: /* LD E,B */
+ E=B;
+ break;
+ case 0x59: /* LD E,C */
+ E=C;
+ break;
+ case 0x5a: /* LD E,D */
+ E=D;
+ break;
+ case 0x5b: /* LD E,E */
+ break;
+ case 0x5c: /* LD E,H */
+ E=H;
+ break;
+ case 0x5d: /* LD E,L */
+ E=L;
+ break;
+ case 0x5e: /* LD E,(HL) */
+ E=Z80_RB_MACRO(HL);
+ break;
+ case 0x5f: /* LD E,A */
+ E=A;
+ break;
+ case 0x60: /* LD H,B */
+ H=B;
+ break;
+ case 0x61: /* LD H,C */
+ H=C;
+ break;
+ case 0x62: /* LD H,D */
+ H=D;
+ break;
+ case 0x63: /* LD H,E */
+ H=E;
+ break;
+ case 0x64: /* LD H,H */
+ break;
+ case 0x65: /* LD H,L */
+ H=L;
+ break;
+ case 0x66: /* LD H,(HL) */
+ H=Z80_RB_MACRO(HL);
+ break;
+ case 0x67: /* LD H,A */
+ H=A;
+ break;
+ case 0x68: /* LD L,B */
+ L=B;
+ break;
+ case 0x69: /* LD L,C */
+ L=C;
+ break;
+ case 0x6a: /* LD L,D */
+ L=D;
+ break;
+ case 0x6b: /* LD L,E */
+ L=E;
+ break;
+ case 0x6c: /* LD L,H */
+ L=H;
+ break;
+ case 0x6d: /* LD L,L */
+ break;
+ case 0x6e: /* LD L,(HL) */
+ L=Z80_RB_MACRO(HL);
+ break;
+ case 0x6f: /* LD L,A */
+ L=A;
+ break;
+ case 0x70: /* LD (HL),B */
+ Z80_WB_MACRO(HL,B);
+ break;
+ case 0x71: /* LD (HL),C */
+ Z80_WB_MACRO(HL,C);
+ break;
+ case 0x72: /* LD (HL),D */
+ Z80_WB_MACRO(HL,D);
+ break;
+ case 0x73: /* LD (HL),E */
+ Z80_WB_MACRO(HL,E);
+ break;
+ case 0x74: /* LD (HL),H */
+ Z80_WB_MACRO(HL,H);
+ break;
+ case 0x75: /* LD (HL),L */
+ Z80_WB_MACRO(HL,L);
+ break;
+ case 0x76: /* HALT */
+ z80.halted=1;
+ PC--;
+ break;
+ case 0x77: /* LD (HL),A */
+ Z80_WB_MACRO(HL,A);
+ break;
+ case 0x78: /* LD A,B */
+ A=B;
+ break;
+ case 0x79: /* LD A,C */
+ A=C;
+ break;
+ case 0x7a: /* LD A,D */
+ A=D;
+ break;
+ case 0x7b: /* LD A,E */
+ A=E;
+ break;
+ case 0x7c: /* LD A,H */
+ A=H;
+ break;
+ case 0x7d: /* LD A,L */
+ A=L;
+ break;
+ case 0x7e: /* LD A,(HL) */
+ A=Z80_RB_MACRO(HL);
+ break;
+ case 0x7f: /* LD A,A */
+ break;
+ case 0x80: /* ADD A,B */
+ ADD(B);
+ break;
+ case 0x81: /* ADD A,C */
+ ADD(C);
+ break;
+ case 0x82: /* ADD A,D */
+ ADD(D);
+ break;
+ case 0x83: /* ADD A,E */
+ ADD(E);
+ break;
+ case 0x84: /* ADD A,H */
+ ADD(H);
+ break;
+ case 0x85: /* ADD A,L */
+ ADD(L);
+ break;
+ case 0x86: /* ADD A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ ADD(bytetemp);
+ }
+ break;
+ case 0x87: /* ADD A,A */
+ ADD(A);
+ break;
+ case 0x88: /* ADC A,B */
+ ADC(B);
+ break;
+ case 0x89: /* ADC A,C */
+ ADC(C);
+ break;
+ case 0x8a: /* ADC A,D */
+ ADC(D);
+ break;
+ case 0x8b: /* ADC A,E */
+ ADC(E);
+ break;
+ case 0x8c: /* ADC A,H */
+ ADC(H);
+ break;
+ case 0x8d: /* ADC A,L */
+ ADC(L);
+ break;
+ case 0x8e: /* ADC A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ ADC(bytetemp);
+ }
+ break;
+ case 0x8f: /* ADC A,A */
+ ADC(A);
+ break;
+ case 0x90: /* SUB A,B */
+ SUB(B);
+ break;
+ case 0x91: /* SUB A,C */
+ SUB(C);
+ break;
+ case 0x92: /* SUB A,D */
+ SUB(D);
+ break;
+ case 0x93: /* SUB A,E */
+ SUB(E);
+ break;
+ case 0x94: /* SUB A,H */
+ SUB(H);
+ break;
+ case 0x95: /* SUB A,L */
+ SUB(L);
+ break;
+ case 0x96: /* SUB A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ SUB(bytetemp);
+ }
+ break;
+ case 0x97: /* SUB A,A */
+ SUB(A);
+ break;
+ case 0x98: /* SBC A,B */
+ SBC(B);
+ break;
+ case 0x99: /* SBC A,C */
+ SBC(C);
+ break;
+ case 0x9a: /* SBC A,D */
+ SBC(D);
+ break;
+ case 0x9b: /* SBC A,E */
+ SBC(E);
+ break;
+ case 0x9c: /* SBC A,H */
+ SBC(H);
+ break;
+ case 0x9d: /* SBC A,L */
+ SBC(L);
+ break;
+ case 0x9e: /* SBC A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ SBC(bytetemp);
+ }
+ break;
+ case 0x9f: /* SBC A,A */
+ SBC(A);
+ break;
+ case 0xa0: /* AND A,B */
+ AND(B);
+ break;
+ case 0xa1: /* AND A,C */
+ AND(C);
+ break;
+ case 0xa2: /* AND A,D */
+ AND(D);
+ break;
+ case 0xa3: /* AND A,E */
+ AND(E);
+ break;
+ case 0xa4: /* AND A,H */
+ AND(H);
+ break;
+ case 0xa5: /* AND A,L */
+ AND(L);
+ break;
+ case 0xa6: /* AND A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ AND(bytetemp);
+ }
+ break;
+ case 0xa7: /* AND A,A */
+ AND(A);
+ break;
+ case 0xa8: /* XOR A,B */
+ XOR(B);
+ break;
+ case 0xa9: /* XOR A,C */
+ XOR(C);
+ break;
+ case 0xaa: /* XOR A,D */
+ XOR(D);
+ break;
+ case 0xab: /* XOR A,E */
+ XOR(E);
+ break;
+ case 0xac: /* XOR A,H */
+ XOR(H);
+ break;
+ case 0xad: /* XOR A,L */
+ XOR(L);
+ break;
+ case 0xae: /* XOR A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ XOR(bytetemp);
+ }
+ break;
+ case 0xaf: /* XOR A,A */
+ XOR(A);
+ break;
+ case 0xb0: /* OR A,B */
+ OR(B);
+ break;
+ case 0xb1: /* OR A,C */
+ OR(C);
+ break;
+ case 0xb2: /* OR A,D */
+ OR(D);
+ break;
+ case 0xb3: /* OR A,E */
+ OR(E);
+ break;
+ case 0xb4: /* OR A,H */
+ OR(H);
+ break;
+ case 0xb5: /* OR A,L */
+ OR(L);
+ break;
+ case 0xb6: /* OR A,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ OR(bytetemp);
+ }
+ break;
+ case 0xb7: /* OR A,A */
+ OR(A);
+ break;
+ case 0xb8: /* CP B */
+ CP(B);
+ break;
+ case 0xb9: /* CP C */
+ CP(C);
+ break;
+ case 0xba: /* CP D */
+ CP(D);
+ break;
+ case 0xbb: /* CP E */
+ CP(E);
+ break;
+ case 0xbc: /* CP H */
+ CP(H);
+ break;
+ case 0xbd: /* CP L */
+ CP(L);
+ break;
+ case 0xbe: /* CP (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ CP(bytetemp);
+ }
+ break;
+ case 0xbf: /* CP A */
+ CP(A);
+ break;
+ case 0xc0: /* RET NZ */
+ contend_read_no_mreq( IR, 1 );
+ if( ! ( F & FLAG_Z ) ) { RET(); }
+ break;
+ case 0xc1: /* POP BC */
+ POP16(C,B);
+ break;
+ case 0xc2: /* JP NZ,nnnn */
+ if( ! ( F & FLAG_Z ) ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xc3: /* JP nnnn */
+ JP();
+ break;
+ case 0xc4: /* CALL NZ,nnnn */
+ if( ! ( F & FLAG_Z ) ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xc5: /* PUSH BC */
+ contend_read_no_mreq( IR, 1 );
+ PUSH16(C,B);
+ break;
+ case 0xc6: /* ADD A,nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ ADD(bytetemp);
+ }
+ break;
+ case 0xc7: /* RST 00 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x00);
+ break;
+ case 0xc8: /* RET Z */
+ contend_read_no_mreq( IR, 1 );
+ if( F & FLAG_Z ) { RET(); }
+ break;
+ case 0xc9: /* RET */
+ RET();
+ break;
+ case 0xca: /* JP Z,nnnn */
+ if( F & FLAG_Z ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xcb: /* shift CB */
+ {
+ uint8 opcode2;
+ opcode2 = Z80_RB_MACRO( PC );
+ z80_tstates++;
+ PC++;
+ R++;
+ switch(opcode2) {
+#include "z80_cb.c"
+ }
+ }
+ break;
+ case 0xcc: /* CALL Z,nnnn */
+ if( F & FLAG_Z ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xcd: /* CALL nnnn */
+ CALL();
+ break;
+ case 0xce: /* ADC A,nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ ADC(bytetemp);
+ }
+ break;
+ case 0xcf: /* RST 8 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x08);
+ break;
+ case 0xd0: /* RET NC */
+ contend_read_no_mreq( IR, 1 );
+ if( ! ( F & FLAG_C ) ) { RET(); }
+ break;
+ case 0xd1: /* POP DE */
+ POP16(E,D);
+ break;
+ case 0xd2: /* JP NC,nnnn */
+ if( ! ( F & FLAG_C ) ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xd3: /* OUT (nn),A */
+ {
+ uint16 outtemp;
+ outtemp = Z80_RB_MACRO( PC++ ) + ( A << 8 );
+ Z80_WP_MACRO( outtemp, A );
+ }
+ break;
+ case 0xd4: /* CALL NC,nnnn */
+ if( ! ( F & FLAG_C ) ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xd5: /* PUSH DE */
+ contend_read_no_mreq( IR, 1 );
+ PUSH16(E,D);
+ break;
+ case 0xd6: /* SUB nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ SUB(bytetemp);
+ }
+ break;
+ case 0xd7: /* RST 10 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x10);
+ break;
+ case 0xd8: /* RET C */
+ contend_read_no_mreq( IR, 1 );
+ if( F & FLAG_C ) { RET(); }
+ break;
+ case 0xd9: /* EXX */
+ {
+ uint16 wordtemp;
+ wordtemp = BC; BC = BC_; BC_ = wordtemp;
+ wordtemp = DE; DE = DE_; DE_ = wordtemp;
+ wordtemp = HL; HL = HL_; HL_ = wordtemp;
+ }
+ break;
+ case 0xda: /* JP C,nnnn */
+ if( F & FLAG_C ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xdb: /* IN A,(nn) */
+ {
+ uint16 intemp;
+ intemp = Z80_RB_MACRO( PC++ ) + ( A << 8 );
+ A=Z80_RP_MACRO( intemp );
+ }
+ break;
+ case 0xdc: /* CALL C,nnnn */
+ if( F & FLAG_C ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xdd: /* shift DD */
+ {
+ uint8 opcode2;
+ opcode2 = Z80_RB_MACRO( PC );
+ z80_tstates++;
+ PC++;
+ R++;
+ switch(opcode2) {
+#define REGISTER IX
+#define REGISTERL IXL
+#define REGISTERH IXH
+#include "z80_ddfd.c"
+#undef REGISTERH
+#undef REGISTERL
+#undef REGISTER
+ }
+ }
+ break;
+ case 0xde: /* SBC A,nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ SBC(bytetemp);
+ }
+ break;
+ case 0xdf: /* RST 18 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x18);
+ break;
+ case 0xe0: /* RET PO */
+ contend_read_no_mreq( IR, 1 );
+ if( ! ( F & FLAG_P ) ) { RET(); }
+ break;
+ case 0xe1: /* POP HL */
+ POP16(L,H);
+ break;
+ case 0xe2: /* JP PO,nnnn */
+ if( ! ( F & FLAG_P ) ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xe3: /* EX (SP),HL */
+ {
+ uint8 bytetempl, bytetemph;
+ bytetempl = Z80_RB_MACRO( SP );
+ bytetemph = Z80_RB_MACRO( SP + 1 ); contend_read_no_mreq( SP + 1, 1 );
+ Z80_WB_MACRO( SP + 1, H );
+ Z80_WB_MACRO( SP, L );
+ contend_write_no_mreq( SP, 1 ); contend_write_no_mreq( SP, 1 );
+ L=bytetempl; H=bytetemph;
+ }
+ break;
+ case 0xe4: /* CALL PO,nnnn */
+ if( ! ( F & FLAG_P ) ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xe5: /* PUSH HL */
+ contend_read_no_mreq( IR, 1 );
+ PUSH16(L,H);
+ break;
+ case 0xe6: /* AND nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ AND(bytetemp);
+ }
+ break;
+ case 0xe7: /* RST 20 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x20);
+ break;
+ case 0xe8: /* RET PE */
+ contend_read_no_mreq( IR, 1 );
+ if( F & FLAG_P ) { RET(); }
+ break;
+ case 0xe9: /* JP HL */
+ PC=HL; /* NB: NOT INDIRECT! */
+ break;
+ case 0xea: /* JP PE,nnnn */
+ if( F & FLAG_P ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xeb: /* EX DE,HL */
+ {
+ uint16 wordtemp=DE; DE=HL; HL=wordtemp;
+ }
+ break;
+ case 0xec: /* CALL PE,nnnn */
+ if( F & FLAG_P ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xed: /* shift ED */
+ {
+ uint8 opcode2;
+ opcode2 = Z80_RB_MACRO( PC );
+ z80_tstates++;
+ PC++;
+ R++;
+ switch(opcode2) {
+#include "z80_ed.c"
+ }
+ }
+ break;
+ case 0xee: /* XOR A,nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ XOR(bytetemp);
+ }
+ break;
+ case 0xef: /* RST 28 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x28);
+ break;
+ case 0xf0: /* RET P */
+ contend_read_no_mreq( IR, 1 );
+ if( ! ( F & FLAG_S ) ) { RET(); }
+ break;
+ case 0xf1: /* POP AF */
+ POP16(F,A);
+ break;
+ case 0xf2: /* JP P,nnnn */
+ if( ! ( F & FLAG_S ) ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xf3: /* DI */
+ IFF1=IFF2=0;
+ break;
+ case 0xf4: /* CALL P,nnnn */
+ if( ! ( F & FLAG_S ) ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xf5: /* PUSH AF */
+ contend_read_no_mreq( IR, 1 );
+ PUSH16(F,A);
+ break;
+ case 0xf6: /* OR nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ OR(bytetemp);
+ }
+ break;
+ case 0xf7: /* RST 30 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x30);
+ break;
+ case 0xf8: /* RET M */
+ contend_read_no_mreq( IR, 1 );
+ if( F & FLAG_S ) { RET(); }
+ break;
+ case 0xf9: /* LD SP,HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SP = HL;
+ break;
+ case 0xfa: /* JP M,nnnn */
+ if( F & FLAG_S ) {
+ JP();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xfb: /* EI */
+ /* Interrupts are not accepted immediately after an EI, but are
+ accepted after the next instruction */
+ IFF1 = IFF2 = 1;
+ z80.interrupts_enabled_at = z80_tstates;
+ //event_add( z80_tstates + 1, z80_interrupt_event );
+ break;
+ case 0xfc: /* CALL M,nnnn */
+ if( F & FLAG_S ) {
+ CALL();
+ } else {
+ contend_read( PC, 3 ); contend_read( PC + 1, 3 ); PC += 2;
+ }
+ break;
+ case 0xfd: /* shift FD */
+ {
+ uint8 opcode2;
+ opcode2 = Z80_RB_MACRO( PC );
+ z80_tstates++;
+ PC++;
+ R++;
+ switch(opcode2) {
+#define REGISTER IY
+#define REGISTERL IYL
+#define REGISTERH IYH
+#include "z80_ddfd.c"
+#undef REGISTERH
+#undef REGISTERL
+#undef REGISTER
+ }
+ }
+ break;
+ case 0xfe: /* CP nn */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( PC++ );
+ CP(bytetemp);
+ }
+ break;
+ case 0xff: /* RST 38 */
+ contend_read_no_mreq( IR, 1 );
+ RST(0x38);
+ break;
diff --git a/waterbox/ngp/z80-fuse/z80.cpp b/waterbox/ngp/z80-fuse/z80.cpp
new file mode 100644
index 0000000000..d37b70795c
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80.cpp
@@ -0,0 +1,183 @@
+/* z80.c: z80 supplementary functions
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+#include "z80.h"
+#include "z80_macros.h"
+
+void (*z80_writebyte)(uint16, uint8);
+uint8 (*z80_readbyte)(uint16);
+void (*z80_writeport)(uint16, uint8);
+uint8 (*z80_readport)(uint16);
+
+/* Whether a half carry occurred or not can be determined by looking at
+ the 3rd bit of the two arguments and the result; these are hashed
+ into this table in the form r12, where r is the 3rd bit of the
+ result, 1 is the 3rd bit of the 1st argument and 2 is the
+ third bit of the 2nd argument; the tables differ for add and subtract
+ operations */
+const uint8 halfcarry_add_table[] =
+ {0, FLAG_H, FLAG_H, FLAG_H, 0, 0, 0, FLAG_H};
+const uint8 halfcarry_sub_table[] =
+ {0, 0, FLAG_H, 0, FLAG_H, 0, FLAG_H, FLAG_H};
+
+/* Similarly, overflow can be determined by looking at the 7th bits; again
+ the hash into this table is r12 */
+const uint8 overflow_add_table[] = {0, 0, 0, FLAG_V, FLAG_V, 0, 0, 0};
+const uint8 overflow_sub_table[] = {0, FLAG_V, 0, 0, 0, 0, FLAG_V, 0};
+
+/* Some more tables; initialised in z80_init_tables() */
+
+uint8 sz53_table[0x100]; /* The S, Z, 5 and 3 bits of the index */
+uint8 parity_table[0x100]; /* The parity of the lookup value */
+uint8 sz53p_table[0x100]; /* OR the above two tables together */
+
+/* This is what everything acts on! */
+processor z80;
+uint64 z80_tstates;
+uint64 last_z80_tstates;
+
+static void z80_init_tables(void);
+
+/* Set up the z80 emulation */
+void z80_init(void)
+{
+ z80_init_tables();
+}
+
+/* Initalise the tables used to set flags */
+static void z80_init_tables(void)
+{
+ int i, j, k;
+ uint8 parity;
+
+ for (i = 0; i < 0x100; i++)
+ {
+ sz53_table[i] = i & (FLAG_3 | FLAG_5 | FLAG_S);
+ j = i;
+ parity = 0;
+ for (k = 0; k < 8; k++)
+ {
+ parity ^= j & 1;
+ j >>= 1;
+ }
+ parity_table[i] = (parity ? 0 : FLAG_P);
+ sz53p_table[i] = sz53_table[i] | parity_table[i];
+ }
+
+ sz53_table[0] |= FLAG_Z;
+ sz53p_table[0] |= FLAG_Z;
+}
+
+/* Reset the z80 */
+void z80_reset(void)
+{
+ AF = BC = DE = HL = 0;
+ AF_ = BC_ = DE_ = HL_ = 0;
+ IX = IY = 0;
+ I = R = R7 = 0;
+ SP = PC = 0;
+ IFF1 = IFF2 = IM = 0;
+ z80.halted = 0;
+
+ z80.interrupts_enabled_at = 0;
+ z80_tstates = last_z80_tstates = 0;
+}
+
+/* Process a z80 maskable interrupt */
+int z80_interrupt(void)
+{
+
+ if (IFF1)
+ {
+
+ /* If interrupts have just been enabled, don't accept the interrupt now,
+ but check after the next instruction has been executed */
+ if (z80_tstates == z80.interrupts_enabled_at)
+ {
+ return 0;
+ }
+
+ if (z80.halted)
+ {
+ PC++;
+ z80.halted = 0;
+ }
+
+ IFF1 = IFF2 = 0;
+
+ Z80_WB_MACRO(--SP, PCH);
+ Z80_WB_MACRO(--SP, PCL);
+
+ R++;
+
+ switch (IM)
+ {
+ case 0:
+ PC = 0x0038;
+ z80_tstates += 7;
+ break;
+ case 1:
+ PC = 0x0038;
+ z80_tstates += 7;
+ break;
+ case 2:
+ {
+ uint16 inttemp = (0x100 * I) + 0xff;
+ PCL = Z80_RB_MACRO(inttemp++);
+ PCH = Z80_RB_MACRO(inttemp);
+ z80_tstates += 7;
+ break;
+ }
+ //default:
+ // ui_error( UI_ERROR_ERROR, "Unknown interrupt mode %d", IM );
+ // fuse_abort();
+ }
+
+ return 1; /* Accepted an interrupt */
+ }
+ else
+ {
+ return 0; /* Did not accept an interrupt */
+ }
+}
+
+/* Process a z80 non-maskable interrupt */
+void z80_nmi(void)
+{
+ if (z80.halted)
+ {
+ PC++;
+ z80.halted = 0;
+ }
+
+ IFF1 = 0;
+
+ Z80_WB_MACRO(--SP, PCH);
+ Z80_WB_MACRO(--SP, PCL);
+
+ /* FIXME: how is R affected? */
+
+ /* FIXME: how does contention apply here? */
+ z80_tstates += 11;
+ PC = 0x0066;
+}
diff --git a/waterbox/ngp/z80-fuse/z80.h b/waterbox/ngp/z80-fuse/z80.h
new file mode 100644
index 0000000000..a87b3c947a
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80.h
@@ -0,0 +1,126 @@
+/* z80.h: z80 emulation core
+ Copyright (c) 1999-2003 Philip Kendall
+
+ $Id: z80.h 4640 2012-01-21 13:26:35Z pak21 $
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+#ifndef FUSE_Z80_H
+#define FUSE_Z80_H
+
+#include "defs.h"
+
+/* Union allowing a register pair to be accessed as bytes or as a word */
+typedef union {
+#ifdef MSB_FIRST
+ struct
+ {
+ uint8 h, l;
+ } b;
+#else
+ struct
+ {
+ uint8 l, h;
+ } b;
+#endif
+ uint16 w;
+} regpair;
+
+/* What's stored in the main processor */
+typedef struct
+{
+ regpair af, bc, de, hl;
+ regpair af_, bc_, de_, hl_;
+ regpair ix, iy;
+ uint8 i;
+ uint16 r; /* The low seven bits of the R register. 16 bits long
+ so it can also act as an RZX instruction counter */
+ uint8 r7; /* The high bit of the R register */
+ regpair sp, pc;
+ uint8 iff1, iff2, im;
+ int halted;
+
+ /* Interrupts were enabled at this time; do not accept any interrupts
+ until z80_tstates > this value */
+ uint64 interrupts_enabled_at;
+
+} processor;
+
+void z80_init(void);
+void z80_reset(void);
+
+int z80_interrupt(void);
+void z80_nmi(void);
+
+int z80_do_opcode(void);
+
+void z80_enable_interrupts(void);
+
+extern processor z80;
+inline uint16 z80_getpc(void) { return z80.pc.w; }
+extern const uint8 halfcarry_add_table[];
+extern const uint8 halfcarry_sub_table[];
+extern const uint8 overflow_add_table[];
+extern const uint8 overflow_sub_table[];
+extern uint8 sz53_table[];
+extern uint8 sz53p_table[];
+extern uint8 parity_table[];
+
+extern uint64 z80_tstates, last_z80_tstates;
+
+extern void (*z80_writebyte)(uint16, uint8);
+extern uint8 (*z80_readbyte)(uint16);
+extern void (*z80_writeport)(uint16, uint8);
+extern uint8 (*z80_readport)(uint16);
+
+// Ok, I lied, not a macro!
+
+//Write mem
+static INLINE void Z80_WB_MACRO(uint16 A, uint8 V)
+{
+ z80_tstates += 3;
+ z80_writebyte(A, V);
+}
+
+// Write port
+static INLINE void Z80_WP_MACRO(uint16 A, uint8 V)
+{
+ z80_tstates += 4;
+ z80_writeport(A, V);
+}
+
+// Read mem
+static INLINE uint8 Z80_RB_MACRO(uint16 A)
+{
+ z80_tstates += 3;
+ return (z80_readbyte(A));
+}
+
+// Read port
+static INLINE uint8 Z80_RP_MACRO(uint16 A)
+{
+ z80_tstates += 4;
+ return (z80_readport(A));
+}
+
+void z80_set_interrupt(int set);
+
+#endif /* #ifndef FUSE_Z80_H */
diff --git a/waterbox/ngp/z80-fuse/z80_cb.c b/waterbox/ngp/z80-fuse/z80_cb.c
new file mode 100644
index 0000000000..aba27af952
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_cb.c
@@ -0,0 +1,930 @@
+/* z80_cb.c: Z80 CBxx opcodes
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+/* NB: this file is autogenerated by 'z80.pl' from 'opcodes_cb.dat',
+ and included in 'z80_ops.c' */
+
+ case 0x00: /* RLC B */
+ RLC(B);
+ break;
+ case 0x01: /* RLC C */
+ RLC(C);
+ break;
+ case 0x02: /* RLC D */
+ RLC(D);
+ break;
+ case 0x03: /* RLC E */
+ RLC(E);
+ break;
+ case 0x04: /* RLC H */
+ RLC(H);
+ break;
+ case 0x05: /* RLC L */
+ RLC(L);
+ break;
+ case 0x06: /* RLC (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ RLC(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x07: /* RLC A */
+ RLC(A);
+ break;
+ case 0x08: /* RRC B */
+ RRC(B);
+ break;
+ case 0x09: /* RRC C */
+ RRC(C);
+ break;
+ case 0x0a: /* RRC D */
+ RRC(D);
+ break;
+ case 0x0b: /* RRC E */
+ RRC(E);
+ break;
+ case 0x0c: /* RRC H */
+ RRC(H);
+ break;
+ case 0x0d: /* RRC L */
+ RRC(L);
+ break;
+ case 0x0e: /* RRC (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ RRC(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x0f: /* RRC A */
+ RRC(A);
+ break;
+ case 0x10: /* RL B */
+ RL(B);
+ break;
+ case 0x11: /* RL C */
+ RL(C);
+ break;
+ case 0x12: /* RL D */
+ RL(D);
+ break;
+ case 0x13: /* RL E */
+ RL(E);
+ break;
+ case 0x14: /* RL H */
+ RL(H);
+ break;
+ case 0x15: /* RL L */
+ RL(L);
+ break;
+ case 0x16: /* RL (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ RL(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x17: /* RL A */
+ RL(A);
+ break;
+ case 0x18: /* RR B */
+ RR(B);
+ break;
+ case 0x19: /* RR C */
+ RR(C);
+ break;
+ case 0x1a: /* RR D */
+ RR(D);
+ break;
+ case 0x1b: /* RR E */
+ RR(E);
+ break;
+ case 0x1c: /* RR H */
+ RR(H);
+ break;
+ case 0x1d: /* RR L */
+ RR(L);
+ break;
+ case 0x1e: /* RR (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ RR(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x1f: /* RR A */
+ RR(A);
+ break;
+ case 0x20: /* SLA B */
+ SLA(B);
+ break;
+ case 0x21: /* SLA C */
+ SLA(C);
+ break;
+ case 0x22: /* SLA D */
+ SLA(D);
+ break;
+ case 0x23: /* SLA E */
+ SLA(E);
+ break;
+ case 0x24: /* SLA H */
+ SLA(H);
+ break;
+ case 0x25: /* SLA L */
+ SLA(L);
+ break;
+ case 0x26: /* SLA (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ SLA(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x27: /* SLA A */
+ SLA(A);
+ break;
+ case 0x28: /* SRA B */
+ SRA(B);
+ break;
+ case 0x29: /* SRA C */
+ SRA(C);
+ break;
+ case 0x2a: /* SRA D */
+ SRA(D);
+ break;
+ case 0x2b: /* SRA E */
+ SRA(E);
+ break;
+ case 0x2c: /* SRA H */
+ SRA(H);
+ break;
+ case 0x2d: /* SRA L */
+ SRA(L);
+ break;
+ case 0x2e: /* SRA (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ SRA(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x2f: /* SRA A */
+ SRA(A);
+ break;
+ case 0x30: /* SLL B */
+ SLL(B);
+ break;
+ case 0x31: /* SLL C */
+ SLL(C);
+ break;
+ case 0x32: /* SLL D */
+ SLL(D);
+ break;
+ case 0x33: /* SLL E */
+ SLL(E);
+ break;
+ case 0x34: /* SLL H */
+ SLL(H);
+ break;
+ case 0x35: /* SLL L */
+ SLL(L);
+ break;
+ case 0x36: /* SLL (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ SLL(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x37: /* SLL A */
+ SLL(A);
+ break;
+ case 0x38: /* SRL B */
+ SRL(B);
+ break;
+ case 0x39: /* SRL C */
+ SRL(C);
+ break;
+ case 0x3a: /* SRL D */
+ SRL(D);
+ break;
+ case 0x3b: /* SRL E */
+ SRL(E);
+ break;
+ case 0x3c: /* SRL H */
+ SRL(H);
+ break;
+ case 0x3d: /* SRL L */
+ SRL(L);
+ break;
+ case 0x3e: /* SRL (HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(HL);
+ contend_read_no_mreq( HL, 1 );
+ SRL(bytetemp);
+ Z80_WB_MACRO(HL,bytetemp);
+ }
+ break;
+ case 0x3f: /* SRL A */
+ SRL(A);
+ break;
+ case 0x40: /* BIT 0,B */
+ BIT( 0, B );
+ break;
+ case 0x41: /* BIT 0,C */
+ BIT( 0, C );
+ break;
+ case 0x42: /* BIT 0,D */
+ BIT( 0, D );
+ break;
+ case 0x43: /* BIT 0,E */
+ BIT( 0, E );
+ break;
+ case 0x44: /* BIT 0,H */
+ BIT( 0, H );
+ break;
+ case 0x45: /* BIT 0,L */
+ BIT( 0, L );
+ break;
+ case 0x46: /* BIT 0,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 0, bytetemp );
+ }
+ break;
+ case 0x47: /* BIT 0,A */
+ BIT( 0, A );
+ break;
+ case 0x48: /* BIT 1,B */
+ BIT( 1, B );
+ break;
+ case 0x49: /* BIT 1,C */
+ BIT( 1, C );
+ break;
+ case 0x4a: /* BIT 1,D */
+ BIT( 1, D );
+ break;
+ case 0x4b: /* BIT 1,E */
+ BIT( 1, E );
+ break;
+ case 0x4c: /* BIT 1,H */
+ BIT( 1, H );
+ break;
+ case 0x4d: /* BIT 1,L */
+ BIT( 1, L );
+ break;
+ case 0x4e: /* BIT 1,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 1, bytetemp );
+ }
+ break;
+ case 0x4f: /* BIT 1,A */
+ BIT( 1, A );
+ break;
+ case 0x50: /* BIT 2,B */
+ BIT( 2, B );
+ break;
+ case 0x51: /* BIT 2,C */
+ BIT( 2, C );
+ break;
+ case 0x52: /* BIT 2,D */
+ BIT( 2, D );
+ break;
+ case 0x53: /* BIT 2,E */
+ BIT( 2, E );
+ break;
+ case 0x54: /* BIT 2,H */
+ BIT( 2, H );
+ break;
+ case 0x55: /* BIT 2,L */
+ BIT( 2, L );
+ break;
+ case 0x56: /* BIT 2,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 2, bytetemp );
+ }
+ break;
+ case 0x57: /* BIT 2,A */
+ BIT( 2, A );
+ break;
+ case 0x58: /* BIT 3,B */
+ BIT( 3, B );
+ break;
+ case 0x59: /* BIT 3,C */
+ BIT( 3, C );
+ break;
+ case 0x5a: /* BIT 3,D */
+ BIT( 3, D );
+ break;
+ case 0x5b: /* BIT 3,E */
+ BIT( 3, E );
+ break;
+ case 0x5c: /* BIT 3,H */
+ BIT( 3, H );
+ break;
+ case 0x5d: /* BIT 3,L */
+ BIT( 3, L );
+ break;
+ case 0x5e: /* BIT 3,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 3, bytetemp );
+ }
+ break;
+ case 0x5f: /* BIT 3,A */
+ BIT( 3, A );
+ break;
+ case 0x60: /* BIT 4,B */
+ BIT( 4, B );
+ break;
+ case 0x61: /* BIT 4,C */
+ BIT( 4, C );
+ break;
+ case 0x62: /* BIT 4,D */
+ BIT( 4, D );
+ break;
+ case 0x63: /* BIT 4,E */
+ BIT( 4, E );
+ break;
+ case 0x64: /* BIT 4,H */
+ BIT( 4, H );
+ break;
+ case 0x65: /* BIT 4,L */
+ BIT( 4, L );
+ break;
+ case 0x66: /* BIT 4,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 4, bytetemp );
+ }
+ break;
+ case 0x67: /* BIT 4,A */
+ BIT( 4, A );
+ break;
+ case 0x68: /* BIT 5,B */
+ BIT( 5, B );
+ break;
+ case 0x69: /* BIT 5,C */
+ BIT( 5, C );
+ break;
+ case 0x6a: /* BIT 5,D */
+ BIT( 5, D );
+ break;
+ case 0x6b: /* BIT 5,E */
+ BIT( 5, E );
+ break;
+ case 0x6c: /* BIT 5,H */
+ BIT( 5, H );
+ break;
+ case 0x6d: /* BIT 5,L */
+ BIT( 5, L );
+ break;
+ case 0x6e: /* BIT 5,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 5, bytetemp );
+ }
+ break;
+ case 0x6f: /* BIT 5,A */
+ BIT( 5, A );
+ break;
+ case 0x70: /* BIT 6,B */
+ BIT( 6, B );
+ break;
+ case 0x71: /* BIT 6,C */
+ BIT( 6, C );
+ break;
+ case 0x72: /* BIT 6,D */
+ BIT( 6, D );
+ break;
+ case 0x73: /* BIT 6,E */
+ BIT( 6, E );
+ break;
+ case 0x74: /* BIT 6,H */
+ BIT( 6, H );
+ break;
+ case 0x75: /* BIT 6,L */
+ BIT( 6, L );
+ break;
+ case 0x76: /* BIT 6,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 6, bytetemp );
+ }
+ break;
+ case 0x77: /* BIT 6,A */
+ BIT( 6, A );
+ break;
+ case 0x78: /* BIT 7,B */
+ BIT( 7, B );
+ break;
+ case 0x79: /* BIT 7,C */
+ BIT( 7, C );
+ break;
+ case 0x7a: /* BIT 7,D */
+ BIT( 7, D );
+ break;
+ case 0x7b: /* BIT 7,E */
+ BIT( 7, E );
+ break;
+ case 0x7c: /* BIT 7,H */
+ BIT( 7, H );
+ break;
+ case 0x7d: /* BIT 7,L */
+ BIT( 7, L );
+ break;
+ case 0x7e: /* BIT 7,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ BIT( 7, bytetemp );
+ }
+ break;
+ case 0x7f: /* BIT 7,A */
+ BIT( 7, A );
+ break;
+ case 0x80: /* RES 0,B */
+ B &= 0xfe;
+ break;
+ case 0x81: /* RES 0,C */
+ C &= 0xfe;
+ break;
+ case 0x82: /* RES 0,D */
+ D &= 0xfe;
+ break;
+ case 0x83: /* RES 0,E */
+ E &= 0xfe;
+ break;
+ case 0x84: /* RES 0,H */
+ H &= 0xfe;
+ break;
+ case 0x85: /* RES 0,L */
+ L &= 0xfe;
+ break;
+ case 0x86: /* RES 0,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xfe );
+ }
+ break;
+ case 0x87: /* RES 0,A */
+ A &= 0xfe;
+ break;
+ case 0x88: /* RES 1,B */
+ B &= 0xfd;
+ break;
+ case 0x89: /* RES 1,C */
+ C &= 0xfd;
+ break;
+ case 0x8a: /* RES 1,D */
+ D &= 0xfd;
+ break;
+ case 0x8b: /* RES 1,E */
+ E &= 0xfd;
+ break;
+ case 0x8c: /* RES 1,H */
+ H &= 0xfd;
+ break;
+ case 0x8d: /* RES 1,L */
+ L &= 0xfd;
+ break;
+ case 0x8e: /* RES 1,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xfd );
+ }
+ break;
+ case 0x8f: /* RES 1,A */
+ A &= 0xfd;
+ break;
+ case 0x90: /* RES 2,B */
+ B &= 0xfb;
+ break;
+ case 0x91: /* RES 2,C */
+ C &= 0xfb;
+ break;
+ case 0x92: /* RES 2,D */
+ D &= 0xfb;
+ break;
+ case 0x93: /* RES 2,E */
+ E &= 0xfb;
+ break;
+ case 0x94: /* RES 2,H */
+ H &= 0xfb;
+ break;
+ case 0x95: /* RES 2,L */
+ L &= 0xfb;
+ break;
+ case 0x96: /* RES 2,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xfb );
+ }
+ break;
+ case 0x97: /* RES 2,A */
+ A &= 0xfb;
+ break;
+ case 0x98: /* RES 3,B */
+ B &= 0xf7;
+ break;
+ case 0x99: /* RES 3,C */
+ C &= 0xf7;
+ break;
+ case 0x9a: /* RES 3,D */
+ D &= 0xf7;
+ break;
+ case 0x9b: /* RES 3,E */
+ E &= 0xf7;
+ break;
+ case 0x9c: /* RES 3,H */
+ H &= 0xf7;
+ break;
+ case 0x9d: /* RES 3,L */
+ L &= 0xf7;
+ break;
+ case 0x9e: /* RES 3,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xf7 );
+ }
+ break;
+ case 0x9f: /* RES 3,A */
+ A &= 0xf7;
+ break;
+ case 0xa0: /* RES 4,B */
+ B &= 0xef;
+ break;
+ case 0xa1: /* RES 4,C */
+ C &= 0xef;
+ break;
+ case 0xa2: /* RES 4,D */
+ D &= 0xef;
+ break;
+ case 0xa3: /* RES 4,E */
+ E &= 0xef;
+ break;
+ case 0xa4: /* RES 4,H */
+ H &= 0xef;
+ break;
+ case 0xa5: /* RES 4,L */
+ L &= 0xef;
+ break;
+ case 0xa6: /* RES 4,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xef );
+ }
+ break;
+ case 0xa7: /* RES 4,A */
+ A &= 0xef;
+ break;
+ case 0xa8: /* RES 5,B */
+ B &= 0xdf;
+ break;
+ case 0xa9: /* RES 5,C */
+ C &= 0xdf;
+ break;
+ case 0xaa: /* RES 5,D */
+ D &= 0xdf;
+ break;
+ case 0xab: /* RES 5,E */
+ E &= 0xdf;
+ break;
+ case 0xac: /* RES 5,H */
+ H &= 0xdf;
+ break;
+ case 0xad: /* RES 5,L */
+ L &= 0xdf;
+ break;
+ case 0xae: /* RES 5,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xdf );
+ }
+ break;
+ case 0xaf: /* RES 5,A */
+ A &= 0xdf;
+ break;
+ case 0xb0: /* RES 6,B */
+ B &= 0xbf;
+ break;
+ case 0xb1: /* RES 6,C */
+ C &= 0xbf;
+ break;
+ case 0xb2: /* RES 6,D */
+ D &= 0xbf;
+ break;
+ case 0xb3: /* RES 6,E */
+ E &= 0xbf;
+ break;
+ case 0xb4: /* RES 6,H */
+ H &= 0xbf;
+ break;
+ case 0xb5: /* RES 6,L */
+ L &= 0xbf;
+ break;
+ case 0xb6: /* RES 6,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0xbf );
+ }
+ break;
+ case 0xb7: /* RES 6,A */
+ A &= 0xbf;
+ break;
+ case 0xb8: /* RES 7,B */
+ B &= 0x7f;
+ break;
+ case 0xb9: /* RES 7,C */
+ C &= 0x7f;
+ break;
+ case 0xba: /* RES 7,D */
+ D &= 0x7f;
+ break;
+ case 0xbb: /* RES 7,E */
+ E &= 0x7f;
+ break;
+ case 0xbc: /* RES 7,H */
+ H &= 0x7f;
+ break;
+ case 0xbd: /* RES 7,L */
+ L &= 0x7f;
+ break;
+ case 0xbe: /* RES 7,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp & 0x7f );
+ }
+ break;
+ case 0xbf: /* RES 7,A */
+ A &= 0x7f;
+ break;
+ case 0xc0: /* SET 0,B */
+ B |= 0x01;
+ break;
+ case 0xc1: /* SET 0,C */
+ C |= 0x01;
+ break;
+ case 0xc2: /* SET 0,D */
+ D |= 0x01;
+ break;
+ case 0xc3: /* SET 0,E */
+ E |= 0x01;
+ break;
+ case 0xc4: /* SET 0,H */
+ H |= 0x01;
+ break;
+ case 0xc5: /* SET 0,L */
+ L |= 0x01;
+ break;
+ case 0xc6: /* SET 0,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x01 );
+ }
+ break;
+ case 0xc7: /* SET 0,A */
+ A |= 0x01;
+ break;
+ case 0xc8: /* SET 1,B */
+ B |= 0x02;
+ break;
+ case 0xc9: /* SET 1,C */
+ C |= 0x02;
+ break;
+ case 0xca: /* SET 1,D */
+ D |= 0x02;
+ break;
+ case 0xcb: /* SET 1,E */
+ E |= 0x02;
+ break;
+ case 0xcc: /* SET 1,H */
+ H |= 0x02;
+ break;
+ case 0xcd: /* SET 1,L */
+ L |= 0x02;
+ break;
+ case 0xce: /* SET 1,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x02 );
+ }
+ break;
+ case 0xcf: /* SET 1,A */
+ A |= 0x02;
+ break;
+ case 0xd0: /* SET 2,B */
+ B |= 0x04;
+ break;
+ case 0xd1: /* SET 2,C */
+ C |= 0x04;
+ break;
+ case 0xd2: /* SET 2,D */
+ D |= 0x04;
+ break;
+ case 0xd3: /* SET 2,E */
+ E |= 0x04;
+ break;
+ case 0xd4: /* SET 2,H */
+ H |= 0x04;
+ break;
+ case 0xd5: /* SET 2,L */
+ L |= 0x04;
+ break;
+ case 0xd6: /* SET 2,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x04 );
+ }
+ break;
+ case 0xd7: /* SET 2,A */
+ A |= 0x04;
+ break;
+ case 0xd8: /* SET 3,B */
+ B |= 0x08;
+ break;
+ case 0xd9: /* SET 3,C */
+ C |= 0x08;
+ break;
+ case 0xda: /* SET 3,D */
+ D |= 0x08;
+ break;
+ case 0xdb: /* SET 3,E */
+ E |= 0x08;
+ break;
+ case 0xdc: /* SET 3,H */
+ H |= 0x08;
+ break;
+ case 0xdd: /* SET 3,L */
+ L |= 0x08;
+ break;
+ case 0xde: /* SET 3,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x08 );
+ }
+ break;
+ case 0xdf: /* SET 3,A */
+ A |= 0x08;
+ break;
+ case 0xe0: /* SET 4,B */
+ B |= 0x10;
+ break;
+ case 0xe1: /* SET 4,C */
+ C |= 0x10;
+ break;
+ case 0xe2: /* SET 4,D */
+ D |= 0x10;
+ break;
+ case 0xe3: /* SET 4,E */
+ E |= 0x10;
+ break;
+ case 0xe4: /* SET 4,H */
+ H |= 0x10;
+ break;
+ case 0xe5: /* SET 4,L */
+ L |= 0x10;
+ break;
+ case 0xe6: /* SET 4,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x10 );
+ }
+ break;
+ case 0xe7: /* SET 4,A */
+ A |= 0x10;
+ break;
+ case 0xe8: /* SET 5,B */
+ B |= 0x20;
+ break;
+ case 0xe9: /* SET 5,C */
+ C |= 0x20;
+ break;
+ case 0xea: /* SET 5,D */
+ D |= 0x20;
+ break;
+ case 0xeb: /* SET 5,E */
+ E |= 0x20;
+ break;
+ case 0xec: /* SET 5,H */
+ H |= 0x20;
+ break;
+ case 0xed: /* SET 5,L */
+ L |= 0x20;
+ break;
+ case 0xee: /* SET 5,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x20 );
+ }
+ break;
+ case 0xef: /* SET 5,A */
+ A |= 0x20;
+ break;
+ case 0xf0: /* SET 6,B */
+ B |= 0x40;
+ break;
+ case 0xf1: /* SET 6,C */
+ C |= 0x40;
+ break;
+ case 0xf2: /* SET 6,D */
+ D |= 0x40;
+ break;
+ case 0xf3: /* SET 6,E */
+ E |= 0x40;
+ break;
+ case 0xf4: /* SET 6,H */
+ H |= 0x40;
+ break;
+ case 0xf5: /* SET 6,L */
+ L |= 0x40;
+ break;
+ case 0xf6: /* SET 6,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x40 );
+ }
+ break;
+ case 0xf7: /* SET 6,A */
+ A |= 0x40;
+ break;
+ case 0xf8: /* SET 7,B */
+ B |= 0x80;
+ break;
+ case 0xf9: /* SET 7,C */
+ C |= 0x80;
+ break;
+ case 0xfa: /* SET 7,D */
+ D |= 0x80;
+ break;
+ case 0xfb: /* SET 7,E */
+ E |= 0x80;
+ break;
+ case 0xfc: /* SET 7,H */
+ H |= 0x80;
+ break;
+ case 0xfd: /* SET 7,L */
+ L |= 0x80;
+ break;
+ case 0xfe: /* SET 7,(HL) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO( HL, bytetemp | 0x80 );
+ }
+ break;
+ case 0xff: /* SET 7,A */
+ A |= 0x80;
+ break;
diff --git a/waterbox/ngp/z80-fuse/z80_ddfd.c b/waterbox/ngp/z80-fuse/z80_ddfd.c
new file mode 100644
index 0000000000..aff392f15d
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_ddfd.c
@@ -0,0 +1,534 @@
+/* z80_ddfd.c Z80 {DD,FD}xx opcodes
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+/* NB: this file is autogenerated by 'z80.pl' from 'opcodes_ddfd.dat',
+ and included in 'z80_ops.c' */
+
+ case 0x09: /* ADD REGISTER,BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(REGISTER,BC);
+ break;
+ case 0x19: /* ADD REGISTER,DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(REGISTER,DE);
+ break;
+ case 0x21: /* LD REGISTER,nnnn */
+ REGISTERL=Z80_RB_MACRO(PC++);
+ REGISTERH=Z80_RB_MACRO(PC++);
+ break;
+ case 0x22: /* LD (nnnn),REGISTER */
+ LD16_NNRR(REGISTERL,REGISTERH);
+ break;
+ case 0x23: /* INC REGISTER */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ REGISTER++;
+ break;
+ case 0x24: /* INC REGISTERH */
+ INC(REGISTERH);
+ break;
+ case 0x25: /* DEC REGISTERH */
+ DEC(REGISTERH);
+ break;
+ case 0x26: /* LD REGISTERH,nn */
+ REGISTERH = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x29: /* ADD REGISTER,REGISTER */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(REGISTER,REGISTER);
+ break;
+ case 0x2a: /* LD REGISTER,(nnnn) */
+ LD16_RRNN(REGISTERL,REGISTERH);
+ break;
+ case 0x2b: /* DEC REGISTER */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ REGISTER--;
+ break;
+ case 0x2c: /* INC REGISTERL */
+ INC(REGISTERL);
+ break;
+ case 0x2d: /* DEC REGISTERL */
+ DEC(REGISTERL);
+ break;
+ case 0x2e: /* LD REGISTERL,nn */
+ REGISTERL = Z80_RB_MACRO( PC++ );
+ break;
+ case 0x34: /* INC (REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ uint16 wordtemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ wordtemp = REGISTER + (int8)offset;
+ bytetemp = Z80_RB_MACRO( wordtemp );
+ contend_read_no_mreq( wordtemp, 1 );
+ INC(bytetemp);
+ Z80_WB_MACRO(wordtemp,bytetemp);
+ }
+ break;
+ case 0x35: /* DEC (REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ uint16 wordtemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ wordtemp = REGISTER + (int8)offset;
+ bytetemp = Z80_RB_MACRO( wordtemp );
+ contend_read_no_mreq( wordtemp, 1 );
+ DEC(bytetemp);
+ Z80_WB_MACRO(wordtemp,bytetemp);
+ }
+ break;
+ case 0x36: /* LD (REGISTER+dd),nn */
+ {
+ uint8 offset, value;
+ offset = Z80_RB_MACRO( PC++ );
+ value = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, value );
+ }
+ break;
+ case 0x39: /* ADD REGISTER,SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADD16(REGISTER,SP);
+ break;
+ case 0x44: /* LD B,REGISTERH */
+ B=REGISTERH;
+ break;
+ case 0x45: /* LD B,REGISTERL */
+ B=REGISTERL;
+ break;
+ case 0x46: /* LD B,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ B = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x4c: /* LD C,REGISTERH */
+ C=REGISTERH;
+ break;
+ case 0x4d: /* LD C,REGISTERL */
+ C=REGISTERL;
+ break;
+ case 0x4e: /* LD C,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ C = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x54: /* LD D,REGISTERH */
+ D=REGISTERH;
+ break;
+ case 0x55: /* LD D,REGISTERL */
+ D=REGISTERL;
+ break;
+ case 0x56: /* LD D,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ D = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x5c: /* LD E,REGISTERH */
+ E=REGISTERH;
+ break;
+ case 0x5d: /* LD E,REGISTERL */
+ E=REGISTERL;
+ break;
+ case 0x5e: /* LD E,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ E = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x60: /* LD REGISTERH,B */
+ REGISTERH=B;
+ break;
+ case 0x61: /* LD REGISTERH,C */
+ REGISTERH=C;
+ break;
+ case 0x62: /* LD REGISTERH,D */
+ REGISTERH=D;
+ break;
+ case 0x63: /* LD REGISTERH,E */
+ REGISTERH=E;
+ break;
+ case 0x64: /* LD REGISTERH,REGISTERH */
+ break;
+ case 0x65: /* LD REGISTERH,REGISTERL */
+ REGISTERH=REGISTERL;
+ break;
+ case 0x66: /* LD H,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ H = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x67: /* LD REGISTERH,A */
+ REGISTERH=A;
+ break;
+ case 0x68: /* LD REGISTERL,B */
+ REGISTERL=B;
+ break;
+ case 0x69: /* LD REGISTERL,C */
+ REGISTERL=C;
+ break;
+ case 0x6a: /* LD REGISTERL,D */
+ REGISTERL=D;
+ break;
+ case 0x6b: /* LD REGISTERL,E */
+ REGISTERL=E;
+ break;
+ case 0x6c: /* LD REGISTERL,REGISTERH */
+ REGISTERL=REGISTERH;
+ break;
+ case 0x6d: /* LD REGISTERL,REGISTERL */
+ break;
+ case 0x6e: /* LD L,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ L = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x6f: /* LD REGISTERL,A */
+ REGISTERL=A;
+ break;
+ case 0x70: /* LD (REGISTER+dd),B */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, B );
+ }
+ break;
+ case 0x71: /* LD (REGISTER+dd),C */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, C );
+ }
+ break;
+ case 0x72: /* LD (REGISTER+dd),D */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, D );
+ }
+ break;
+ case 0x73: /* LD (REGISTER+dd),E */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, E );
+ }
+ break;
+ case 0x74: /* LD (REGISTER+dd),H */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, H );
+ }
+ break;
+ case 0x75: /* LD (REGISTER+dd),L */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, L );
+ }
+ break;
+ case 0x77: /* LD (REGISTER+dd),A */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ Z80_WB_MACRO( REGISTER + (int8)offset, A );
+ }
+ break;
+ case 0x7c: /* LD A,REGISTERH */
+ A=REGISTERH;
+ break;
+ case 0x7d: /* LD A,REGISTERL */
+ A=REGISTERL;
+ break;
+ case 0x7e: /* LD A,(REGISTER+dd) */
+ {
+ uint8 offset;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ A = Z80_RB_MACRO( REGISTER + (int8)offset );
+ }
+ break;
+ case 0x84: /* ADD A,REGISTERH */
+ ADD(REGISTERH);
+ break;
+ case 0x85: /* ADD A,REGISTERL */
+ ADD(REGISTERL);
+ break;
+ case 0x86: /* ADD A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ ADD(bytetemp);
+ }
+ break;
+ case 0x8c: /* ADC A,REGISTERH */
+ ADC(REGISTERH);
+ break;
+ case 0x8d: /* ADC A,REGISTERL */
+ ADC(REGISTERL);
+ break;
+ case 0x8e: /* ADC A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ ADC(bytetemp);
+ }
+ break;
+ case 0x94: /* SUB A,REGISTERH */
+ SUB(REGISTERH);
+ break;
+ case 0x95: /* SUB A,REGISTERL */
+ SUB(REGISTERL);
+ break;
+ case 0x96: /* SUB A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ SUB(bytetemp);
+ }
+ break;
+ case 0x9c: /* SBC A,REGISTERH */
+ SBC(REGISTERH);
+ break;
+ case 0x9d: /* SBC A,REGISTERL */
+ SBC(REGISTERL);
+ break;
+ case 0x9e: /* SBC A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ SBC(bytetemp);
+ }
+ break;
+ case 0xa4: /* AND A,REGISTERH */
+ AND(REGISTERH);
+ break;
+ case 0xa5: /* AND A,REGISTERL */
+ AND(REGISTERL);
+ break;
+ case 0xa6: /* AND A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ AND(bytetemp);
+ }
+ break;
+ case 0xac: /* XOR A,REGISTERH */
+ XOR(REGISTERH);
+ break;
+ case 0xad: /* XOR A,REGISTERL */
+ XOR(REGISTERL);
+ break;
+ case 0xae: /* XOR A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ XOR(bytetemp);
+ }
+ break;
+ case 0xb4: /* OR A,REGISTERH */
+ OR(REGISTERH);
+ break;
+ case 0xb5: /* OR A,REGISTERL */
+ OR(REGISTERL);
+ break;
+ case 0xb6: /* OR A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ OR(bytetemp);
+ }
+ break;
+ case 0xbc: /* CP A,REGISTERH */
+ CP(REGISTERH);
+ break;
+ case 0xbd: /* CP A,REGISTERL */
+ CP(REGISTERL);
+ break;
+ case 0xbe: /* CP A,(REGISTER+dd) */
+ {
+ uint8 offset, bytetemp;
+ offset = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 );
+ contend_read_no_mreq( PC, 1 ); PC++;
+ bytetemp = Z80_RB_MACRO( REGISTER + (int8)offset );
+ CP(bytetemp);
+ }
+ break;
+ case 0xcb: /* shift DDFDCB */
+ {
+ uint16 tempaddr; uint8 opcode3;
+ tempaddr = REGISTER + (int8)Z80_RB_MACRO( PC );
+ PC++;
+ opcode3 = Z80_RB_MACRO( PC );
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); PC++;
+ switch(opcode3) {
+#include "z80_ddfdcb.c"
+ }
+ }
+ break;
+ case 0xe1: /* POP REGISTER */
+ POP16(REGISTERL,REGISTERH);
+ break;
+ case 0xe3: /* EX (SP),REGISTER */
+ {
+ uint8 bytetempl, bytetemph;
+ bytetempl = Z80_RB_MACRO( SP );
+ bytetemph = Z80_RB_MACRO( SP + 1 ); contend_read_no_mreq( SP + 1, 1 );
+ Z80_WB_MACRO( SP + 1, REGISTERH );
+ Z80_WB_MACRO( SP, REGISTERL );
+ contend_write_no_mreq( SP, 1 ); contend_write_no_mreq( SP, 1 );
+ REGISTERL=bytetempl; REGISTERH=bytetemph;
+ }
+ break;
+ case 0xe5: /* PUSH REGISTER */
+ contend_read_no_mreq( IR, 1 );
+ PUSH16(REGISTERL,REGISTERH);
+ break;
+ case 0xe9: /* JP REGISTER */
+ PC=REGISTER; /* NB: NOT INDIRECT! */
+ break;
+ case 0xf9: /* LD SP,REGISTER */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SP = REGISTER;
+ break;
+ default: /* Instruction did not involve H or L, so backtrack
+ one instruction and parse again */
+ PC--;
+ R--;
+ opcode = opcode2;
+ break; // FIXME!
+ //goto end_opcode;
diff --git a/waterbox/ngp/z80-fuse/z80_ddfdcb.c b/waterbox/ngp/z80-fuse/z80_ddfdcb.c
new file mode 100644
index 0000000000..9e59d53229
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_ddfdcb.c
@@ -0,0 +1,1226 @@
+/* z80_ddfdcb.c Z80 {DD,FD}CBxx opcodes
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+/* NB: this file is autogenerated by 'z80.pl' from 'opcodes_ddfdcb.dat',
+ and included in 'z80_ops.c' */
+
+ case 0x00: /* LD B,RLC (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x01: /* LD C,RLC (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x02: /* LD D,RLC (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x03: /* LD E,RLC (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x04: /* LD H,RLC (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x05: /* LD L,RLC (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x06: /* RLC (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x07: /* LD A,RLC (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RLC(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x08: /* LD B,RRC (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x09: /* LD C,RRC (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x0a: /* LD D,RRC (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x0b: /* LD E,RRC (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x0c: /* LD H,RRC (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x0d: /* LD L,RRC (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x0e: /* RRC (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x0f: /* LD A,RRC (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RRC(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x10: /* LD B,RL (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x11: /* LD C,RL (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x12: /* LD D,RL (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x13: /* LD E,RL (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x14: /* LD H,RL (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x15: /* LD L,RL (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x16: /* RL (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x17: /* LD A,RL (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RL(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x18: /* LD B,RR (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x19: /* LD C,RR (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x1a: /* LD D,RR (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x1b: /* LD E,RR (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x1c: /* LD H,RR (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x1d: /* LD L,RR (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x1e: /* RR (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x1f: /* LD A,RR (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ RR(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x20: /* LD B,SLA (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x21: /* LD C,SLA (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x22: /* LD D,SLA (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x23: /* LD E,SLA (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x24: /* LD H,SLA (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x25: /* LD L,SLA (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x26: /* SLA (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x27: /* LD A,SLA (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLA(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x28: /* LD B,SRA (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x29: /* LD C,SRA (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x2a: /* LD D,SRA (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x2b: /* LD E,SRA (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x2c: /* LD H,SRA (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x2d: /* LD L,SRA (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x2e: /* SRA (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x2f: /* LD A,SRA (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRA(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x30: /* LD B,SLL (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x31: /* LD C,SLL (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x32: /* LD D,SLL (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x33: /* LD E,SLL (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x34: /* LD H,SLL (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x35: /* LD L,SLL (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x36: /* SLL (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x37: /* LD A,SLL (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SLL(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x38: /* LD B,SRL (REGISTER+dd) */
+ B=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(B);
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x39: /* LD C,SRL (REGISTER+dd) */
+ C=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(C);
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x3a: /* LD D,SRL (REGISTER+dd) */
+ D=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(D);
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x3b: /* LD E,SRL (REGISTER+dd) */
+ E=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(E);
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x3c: /* LD H,SRL (REGISTER+dd) */
+ H=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(H);
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x3d: /* LD L,SRL (REGISTER+dd) */
+ L=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(L);
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x3e: /* SRL (REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(bytetemp);
+ Z80_WB_MACRO(tempaddr,bytetemp);
+ }
+ break;
+ case 0x3f: /* LD A,SRL (REGISTER+dd) */
+ A=Z80_RB_MACRO(tempaddr);
+ contend_read_no_mreq( tempaddr, 1 );
+ SRL(A);
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47: /* BIT 0,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 0, bytetemp, tempaddr );
+ }
+ break;
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f: /* BIT 1,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 1, bytetemp, tempaddr );
+ }
+ break;
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57: /* BIT 2,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 2, bytetemp, tempaddr );
+ }
+ break;
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f: /* BIT 3,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 3, bytetemp, tempaddr );
+ }
+ break;
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67: /* BIT 4,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 4, bytetemp, tempaddr );
+ }
+ break;
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f: /* BIT 5,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 5, bytetemp, tempaddr );
+ }
+ break;
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77: /* BIT 6,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 6, bytetemp, tempaddr );
+ }
+ break;
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f: /* BIT 7,(REGISTER+dd) */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ BIT_I( 7, bytetemp, tempaddr );
+ }
+ break;
+ case 0x80: /* LD B,RES 0,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x81: /* LD C,RES 0,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x82: /* LD D,RES 0,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x83: /* LD E,RES 0,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x84: /* LD H,RES 0,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x85: /* LD L,RES 0,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x86: /* RES 0,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xfe );
+ }
+ break;
+ case 0x87: /* LD A,RES 0,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xfe;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x88: /* LD B,RES 1,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x89: /* LD C,RES 1,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x8a: /* LD D,RES 1,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x8b: /* LD E,RES 1,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x8c: /* LD H,RES 1,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x8d: /* LD L,RES 1,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x8e: /* RES 1,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xfd );
+ }
+ break;
+ case 0x8f: /* LD A,RES 1,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xfd;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x90: /* LD B,RES 2,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x91: /* LD C,RES 2,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x92: /* LD D,RES 2,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x93: /* LD E,RES 2,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x94: /* LD H,RES 2,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x95: /* LD L,RES 2,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x96: /* RES 2,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xfb );
+ }
+ break;
+ case 0x97: /* LD A,RES 2,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xfb;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0x98: /* LD B,RES 3,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0x99: /* LD C,RES 3,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0x9a: /* LD D,RES 3,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0x9b: /* LD E,RES 3,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0x9c: /* LD H,RES 3,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0x9d: /* LD L,RES 3,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0x9e: /* RES 3,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xf7 );
+ }
+ break;
+ case 0x9f: /* LD A,RES 3,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xf7;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xa0: /* LD B,RES 4,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xa1: /* LD C,RES 4,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xa2: /* LD D,RES 4,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xa3: /* LD E,RES 4,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xa4: /* LD H,RES 4,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xa5: /* LD L,RES 4,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xa6: /* RES 4,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xef );
+ }
+ break;
+ case 0xa7: /* LD A,RES 4,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xef;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xa8: /* LD B,RES 5,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xa9: /* LD C,RES 5,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xaa: /* LD D,RES 5,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xab: /* LD E,RES 5,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xac: /* LD H,RES 5,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xad: /* LD L,RES 5,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xae: /* RES 5,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xdf );
+ }
+ break;
+ case 0xaf: /* LD A,RES 5,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xdf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xb0: /* LD B,RES 6,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xb1: /* LD C,RES 6,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xb2: /* LD D,RES 6,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xb3: /* LD E,RES 6,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xb4: /* LD H,RES 6,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xb5: /* LD L,RES 6,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xb6: /* RES 6,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0xbf );
+ }
+ break;
+ case 0xb7: /* LD A,RES 6,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0xbf;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xb8: /* LD B,RES 7,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xb9: /* LD C,RES 7,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xba: /* LD D,RES 7,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xbb: /* LD E,RES 7,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xbc: /* LD H,RES 7,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xbd: /* LD L,RES 7,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xbe: /* RES 7,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp & 0x7f );
+ }
+ break;
+ case 0xbf: /* LD A,RES 7,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) & 0x7f;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xc0: /* LD B,SET 0,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xc1: /* LD C,SET 0,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xc2: /* LD D,SET 0,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xc3: /* LD E,SET 0,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xc4: /* LD H,SET 0,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xc5: /* LD L,SET 0,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xc6: /* SET 0,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x01 );
+ }
+ break;
+ case 0xc7: /* LD A,SET 0,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x01;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xc8: /* LD B,SET 1,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xc9: /* LD C,SET 1,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xca: /* LD D,SET 1,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xcb: /* LD E,SET 1,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xcc: /* LD H,SET 1,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xcd: /* LD L,SET 1,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xce: /* SET 1,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x02 );
+ }
+ break;
+ case 0xcf: /* LD A,SET 1,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x02;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xd0: /* LD B,SET 2,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xd1: /* LD C,SET 2,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xd2: /* LD D,SET 2,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xd3: /* LD E,SET 2,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xd4: /* LD H,SET 2,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xd5: /* LD L,SET 2,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xd6: /* SET 2,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x04 );
+ }
+ break;
+ case 0xd7: /* LD A,SET 2,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x04;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xd8: /* LD B,SET 3,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xd9: /* LD C,SET 3,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xda: /* LD D,SET 3,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xdb: /* LD E,SET 3,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xdc: /* LD H,SET 3,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xdd: /* LD L,SET 3,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xde: /* SET 3,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x08 );
+ }
+ break;
+ case 0xdf: /* LD A,SET 3,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x08;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xe0: /* LD B,SET 4,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xe1: /* LD C,SET 4,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xe2: /* LD D,SET 4,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xe3: /* LD E,SET 4,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xe4: /* LD H,SET 4,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xe5: /* LD L,SET 4,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xe6: /* SET 4,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x10 );
+ }
+ break;
+ case 0xe7: /* LD A,SET 4,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x10;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xe8: /* LD B,SET 5,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xe9: /* LD C,SET 5,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xea: /* LD D,SET 5,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xeb: /* LD E,SET 5,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xec: /* LD H,SET 5,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xed: /* LD L,SET 5,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xee: /* SET 5,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x20 );
+ }
+ break;
+ case 0xef: /* LD A,SET 5,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x20;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xf0: /* LD B,SET 6,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xf1: /* LD C,SET 6,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xf2: /* LD D,SET 6,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xf3: /* LD E,SET 6,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xf4: /* LD H,SET 6,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xf5: /* LD L,SET 6,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xf6: /* SET 6,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x40 );
+ }
+ break;
+ case 0xf7: /* LD A,SET 6,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x40;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
+ case 0xf8: /* LD B,SET 7,(REGISTER+dd) */
+ B = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, B);
+ break;
+ case 0xf9: /* LD C,SET 7,(REGISTER+dd) */
+ C = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, C);
+ break;
+ case 0xfa: /* LD D,SET 7,(REGISTER+dd) */
+ D = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, D);
+ break;
+ case 0xfb: /* LD E,SET 7,(REGISTER+dd) */
+ E = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, E);
+ break;
+ case 0xfc: /* LD H,SET 7,(REGISTER+dd) */
+ H = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, H);
+ break;
+ case 0xfd: /* LD L,SET 7,(REGISTER+dd) */
+ L = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, L);
+ break;
+ case 0xfe: /* SET 7,(REGISTER+dd) */
+ {
+ uint8 bytetemp;
+ bytetemp = Z80_RB_MACRO( tempaddr );
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO( tempaddr, bytetemp | 0x80 );
+ }
+ break;
+ case 0xff: /* LD A,SET 7,(REGISTER+dd) */
+ A = Z80_RB_MACRO(tempaddr) | 0x80;
+ contend_read_no_mreq( tempaddr, 1 );
+ Z80_WB_MACRO(tempaddr, A);
+ break;
diff --git a/waterbox/ngp/z80-fuse/z80_ed.c b/waterbox/ngp/z80-fuse/z80_ed.c
new file mode 100644
index 0000000000..e53ce22942
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_ed.c
@@ -0,0 +1,567 @@
+/* z80_ed.c: Z80 CBxx opcodes
+ Copyright (c) 1999-2003 Philip Kendall
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+/* NB: this file is autogenerated by 'z80.pl' from 'opcodes_ed.dat',
+ and included in 'z80_ops.c' */
+
+ case 0x40: /* IN B,(C) */
+ Z80_IN( B, BC );
+ break;
+ case 0x41: /* OUT (C),B */
+ Z80_WP_MACRO( BC, B );
+ break;
+ case 0x42: /* SBC HL,BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SBC16(BC);
+ break;
+ case 0x43: /* LD (nnnn),BC */
+ LD16_NNRR(C,B);
+ break;
+ case 0x44:
+ case 0x4c:
+ case 0x54:
+ case 0x5c:
+ case 0x64:
+ case 0x6c:
+ case 0x74:
+ case 0x7c: /* NEG */
+ {
+ uint8 bytetemp=A;
+ A=0;
+ SUB(bytetemp);
+ }
+ break;
+ case 0x45:
+ case 0x4d:
+ case 0x55:
+ case 0x5d:
+ case 0x65:
+ case 0x6d:
+ case 0x75:
+ case 0x7d: /* RETN */
+ IFF1=IFF2;
+ RET();
+ break;
+ case 0x46:
+ case 0x4e:
+ case 0x66:
+ case 0x6e: /* IM 0 */
+ IM=0;
+ break;
+ case 0x47: /* LD I,A */
+ contend_read_no_mreq( IR, 1 );
+ I=A;
+ break;
+ case 0x48: /* IN C,(C) */
+ Z80_IN( C, BC );
+ break;
+ case 0x49: /* OUT (C),C */
+ Z80_WP_MACRO( BC, C );
+ break;
+ case 0x4a: /* ADC HL,BC */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADC16(BC);
+ break;
+ case 0x4b: /* LD BC,(nnnn) */
+ LD16_RRNN(C,B);
+ break;
+ case 0x4f: /* LD R,A */
+ contend_read_no_mreq( IR, 1 );
+ R=R7=A;
+ break;
+ case 0x50: /* IN D,(C) */
+ Z80_IN( D, BC );
+ break;
+ case 0x51: /* OUT (C),D */
+ Z80_WP_MACRO( BC, D );
+ break;
+ case 0x52: /* SBC HL,DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SBC16(DE);
+ break;
+ case 0x53: /* LD (nnnn),DE */
+ LD16_NNRR(E,D);
+ break;
+ case 0x56:
+ case 0x76: /* IM 1 */
+ IM=1;
+ break;
+ case 0x57: /* LD A,I */
+ contend_read_no_mreq( IR, 1 );
+ A=I;
+ F = ( F & FLAG_C ) | sz53_table[A] | ( IFF2 ? FLAG_V : 0 );
+ break;
+ case 0x58: /* IN E,(C) */
+ Z80_IN( E, BC );
+ break;
+ case 0x59: /* OUT (C),E */
+ Z80_WP_MACRO( BC, E );
+ break;
+ case 0x5a: /* ADC HL,DE */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADC16(DE);
+ break;
+ case 0x5b: /* LD DE,(nnnn) */
+ LD16_RRNN(E,D);
+ break;
+ case 0x5e:
+ case 0x7e: /* IM 2 */
+ IM=2;
+ break;
+ case 0x5f: /* LD A,R */
+ contend_read_no_mreq( IR, 1 );
+ A=(R&0x7f) | (R7&0x80);
+ F = ( F & FLAG_C ) | sz53_table[A] | ( IFF2 ? FLAG_V : 0 );
+ break;
+ case 0x60: /* IN H,(C) */
+ Z80_IN( H, BC );
+ break;
+ case 0x61: /* OUT (C),H */
+ Z80_WP_MACRO( BC, H );
+ break;
+ case 0x62: /* SBC HL,HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SBC16(HL);
+ break;
+ case 0x63: /* LD (nnnn),HL */
+ LD16_NNRR(L,H);
+ break;
+ case 0x67: /* RRD */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO(HL, ( A << 4 ) | ( bytetemp >> 4 ) );
+ A = ( A & 0xf0 ) | ( bytetemp & 0x0f );
+ F = ( F & FLAG_C ) | sz53p_table[A];
+ }
+ break;
+ case 0x68: /* IN L,(C) */
+ Z80_IN( L, BC );
+ break;
+ case 0x69: /* OUT (C),L */
+ Z80_WP_MACRO( BC, L );
+ break;
+ case 0x6a: /* ADC HL,HL */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADC16(HL);
+ break;
+ case 0x6b: /* LD HL,(nnnn) */
+ LD16_RRNN(L,H);
+ break;
+ case 0x6f: /* RLD */
+ {
+ uint8 bytetemp = Z80_RB_MACRO( HL );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ Z80_WB_MACRO(HL, (bytetemp << 4 ) | ( A & 0x0f ) );
+ A = ( A & 0xf0 ) | ( bytetemp >> 4 );
+ F = ( F & FLAG_C ) | sz53p_table[A];
+ }
+ break;
+ case 0x70: /* IN F,(C) */
+ {
+ uint8 bytetemp;
+ Z80_IN( bytetemp, BC );
+ }
+ break;
+ case 0x71: /* OUT (C),0 */
+ Z80_WP_MACRO( BC, 0 );
+ break;
+ case 0x72: /* SBC HL,SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ SBC16(SP);
+ break;
+ case 0x73: /* LD (nnnn),SP */
+ LD16_NNRR(SPL,SPH);
+ break;
+ case 0x78: /* IN A,(C) */
+ Z80_IN( A, BC );
+ break;
+ case 0x79: /* OUT (C),A */
+ Z80_WP_MACRO( BC, A );
+ break;
+ case 0x7a: /* ADC HL,SP */
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ contend_read_no_mreq( IR, 1 );
+ ADC16(SP);
+ break;
+ case 0x7b: /* LD SP,(nnnn) */
+ LD16_RRNN(SPL,SPH);
+ break;
+ case 0xa0: /* LDI */
+ {
+ uint8 bytetemp=Z80_RB_MACRO( HL );
+ BC--;
+ Z80_WB_MACRO(DE,bytetemp);
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ DE++; HL++;
+ bytetemp += A;
+ F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |
+ ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );
+ }
+ break;
+ case 0xa1: /* CPI */
+ {
+ uint8 value = Z80_RB_MACRO( HL ), bytetemp = A - value,
+ lookup = ( ( A & 0x08 ) >> 3 ) |
+ ( ( (value) & 0x08 ) >> 2 ) |
+ ( ( bytetemp & 0x08 ) >> 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ HL++; BC--;
+ F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
+ halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |
+ ( bytetemp & FLAG_S );
+ if(F & FLAG_H) bytetemp--;
+ F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );
+ }
+ break;
+ case 0xa2: /* INI */
+ {
+ uint8 initemp, initemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ initemp = Z80_RP_MACRO( BC );
+ Z80_WB_MACRO( HL, initemp );
+
+ B--; HL++;
+ initemp2 = initemp + C + 1;
+ F = ( initemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( initemp2 < initemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( initemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+ }
+ break;
+ case 0xa3: /* OUTI */
+ {
+ uint8 outitemp, outitemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ outitemp = Z80_RB_MACRO( HL );
+ B--; /* This does happen first, despite what the specs say */
+ Z80_WP_MACRO(BC,outitemp);
+
+ HL++;
+ outitemp2 = outitemp + L;
+ F = ( outitemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( outitemp2 < outitemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( outitemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+ }
+ break;
+ case 0xa8: /* LDD */
+ {
+ uint8 bytetemp=Z80_RB_MACRO( HL );
+ BC--;
+ Z80_WB_MACRO(DE,bytetemp);
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ DE--; HL--;
+ bytetemp += A;
+ F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |
+ ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );
+ }
+ break;
+ case 0xa9: /* CPD */
+ {
+ uint8 value = Z80_RB_MACRO( HL ), bytetemp = A - value,
+ lookup = ( ( A & 0x08 ) >> 3 ) |
+ ( ( (value) & 0x08 ) >> 2 ) |
+ ( ( bytetemp & 0x08 ) >> 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ HL--; BC--;
+ F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
+ halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |
+ ( bytetemp & FLAG_S );
+ if(F & FLAG_H) bytetemp--;
+ F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );
+ }
+ break;
+ case 0xaa: /* IND */
+ {
+ uint8 initemp, initemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ initemp = Z80_RP_MACRO( BC );
+ Z80_WB_MACRO( HL, initemp );
+
+ B--; HL--;
+ initemp2 = initemp + C - 1;
+ F = ( initemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( initemp2 < initemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( initemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+ }
+ break;
+ case 0xab: /* OUTD */
+ {
+ uint8 outitemp, outitemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ outitemp = Z80_RB_MACRO( HL );
+ B--; /* This does happen first, despite what the specs say */
+ Z80_WP_MACRO(BC,outitemp);
+
+ HL--;
+ outitemp2 = outitemp + L;
+ F = ( outitemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( outitemp2 < outitemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( outitemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+ }
+ break;
+ case 0xb0: /* LDIR */
+ {
+ uint8 bytetemp=Z80_RB_MACRO( HL );
+ Z80_WB_MACRO(DE,bytetemp);
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ BC--;
+ bytetemp += A;
+ F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |
+ ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );
+ if(BC) {
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ contend_write_no_mreq( DE, 1 );
+ PC-=2;
+ }
+ HL++; DE++;
+ }
+ break;
+ case 0xb1: /* CPIR */
+ {
+ uint8 value = Z80_RB_MACRO( HL ), bytetemp = A - value,
+ lookup = ( ( A & 0x08 ) >> 3 ) |
+ ( ( (value) & 0x08 ) >> 2 ) |
+ ( ( bytetemp & 0x08 ) >> 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ BC--;
+ F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
+ halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |
+ ( bytetemp & FLAG_S );
+ if(F & FLAG_H) bytetemp--;
+ F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );
+ if( ( F & ( FLAG_V | FLAG_Z ) ) == FLAG_V ) {
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ PC-=2;
+ }
+ HL++;
+ }
+ break;
+ case 0xb2: /* INIR */
+ {
+ uint8 initemp, initemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ initemp = Z80_RP_MACRO( BC );
+ Z80_WB_MACRO( HL, initemp );
+
+ B--;
+ initemp2 = initemp + C + 1;
+ F = ( initemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( initemp2 < initemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( initemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+
+ if( B ) {
+ contend_write_no_mreq( HL, 1 ); contend_write_no_mreq( HL, 1 );
+ contend_write_no_mreq( HL, 1 ); contend_write_no_mreq( HL, 1 );
+ contend_write_no_mreq( HL, 1 );
+ PC -= 2;
+ }
+ HL++;
+ }
+ break;
+ case 0xb3: /* OTIR */
+ {
+ uint8 outitemp, outitemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ outitemp = Z80_RB_MACRO( HL );
+ B--; /* This does happen first, despite what the specs say */
+ Z80_WP_MACRO(BC,outitemp);
+
+ HL++;
+ outitemp2 = outitemp + L;
+ F = ( outitemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( outitemp2 < outitemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( outitemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+
+ if( B ) {
+ contend_read_no_mreq( BC, 1 ); contend_read_no_mreq( BC, 1 );
+ contend_read_no_mreq( BC, 1 ); contend_read_no_mreq( BC, 1 );
+ contend_read_no_mreq( BC, 1 );
+ PC -= 2;
+ }
+ }
+ break;
+ case 0xb8: /* LDDR */
+ {
+ uint8 bytetemp=Z80_RB_MACRO( HL );
+ Z80_WB_MACRO(DE,bytetemp);
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ BC--;
+ bytetemp += A;
+ F = ( F & ( FLAG_C | FLAG_Z | FLAG_S ) ) | ( BC ? FLAG_V : 0 ) |
+ ( bytetemp & FLAG_3 ) | ( (bytetemp & 0x02) ? FLAG_5 : 0 );
+ if(BC) {
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ contend_write_no_mreq( DE, 1 ); contend_write_no_mreq( DE, 1 );
+ contend_write_no_mreq( DE, 1 );
+ PC-=2;
+ }
+ HL--; DE--;
+ }
+ break;
+ case 0xb9: /* CPDR */
+ {
+ uint8 value = Z80_RB_MACRO( HL ), bytetemp = A - value,
+ lookup = ( ( A & 0x08 ) >> 3 ) |
+ ( ( (value) & 0x08 ) >> 2 ) |
+ ( ( bytetemp & 0x08 ) >> 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ BC--;
+ F = ( F & FLAG_C ) | ( BC ? ( FLAG_V | FLAG_N ) : FLAG_N ) |
+ halfcarry_sub_table[lookup] | ( bytetemp ? 0 : FLAG_Z ) |
+ ( bytetemp & FLAG_S );
+ if(F & FLAG_H) bytetemp--;
+ F |= ( bytetemp & FLAG_3 ) | ( (bytetemp&0x02) ? FLAG_5 : 0 );
+ if( ( F & ( FLAG_V | FLAG_Z ) ) == FLAG_V ) {
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 ); contend_read_no_mreq( HL, 1 );
+ contend_read_no_mreq( HL, 1 );
+ PC-=2;
+ }
+ HL--;
+ }
+ break;
+ case 0xba: /* INDR */
+ {
+ uint8 initemp, initemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ initemp = Z80_RP_MACRO( BC );
+ Z80_WB_MACRO( HL, initemp );
+
+ B--;
+ initemp2 = initemp + C - 1;
+ F = ( initemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( initemp2 < initemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( initemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+
+ if( B ) {
+ contend_write_no_mreq( HL, 1 ); contend_write_no_mreq( HL, 1 );
+ contend_write_no_mreq( HL, 1 ); contend_write_no_mreq( HL, 1 );
+ contend_write_no_mreq( HL, 1 );
+ PC -= 2;
+ }
+ HL--;
+ }
+ break;
+ case 0xbb: /* OTDR */
+ {
+ uint8 outitemp, outitemp2;
+
+ contend_read_no_mreq( IR, 1 );
+ outitemp = Z80_RB_MACRO( HL );
+ B--; /* This does happen first, despite what the specs say */
+ Z80_WP_MACRO(BC,outitemp);
+
+ HL--;
+ outitemp2 = outitemp + L;
+ F = ( outitemp & 0x80 ? FLAG_N : 0 ) |
+ ( ( outitemp2 < outitemp ) ? FLAG_H | FLAG_C : 0 ) |
+ ( parity_table[ ( outitemp2 & 0x07 ) ^ B ] ? FLAG_P : 0 ) |
+ sz53_table[B];
+
+ if( B ) {
+ contend_read_no_mreq( BC, 1 ); contend_read_no_mreq( BC, 1 );
+ contend_read_no_mreq( BC, 1 ); contend_read_no_mreq( BC, 1 );
+ contend_read_no_mreq( BC, 1 );
+ PC -= 2;
+ }
+ }
+ break;
+ case 0xfb: /* slttrap */
+ //slt_trap( HL, A );
+ break;
+ default: /* All other opcodes are NOPD */
+ break;
diff --git a/waterbox/ngp/z80-fuse/z80_macros.h b/waterbox/ngp/z80-fuse/z80_macros.h
new file mode 100644
index 0000000000..e109994fc5
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_macros.h
@@ -0,0 +1,432 @@
+/* z80_macros.h: Some commonly used z80 things as macros
+ Copyright (c) 1999-2011 Philip Kendall
+
+ $Id: z80_macros.h 4624 2012-01-09 20:59:35Z pak21 $
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+#ifndef FUSE_Z80_MACROS_H
+#define FUSE_Z80_MACROS_H
+
+/* Macros used for accessing the registers */
+#define A z80.af.b.h
+#define F z80.af.b.l
+#define AF z80.af.w
+
+#define B z80.bc.b.h
+#define C z80.bc.b.l
+#define BC z80.bc.w
+
+#define D z80.de.b.h
+#define E z80.de.b.l
+#define DE z80.de.w
+
+#define H z80.hl.b.h
+#define L z80.hl.b.l
+#define HL z80.hl.w
+
+#define A_ z80.af_.b.h
+#define F_ z80.af_.b.l
+#define AF_ z80.af_.w
+
+#define B_ z80.bc_.b.h
+#define C_ z80.bc_.b.l
+#define BC_ z80.bc_.w
+
+#define D_ z80.de_.b.h
+#define E_ z80.de_.b.l
+#define DE_ z80.de_.w
+
+#define H_ z80.hl_.b.h
+#define L_ z80.hl_.b.l
+#define HL_ z80.hl_.w
+
+#define IXH z80.ix.b.h
+#define IXL z80.ix.b.l
+#define IX z80.ix.w
+
+#define IYH z80.iy.b.h
+#define IYL z80.iy.b.l
+#define IY z80.iy.w
+
+#define SPH z80.sp.b.h
+#define SPL z80.sp.b.l
+#define SP z80.sp.w
+
+#define PCH z80.pc.b.h
+#define PCL z80.pc.b.l
+#define PC z80.pc.w
+
+#define I z80.i
+#define R z80.r
+#define R7 z80.r7
+
+#define IFF1 z80.iff1
+#define IFF2 z80.iff2
+#define IM z80.im
+
+#define IR ( ( z80.i ) << 8 | ( z80.r7 & 0x80 ) | ( z80.r & 0x7f ) )
+
+/* The flags */
+
+#define FLAG_C 0x01
+#define FLAG_N 0x02
+#define FLAG_P 0x04
+#define FLAG_V FLAG_P
+#define FLAG_3 0x08
+#define FLAG_H 0x10
+#define FLAG_5 0x20
+#define FLAG_Z 0x40
+#define FLAG_S 0x80
+
+/* Get the appropriate contended memory delay. Use a macro for performance
+ reasons in the main core, but a function for flexibility when building
+ the core tester */
+
+#ifndef CORETEST
+
+#if 0
+#define contend_read(address,time) \
+ if( memory_map_read[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \
+ z80_tstates += ula_contention[ z80_tstates ]; \
+ z80_tstates += (time);
+
+#define contend_read_no_mreq(address,time) \
+ if( memory_map_read[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \
+ z80_tstates += ula_contention_no_mreq[ z80_tstates ]; \
+ z80_tstates += (time);
+
+#define contend_write_no_mreq(address,time) \
+ if( memory_map_write[ (address) >> MEMORY_PAGE_SIZE_LOGARITHM ].contended ) \
+ z80_tstates += ula_contention_no_mreq[ z80_tstates ]; \
+ z80_tstates += (time);
+#endif
+
+#define contend_read(address,time) \
+ z80_tstates += (time);
+
+#define contend_read_no_mreq(address,time) \
+ z80_tstates += (time);
+
+#define contend_write_no_mreq(address,time) \
+ z80_tstates += (time);
+
+
+#else /* #ifndef CORETEST */
+
+void contend_read( uint16 address, uint32 time );
+void contend_read_no_mreq( uint16 address, uint32 time );
+void contend_write_no_mreq( uint16 address, uint32 time );
+
+#endif /* #ifndef CORETEST */
+
+/* Some commonly used instructions */
+#define AND(value)\
+{\
+ A &= (value);\
+ F = FLAG_H | sz53p_table[A];\
+}
+
+#define ADC(value)\
+{\
+ uint16 adctemp = A + (value) + ( F & FLAG_C ); \
+ uint8 lookup = ( ( A & 0x88 ) >> 3 ) | \
+ ( ( (value) & 0x88 ) >> 2 ) | \
+ ( ( adctemp & 0x88 ) >> 1 ); \
+ A=adctemp;\
+ F = ( adctemp & 0x100 ? FLAG_C : 0 ) |\
+ halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\
+ sz53_table[A];\
+}
+
+#define ADC16(value)\
+{\
+ uint32 add16temp= HL + (value) + ( F & FLAG_C ); \
+ uint8 lookup = ( ( HL & 0x8800 ) >> 11 ) | \
+ ( ( (value) & 0x8800 ) >> 10 ) | \
+ ( ( add16temp & 0x8800 ) >> 9 ); \
+ HL = add16temp;\
+ F = ( add16temp & 0x10000 ? FLAG_C : 0 )|\
+ overflow_add_table[lookup >> 4] |\
+ ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\
+ halfcarry_add_table[lookup&0x07]|\
+ ( HL ? 0 : FLAG_Z );\
+}
+
+#define ADD(value)\
+{\
+ uint16 addtemp = A + (value); \
+ uint8 lookup = ( ( A & 0x88 ) >> 3 ) | \
+ ( ( (value) & 0x88 ) >> 2 ) | \
+ ( ( addtemp & 0x88 ) >> 1 ); \
+ A=addtemp;\
+ F = ( addtemp & 0x100 ? FLAG_C : 0 ) |\
+ halfcarry_add_table[lookup & 0x07] | overflow_add_table[lookup >> 4] |\
+ sz53_table[A];\
+}
+
+#define ADD16(value1,value2)\
+{\
+ uint32 add16temp = (value1) + (value2); \
+ uint8 lookup = ( ( (value1) & 0x0800 ) >> 11 ) | \
+ ( ( (value2) & 0x0800 ) >> 10 ) | \
+ ( ( add16temp & 0x0800 ) >> 9 ); \
+ (value1) = add16temp;\
+ F = ( F & ( FLAG_V | FLAG_Z | FLAG_S ) ) |\
+ ( add16temp & 0x10000 ? FLAG_C : 0 )|\
+ ( ( add16temp >> 8 ) & ( FLAG_3 | FLAG_5 ) ) |\
+ halfcarry_add_table[lookup];\
+}
+
+/* This may look fairly inefficient, but the (gcc) optimiser does the
+ right thing assuming it's given a constant for 'bit' */
+#define BIT( bit, value ) \
+{ \
+ F = ( F & FLAG_C ) | FLAG_H | ( value & ( FLAG_3 | FLAG_5 ) ); \
+ if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \
+ if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \
+}
+
+#define BIT_I( bit, value, address ) \
+{ \
+ F = ( F & FLAG_C ) | FLAG_H | ( ( address >> 8 ) & ( FLAG_3 | FLAG_5 ) ); \
+ if( ! ( (value) & ( 0x01 << (bit) ) ) ) F |= FLAG_P | FLAG_Z; \
+ if( (bit) == 7 && (value) & 0x80 ) F |= FLAG_S; \
+}
+
+#define CALL()\
+{\
+ uint8 calltempl, calltemph; \
+ calltempl=Z80_RB_MACRO(PC++);\
+ calltemph=Z80_RB_MACRO( PC ); \
+ contend_read_no_mreq( PC, 1 ); PC++;\
+ PUSH16(PCL,PCH);\
+ PCL=calltempl; PCH=calltemph;\
+}
+
+#define CP(value)\
+{\
+ uint16 cptemp = A - value; \
+ uint8 lookup = ( ( A & 0x88 ) >> 3 ) | \
+ ( ( (value) & 0x88 ) >> 2 ) | \
+ ( ( cptemp & 0x88 ) >> 1 ); \
+ F = ( cptemp & 0x100 ? FLAG_C : ( cptemp ? 0 : FLAG_Z ) ) | FLAG_N |\
+ halfcarry_sub_table[lookup & 0x07] |\
+ overflow_sub_table[lookup >> 4] |\
+ ( value & ( FLAG_3 | FLAG_5 ) ) |\
+ ( cptemp & FLAG_S );\
+}
+
+/* Macro for the {DD,FD} CB dd xx rotate/shift instructions */
+#define DDFDCB_ROTATESHIFT(time, target, instruction)\
+z80_tstates+=(time);\
+{\
+ (target) = Z80_RB_MACRO( tempaddr );\
+ instruction( (target) );\
+ Z80_WB_MACRO( tempaddr, (target) );\
+}\
+break
+
+#define DEC(value)\
+{\
+ F = ( F & FLAG_C ) | ( (value)&0x0f ? 0 : FLAG_H ) | FLAG_N;\
+ (value)--;\
+ F |= ( (value)==0x7f ? FLAG_V : 0 ) | sz53_table[value];\
+}
+
+#define Z80_IN( reg, port )\
+{\
+ (reg)=Z80_RP_MACRO((port));\
+ F = ( F & FLAG_C) | sz53p_table[(reg)];\
+}
+
+#define INC(value)\
+{\
+ (value)++;\
+ F = ( F & FLAG_C ) | ( (value)==0x80 ? FLAG_V : 0 ) |\
+ ( (value)&0x0f ? 0 : FLAG_H ) | sz53_table[(value)];\
+}
+
+#define LD16_NNRR(regl,regh)\
+{\
+ uint16 ldtemp; \
+ ldtemp=Z80_RB_MACRO(PC++);\
+ ldtemp|=Z80_RB_MACRO(PC++) << 8;\
+ Z80_WB_MACRO(ldtemp++,(regl));\
+ Z80_WB_MACRO(ldtemp,(regh));\
+ break;\
+}
+
+#define LD16_RRNN(regl,regh)\
+{\
+ uint16 ldtemp; \
+ ldtemp=Z80_RB_MACRO(PC++);\
+ ldtemp|=Z80_RB_MACRO(PC++) << 8;\
+ (regl)=Z80_RB_MACRO(ldtemp++);\
+ (regh)=Z80_RB_MACRO(ldtemp);\
+ break;\
+}
+
+#define JP()\
+{\
+ uint16 jptemp=PC; \
+ PCL=Z80_RB_MACRO(jptemp++);\
+ PCH=Z80_RB_MACRO(jptemp);\
+}
+
+#define JR()\
+{\
+ int8 jrtemp = Z80_RB_MACRO( PC ); \
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); \
+ contend_read_no_mreq( PC, 1 ); contend_read_no_mreq( PC, 1 ); \
+ contend_read_no_mreq( PC, 1 ); \
+ PC += jrtemp; \
+}
+
+#define OR(value)\
+{\
+ A |= (value);\
+ F = sz53p_table[A];\
+}
+
+#define POP16(regl,regh)\
+{\
+ (regl)=Z80_RB_MACRO(SP++);\
+ (regh)=Z80_RB_MACRO(SP++);\
+}
+
+#define PUSH16(regl,regh)\
+{\
+ Z80_WB_MACRO( --SP, (regh) );\
+ Z80_WB_MACRO( --SP, (regl) );\
+}
+
+#define RET()\
+{\
+ POP16(PCL,PCH);\
+}
+
+#define RL(value)\
+{\
+ uint8 rltemp = (value); \
+ (value) = ( (value)<<1 ) | ( F & FLAG_C );\
+ F = ( rltemp >> 7 ) | sz53p_table[(value)];\
+}
+
+#define RLC(value)\
+{\
+ (value) = ( (value)<<1 ) | ( (value)>>7 );\
+ F = ( (value) & FLAG_C ) | sz53p_table[(value)];\
+}
+
+#define RR(value)\
+{\
+ uint8 rrtemp = (value); \
+ (value) = ( (value)>>1 ) | ( F << 7 );\
+ F = ( rrtemp & FLAG_C ) | sz53p_table[(value)];\
+}
+
+#define RRC(value)\
+{\
+ F = (value) & FLAG_C;\
+ (value) = ( (value)>>1 ) | ( (value)<<7 );\
+ F |= sz53p_table[(value)];\
+}
+
+#define RST(value)\
+{\
+ PUSH16(PCL,PCH);\
+ PC=(value);\
+}
+
+#define SBC(value)\
+{\
+ uint16 sbctemp = A - (value) - ( F & FLAG_C ); \
+ uint8 lookup = ( ( A & 0x88 ) >> 3 ) | \
+ ( ( (value) & 0x88 ) >> 2 ) | \
+ ( ( sbctemp & 0x88 ) >> 1 ); \
+ A=sbctemp;\
+ F = ( sbctemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\
+ halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\
+ sz53_table[A];\
+}
+
+#define SBC16(value)\
+{\
+ uint32 sub16temp = HL - (value) - (F & FLAG_C); \
+ uint8 lookup = ( ( HL & 0x8800 ) >> 11 ) | \
+ ( ( (value) & 0x8800 ) >> 10 ) | \
+ ( ( sub16temp & 0x8800 ) >> 9 ); \
+ HL = sub16temp;\
+ F = ( sub16temp & 0x10000 ? FLAG_C : 0 ) |\
+ FLAG_N | overflow_sub_table[lookup >> 4] |\
+ ( H & ( FLAG_3 | FLAG_5 | FLAG_S ) ) |\
+ halfcarry_sub_table[lookup&0x07] |\
+ ( HL ? 0 : FLAG_Z) ;\
+}
+
+#define SLA(value)\
+{\
+ F = (value) >> 7;\
+ (value) <<= 1;\
+ F |= sz53p_table[(value)];\
+}
+
+#define SLL(value)\
+{\
+ F = (value) >> 7;\
+ (value) = ( (value) << 1 ) | 0x01;\
+ F |= sz53p_table[(value)];\
+}
+
+#define SRA(value)\
+{\
+ F = (value) & FLAG_C;\
+ (value) = ( (value) & 0x80 ) | ( (value) >> 1 );\
+ F |= sz53p_table[(value)];\
+}
+
+#define SRL(value)\
+{\
+ F = (value) & FLAG_C;\
+ (value) >>= 1;\
+ F |= sz53p_table[(value)];\
+}
+
+#define SUB(value)\
+{\
+ uint16 subtemp = A - (value); \
+ uint8 lookup = ( ( A & 0x88 ) >> 3 ) | \
+ ( ( (value) & 0x88 ) >> 2 ) | \
+ ( (subtemp & 0x88 ) >> 1 ); \
+ A=subtemp;\
+ F = ( subtemp & 0x100 ? FLAG_C : 0 ) | FLAG_N |\
+ halfcarry_sub_table[lookup & 0x07] | overflow_sub_table[lookup >> 4] |\
+ sz53_table[A];\
+}
+
+#define XOR(value)\
+{\
+ A ^= (value);\
+ F = sz53p_table[A];\
+}
+
+#endif /* #ifndef FUSE_Z80_MACROS_H */
diff --git a/waterbox/ngp/z80-fuse/z80_ops.cpp b/waterbox/ngp/z80-fuse/z80_ops.cpp
new file mode 100644
index 0000000000..bbe985c567
--- /dev/null
+++ b/waterbox/ngp/z80-fuse/z80_ops.cpp
@@ -0,0 +1,74 @@
+/* z80_ops.c: Process the next opcode
+ Copyright (c) 1999-2005 Philip Kendall, Witold Filipczyk
+
+ $Id: z80_ops.c 4624 2012-01-09 20:59:35Z pak21 $
+
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Author contact information:
+
+ E-mail: philip-fuse@shadowmagic.org.uk
+
+*/
+
+#include "z80.h"
+
+#include "z80_macros.h"
+
+static int iline = 0;
+
+void z80_set_interrupt(int set)
+{
+ iline = set;
+}
+
+int z80_do_opcode( void )
+{
+ if(iline)
+ {
+ if(z80_interrupt())
+ {
+ int ret = z80_tstates - last_z80_tstates;
+ last_z80_tstates = z80_tstates;
+ return(ret);
+ }
+ }
+
+ uint8 opcode;
+
+ /* Check to see if M1 cycles happen on even z80_tstates */
+ //if( z80_tstates & 1 )
+ // z80_tstates++;
+ //uint16 lastpc = PC;
+
+ opcode = Z80_RB_MACRO( PC );
+ //printf("Z80-op: %04x, %02x\n", PC, opcode);
+ z80_tstates++;
+
+ PC++;
+ R++;
+
+ switch(opcode)
+ {
+ #include "opcodes_base.c"
+ }
+
+ int ret = z80_tstates - last_z80_tstates;
+ last_z80_tstates = z80_tstates;
+
+ //printf("PC: %04x, %02x, time=%d\n", lastpc, opcode, ret);
+
+ return(ret);
+}