Exploding your computer NYI https://www.youtube.com/watch?v=dUHYNmNrqoY
This commit is contained in:
parent
f75ad4a472
commit
3ec7b0252f
|
@ -71,3 +71,5 @@ ExternalCoreProjects/Virtu/bin/*.*
|
|||
|
||||
**/StyleCop.Cache
|
||||
libsnes/vs2015/libsnes.VC.db
|
||||
waterbox/**/*.wbx
|
||||
waterbox/**/*.wbx.in
|
||||
|
|
|
@ -97,6 +97,7 @@ namespace BizHawk.Client.ApiHawk
|
|||
return CoreSystem.WonderSwan;
|
||||
|
||||
case "VB":
|
||||
case "NGP":
|
||||
return 0; // like I give a shit
|
||||
|
||||
default:
|
||||
|
|
|
@ -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('_', ' ');
|
||||
|
|
|
@ -1209,6 +1209,8 @@
|
|||
<Compile Include="Consoles\Sega\SMS\VDP.ModeTMS.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\VDP.Mode4.cs" />
|
||||
<Compile Include="Consoles\Sega\SMS\VDP.Tables.cs" />
|
||||
<Compile Include="Consoles\SNK\LibNeoGeo.cs" />
|
||||
<Compile Include="Consoles\SNK\NeoGeo.cs" />
|
||||
<Compile Include="Consoles\Sony\PSP\PPSSPPDll.cs" />
|
||||
<Compile Include="Consoles\Sony\PSP\PSP.cs" />
|
||||
<Compile Include="Consoles\Sony\PSX\Octoshock.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();
|
||||
}
|
||||
}
|
|
@ -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<LibNeoGeo>(_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
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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))
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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<blip_good_quality,1> 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<blip_med_quality,1> Synth;
|
||||
Synth synth;
|
||||
|
||||
void reset();
|
||||
void run( sms_time_t, sms_time_t );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
};
|
|
@ -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])();
|
||||
}
|
||||
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
|
@ -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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
|
@ -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,
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
||||
|
||||
//=============================================================================
|
|
@ -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])
|
||||
|
||||
//=============================================================================
|
|
@ -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])
|
||||
|
||||
//=============================================================================
|
|
@ -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])
|
||||
|
||||
//=============================================================================
|
|
@ -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])
|
||||
|
||||
//=============================================================================
|
|
@ -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),
|
||||
|
||||
//=============================================================================
|
|
@ -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),
|
||||
|
||||
//=============================================================================
|
|
@ -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),
|
||||
|
||||
//=============================================================================
|
|
@ -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),
|
||||
|
||||
//=============================================================================
|
|
@ -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]),
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
|
@ -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),
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
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 <emulibc.h>
|
||||
#define EXPORT extern "C" ECL_EXPORT
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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<true> 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<int isbigendian, typename T, bool aligned>
|
||||
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<typename T, bool aligned = false>
|
||||
static INLINE T MDFN_densb(const void* ptr)
|
||||
{
|
||||
return MDFN_deXsb<-1, T, aligned>(ptr);
|
||||
}
|
||||
|
||||
//
|
||||
// Little endian.
|
||||
//
|
||||
template<typename T, bool aligned = false>
|
||||
static INLINE T MDFN_delsb(const void* ptr)
|
||||
{
|
||||
return MDFN_deXsb<0, T, aligned>(ptr);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE uint16 MDFN_de16lsb(const void* ptr)
|
||||
{
|
||||
return MDFN_delsb<uint16, aligned>(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<bool aligned = false>
|
||||
static INLINE uint32 MDFN_de32lsb(const void* ptr)
|
||||
{
|
||||
return MDFN_delsb<uint32, aligned>(ptr);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE uint64 MDFN_de64lsb(const void* ptr)
|
||||
{
|
||||
return MDFN_delsb<uint64, aligned>(ptr);
|
||||
}
|
||||
|
||||
//
|
||||
// Big endian.
|
||||
//
|
||||
template<typename T, bool aligned = false>
|
||||
static INLINE T MDFN_demsb(const void* ptr)
|
||||
{
|
||||
return MDFN_deXsb<1, T, aligned>(ptr);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE uint16 MDFN_de16msb(const void* ptr)
|
||||
{
|
||||
return MDFN_demsb<uint16, aligned>(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<bool aligned = false>
|
||||
static INLINE uint32 MDFN_de32msb(const void* ptr)
|
||||
{
|
||||
return MDFN_demsb<uint32, aligned>(ptr);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE uint64 MDFN_de64msb(const void* ptr)
|
||||
{
|
||||
return MDFN_demsb<uint64, aligned>(ptr);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// X endian.
|
||||
//
|
||||
template<int isbigendian, typename T, bool aligned>
|
||||
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<typename T, bool aligned = false>
|
||||
static INLINE void MDFN_ennsb(void* ptr, T value)
|
||||
{
|
||||
MDFN_enXsb<-1, T, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
//
|
||||
// Little endian.
|
||||
//
|
||||
template<typename T, bool aligned = false>
|
||||
static INLINE void MDFN_enlsb(void* ptr, T value)
|
||||
{
|
||||
MDFN_enXsb<0, T, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE void MDFN_en16lsb(void* ptr, uint16 value)
|
||||
{
|
||||
MDFN_enlsb<uint16, aligned>(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<bool aligned = false>
|
||||
static INLINE void MDFN_en32lsb(void* ptr, uint32 value)
|
||||
{
|
||||
MDFN_enlsb<uint32, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE void MDFN_en64lsb(void* ptr, uint64 value)
|
||||
{
|
||||
MDFN_enlsb<uint64, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Big endian.
|
||||
//
|
||||
template<typename T, bool aligned = false>
|
||||
static INLINE void MDFN_enmsb(void* ptr, T value)
|
||||
{
|
||||
MDFN_enXsb<1, T, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE void MDFN_en16msb(void* ptr, uint16 value)
|
||||
{
|
||||
MDFN_enmsb<uint16, aligned>(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<bool aligned = false>
|
||||
static INLINE void MDFN_en32msb(void* ptr, uint32 value)
|
||||
{
|
||||
MDFN_enmsb<uint32, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
template<bool aligned = false>
|
||||
static INLINE void MDFN_en64msb(void* ptr, uint64 value)
|
||||
{
|
||||
MDFN_enmsb<uint64, aligned>(ptr, value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
template<typename T, typename BT>
|
||||
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<size_t>(2, sizeof(T)))));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static INLINE void ne16_wbo_be(uint16* const base, const size_t byte_offset, const T value)
|
||||
{
|
||||
uint8* const ptr = ne16_ptr_be<T>(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<typename T>
|
||||
static INLINE T ne16_rbo_be(const uint16* const base, const size_t byte_offset)
|
||||
{
|
||||
uint8* const ptr = ne16_ptr_be<T>(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<typename T, bool IsWrite>
|
||||
static INLINE void ne16_rwbo_be(uint16* const base, const size_t byte_offset, T* value)
|
||||
{
|
||||
if(IsWrite)
|
||||
ne16_wbo_be<T>(base, byte_offset, *value);
|
||||
else
|
||||
*value = ne16_rbo_be<T>(base, byte_offset);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
template<typename T, typename BT>
|
||||
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<size_t>(2, sizeof(T)))));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static INLINE void ne16_wbo_le(uint16* const base, const size_t byte_offset, const T value)
|
||||
{
|
||||
uint8* const ptr = ne16_ptr_le<T>(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<typename T>
|
||||
static INLINE T ne16_rbo_le(const uint16* const base, const size_t byte_offset)
|
||||
{
|
||||
uint8* const ptr = ne16_ptr_le<T>(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<typename T, bool IsWrite>
|
||||
static INLINE void ne16_rwbo_le(uint16* const base, const size_t byte_offset, T* value)
|
||||
{
|
||||
if(IsWrite)
|
||||
ne16_wbo_le<T>(base, byte_offset, *value);
|
||||
else
|
||||
*value = ne16_rbo_le<T>(base, byte_offset);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
template<typename T>
|
||||
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<typename T>
|
||||
static INLINE void ne64_wbo_be(uint64* const base, const size_t byte_offset, const T value)
|
||||
{
|
||||
uint8* const ptr = ne64_ptr_be<T>(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<typename T>
|
||||
static INLINE T ne64_rbo_be(uint64* const base, const size_t byte_offset)
|
||||
{
|
||||
uint8* const ptr = ne64_ptr_be<T>(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<typename T, bool IsWrite>
|
||||
static INLINE void ne64_rwbo_be(uint64* const base, const size_t byte_offset, T* value)
|
||||
{
|
||||
if(IsWrite)
|
||||
ne64_wbo_be<T>(base, byte_offset, *value);
|
||||
else
|
||||
*value = ne64_rbo_be<T>(base, byte_offset);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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 <vector>
|
||||
|
||||
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<uint8> 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<uint8> &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<uint8> flashdata;
|
||||
|
||||
make_flash_commit(flashdata);
|
||||
|
||||
if (flashdata.size() > 0)
|
||||
{
|
||||
callback(&flashdata[0], flashdata.size());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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<true>(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<true>(&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<true>(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<true>(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<true>(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<true>(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<true>(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);
|
||||
}
|
||||
}
|
||||
|
||||
//==========
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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<true>(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<true>(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<true>(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<true>(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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==========
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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<true>(&FastReadMap[address >> 16][address]));
|
||||
|
||||
uint16 *ptr = (uint16 *)translate_address_read(address);
|
||||
if (ptr)
|
||||
return MDFN_de16lsb<true>(ptr);
|
||||
|
||||
if (address >= 0x8000 && address <= 0xbfff)
|
||||
return (NGPGfx->read16(address));
|
||||
|
||||
if (address >= 0x4000 && address <= 0x7fff)
|
||||
{
|
||||
return (MDFN_de16lsb<true>(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<true>(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<true>(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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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
|
|
@ -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 <algorithm>
|
||||
|
||||
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();
|
||||
}
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
|
@ -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 <ctime>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef __NGP_RTC_H
|
||||
#define __NGP_RTC_H
|
||||
|
||||
namespace MDFN_IEN_NGP
|
||||
{
|
||||
|
||||
uint8 rtc_read8(uint32 address);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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<blip_good_quality, 0xFF> 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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,457 @@
|
|||
// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
|
||||
|
||||
#include "Blip_Buffer.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.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., 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;
|
||||
}
|
||||
|
|
@ -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 <limits.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// 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<int quality,int range>
|
||||
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 <assert.h>
|
||||
|
||||
template<int quality,int range>
|
||||
blip_inline void Blip_Synth<quality,range>::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<int quality,int range>
|
||||
#if BLIP_BUFFER_FAST
|
||||
blip_inline
|
||||
#endif
|
||||
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
|
||||
{
|
||||
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
|
||||
}
|
||||
|
||||
template<int quality,int range>
|
||||
#if BLIP_BUFFER_FAST
|
||||
blip_inline
|
||||
#endif
|
||||
void Blip_Synth<quality,range>::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
|
|
@ -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] );
|
||||
}
|
||||
|
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
|
@ -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;
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue