From 3ec7b0252f634c8634c4acddcef7f3df0940cce2 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Mon, 29 May 2017 20:21:34 -0400 Subject: [PATCH] Exploding your computer NYI https://www.youtube.com/watch?v=dUHYNmNrqoY --- .gitignore | 2 + ...izHawkSystemIdToCoreSystemEnumConverter.cs | 1 + BizHawk.Emulation.Common/Database/Database.cs | 5 + .../BizHawk.Emulation.Cores.csproj | 4 +- .../Consoles/SNK/LibNeoGeo.cs | 36 + .../Consoles/SNK/NeoGeo.cs | 153 ++ waterbox/ngp/.vscode/settings.json | 11 + waterbox/ngp/Makefile | 44 + waterbox/ngp/T6W28_Apu.cpp | 422 ++++ waterbox/ngp/T6W28_Apu.h | 95 + waterbox/ngp/T6W28_Oscs.h | 60 + .../ngp/TLCS-900h/TLCS900h_disassemble.cpp | 641 +++++ waterbox/ngp/TLCS-900h/TLCS900h_disassemble.h | 77 + .../TLCS-900h/TLCS900h_disassemble_dst.cpp | 240 ++ .../TLCS-900h/TLCS900h_disassemble_extra.cpp | 199 ++ .../TLCS-900h/TLCS900h_disassemble_reg.cpp | 662 +++++ .../TLCS-900h/TLCS900h_disassemble_src.cpp | 507 ++++ waterbox/ngp/TLCS-900h/TLCS900h_interpret.cpp | 975 ++++++++ waterbox/ngp/TLCS-900h/TLCS900h_interpret.h | 137 ++ .../ngp/TLCS-900h/TLCS900h_interpret_dst.cpp | 315 +++ .../ngp/TLCS-900h/TLCS900h_interpret_dst.h | 132 + .../ngp/TLCS-900h/TLCS900h_interpret_reg.cpp | 2187 +++++++++++++++++ .../ngp/TLCS-900h/TLCS900h_interpret_reg.h | 305 +++ .../TLCS-900h/TLCS900h_interpret_single.cpp | 428 ++++ .../ngp/TLCS-900h/TLCS900h_interpret_single.h | 170 ++ .../ngp/TLCS-900h/TLCS900h_interpret_src.cpp | 1266 ++++++++++ .../ngp/TLCS-900h/TLCS900h_interpret_src.h | 200 ++ waterbox/ngp/TLCS-900h/TLCS900h_registers.cpp | 208 ++ waterbox/ngp/TLCS-900h/TLCS900h_registers.h | 126 + .../ngp/TLCS-900h/TLCS900h_registers_mapB.h | 83 + .../TLCS-900h/TLCS900h_registers_mapCodeB0.h | 105 + .../TLCS-900h/TLCS900h_registers_mapCodeB1.h | 105 + .../TLCS-900h/TLCS900h_registers_mapCodeB2.h | 105 + .../TLCS-900h/TLCS900h_registers_mapCodeB3.h | 105 + .../TLCS-900h/TLCS900h_registers_mapCodeL0.h | 60 + .../TLCS-900h/TLCS900h_registers_mapCodeL1.h | 60 + .../TLCS-900h/TLCS900h_registers_mapCodeL2.h | 60 + .../TLCS-900h/TLCS900h_registers_mapCodeL3.h | 60 + .../TLCS-900h/TLCS900h_registers_mapCodeW0.h | 94 + .../TLCS-900h/TLCS900h_registers_mapCodeW1.h | 94 + .../TLCS-900h/TLCS900h_registers_mapCodeW2.h | 94 + .../TLCS-900h/TLCS900h_registers_mapCodeW3.h | 94 + .../ngp/TLCS-900h/TLCS900h_registers_mapL.h | 84 + .../ngp/TLCS-900h/TLCS900h_registers_mapW.h | 84 + waterbox/ngp/Z80_interface.cpp | 139 ++ waterbox/ngp/Z80_interface.h | 37 + waterbox/ngp/bios.cpp | 241 ++ waterbox/ngp/bios.h | 55 + waterbox/ngp/biosHLE.cpp | 629 +++++ waterbox/ngp/defs.h | 85 + waterbox/ngp/dma.cpp | 379 +++ waterbox/ngp/dma.h | 60 + waterbox/ngp/endian.h | 494 ++++ waterbox/ngp/flash.cpp | 318 +++ waterbox/ngp/flash.h | 30 + waterbox/ngp/gfx.cpp | 474 ++++ waterbox/ngp/gfx.h | 105 + waterbox/ngp/gfx_scanline_colour.cpp | 270 ++ waterbox/ngp/gfx_scanline_mono.cpp | 253 ++ waterbox/ngp/interrupt.cpp | 598 +++++ waterbox/ngp/interrupt.h | 61 + waterbox/ngp/mem.cpp | 673 +++++ waterbox/ngp/mem.h | 61 + waterbox/ngp/neopop.cpp | 268 ++ waterbox/ngp/neopop.h | 178 ++ waterbox/ngp/rom.cpp | 136 + waterbox/ngp/rtc.cpp | 70 + waterbox/ngp/rtc.h | 11 + waterbox/ngp/sound.cpp | 114 + waterbox/ngp/sound.h | 34 + waterbox/ngp/sound/Blip_Buffer.cpp | 457 ++++ waterbox/ngp/sound/Blip_Buffer.h | 498 ++++ waterbox/ngp/sound/Stereo_Buffer.cpp | 146 ++ waterbox/ngp/sound/Stereo_Buffer.h | 69 + waterbox/ngp/z80-fuse/opcodes_base.c | 1123 +++++++++ waterbox/ngp/z80-fuse/z80.cpp | 183 ++ waterbox/ngp/z80-fuse/z80.h | 126 + waterbox/ngp/z80-fuse/z80_cb.c | 930 +++++++ waterbox/ngp/z80-fuse/z80_ddfd.c | 534 ++++ waterbox/ngp/z80-fuse/z80_ddfdcb.c | 1226 +++++++++ waterbox/ngp/z80-fuse/z80_ed.c | 567 +++++ waterbox/ngp/z80-fuse/z80_macros.h | 432 ++++ waterbox/ngp/z80-fuse/z80_ops.cpp | 74 + 83 files changed, 23032 insertions(+), 1 deletion(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/SNK/LibNeoGeo.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/SNK/NeoGeo.cs create mode 100644 waterbox/ngp/.vscode/settings.json create mode 100644 waterbox/ngp/Makefile create mode 100644 waterbox/ngp/T6W28_Apu.cpp create mode 100644 waterbox/ngp/T6W28_Apu.h create mode 100644 waterbox/ngp/T6W28_Oscs.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble_dst.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble_extra.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble_reg.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_disassemble_src.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_dst.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_reg.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_single.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_interpret_src.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers.cpp create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapB.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB0.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB1.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB2.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeB3.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL0.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL1.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL2.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeL3.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW0.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW1.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW2.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapCodeW3.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapL.h create mode 100644 waterbox/ngp/TLCS-900h/TLCS900h_registers_mapW.h create mode 100644 waterbox/ngp/Z80_interface.cpp create mode 100644 waterbox/ngp/Z80_interface.h create mode 100644 waterbox/ngp/bios.cpp create mode 100644 waterbox/ngp/bios.h create mode 100644 waterbox/ngp/biosHLE.cpp create mode 100644 waterbox/ngp/defs.h create mode 100644 waterbox/ngp/dma.cpp create mode 100644 waterbox/ngp/dma.h create mode 100644 waterbox/ngp/endian.h create mode 100644 waterbox/ngp/flash.cpp create mode 100644 waterbox/ngp/flash.h create mode 100644 waterbox/ngp/gfx.cpp create mode 100644 waterbox/ngp/gfx.h create mode 100644 waterbox/ngp/gfx_scanline_colour.cpp create mode 100644 waterbox/ngp/gfx_scanline_mono.cpp create mode 100644 waterbox/ngp/interrupt.cpp create mode 100644 waterbox/ngp/interrupt.h create mode 100644 waterbox/ngp/mem.cpp create mode 100644 waterbox/ngp/mem.h create mode 100644 waterbox/ngp/neopop.cpp create mode 100644 waterbox/ngp/neopop.h create mode 100644 waterbox/ngp/rom.cpp create mode 100644 waterbox/ngp/rtc.cpp create mode 100644 waterbox/ngp/rtc.h create mode 100644 waterbox/ngp/sound.cpp create mode 100644 waterbox/ngp/sound.h create mode 100644 waterbox/ngp/sound/Blip_Buffer.cpp create mode 100644 waterbox/ngp/sound/Blip_Buffer.h create mode 100644 waterbox/ngp/sound/Stereo_Buffer.cpp create mode 100644 waterbox/ngp/sound/Stereo_Buffer.h create mode 100644 waterbox/ngp/z80-fuse/opcodes_base.c create mode 100644 waterbox/ngp/z80-fuse/z80.cpp create mode 100644 waterbox/ngp/z80-fuse/z80.h create mode 100644 waterbox/ngp/z80-fuse/z80_cb.c create mode 100644 waterbox/ngp/z80-fuse/z80_ddfd.c create mode 100644 waterbox/ngp/z80-fuse/z80_ddfdcb.c create mode 100644 waterbox/ngp/z80-fuse/z80_ed.c create mode 100644 waterbox/ngp/z80-fuse/z80_macros.h create mode 100644 waterbox/ngp/z80-fuse/z80_ops.cpp 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); +}