Compare commits

...

22 Commits

Author SHA1 Message Date
f53fcbfee0 MAME:MC68000 Register* 更换所有下标取值,改为直接指针运算解引用 2025-11-26 17:09:08 +08:00
79ada55c3c MAME:MC68000 Register* A 更换所有下标取值,改为直接指针运算解引用 2025-11-26 16:01:42 +08:00
7ecd7d45a0 MAME:MC68000 Table指针化 2025-11-26 15:17:24 +08:00
a3e5f75694 MAME: NEOGEO性能优化 video的sprite处理,从数组指针取下标,改为纯指针运算解引用。此外video每一帧的背景拷贝使用Buffer.BlockCopy 2025-11-20 23:17:25 +08:00
1e3cf56675 MAME:修正优化过程中NEOGEO MReadOpWord 造成的内存映射bug(rom写成ram导致读取错误) 2025-11-18 00:38:55 +08:00
7f20da42e6 Essgee:GAMEBOY DMGAudio 修改掉接口访问器设置音量的做法,避免每帧14万次的volume访问器堆栈耗费性能 2025-11-17 23:22:26 +08:00
bb32fd3736 持续优化 2025-11-17 18:34:15 +08:00
a806deed55 MAME: MV68000.MOVE命令优化 2025-11-17 18:12:22 +08:00
c1ad639f7a MAME:DSP 指针计算,避免下标再次计算指针 2025-11-17 16:28:22 +08:00
212810384e MAME:MC68000 Register[8] A、D 指针化 2025-11-17 16:27:45 +08:00
382ee2d1b9 MAME:NEOGEO/MC68000的一些减少下标地址计算,改为指针本身直接运算和解引用,以及减少某些重复操作 2025-11-17 13:34:06 +08:00
96039886f4 MAME:NEOGEO 把高频sprite频处理从优化后的指针化的unsafe数组,循环直接改为指针推进,避免重新计算地址,争取到了一些性能 2025-11-17 01:29:37 +08:00
4914db1b54 MAME:一些进一步小细节优化 2025-11-16 23:15:36 +08:00
0009a2d00e 哎,自动补全using shit 2025-11-13 16:43:59 +08:00
898353b652 MAME:ADPCMA_calc_chan内联,减少adpcm[c]寻址 | MC68000 CMPI内联ReadValueB 2025-11-13 16:33:46 +08:00
e41c910496 MAME:Sound 一些指针缓存 2025-11-13 15:16:22 +08:00
e394d38e27 Timer 优化 2025-11-13 15:15:31 +08:00
6edb3b5400 MAME:规范代码 2025-11-13 14:02:50 +08:00
f49f7fef00 MAME: List<emu_timer> 改为了等效的紧凑emu_timer数组实现 2025-11-13 14:02:26 +08:00
48c7fe00eb MAME:内联Drawgfx.common_drawgfx_m92 2025-11-12 18:53:55 +08:00
4649149103 MAME:YM2151.chan_calc 手动内联,和大量指针寻址缓存。对Cps1、M72和Mamco平台均可得到间接有效优化 2025-11-12 17:31:47 +08:00
d7322d8e91 MAME:解决NEOGEO加载BIOS时开销大的问题,核心是mame watchdog在加载bios时每帧进行数千次watchdog reset,其实每帧至多只需要一次即可得到等效效果,进行一个限制,加载BIOS时和平常游戏时性能接近 2025-11-12 16:13:37 +08:00
30 changed files with 2929 additions and 1001 deletions

View File

@ -2,7 +2,8 @@
{
public partial class CGBAudio
{
public class CGBWave : Wave, IDMGAudioChannel
//本身wave就继承了IDMGAudioChannel
public class CGBWave : Wave//, IDMGAudioChannel
{
public override void Reset()
{

View File

@ -39,16 +39,16 @@ namespace Essgee.Emulation.Audio
bool isChannelEnabled, isDacEnabled;
int lengthCounter;
public int OutputVolume { get; private set; }
//public int OutputVolume { get; private set; }
public bool IsActive { get { return lengthCounter != 0; } }
public override bool IsActive { get { return lengthCounter != 0; } }
public Noise()
{
//
}
public void Reset()
public override void Reset()
{
noiseCounter = 0;
lfsr = 0;
@ -63,7 +63,7 @@ namespace Essgee.Emulation.Audio
OutputVolume = volume;
}
public void LengthCounterClock()
public override void LengthCounterClock()
{
if (lengthCounter > 0 && lengthEnable)
{
@ -73,12 +73,12 @@ namespace Essgee.Emulation.Audio
}
}
public void SweepClock()
public override void SweepClock()
{
throw new Exception("Channel type does not support sweep");
}
public void VolumeEnvelopeClock()
public override void VolumeEnvelopeClock()
{
envelopeCounter--;
if (envelopeCounter == 0)
@ -99,7 +99,7 @@ namespace Essgee.Emulation.Audio
}
}
public void Step()
public override void Step()
{
if (!isChannelEnabled) return;
@ -132,7 +132,7 @@ namespace Essgee.Emulation.Audio
lfsr = 0x7FFF;
}
public void WritePort(byte port, byte value)
public override void WritePort(byte port, byte value)
{
switch (port)
{
@ -168,7 +168,7 @@ namespace Essgee.Emulation.Audio
}
}
public byte ReadPort(byte port)
public override byte ReadPort(byte port)
{
switch (port)
{
@ -200,12 +200,12 @@ namespace Essgee.Emulation.Audio
}
}
public void WriteWaveRam(byte offset, byte value)
public override void WriteWaveRam(byte offset, byte value)
{
throw new Exception("Channel type does have Wave RAM");
}
public byte ReadWaveRam(byte offset)
public override byte ReadWaveRam(byte offset)
{
throw new Exception("Channel type does have Wave RAM");
}

View File

@ -74,16 +74,16 @@ namespace Essgee.Emulation.Audio
bool isChannelEnabled, isDacEnabled;
int lengthCounter, dutyCounter;
public int OutputVolume { get; private set; }
//public int OutputVolume { get; private set; }
public bool IsActive { get { return lengthCounter != 0; } }
public override bool IsActive { get { return lengthCounter != 0; } }
public Square(bool hasSweep)
{
channelSupportsSweep = hasSweep;
}
public void Reset()
public override void Reset()
{
isSweepEnabled = false;
sweepCounter = sweepFreqShadow = 0;
@ -100,7 +100,7 @@ namespace Essgee.Emulation.Audio
OutputVolume = volume;
}
public void LengthCounterClock()
public override void LengthCounterClock()
{
if (lengthCounter > 0 && lengthEnable)
{
@ -110,7 +110,7 @@ namespace Essgee.Emulation.Audio
}
}
public void SweepClock()
public override void SweepClock()
{
if (!channelSupportsSweep) return;
@ -133,7 +133,7 @@ namespace Essgee.Emulation.Audio
}
}
public void VolumeEnvelopeClock()
public override void VolumeEnvelopeClock()
{
envelopeCounter--;
if (envelopeCounter == 0)
@ -154,7 +154,7 @@ namespace Essgee.Emulation.Audio
}
}
public void Step()
public override void Step()
{
if (!isChannelEnabled) return;
@ -202,7 +202,7 @@ namespace Essgee.Emulation.Audio
return newFrequency;
}
public void WritePort(byte port, byte value)
public override void WritePort(byte port, byte value)
{
switch (port)
{
@ -244,7 +244,7 @@ namespace Essgee.Emulation.Audio
}
}
public byte ReadPort(byte port)
public override byte ReadPort(byte port)
{
switch (port)
{
@ -281,12 +281,12 @@ namespace Essgee.Emulation.Audio
}
}
public void WriteWaveRam(byte offset, byte value)
public override void WriteWaveRam(byte offset, byte value)
{
throw new Exception("Channel type does have Wave RAM");
}
public byte ReadWaveRam(byte offset)
public override byte ReadWaveRam(byte offset)
{
throw new Exception("Channel type does have Wave RAM");
}

View File

@ -30,16 +30,16 @@ namespace Essgee.Emulation.Audio
bool isChannelEnabled;
int lengthCounter;
public int OutputVolume { get; private set; }
//public int OutputVolume { get; private set; }
public bool IsActive { get { return isDacEnabled; } } // TODO: correct? lengthCounter check makes Zelda Oracle games hang
public override bool IsActive { get { return isDacEnabled; } } // TODO: correct? lengthCounter check makes Zelda Oracle games hang
public Wave()
{
sampleBuffer = new byte[16];
}
public virtual void Reset()
public override void Reset()
{
for (var i = 0; i < sampleBuffer.Length; i++) sampleBuffer[i] = (byte)EmuStandInfo.Random.Next(255);
frequencyCounter = positionCounter = 0;
@ -51,7 +51,7 @@ namespace Essgee.Emulation.Audio
OutputVolume = volume;
}
public void LengthCounterClock()
public override void LengthCounterClock()
{
if (lengthCounter > 0 && lengthEnable)
{
@ -61,17 +61,17 @@ namespace Essgee.Emulation.Audio
}
}
public void SweepClock()
public override void SweepClock()
{
throw new Exception("Channel type does not support sweep");
}
public void VolumeEnvelopeClock()
public override void VolumeEnvelopeClock()
{
throw new Exception("Channel type does not support envelope");
}
public void Step()
public override void Step()
{
if (!isChannelEnabled) return;
@ -105,7 +105,7 @@ namespace Essgee.Emulation.Audio
positionCounter = 0;
}
public void WritePort(byte port, byte value)
public override void WritePort(byte port, byte value)
{
switch (port)
{
@ -137,7 +137,7 @@ namespace Essgee.Emulation.Audio
}
}
public byte ReadPort(byte port)
public override byte ReadPort(byte port)
{
switch (port)
{
@ -166,7 +166,7 @@ namespace Essgee.Emulation.Audio
// TODO: more details on behavior on access w/ channel enabled
public void WriteWaveRam(byte offset, byte value)
public override void WriteWaveRam(byte offset, byte value)
{
if (!isDacEnabled)
sampleBuffer[offset & (sampleBuffer.Length - 1)] = value;
@ -174,7 +174,7 @@ namespace Essgee.Emulation.Audio
sampleBuffer[positionCounter & (sampleBuffer.Length - 1)] = value;
}
public byte ReadWaveRam(byte offset)
public override byte ReadWaveRam(byte offset)
{
if (!isDacEnabled)
return sampleBuffer[offset & (sampleBuffer.Length - 1)];

View File

@ -1,19 +1,33 @@
namespace Essgee.Emulation.Audio
{
public interface IDMGAudioChannel
//public interface IDMGAudioChannel
// {
// int OutputVolume { get; }
// bool IsActive { get; }
// void Reset();
// void LengthCounterClock();
// void SweepClock();
// void VolumeEnvelopeClock();
// void Step();
// void WritePort(byte port, byte value);
// byte ReadPort(byte port);
// void WriteWaveRam(byte offset, byte value);
// byte ReadWaveRam(byte offset);
//}
public abstract class IDMGAudioChannel
{
int OutputVolume { get; }
bool IsActive { get; }
void Reset();
void LengthCounterClock();
void SweepClock();
void VolumeEnvelopeClock();
void Step();
void WritePort(byte port, byte value);
byte ReadPort(byte port);
void WriteWaveRam(byte offset, byte value);
byte ReadWaveRam(byte offset);
public int OutputVolume;
public abstract bool IsActive { get; }
public abstract void Reset();
public abstract void LengthCounterClock();
public abstract void SweepClock();
public abstract void VolumeEnvelopeClock();
public abstract void Step();
public abstract void WritePort(byte port, byte value);
public abstract byte ReadPort(byte port);
public abstract void WriteWaveRam(byte offset, byte value);
public abstract byte ReadWaveRam(byte offset);
}
}

View File

@ -2,8 +2,46 @@ using System;
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
//void AND0() // AND <ea>, Dn
//{
// int dstReg = (op >> 9) & 0x07;
// int size = (op >> 6) & 0x03;
// int srcMode = (op >> 3) & 0x07;
// int srcReg = op & 0x07;
// V = false;
// C = false;
// switch (size)
// {
// case 0: // Byte
// D_ptr_dstReg->s8 &= ReadValueB(srcMode, srcReg);
// pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
// N = (D_ptr_dstReg->s8 & 0x80) != 0;
// Z = (D_ptr_dstReg->s8 == 0);
// return;
// case 1: // Word
// D_ptr_dstReg->s16 &= ReadValueW(srcMode, srcReg);
// pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
// N = (D_ptr_dstReg->s16 & 0x8000) != 0;
// Z = (D_ptr_dstReg->s16 == 0);
// return;
// case 2: // Long
// D_ptr_dstReg->s32 &= ReadValueL(srcMode, srcReg);
// if (srcMode == 0 || (srcMode == 7 && srcReg == 4))
// {
// pendingCycles -= 8 + EACyclesL[srcMode, srcReg];
// }
// else
// {
// pendingCycles -= 6 + EACyclesL[srcMode, srcReg];
// }
// N = (D_ptr_dstReg->s32 & 0x80000000) != 0;
// Z = (D_ptr_dstReg->s32 == 0);
// return;
// }
//}
void AND0() // AND <ea>, Dn
{
int dstReg = (op >> 9) & 0x07;
@ -11,25 +49,25 @@ namespace cpu.m68000
int srcMode = (op >> 3) & 0x07;
int srcReg = op & 0x07;
Register* D_ptr_dstReg = D + dstReg;
V = false;
C = false;
switch (size)
{
case 0: // Byte
D[dstReg].s8 &= ReadValueB(srcMode, srcReg);
D_ptr_dstReg->s8 &= ReadValueB(srcMode, srcReg);
pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
N = (D[dstReg].s8 & 0x80) != 0;
Z = (D[dstReg].s8 == 0);
N = (D_ptr_dstReg->s8 & 0x80) != 0;
Z = (D_ptr_dstReg->s8 == 0);
return;
case 1: // Word
D[dstReg].s16 &= ReadValueW(srcMode, srcReg);
D_ptr_dstReg->s16 &= ReadValueW(srcMode, srcReg);
pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
N = (D[dstReg].s16 & 0x8000) != 0;
Z = (D[dstReg].s16 == 0);
N = (D_ptr_dstReg->s16 & 0x8000) != 0;
Z = (D_ptr_dstReg->s16 == 0);
return;
case 2: // Long
D[dstReg].s32 &= ReadValueL(srcMode, srcReg);
D_ptr_dstReg->s32 &= ReadValueL(srcMode, srcReg);
if (srcMode == 0 || (srcMode == 7 && srcReg == 4))
{
pendingCycles -= 8 + EACyclesL[srcMode, srcReg];
@ -38,13 +76,12 @@ namespace cpu.m68000
{
pendingCycles -= 6 + EACyclesL[srcMode, srcReg];
}
N = (D[dstReg].s32 & 0x80000000) != 0;
Z = (D[dstReg].s32 == 0);
N = (D_ptr_dstReg->s32 & 0x80000000) != 0;
Z = (D_ptr_dstReg->s32 == 0);
return;
}
}
void AND1() // AND Dn, <ea>
{
int srcReg = (op >> 9) & 0x07;
@ -55,12 +92,13 @@ namespace cpu.m68000
V = false;
C = false;
Register* D_ptr_srcReg = D + srcReg;
switch (size)
{
case 0: // Byte
{
sbyte dest = PeekValueB(dstMode, dstReg);
sbyte value = (sbyte)(dest & D[srcReg].s8);
sbyte value = (sbyte)(dest & D_ptr_srcReg->s8);
WriteValueB(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x80) != 0;
@ -70,7 +108,7 @@ namespace cpu.m68000
case 1: // Word
{
short dest = PeekValueW(dstMode, dstReg);
short value = (short)(dest & D[srcReg].s16);
short value = (short)(dest & D_ptr_srcReg->s16);
WriteValueW(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x8000) != 0;
@ -80,7 +118,7 @@ namespace cpu.m68000
case 2: // Long
{
int dest = PeekValueL(dstMode, dstReg);
int value = dest & D[srcReg].s32;
int value = dest & D_ptr_srcReg->s32;
WriteValueL(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesL[dstMode, dstReg];
N = (value & 0x80000000) != 0;
@ -158,12 +196,13 @@ namespace cpu.m68000
V = false;
C = false;
Register* D_ptr_srcReg = D + srcReg;
switch (size)
{
case 0: // Byte
{
sbyte dest = PeekValueB(dstMode, dstReg);
sbyte value = (sbyte)(dest ^ D[srcReg].s8);
sbyte value = (sbyte)(dest ^ D_ptr_srcReg->s8);
WriteValueB(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x80) != 0;
@ -173,7 +212,7 @@ namespace cpu.m68000
case 1: // Word
{
short dest = PeekValueW(dstMode, dstReg);
short value = (short)(dest ^ D[srcReg].s16);
short value = (short)(dest ^ D_ptr_srcReg->s16);
WriteValueW(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x8000) != 0;
@ -183,7 +222,7 @@ namespace cpu.m68000
case 2: // Long
{
int dest = PeekValueL(dstMode, dstReg);
int value = dest ^ D[srcReg].s32;
int value = dest ^ D_ptr_srcReg->s32;
WriteValueL(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesL[dstMode, dstReg];
N = (value & 0x80000000) != 0;
@ -259,22 +298,23 @@ namespace cpu.m68000
V = false;
C = false;
Register* D_ptr_dstReg = D + dstReg;
switch (size)
{
case 0: // Byte
D[dstReg].s8 |= ReadValueB(srcMode, srcReg);
D_ptr_dstReg->s8 |= ReadValueB(srcMode, srcReg);
pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
N = (D[dstReg].s8 & 0x80) != 0;
Z = (D[dstReg].s8 == 0);
N = (D_ptr_dstReg->s8 & 0x80) != 0;
Z = (D_ptr_dstReg->s8 == 0);
return;
case 1: // Word
D[dstReg].s16 |= ReadValueW(srcMode, srcReg);
D_ptr_dstReg->s16 |= ReadValueW(srcMode, srcReg);
pendingCycles -= (srcMode == 0) ? 4 : 4 + EACyclesBW[srcMode, srcReg];
N = (D[dstReg].s16 & 0x8000) != 0;
Z = (D[dstReg].s16 == 0);
N = (D_ptr_dstReg->s16 & 0x8000) != 0;
Z = (D_ptr_dstReg->s16 == 0);
return;
case 2: // Long
D[dstReg].s32 |= ReadValueL(srcMode, srcReg);
D_ptr_dstReg->s32 |= ReadValueL(srcMode, srcReg);
if (srcMode == 0 || (srcMode == 7 && srcReg == 4))
{
pendingCycles -= 8 + EACyclesL[srcMode, srcReg];
@ -283,8 +323,8 @@ namespace cpu.m68000
{
pendingCycles -= 6 + EACyclesL[srcMode, srcReg];
}
N = (D[dstReg].s32 & 0x80000000) != 0;
Z = (D[dstReg].s32 == 0);
N = (D_ptr_dstReg->s32 & 0x80000000) != 0;
Z = (D_ptr_dstReg->s32 == 0);
return;
}
}
@ -300,12 +340,13 @@ namespace cpu.m68000
V = false;
C = false;
Register* D_ptr_srcReg = D + srcReg;
switch (size)
{
case 0: // Byte
{
sbyte dest = PeekValueB(dstMode, dstReg);
sbyte value = (sbyte)(dest | D[srcReg].s8);
sbyte value = (sbyte)(dest | D_ptr_srcReg->s8);
WriteValueB(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x80) != 0;
@ -315,7 +356,7 @@ namespace cpu.m68000
case 1: // Word
{
short dest = PeekValueW(dstMode, dstReg);
short value = (short)(dest | D[srcReg].s16);
short value = (short)(dest | D_ptr_srcReg->s16);
WriteValueW(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 4 : 8 + EACyclesBW[dstMode, dstReg];
N = (value & 0x8000) != 0;
@ -325,7 +366,7 @@ namespace cpu.m68000
case 2: // Long
{
int dest = PeekValueL(dstMode, dstReg);
int value = dest | D[srcReg].s32;
int value = dest | D_ptr_srcReg->s32;
WriteValueL(dstMode, dstReg, value);
pendingCycles -= (dstMode == 0) ? 8 : 12 + EACyclesL[dstMode, dstReg];
N = (value & 0x80000000) != 0;
@ -442,42 +483,43 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u8 & 0x80) != 0;
D[reg].u8 <<= 1;
C = X = (D_ptr_reg->u8 & 0x80) != 0;
D_ptr_reg->u8 <<= 1;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u16 & 0x8000) != 0;
D[reg].u16 <<= 1;
C = X = (D_ptr_reg->u16 & 0x8000) != 0;
D_ptr_reg->u16 <<= 1;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u32 & 0x80000000) != 0;
D[reg].u32 <<= 1;
C = X = (D_ptr_reg->u32 & 0x80000000) != 0;
D_ptr_reg->u32 <<= 1;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -515,42 +557,43 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u8 & 1) != 0;
D[reg].u8 >>= 1;
C = X = (D_ptr_reg->u8 & 1) != 0;
D_ptr_reg->u8 >>= 1;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u16 & 1) != 0;
D[reg].u16 >>= 1;
C = X = (D_ptr_reg->u16 & 1) != 0;
D_ptr_reg->u16 >>= 1;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = X = (D[reg].u32 & 1) != 0;
D[reg].u32 >>= 1;
C = X = (D_ptr_reg->u32 & 1) != 0;
D_ptr_reg->u32 >>= 1;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -589,48 +632,49 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s8 < 0;
C = X = (D[reg].u8 & 0x80) != 0;
D[reg].s8 <<= 1;
V |= (D[reg].s8 < 0) != msb;
bool msb = D_ptr_reg->s8 < 0;
C = X = (D_ptr_reg->u8 & 0x80) != 0;
D_ptr_reg->s8 <<= 1;
V |= (D_ptr_reg->s8 < 0) != msb;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s16 < 0;
C = X = (D[reg].u16 & 0x8000) != 0;
D[reg].s16 <<= 1;
V |= (D[reg].s16 < 0) != msb;
bool msb = D_ptr_reg->s16 < 0;
C = X = (D_ptr_reg->u16 & 0x8000) != 0;
D_ptr_reg->s16 <<= 1;
V |= (D_ptr_reg->s16 < 0) != msb;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s32 < 0;
C = X = (D[reg].u32 & 0x80000000) != 0;
D[reg].s32 <<= 1;
V |= (D[reg].s32 < 0) != msb;
bool msb = D_ptr_reg->s32 < 0;
C = X = (D_ptr_reg->u32 & 0x80000000) != 0;
D_ptr_reg->s32 <<= 1;
V |= (D_ptr_reg->s32 < 0) != msb;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -669,48 +713,49 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s8 < 0;
C = X = (D[reg].u8 & 1) != 0;
D[reg].s8 >>= 1;
V |= (D[reg].s8 < 0) != msb;
bool msb = D_ptr_reg->s8 < 0;
C = X = (D_ptr_reg->u8 & 1) != 0;
D_ptr_reg->s8 >>= 1;
V |= (D_ptr_reg->s8 < 0) != msb;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s16 < 0;
C = X = (D[reg].u16 & 1) != 0;
D[reg].s16 >>= 1;
V |= (D[reg].s16 < 0) != msb;
bool msb = D_ptr_reg->s16 < 0;
C = X = (D_ptr_reg->u16 & 1) != 0;
D_ptr_reg->s16 >>= 1;
V |= (D_ptr_reg->s16 < 0) != msb;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
bool msb = D[reg].s32 < 0;
C = X = (D[reg].u32 & 1) != 0;
D[reg].s32 >>= 1;
V |= (D[reg].s32 < 0) != msb;
bool msb = D_ptr_reg->s32 < 0;
C = X = (D_ptr_reg->u32 & 1) != 0;
D_ptr_reg->s32 >>= 1;
V |= (D_ptr_reg->s32 < 0) != msb;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -752,42 +797,43 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 0x80) != 0;
D[reg].u8 = (byte)((D[reg].u8 << 1) | (D[reg].u8 >> 7));
C = (D_ptr_reg->u8 & 0x80) != 0;
D_ptr_reg->u8 = (byte)((D_ptr_reg->u8 << 1) | (D_ptr_reg->u8 >> 7));
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 0x8000) != 0;
D[reg].u16 = (ushort)((D[reg].u16 << 1) | (D[reg].u16 >> 15));
C = (D_ptr_reg->u16 & 0x8000) != 0;
D_ptr_reg->u16 = (ushort)((D_ptr_reg->u16 << 1) | (D_ptr_reg->u16 >> 15));
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].u32 & 0x80000000) != 0;
D[reg].u32 = ((D[reg].u32 << 1) | (D[reg].u32 >> 31));
C = (D_ptr_reg->u32 & 0x80000000) != 0;
D_ptr_reg->u32 = ((D_ptr_reg->u32 << 1) | (D_ptr_reg->u32 >> 31));
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -825,42 +871,43 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
V = false;
C = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 1) != 0;
D[reg].u8 = (byte)((D[reg].u8 >> 1) | (D[reg].u8 << 7));
C = (D_ptr_reg->u8 & 1) != 0;
D_ptr_reg->u8 = (byte)((D_ptr_reg->u8 >> 1) | (D_ptr_reg->u8 << 7));
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].u8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->u8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 1) != 0;
D[reg].u16 = (ushort)((D[reg].u16 >> 1) | (D[reg].u16 << 15));
C = (D_ptr_reg->u16 & 1) != 0;
D_ptr_reg->u16 = (ushort)((D_ptr_reg->u16 >> 1) | (D_ptr_reg->u16 << 15));
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].u16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->u16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].u32 & 1) != 0;
D[reg].u32 = ((D[reg].u32 >> 1) | (D[reg].u32 << 31));
C = (D_ptr_reg->u32 & 1) != 0;
D_ptr_reg->u32 = ((D_ptr_reg->u32 >> 1) | (D_ptr_reg->u32 << 31));
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -898,45 +945,46 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
C = X;
V = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 0x80) != 0;
D[reg].u8 = (byte)((D[reg].u8 << 1) | (X ? 1 : 0));
C = (D_ptr_reg->u8 & 0x80) != 0;
D_ptr_reg->u8 = (byte)((D_ptr_reg->u8 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].s8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->s8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 0x8000) != 0;
D[reg].u16 = (ushort)((D[reg].u16 << 1) | (X ? 1 : 0));
C = (D_ptr_reg->u16 & 0x8000) != 0;
D_ptr_reg->u16 = (ushort)((D_ptr_reg->u16 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].s16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->s16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].s32 & 0x80000000) != 0;
D[reg].s32 = ((D[reg].s32 << 1) | (X ? 1 : 0));
C = (D_ptr_reg->s32 & 0x80000000) != 0;
D_ptr_reg->s32 = ((D_ptr_reg->s32 << 1) | (X ? 1 : 0));
X = C;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].s32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->s32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -977,45 +1025,46 @@ namespace cpu.m68000
int m = (op >> 5) & 1;
int reg = op & 7;
Register* D_ptr_rot = D + rot;
if (m == 0 && rot == 0) rot = 8;
else if (m == 1) rot = D[rot].s32 & 63;
else if (m == 1) rot = D_ptr_rot->s32 & 63;
C = X;
V = false;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // byte
for (int i = 0; i < rot; i++)
{
C = (D[reg].u8 & 1) != 0;
D[reg].u8 = (byte)((D[reg].u8 >> 1) | (X ? 0x80 : 0));
C = (D_ptr_reg->u8 & 1) != 0;
D_ptr_reg->u8 = (byte)((D_ptr_reg->u8 >> 1) | (X ? 0x80 : 0));
X = C;
}
N = (D[reg].s8 & 0x80) != 0;
Z = D[reg].s8 == 0;
N = (D_ptr_reg->s8 & 0x80) != 0;
Z = D_ptr_reg->s8 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 1: // word
for (int i = 0; i < rot; i++)
{
C = (D[reg].u16 & 1) != 0;
D[reg].u16 = (ushort)((D[reg].u16 >> 1) | (X ? 0x8000 : 0));
C = (D_ptr_reg->u16 & 1) != 0;
D_ptr_reg->u16 = (ushort)((D_ptr_reg->u16 >> 1) | (X ? 0x8000 : 0));
X = C;
}
N = (D[reg].s16 & 0x8000) != 0;
Z = D[reg].s16 == 0;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = D_ptr_reg->s16 == 0;
pendingCycles -= 6 + (rot * 2);
return;
case 2: // long
for (int i = 0; i < rot; i++)
{
C = (D[reg].s32 & 1) != 0;
D[reg].u32 = ((D[reg].u32 >> 1) | (X ? 0x80000000 : 0));
C = (D_ptr_reg->s32 & 1) != 0;
D_ptr_reg->u32 = ((D_ptr_reg->u32 >> 1) | (X ? 0x80000000 : 0));
X = C;
}
N = (D[reg].s32 & 0x80000000) != 0;
Z = D[reg].s32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = D_ptr_reg->s32 == 0;
pendingCycles -= 8 + (rot * 2);
return;
}
@ -1051,10 +1100,11 @@ namespace cpu.m68000
void SWAP()
{
int reg = op & 7;
D[reg].u32 = (D[reg].u32 << 16) | (D[reg].u32 >> 16);
Register* D_ptr_reg = D + reg;
D_ptr_reg->u32 = (D_ptr_reg->u32 << 16) | (D_ptr_reg->u32 >> 16);
V = C = false;
Z = D[reg].u32 == 0;
N = (D[reg].s32 & 0x80000000) != 0;
Z = D_ptr_reg->u32 == 0;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
pendingCycles -= 4;
}

View File

@ -3,7 +3,7 @@ using System.Text;
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
void MOVE()
{
@ -17,22 +17,38 @@ namespace cpu.m68000
switch (size)
{
case 1: // Byte
{
value = ReadValueB(srcMode, srcReg);
WriteValueB(dstMode, dstReg, (sbyte)value);
pendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
//pendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
int i = srcMode + (srcMode == 7 ? srcReg : 0);
int j = srcMode + dstMode + (dstMode == 7 ? dstReg : 0);
pendingCycles -= *(MoveCyclesBW + (i * MoveCyclesBW_Columns) + j);
N = (value & 0x80) != 0;
}
break;
case 3: // Word
{
value = ReadValueW(srcMode, srcReg);
WriteValueW(dstMode, dstReg, (short)value);
pendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
//pendingCycles -= MoveCyclesBW[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
int i = srcMode + (srcMode == 7 ? srcReg : 0);
int j = srcMode + dstMode + (dstMode == 7 ? dstReg : 0);
pendingCycles -= *(MoveCyclesBW + (i * MoveCyclesBW_Columns) + j);
N = (value & 0x8000) != 0;
break;
}
case 2: // Long
{
value = ReadValueL(srcMode, srcReg);
WriteValueL(dstMode, dstReg, value);
pendingCycles -= MoveCyclesL[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
//pendingCycles -= MoveCyclesL[srcMode + (srcMode == 7 ? srcReg : 0), dstMode + (dstMode == 7 ? dstReg : 0)];
int i = srcMode + (srcMode == 7 ? srcReg : 0);
int j = dstMode + (dstMode == 7 ? dstReg : 0);
pendingCycles -= *(MoveCyclesL + (i * MoveCyclesL_Columns) + j);
N = (value & 0x80000000) != 0;
}
break;
}
@ -48,10 +64,10 @@ namespace cpu.m68000
int dstReg = ((op >> 9) & 0x07);
int srcMode = ((op >> 3) & 0x07);
int srcReg = (op & 0x07);
Register* A_dstReg = A + dstReg;
if (size == 3) // Word
{
A[dstReg].s32 = ReadValueW(srcMode, srcReg);
A_dstReg->s32 = ReadValueW(srcMode, srcReg);
switch (srcMode)
{
case 0: pendingCycles -= 4; break;
@ -76,7 +92,7 @@ namespace cpu.m68000
}
else
{ // Long
A[dstReg].s32 = ReadValueL(srcMode, srcReg);
A_dstReg->s32 = ReadValueL(srcMode, srcReg);
switch (srcMode)
{
case 0: pendingCycles -= 4; break;
@ -108,26 +124,28 @@ namespace cpu.m68000
int dir = ((op >> 7) & 0x01);
int size = ((op >> 6) & 0x01);
int aReg = (op & 0x07);
Register* A_ptr_aReg = A + aReg;
Register* D_ptr_dReg = D + dReg;
if (dir == 0 && size == 0)
{
int ea;
ea = A[aReg].s32 + ReadOpWord(PC); PC += 2;
D[dReg].u32 = (D[dReg].u32 & 0xffff0000) | (ushort)(((byte)ReadByte(ea) << 8) + (byte)ReadByte(ea + 2));
ea = A_ptr_aReg->s32 + ReadOpWord(PC); PC += 2;
D_ptr_dReg->u32 = (D_ptr_dReg->u32 & 0xffff0000) | (ushort)(((byte)ReadByte(ea) << 8) + (byte)ReadByte(ea + 2));
pendingCycles -= 16;
}
else if (dir == 0 && size == 1)
{
int ea;
ea = A[aReg].s32 + ReadOpWord(PC); PC += 2;
D[dReg].u32 = (uint)(((byte)ReadByte(ea) << 24) + ((byte)ReadByte(ea + 2) << 16) + ((byte)ReadByte(ea + 4) << 8) + (byte)ReadByte(ea + 6));
ea = A_ptr_aReg->s32 + ReadOpWord(PC); PC += 2;
D_ptr_dReg->u32 = (uint)(((byte)ReadByte(ea) << 24) + ((byte)ReadByte(ea + 2) << 16) + ((byte)ReadByte(ea + 4) << 8) + (byte)ReadByte(ea + 6));
pendingCycles -= 24;
}
else if (dir == 1 && size == 0)
{
uint src;
int ea;
ea = A[aReg].s32 + ReadOpWord(PC); PC += 2;
src = D[dReg].u32;
ea = A_ptr_aReg->s32 + ReadOpWord(PC); PC += 2;
src = D_ptr_dReg->u32;
WriteByte(ea, (sbyte)((src >> 8) & 0xff));
WriteByte(ea + 2, (sbyte)(src & 0xff));
pendingCycles -= 16;
@ -136,8 +154,8 @@ namespace cpu.m68000
{
uint src;
int ea;
ea = A[aReg].s32 + ReadOpWord(PC); PC += 2;
src = D[dReg].u32;
ea = A_ptr_aReg->s32 + ReadOpWord(PC); PC += 2;
src = D_ptr_dReg->u32;
WriteByte(ea, (sbyte)((src >> 24) & 0xff));
WriteByte(ea + 2, (sbyte)((src >> 16) & 0xff));
WriteByte(ea + 4, (sbyte)((src >> 8) & 0xff));
@ -224,6 +242,7 @@ namespace cpu.m68000
int address = ReadAddress(dstMode, dstReg);
int regCount = 0;
Register* A_dstReg = A + dstReg;
if (size == 0)
{
// word-assign
@ -234,7 +253,7 @@ namespace cpu.m68000
if ((registers & 1) == 1)
{
address -= 2;
WriteWord(address, A[i].s16);
WriteWord(address, (A + i)->s16);
regCount++;
}
registers >>= 1;
@ -244,12 +263,12 @@ namespace cpu.m68000
if ((registers & 1) == 1)
{
address -= 2;
WriteWord(address, D[i].s16);
WriteWord(address, (D + i)->s16);
regCount++;
}
registers >>= 1;
}
A[dstReg].s32 = address;
A_dstReg->s32 = address;
}
else
{ // increment address
@ -257,7 +276,7 @@ namespace cpu.m68000
{
if ((registers & 1) == 1)
{
WriteWord(address, D[i].s16);
WriteWord(address, (D + i)->s16);
address += 2;
regCount++;
}
@ -267,7 +286,7 @@ namespace cpu.m68000
{
if ((registers & 1) == 1)
{
WriteWord(address, A[i].s16);
WriteWord(address, (A + i)->s16);
address += 2;
regCount++;
}
@ -286,7 +305,7 @@ namespace cpu.m68000
if ((registers & 1) == 1)
{
address -= 4;
WriteLong(address, A[i].s32);
WriteLong(address, (A + i)->s32);
regCount++;
}
registers >>= 1;
@ -296,12 +315,12 @@ namespace cpu.m68000
if ((registers & 1) == 1)
{
address -= 4;
WriteLong(address, D[i].s32);
WriteLong(address, (D + i)->s32);
regCount++;
}
registers >>= 1;
}
A[dstReg].s32 = address;
A_dstReg->s32 = address;
}
else
{ // increment address
@ -309,7 +328,7 @@ namespace cpu.m68000
{
if ((registers & 1) == 1)
{
WriteLong(address, D[i].s32);
WriteLong(address, (D + i)->s32);
address += 4;
regCount++;
}
@ -319,7 +338,7 @@ namespace cpu.m68000
{
if ((registers & 1) == 1)
{
WriteLong(address, A[i].s32);
WriteLong(address, (A + i)->s32);
address += 4;
regCount++;
}
@ -367,11 +386,11 @@ namespace cpu.m68000
{
if (srcMode == 7 && (srcReg == 2 || srcReg == 3))
{
D[i].s32 = ReadPcrelWord(address);
(D + i)->s32 = ReadPcrelWord(address);
}
else
{
D[i].s32 = ReadWord(address);
(D + i)->s32 = ReadWord(address);
}
address += 2;
regCount++;
@ -384,11 +403,11 @@ namespace cpu.m68000
{
if (srcMode == 7 && (srcReg == 2 || srcReg == 3))
{
A[i].s32 = ReadPcrelWord(address);
(A + i)->s32 = ReadPcrelWord(address);
}
else
{
A[i].s32 = ReadWord(address);
(A + i)->s32 = ReadWord(address);
}
address += 2;
regCount++;
@ -397,7 +416,7 @@ namespace cpu.m68000
}
pendingCycles -= regCount * 4;
if (srcMode == 3)
A[srcReg].s32 = address;
(A + srcReg)->s32 = address;
}
else
{
@ -408,11 +427,11 @@ namespace cpu.m68000
{
if (srcMode == 7 && (srcReg == 2 || srcReg == 3))
{
D[i].s32 = ReadPcrelLong(address);
(D + i)->s32 = ReadPcrelLong(address);
}
else
{
D[i].s32 = ReadLong(address);
(D + i)->s32 = ReadLong(address);
}
address += 4;
regCount++;
@ -425,11 +444,11 @@ namespace cpu.m68000
{
if (srcMode == 7 && (srcReg == 2 || srcReg == 3))
{
A[i].s32 = ReadPcrelLong(address);
(A + i)->s32 = ReadPcrelLong(address);
}
else
{
A[i].s32 = ReadLong(address);
(A + i)->s32 = ReadLong(address);
}
address += 4;
regCount++;
@ -438,7 +457,7 @@ namespace cpu.m68000
}
pendingCycles -= regCount * 8;
if (srcMode == 3)
A[srcReg].s32 = address;
(A + srcReg)->s32 = address;
}
switch (srcMode)
@ -466,7 +485,7 @@ namespace cpu.m68000
int sReg = (op >> 0) & 7;
int dReg = (op >> 9) & 7;
A[dReg].u32 = (uint)ReadAddress(mode, sReg);
(A + dReg)->u32 = (uint)ReadAddress(mode, sReg);
switch (mode)
{
case 2: pendingCycles -= 4; break;
@ -509,18 +528,18 @@ namespace cpu.m68000
{
int size = (op >> 6) & 1;
int reg = op & 7;
Register* D_ptr_reg = D + reg;
switch (size)
{
case 0: // ext.w
D[reg].s16 = D[reg].s8;
N = (D[reg].s16 & 0x8000) != 0;
Z = (D[reg].s16 == 0);
D_ptr_reg->s16 = D_ptr_reg->s8;
N = (D_ptr_reg->s16 & 0x8000) != 0;
Z = (D_ptr_reg->s16 == 0);
break;
case 1: // ext.l
D[reg].s32 = D[reg].s16;
N = (D[reg].s32 & 0x80000000) != 0;
Z = (D[reg].s32 == 0);
D_ptr_reg->s32 = D_ptr_reg->s16;
N = (D_ptr_reg->s32 & 0x80000000) != 0;
Z = (D_ptr_reg->s32 == 0);
break;
}
@ -530,14 +549,41 @@ namespace cpu.m68000
}
//void PEA()
//{
// int mode = (op >> 3) & 7;
// int reg = (op >> 0) & 7;
// int ea = ReadAddress(mode, reg);
// ptrA7->s32 -= 4;
// WriteLong(ptrA7->s32, ea);
// switch (mode)
// {
// case 2: pendingCycles -= 12; break;
// case 5: pendingCycles -= 16; break;
// case 6: pendingCycles -= 20; break;
// case 7:
// switch (reg)
// {
// case 0: pendingCycles -= 16; break;
// case 1: pendingCycles -= 20; break;
// case 2: pendingCycles -= 16; break;
// case 3: pendingCycles -= 20; break;
// }
// break;
// }
//}
void PEA()
{
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int ea = ReadAddress(mode, reg);
A[7].s32 -= 4;
WriteLong(A[7].s32, ea);
Register* ptrA7 = &A[7];
ptrA7->s32 -= 4;
WriteLong(ptrA7->s32, ea);
switch (mode)
{

View File

@ -2,7 +2,7 @@ using System;
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
void ADD0()
{
@ -11,44 +11,45 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* D_ptr_Dreg = D + Dreg;
switch (size)
{
case 0: // byte
{
sbyte value = ReadValueB(mode, reg);
int result = D[Dreg].s8 + value;
int uresult = D[Dreg].u8 + (byte)value;
int result = D_ptr_Dreg->s8 + value;
int uresult = D_ptr_Dreg->u8 + (byte)value;
X = C = (uresult & 0x100) != 0;
V = result > sbyte.MaxValue || result < sbyte.MinValue;
N = (result & 0x80) != 0;
Z = (result & 0xff) == 0;
D[Dreg].s8 = (sbyte)result;
D_ptr_Dreg->s8 = (sbyte)result;
pendingCycles -= 4 + EACyclesBW[mode, reg];
return;
}
case 1: // word
{
short value = ReadValueW(mode, reg);
int result = D[Dreg].s16 + value;
int uresult = D[Dreg].u16 + (ushort)value;
int result = D_ptr_Dreg->s16 + value;
int uresult = D_ptr_Dreg->u16 + (ushort)value;
X = C = (uresult & 0x10000) != 0;
V = result > short.MaxValue || result < short.MinValue;
N = (result & 0x8000) != 0;
Z = (result & 0xffff) == 0;
D[Dreg].s16 = (short)result;
D_ptr_Dreg->s16 = (short)result;
pendingCycles -= 4 + EACyclesBW[mode, reg];
return;
}
case 2: // long
{
int value = ReadValueL(mode, reg);
long result = (long)D[Dreg].s32 + (long)value;
ulong uresult = (ulong)D[Dreg].u32 + ((ulong)(uint)value);
long result = (long)D_ptr_Dreg->s32 + (long)value;
ulong uresult = (ulong)D_ptr_Dreg->u32 + ((ulong)(uint)value);
X = C = (uresult & 0x100000000) != 0;
V = result > int.MaxValue || result < int.MinValue;
N = (result & 0x80000000) != 0;
Z = (uint)result == 0;
D[Dreg].s32 = (int)result;
D_ptr_Dreg->s32 = (int)result;
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
{
pendingCycles -= 8 + EACyclesL[mode, reg];
@ -69,13 +70,14 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* D_ptr_Dreg = D + Dreg;
switch (size)
{
case 0: // byte
{
sbyte value = PeekValueB(mode, reg);
int result = value + D[Dreg].s8;
int uresult = (byte)value + D[Dreg].u8;
int result = value + D_ptr_Dreg->s8;
int uresult = (byte)value + D_ptr_Dreg->u8;
X = C = (uresult & 0x100) != 0;
V = result > sbyte.MaxValue || result < sbyte.MinValue;
N = (result & 0x80) != 0;
@ -87,8 +89,8 @@ namespace cpu.m68000
case 1: // word
{
short value = PeekValueW(mode, reg);
int result = value + D[Dreg].s16;
int uresult = (ushort)value + D[Dreg].u16;
int result = value + D_ptr_Dreg->s16;
int uresult = (ushort)value + D_ptr_Dreg->u16;
X = C = (uresult & 0x10000) != 0;
V = result > short.MaxValue || result < short.MinValue;
N = (result & 0x8000) != 0;
@ -100,8 +102,8 @@ namespace cpu.m68000
case 2: // long
{
int value = PeekValueL(mode, reg);
long result = (long)value + (long)D[Dreg].s32;
ulong uresult = ((ulong)(uint)value) + (ulong)D[Dreg].u32;
long result = (long)value + (long)D_ptr_Dreg->s32;
ulong uresult = ((ulong)(uint)value) + (ulong)D_ptr_Dreg->u32;
X = C = (uresult & 0x100000000) != 0;
V = result > int.MaxValue || result < int.MinValue;
N = (result & 0x80000000) != 0;
@ -253,16 +255,17 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* A_ptr_aReg = A + aReg;
if (size == 0) // word
{
int value = ReadValueW(mode, reg);
A[aReg].s32 += value;
A_ptr_aReg->s32 += value;
pendingCycles -= 8 + EACyclesBW[mode, reg];
}
else
{ // long
int value = ReadValueL(mode, reg);
A[aReg].s32 += value;
A_ptr_aReg->s32 += value;
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
pendingCycles -= 8 + EACyclesL[mode, reg];
else
@ -278,44 +281,45 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* D_ptr_dReg = D + dReg;
switch (size)
{
case 0: // byte
{
sbyte a = D[dReg].s8;
sbyte a = D_ptr_dReg->s8;
sbyte b = ReadValueB(mode, reg);
int result = a - b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > sbyte.MaxValue || result < sbyte.MinValue;
N = (result & 0x80) != 0;
Z = result == 0;
D[dReg].s8 = (sbyte)result;
D_ptr_dReg->s8 = (sbyte)result;
pendingCycles -= 4 + EACyclesBW[mode, reg];
return;
}
case 1: // word
{
short a = D[dReg].s16;
short a = D_ptr_dReg->s16;
short b = ReadValueW(mode, reg);
int result = a - b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > short.MaxValue || result < short.MinValue;
N = (result & 0x8000) != 0;
Z = result == 0;
D[dReg].s16 = (short)result;
D_ptr_dReg->s16 = (short)result;
pendingCycles -= 4 + EACyclesBW[mode, reg];
return;
}
case 2: // long
{
int a = D[dReg].s32;
int a = D_ptr_dReg->s32;
int b = ReadValueL(mode, reg);
long result = (long)a - (long)b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > int.MaxValue || result < int.MinValue;
N = (result & 0x80000000) != 0;
Z = result == 0;
D[dReg].s32 = (int)result;
D_ptr_dReg->s32 = (int)result;
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
{
pendingCycles -= 8 + EACyclesL[mode, reg];
@ -336,12 +340,13 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* D_ptr_dReg = D + dReg;
switch (size)
{
case 0: // byte
{
sbyte a = PeekValueB(mode, reg);
sbyte b = D[dReg].s8;
sbyte b = D_ptr_dReg->s8;
int result = a - b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > sbyte.MaxValue || result < sbyte.MinValue;
@ -354,7 +359,7 @@ namespace cpu.m68000
case 1: // word
{
short a = PeekValueW(mode, reg);
short b = D[dReg].s16;
short b = D_ptr_dReg->s16;
int result = a - b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > short.MaxValue || result < short.MinValue;
@ -367,7 +372,7 @@ namespace cpu.m68000
case 2: // long
{
int a = PeekValueL(mode, reg);
int b = D[dReg].s32;
int b = D_ptr_dReg->s32;
long result = (long)a - (long)b;
X = C = ((a < b) ^ ((a ^ b) >= 0) == false);
V = result > int.MaxValue || result < int.MinValue;
@ -514,16 +519,17 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* A_ptr_aReg = A + aReg;
if (size == 0) // word
{
int value = ReadValueW(mode, reg);
A[aReg].s32 -= value;
A_ptr_aReg->s32 -= value;
pendingCycles -= 8 + EACyclesBW[mode, reg];
}
else
{ // long
int value = ReadValueL(mode, reg);
A[aReg].s32 -= value;
A_ptr_aReg->s32 -= value;
if (mode == 0 || mode == 1 || (mode == 7 && reg == 4))
pendingCycles -= 8 + EACyclesL[mode, reg];
else
@ -667,7 +673,7 @@ namespace cpu.m68000
int boundMode = (op >> 3) & 0x07;
int boundReg = op & 0x07;
short src, bound;
src = D[dreg].s16;
src = (D + dreg)->s16;
bound = ReadValueW(boundMode, boundReg);
Z = (src == 0);
V = false;
@ -744,8 +750,9 @@ namespace cpu.m68000
{
int dstReg = (op >> 9) & 0x07;
int srcReg = op & 0x07;
uint dst = D[dstReg].u32;
uint src = D[srcReg].u32;
Register* D_ptr_dstReg = D + dstReg;
uint dst = D_ptr_dstReg->u32;
uint src = (D + srcReg)->u32;
uint res;
res = (uint)((dst & 0x0f) - (src & 0x0f) - (X ? 1 : 0));
V = false;
@ -766,7 +773,7 @@ namespace cpu.m68000
}
res = res & 0xff;
Z &= (res == 0);
D[dstReg].u32 = (D[dstReg].u32 & 0xffffff00) | res;
D_ptr_dstReg->u32 = (D_ptr_dstReg->u32 & 0xffffff00) | res;
pendingCycles -= 6;
}
@ -775,25 +782,27 @@ namespace cpu.m68000
{
int dstReg = (op >> 9) & 0x07;
int srcReg = op & 0x07;
Register* A_srcReg = A + srcReg;
Register* A_dstReg = A + dstReg;
uint src, dst, res;
if (srcReg == 7)
{
A[srcReg].u32 -= 2;
A_srcReg->u32 -= 2;
}
else
{
A[srcReg].u32--;
A_srcReg->u32--;
}
if (dstReg == 7)
{
A[dstReg].u32 -= 2;
A_dstReg->u32 -= 2;
}
else
{
A[dstReg].u32--;
A_dstReg->u32--;
}
src = (uint)ReadByte(A[srcReg].s32);
dst = (uint)ReadByte(A[dstReg].s32);
src = (uint)ReadByte(A_srcReg->s32);
dst = (uint)ReadByte(A_dstReg->s32);
res = (uint)((dst & 0x0f) - (src & 0x0f) - (X ? 1 : 0));
V = false;
if (res > 9)
@ -813,7 +822,7 @@ namespace cpu.m68000
}
res = res & 0xff;
Z &= (res == 0);
WriteByte(A[dstReg].s32, (sbyte)res);
WriteByte(A_dstReg->s32, (sbyte)res);
pendingCycles -= 18;
}
@ -823,8 +832,10 @@ namespace cpu.m68000
int dstReg = (op >> 9) & 0x07;
int srcReg = op & 0x07;
uint src, dst, res;
src = D[srcReg].u32;
dst = D[dstReg].u32;
Register* D_ptr_srcReg = D + srcReg;
Register* D_ptr_dstReg = D + dstReg;
src = D_ptr_srcReg->u32;
dst = D_ptr_dstReg->u32;
res = (uint)((src & 0x0f) + (dst & 0x0f) + (X ? 1 : 0));
V = (((~res) & 0x80) != 0);
if (res > 9)
@ -841,7 +852,7 @@ namespace cpu.m68000
N = ((res & 0x80) != 0);
res = res & 0xff;
Z &= (res == 0);
D[dstReg].u32 = (((D[dstReg].u32) & 0xffffff00) | res);
D_ptr_dstReg->u32 = (((D_ptr_dstReg->u32) & 0xffffff00) | res);
pendingCycles -= 6;
}
@ -850,25 +861,27 @@ namespace cpu.m68000
{
int dstReg = (op >> 9) & 0x07;
int srcReg = op & 0x07;
Register* A_srcReg = A + srcReg;
Register* A_dstReg = A + dstReg;
uint src, dst, res;
if (srcReg == 7)
{
A[srcReg].u32 -= 2;
A_srcReg->u32 -= 2;
}
else
{
A[srcReg].u32--;
A_srcReg->u32--;
}
if (dstReg == 7)
{
A[dstReg].u32 -= 2;
A_dstReg->u32 -= 2;
}
else
{
A[dstReg].u32--;
A_dstReg->u32--;
}
src = (uint)ReadByte(A[srcReg].s32);
dst = (uint)ReadByte(A[dstReg].s32);
src = (uint)ReadByte(A_srcReg->s32);
dst = (uint)ReadByte(A_dstReg->s32);
res = (uint)((src & 0x0f) + (dst & 0x0f) + (X ? 1 : 0));
V = (((~res) & 0x80) != 0);
if (res > 9)
@ -885,7 +898,7 @@ namespace cpu.m68000
N = ((res & 0x80) != 0);
res = res & 0xff;
Z &= (res == 0);
WriteByte(A[dstReg].s32, (sbyte)res);
WriteByte(A_dstReg->s32, (sbyte)res);
pendingCycles -= 18;
}
@ -894,10 +907,12 @@ namespace cpu.m68000
{
int reg_a = (op >> 9) & 0x07;
int reg_b = op & 0x07;
Register* D_ptr_reg_a = D + reg_a;
Register* D_ptr_reg_b = D + reg_b;
uint tmp;
tmp = D[reg_a].u32;
D[reg_a].u32 = D[reg_b].u32;
D[reg_b].u32 = tmp;
tmp = D_ptr_reg_a->u32;
D_ptr_reg_a->u32 = D_ptr_reg_b->u32;
D_ptr_reg_b->u32 = tmp;
pendingCycles -= 6;
}
@ -907,9 +922,11 @@ namespace cpu.m68000
int reg_a = (op >> 9) & 0x07;
int reg_b = op & 0x07;
uint tmp;
tmp = A[reg_a].u32;
A[reg_a].u32 = A[reg_b].u32;
A[reg_b].u32 = tmp;
Register* A_ptr_reg_a = A + reg_a;
Register* A_ptr_reg_b = A + reg_b;
tmp = A_ptr_reg_a->u32;
A_ptr_reg_a->u32 = A_ptr_reg_b->u32;
A_ptr_reg_b->u32 = tmp;
pendingCycles -= 6;
}
@ -918,10 +935,12 @@ namespace cpu.m68000
{
int reg_a = (op >> 9) & 0x07;
int reg_b = op & 0x07;
Register* A_ptr_reg_b = A + reg_b;
Register* D_ptr_reg_a = D + reg_a;
uint tmp;
tmp = D[reg_a].u32;
D[reg_a].u32 = A[reg_b].u32;
A[reg_b].u32 = tmp;
tmp = D_ptr_reg_a->u32;
D_ptr_reg_a->u32 = A_ptr_reg_b->u32;
A_ptr_reg_b->u32 = tmp;
pendingCycles -= 6;
}
@ -931,12 +950,14 @@ namespace cpu.m68000
int dstReg = (op >> 9) & 0x07;
int size = (op >> 6) & 0x03;
int srcReg = op & 0x07;
Register* D_ptr_srcReg = D + srcReg;
Register* D_ptr_dstReg = D + dstReg;
switch (size)
{
case 0:
{
uint src = D[srcReg].u32 & 0xff;
uint dst = D[dstReg].u32 & 0xff;
uint src = D_ptr_srcReg->u32 & 0xff;
uint dst = D_ptr_dstReg->u32 & 0xff;
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x80) != 0);
@ -944,14 +965,14 @@ namespace cpu.m68000
X = C = ((res & 0x100) != 0);
res = res & 0xff;
Z &= (res == 0);
D[dstReg].u32 = (D[dstReg].u32 & 0xffffff00) | res;
D_ptr_dstReg->u32 = (D_ptr_dstReg->u32 & 0xffffff00) | res;
pendingCycles -= 4;
return;
}
case 1:
{
uint src = D[srcReg].u32 & 0xffff;
uint dst = D[dstReg].u32 & 0xffff;
uint src = D_ptr_srcReg->u32 & 0xffff;
uint dst = D_ptr_dstReg->u32 & 0xffff;
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x8000) != 0);
@ -959,21 +980,21 @@ namespace cpu.m68000
X = C = ((res & 0x10000) != 0);
res = res & 0xffff;
Z &= (res == 0);
D[dstReg].u32 = (D[dstReg].u32 & 0xffff0000) | res;
D_ptr_dstReg->u32 = (D_ptr_dstReg->u32 & 0xffff0000) | res;
pendingCycles -= 4;
return;
}
case 2:
{
uint src = D[srcReg].u32;
uint dst = D[dstReg].u32;
uint src = D_ptr_srcReg->u32;
uint dst = D_ptr_dstReg->u32;
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x80000000) != 0);
V = ((((src ^ res) & (dst ^ res)) & 0x80000000) != 0);
X = C = ((((src & dst) | (~res & (src | dst))) & 0x80000000) != 0);
Z &= (res == 0);
D[dstReg].u32 = res;
D_ptr_dstReg->u32 = res;
pendingCycles -= 8;
return;
}
@ -986,28 +1007,30 @@ namespace cpu.m68000
int dstReg = (op >> 9) & 0x07;
int size = (op >> 6) & 0x03;
int srcReg = op & 0x07;
Register* A_srcReg = A + srcReg;
Register* A_dstReg = A + dstReg;
switch (size)
{
case 0:
{
if (srcReg == 7)
{
A[srcReg].u32 -= 2;
A_srcReg->u32 -= 2;
}
else
{
A[srcReg].u32--;
A_srcReg->u32--;
}
if (dstReg == 7)
{
A[dstReg].u32 -= 2;
A_dstReg->u32 -= 2;
}
else
{
A[dstReg].u32--;
A_dstReg->u32--;
}
uint src = (uint)ReadByte(A[srcReg].s32);
uint dst = (uint)ReadByte(A[dstReg].s32);
uint src = (uint)ReadByte(A_srcReg->s32);
uint dst = (uint)ReadByte(A_dstReg->s32);
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x80) != 0);
@ -1015,16 +1038,16 @@ namespace cpu.m68000
X = C = ((res & 0x100) != 0);
res = res & 0xff;
Z &= (res == 0);
WriteByte(A[dstReg].s32, (sbyte)res);
WriteByte(A_dstReg->s32, (sbyte)res);
pendingCycles -= 18;
return;
}
case 1:
{
A[srcReg].u32 -= 2;
uint src = (uint)ReadWord(A[srcReg].s32);
A[dstReg].u32 -= 2;
uint dst = (uint)ReadWord(A[dstReg].s32);
A_srcReg->u32 -= 2;
uint src = (uint)ReadWord(A_srcReg->s32);
A_dstReg->u32 -= 2;
uint dst = (uint)ReadWord(A_dstReg->s32);
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x8000) != 0);
@ -1032,23 +1055,23 @@ namespace cpu.m68000
X = C = ((res & 0x10000) != 0);
res = res & 0xffff;
Z &= (res == 0);
WriteWord(A[dstReg].s32, (short)res);
WriteWord(A_dstReg->s32, (short)res);
pendingCycles -= 18;
return;
}
case 2:
{
A[srcReg].u32 -= 4;
uint src = (uint)ReadLong(A[srcReg].s32);
A[dstReg].u32 -= 4;
uint dst = (uint)ReadWord(A[dstReg].s32);
A_srcReg->u32 -= 4;
uint src = (uint)ReadLong(A_srcReg->s32);
A_dstReg->u32 -= 4;
uint dst = (uint)ReadWord(A_dstReg->s32);
uint res;
res = (uint)(dst + src + (X ? 1 : 0));
N = ((res & 0x80000000) != 0);
V = (((((src ^ res) & (dst ^ res)) >> 24) & 0x80) != 0);
X = C = (((((src & dst) | (~res & (src | dst))) >> 23) & 0x100) != 0);
Z &= (res == 0);
WriteLong(A[dstReg].s32, (int)res);
WriteLong(A_dstReg->s32, (int)res);
pendingCycles -= 30;
return;
}
@ -1061,12 +1084,14 @@ namespace cpu.m68000
int dstReg = (op >> 9) & 0x07;
int size = (op >> 6) & 0x03;
int srcReg = op & 0x07;
Register* D_ptr_srcReg = D + srcReg;
Register* D_ptr_dstReg = D + dstReg;
switch (size)
{
case 0:
{
uint src = D[srcReg].u32 & 0xff;
uint dst = D[dstReg].u32 & 0xff;
uint src = D_ptr_srcReg->u32 & 0xff;
uint dst = D_ptr_dstReg->u32 & 0xff;
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x80) != 0);
@ -1074,14 +1099,14 @@ namespace cpu.m68000
V = ((((src ^ dst) & (res ^ dst)) & 0x80) != 0);
res = res & 0xff;
Z &= (res == 0);
D[dstReg].u32 = (D[dstReg].u32 & 0xffffff00) | res;
D_ptr_dstReg->u32 = (D_ptr_dstReg->u32 & 0xffffff00) | res;
pendingCycles -= 4;
return;
}
case 1:
{
uint src = D[srcReg].u32 & 0xffff;
uint dst = D[dstReg].u32 & 0xffff;
uint src = D_ptr_srcReg->u32 & 0xffff;
uint dst = D_ptr_dstReg->u32 & 0xffff;
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x8000) != 0);
@ -1089,21 +1114,21 @@ namespace cpu.m68000
V = ((((src ^ dst) & (res ^ dst)) & 0x8000) != 0);
res = res & 0xffff;
Z &= (res == 0);
D[dstReg].u32 = (D[dstReg].u32 & 0xffff0000) | res;
D_ptr_dstReg->u32 = (D_ptr_dstReg->u32 & 0xffff0000) | res;
pendingCycles -= 4;
return;
}
case 2:
{
uint src = D[srcReg].u32;
uint dst = D[dstReg].u32;
uint src = D_ptr_srcReg->u32;
uint dst = D_ptr_dstReg->u32;
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x80000000) != 0);
X = C = (((((src & res) | (~dst & (src | res))) >> 23) & 0x100) != 0);
V = (((((src ^ dst) & (res ^ dst)) >> 24) & 0x80) != 0);
Z &= (res == 0);
D[dstReg].u32 = res;
D_ptr_dstReg->u32 = res;
pendingCycles -= 8;
return;
}
@ -1116,28 +1141,30 @@ namespace cpu.m68000
int dstReg = (op >> 9) & 0x07;
int size = (op >> 6) & 0x03;
int srcReg = op & 0x07;
Register* A_srcReg = A + srcReg;
Register* A_dstReg = A + dstReg;
switch (size)
{
case 0:
{
if (srcReg == 7)
{
A[srcReg].u32 -= 2;
A_srcReg->u32 -= 2;
}
else
{
A[srcReg].u32--;
A_srcReg->u32--;
}
if (dstReg == 7)
{
A[dstReg].u32 -= 2;
A_dstReg->u32 -= 2;
}
else
{
A[dstReg].u32--;
A_dstReg->u32--;
}
uint src = (uint)ReadByte(A[srcReg].s32);
uint dst = (uint)ReadByte(A[dstReg].s32);
uint src = (uint)ReadByte(A_srcReg->s32);
uint dst = (uint)ReadByte(A_dstReg->s32);
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x80) != 0);
@ -1145,16 +1172,16 @@ namespace cpu.m68000
V = ((((src ^ dst) & (res ^ dst)) & 0x80) != 0);
res = res & 0xff;
Z &= (res == 0);
WriteByte(A[dstReg].s32, (sbyte)res);
WriteByte(A_dstReg->s32, (sbyte)res);
pendingCycles -= 18;
return;
}
case 1:
{
A[srcReg].u32 -= 2;
uint src = (uint)ReadWord(A[srcReg].s32);
A[dstReg].u32 -= 2;
uint dst = (uint)ReadWord(A[dstReg].s32);
A_srcReg->u32 -= 2;
uint src = (uint)ReadWord(A_srcReg->s32);
A_dstReg->u32 -= 2;
uint dst = (uint)ReadWord(A_dstReg->s32);
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x8000) != 0);
@ -1162,23 +1189,23 @@ namespace cpu.m68000
V = ((((src ^ dst) & (res ^ dst)) & 0x8000) != 0);
res = res & 0xffff;
Z &= (res == 0);
WriteWord(A[dstReg].s32, (short)res);
WriteWord(A_dstReg->s32, (short)res);
pendingCycles -= 18;
return;
}
case 2:
{
A[srcReg].u32 -= 4;
uint src = (uint)ReadLong(A[srcReg].s32);
A[dstReg].u32 -= 4;
uint dst = (uint)ReadWord(A[dstReg].s32);
A_srcReg->u32 -= 4;
uint src = (uint)ReadLong(A_srcReg->s32);
A_dstReg->u32 -= 4;
uint dst = (uint)ReadWord(A_dstReg->s32);
uint res;
res = (uint)(dst - src - (X ? 1 : 0));
N = ((res & 0x80000000) != 0);
X = C = (((((src & res) | (~dst & (src | res))) >> 23) & 0x100) != 0);
V = (((((src ^ dst) & (res ^ dst)) >> 24) & 0x80) != 0);
Z &= (res == 0);
WriteLong(A[dstReg].s32, (int)res);
WriteLong(A_dstReg->s32, (int)res);
pendingCycles -= 30;
return;
}
@ -1186,6 +1213,54 @@ namespace cpu.m68000
}
//void CMP()
//{
// int dReg = (op >> 9) & 7;
// int size = (op >> 6) & 3;
// int mode = (op >> 3) & 7;
// int reg = (op >> 0) & 7;
// switch (size)
// {
// case 0: // byte
// {
// sbyte a = D_ptr_dReg->s8;
// sbyte b = ReadValueB(mode, reg);
// int result = a - b;
// N = (result & 0x80) != 0;
// Z = result == 0;
// V = result > sbyte.MaxValue || result < sbyte.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// pendingCycles -= 4 + EACyclesBW[mode, reg];
// return;
// }
// case 1: // word
// {
// short a = D_ptr_dReg->s16;
// short b = ReadValueW(mode, reg);
// int result = a - b;
// N = (result & 0x8000) != 0;
// Z = result == 0;
// V = result > short.MaxValue || result < short.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// pendingCycles -= 4 + EACyclesBW[mode, reg];
// return;
// }
// case 2: // long
// {
// int a = D_ptr_dReg->s32;
// int b = ReadValueL(mode, reg);
// long result = (long)a - (long)b;
// N = (result & 0x80000000) != 0;
// Z = (uint)result == 0;
// V = result > int.MaxValue || result < int.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// pendingCycles -= 6 + EACyclesL[mode, reg];
// return;
// }
// }
//}
void CMP()
{
int dReg = (op >> 9) & 7;
@ -1197,7 +1272,7 @@ namespace cpu.m68000
{
case 0: // byte
{
sbyte a = D[dReg].s8;
sbyte a = (D + dReg)->s8;
sbyte b = ReadValueB(mode, reg);
int result = a - b;
N = (result & 0x80) != 0;
@ -1209,7 +1284,7 @@ namespace cpu.m68000
}
case 1: // word
{
short a = D[dReg].s16;
short a = (D + dReg)->s16;
short b = ReadValueW(mode, reg);
int result = a - b;
N = (result & 0x8000) != 0;
@ -1221,7 +1296,7 @@ namespace cpu.m68000
}
case 2: // long
{
int a = D[dReg].s32;
int a = (D + dReg)->s32;
int b = ReadValueL(mode, reg);
long result = (long)a - (long)b;
N = (result & 0x80000000) != 0;
@ -1242,11 +1317,12 @@ namespace cpu.m68000
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* A_ptr_aReg = A + aReg;
switch (size)
{
case 0: // word
{
int a = A[aReg].s32;
int a = A_ptr_aReg->s32;
short b = ReadValueW(mode, reg);
long result = a - b;
N = (result & 0x80000000) != 0;
@ -1258,7 +1334,7 @@ namespace cpu.m68000
}
case 1: // long
{
int a = A[aReg].s32;
int a = A_ptr_aReg->s32;
int b = ReadValueL(mode, reg);
long result = a - b;
N = (result & 0x80000000) != 0;
@ -1278,12 +1354,14 @@ namespace cpu.m68000
int size = (op >> 6) & 3;
int ayReg = (op >> 0) & 7;
Register* A_axReg = A + axReg;
Register* A_ayReg = A + ayReg;
switch (size)
{
case 0: // byte
{
sbyte a = ReadByte(A[axReg].s32); A[axReg].s32 += 1; // Does A7 stay word aligned???
sbyte b = ReadByte(A[ayReg].s32); A[ayReg].s32 += 1;
sbyte a = ReadByte(A_axReg->s32); A_axReg->s32 += 1; // Does A7 stay word aligned???
sbyte b = ReadByte(A_ayReg->s32); A_ayReg->s32 += 1;
int result = a - b;
N = (result & 0x80) != 0;
Z = (result & 0xff) == 0;
@ -1294,8 +1372,8 @@ namespace cpu.m68000
}
case 1: // word
{
short a = ReadWord(A[axReg].s32); A[axReg].s32 += 2;
short b = ReadWord(A[ayReg].s32); A[ayReg].s32 += 2;
short a = ReadWord(A_axReg->s32); A_axReg->s32 += 2;
short b = ReadWord(A_ayReg->s32); A_ayReg->s32 += 2;
int result = a - b;
N = (result & 0x8000) != 0;
Z = (result & 0xffff) == 0;
@ -1306,8 +1384,8 @@ namespace cpu.m68000
}
case 2: // long
{
int a = ReadLong(A[axReg].s32); A[axReg].s32 += 4;
int b = ReadLong(A[ayReg].s32); A[ayReg].s32 += 4;
int a = ReadLong(A_axReg->s32); A_axReg->s32 += 4;
int b = ReadLong(A_ayReg->s32); A_ayReg->s32 += 4;
long result = a - b;
N = (result & 0x80000000) != 0;
Z = (uint)result == 0;
@ -1320,18 +1398,120 @@ namespace cpu.m68000
}
//void CMPI()
//{
// int size = (op >> 6) & 3;
// int mode = (op >> 3) & 7;
// int reg = (op >> 0) & 7;
// switch (size)
// {
// case 0: // byte
// {
// sbyte b = (sbyte)ReadOpWord(PC); PC += 2;
// sbyte a = ReadValueB(mode, reg);
// int result = a - b;
// N = (result & 0x80) != 0;
// Z = result == 0;
// V = result > sbyte.MaxValue || result < sbyte.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// if (mode == 0) pendingCycles -= 8;
// else pendingCycles -= 8 + EACyclesBW[mode, reg];
// return;
// }
// case 1: // word
// {
// short b = ReadOpWord(PC); PC += 2;
// short a = ReadValueW(mode, reg);
// int result = a - b;
// N = (result & 0x8000) != 0;
// Z = result == 0;
// V = result > short.MaxValue || result < short.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// if (mode == 0) pendingCycles -= 8;
// else pendingCycles -= 8 + EACyclesBW[mode, reg];
// return;
// }
// case 2: // long
// {
// int b = ReadOpLong(PC); PC += 4;
// int a = ReadValueL(mode, reg);
// long result = a - b;
// N = (result & 0x80000000) != 0;
// Z = result == 0;
// V = result > int.MaxValue || result < int.MinValue;
// C = ((a < b) ^ ((a ^ b) >= 0) == false);
// if (mode == 0) pendingCycles -= 14;
// else pendingCycles -= 12 + EACyclesL[mode, reg];
// return;
// }
// }
//}
//ÊÖ¶¯ÄÚÁª
void CMPI()
{
int size = (op >> 6) & 3;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
Register* A_ptr_reg = A + reg;
switch (size)
{
case 0: // byte
{
sbyte b = (sbyte)ReadOpWord(PC); PC += 2;
sbyte a = ReadValueB(mode, reg);
//sbyte a = ReadValueB(mode, reg);
sbyte a = 0;
{
sbyte value;
switch (mode)
{
case 0: // Dn
a = (D + reg)->s8; break;
case 1: // An
a = A_ptr_reg->s8; break;
case 2: // (An)
a = ReadByte(A_ptr_reg->s32); break;
case 3: // (An)+
value = ReadByte(A_ptr_reg->s32);
A_ptr_reg->s32 += reg == 7 ? 2 : 1;
a = value; break;
case 4: // -(An)
A_ptr_reg->s32 -= reg == 7 ? 2 : 1;
a = ReadByte(A_ptr_reg->s32); break;
case 5: // (d16,An)
value = ReadByte((A_ptr_reg->s32 + ReadOpWord(PC))); PC += 2;
a = value; break;
case 6: // (d8,An,Xn)
a = ReadByte(A_ptr_reg->s32 + GetIndex()); break;
case 7:
switch (reg)
{
case 0: // (imm).W
value = ReadByte(ReadOpWord(PC)); PC += 2;
a = value; break;
case 1: // (imm).L
value = ReadByte(ReadOpLong(PC)); PC += 4;
a = value; break;
case 2: // (d16,PC)
value = ReadOpByte(PC + ReadOpWord(PC)); PC += 2;
a = value; break;
case 3: // (d8,PC,Xn)
int pc = PC;
value = ReadOpByte((pc + GetIndex()));
a = value; break;
case 4: // immediate
value = (sbyte)ReadOpWord(PC); PC += 2;
a = value; break;
default:
throw new Exception("Invalid addressing mode!");
}
break;
default:
throw new Exception("Invalid addressing mode!");
}
}
int result = a - b;
N = (result & 0x80) != 0;
Z = result == 0;
@ -1376,9 +1556,9 @@ namespace cpu.m68000
int dreg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
uint result = (uint)(D[dreg].u16 * (ushort)ReadValueW(mode, reg));
D[dreg].u32 = result;
Register* D_ptr_dreg = D + dreg;
uint result = (uint)(D_ptr_dreg->u16 * (ushort)ReadValueW(mode, reg));
D_ptr_dreg->u32 = result;
V = false;
C = false;
@ -1394,9 +1574,9 @@ namespace cpu.m68000
int dreg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = (op >> 0) & 7;
int result = D[dreg].s16 * ReadValueW(mode, reg);
D[dreg].s32 = result;
Register* D_ptr_dreg = D + dreg;
int result = D_ptr_dreg->s16 * ReadValueW(mode, reg);
D_ptr_dreg->s32 = result;
V = false;
C = false;
@ -1414,7 +1594,8 @@ namespace cpu.m68000
int reg = (op >> 0) & 7;
uint source = (ushort)ReadValueW(mode, reg);
uint dest = D[dreg].u32;
Register* D_ptr_dreg = D + dreg;
uint dest = D_ptr_dreg->u32;
if (source == 0)
{
@ -1430,7 +1611,7 @@ namespace cpu.m68000
N = (quotient & 0x8000) != 0;
V = false;
C = false;
D[dreg].u32 = (quotient & 0xFFFF) | (remainder << 16);
D_ptr_dreg->u32 = (quotient & 0xFFFF) | (remainder << 16);
}
else
{
@ -1448,7 +1629,8 @@ namespace cpu.m68000
int reg = (op >> 0) & 7;
int source = ReadValueW(mode, reg);
int dest = D[dreg].s32;
Register* D_ptr_dreg = D + dreg;
int dest = D_ptr_dreg->s32;
if (source == 0)
{
@ -1464,7 +1646,7 @@ namespace cpu.m68000
N = (quotient & 0x8000) != 0;
V = false;
C = false;
D[dreg].s32 = (quotient & 0xFFFF) | (remainder << 16);
D_ptr_dreg->s32 = (quotient & 0xFFFF) | (remainder << 16);
}
else
{

View File

@ -1,8 +1,9 @@
using System;
using System.Text.RegularExpressions;
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
bool TestCondition(int condition)
{
@ -106,17 +107,18 @@ namespace cpu.m68000
{
sbyte displacement8 = (sbyte)op;
A[7].s32 -= 4;
Register* ptrA7 = &A[7];
ptrA7->s32 -= 4;
if (displacement8 != 0)
{
// use embedded displacement
WriteLong(A[7].s32, PC);
WriteLong(ptrA7->s32, PC);
PC += displacement8;
}
else
{
// use extension word displacement
WriteLong(A[7].s32, PC + 2);
WriteLong(ptrA7->s32, PC + 2);
PC += ReadOpWord(PC);
}
pendingCycles -= 18;
@ -133,9 +135,10 @@ namespace cpu.m68000
else
{
int reg = op & 7;
D[reg].u16--;
Register* D_ptr_reg = D + reg;
D_ptr_reg->u16--;
if (D[reg].u16 == 0xFFFF)
if (D_ptr_reg->u16 == 0xFFFF)
{
PC += 2; // counter underflowed, break out of loop
pendingCycles -= 14;
@ -151,19 +154,21 @@ namespace cpu.m68000
void RTS()
{
PC = ReadLong(A[7].s32);
A[7].s32 += 4;
Register* ptrA7 = &A[7];
PC = ReadLong(ptrA7->s32);
ptrA7->s32 += 4;
pendingCycles -= 16;
}
void RTR()
{
short value = ReadWord(A[7].s32);
A[7].s32 += 2;
Register* ptrA7 = &A[7];
short value = ReadWord(ptrA7->s32);
ptrA7->s32 += 2;
CCR = value;
PC = ReadLong(A[7].s32);
A[7].s32 += 4;
PC = ReadLong(ptrA7->s32);
ptrA7->s32 += 4;
pendingCycles -= 20;
}
@ -181,10 +186,11 @@ namespace cpu.m68000
void RTE()
{
short newSR = ReadWord(A[7].s32);
A[7].s32 += 2;
PC = ReadLong(A[7].s32);
A[7].s32 += 4;
Register* ptrA7 = &A[7];
short newSR = ReadWord(ptrA7->s32);
ptrA7->s32 += 2;
PC = ReadLong(ptrA7->s32);
ptrA7->s32 += 4;
SR = newSR;
pendingCycles -= 20;
}
@ -202,7 +208,7 @@ namespace cpu.m68000
C = false;
/*if (mode == 0)
{
//D[reg].u8 = (byte)(result | 0x80);
//D_ptr_reg->u8 = (byte)(result | 0x80);
}*/
WriteValueB(mode, reg, (sbyte)(result | 0x80));
pendingCycles -= (mode == 0) ? 4 : 14 + EACyclesBW[mode, reg];
@ -236,7 +242,8 @@ namespace cpu.m68000
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
pendingCycles -= 10;
}
else
@ -253,13 +260,14 @@ namespace cpu.m68000
int dReg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = op & 7;
int bit = D[dReg].s32;
int bit = (D + dReg)->s32;
if (mode == 0)
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
pendingCycles -= 6;
}
else
@ -281,8 +289,9 @@ namespace cpu.m68000
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 ^= mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 ^= mask;
pendingCycles -= 12;
}
else
@ -303,14 +312,15 @@ namespace cpu.m68000
int dReg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = op & 7;
int bit = D[dReg].s32;
int bit = (D + dReg)->s32;
if (mode == 0)
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 ^= mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 ^= mask;
pendingCycles -= 8;
}
else
@ -335,8 +345,9 @@ namespace cpu.m68000
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 &= ~mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 &= ~mask;
pendingCycles -= 14;
}
else
@ -356,14 +367,15 @@ namespace cpu.m68000
int dReg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = op & 7;
int bit = D[dReg].s32;
int bit = (D + dReg)->s32;
if (mode == 0)
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 &= ~mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 &= ~mask;
pendingCycles -= 10;
}
else
@ -389,8 +401,9 @@ namespace cpu.m68000
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 |= mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 |= mask;
pendingCycles -= 12;
}
else
@ -411,14 +424,15 @@ namespace cpu.m68000
int dReg = (op >> 9) & 7;
int mode = (op >> 3) & 7;
int reg = op & 7;
int bit = D[dReg].s32;
int bit = (D + dReg)->s32;
if (mode == 0)
{
bit &= 31;
int mask = 1 << bit;
Z = (D[reg].s32 & mask) == 0;
D[reg].s32 |= mask;
Register* D_ptr_reg = D + reg;
Z = (D_ptr_reg->s32 & mask) == 0;
D_ptr_reg->s32 |= mask;
pendingCycles -= 8;
}
else
@ -467,8 +481,9 @@ namespace cpu.m68000
int reg = (op >> 0) & 7;
int addr = ReadAddress(mode, reg);
A[7].s32 -= 4;
WriteLong(A[7].s32, PC);
Register* ptrA7 = &A[7];
ptrA7->s32 -= 4;
WriteLong(ptrA7->s32, PC);
PC = addr;
switch (mode)
@ -492,11 +507,14 @@ namespace cpu.m68000
void LINK()
{
int reg = op & 7;
A[7].s32 -= 4;
Register* ptrA7 = &A[7];
Register* A_ptr_reg = A + reg;
ptrA7->s32 -= 4;
short offset = ReadOpWord(PC); PC += 2;
WriteLong(A[7].s32, A[reg].s32);
A[reg].s32 = A[7].s32;
A[7].s32 += offset;
WriteLong(ptrA7->s32, A_ptr_reg->s32);
A_ptr_reg->s32 = ptrA7->s32;
ptrA7->s32 += offset;
pendingCycles -= 16;
}
@ -504,9 +522,11 @@ namespace cpu.m68000
void UNLK()
{
int reg = op & 7;
A[7].s32 = A[reg].s32;
A[reg].s32 = ReadLong(A[7].s32);
A[7].s32 += 4;
Register* ptrA7 = &A[7];
Register* A_ptr_reg = A + reg;
ptrA7->s32 = A_ptr_reg->s32;
A_ptr_reg->s32 = ReadLong(ptrA7->s32);
ptrA7->s32 += 4;
pendingCycles -= 12;
}

View File

@ -2,7 +2,7 @@ using System;
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
unsafe void MOVEtSR()
{
@ -61,13 +61,14 @@ namespace cpu.m68000
}
else
{
Register* A_ptr_reg = A + reg;
if (dir == 0)
{
usp = A[reg].s32;
usp = A_ptr_reg->s32;
}
else
{
A[reg].s32 = usp;
A_ptr_reg->s32 = usp;
}
}
pendingCycles -= 4;
@ -125,24 +126,26 @@ namespace cpu.m68000
void TrapVector(int vector)
{
Register* ptrA7 = &A[7];
short sr = (short)SR; // capture current SR.
S = true; // switch to supervisor mode, if not already in it.
A[7].s32 -= 4; // Push PC on stack
WriteLong(A[7].s32, PC);
A[7].s32 -= 2; // Push SR on stack
WriteWord(A[7].s32, sr);
ptrA7->s32 -= 4; // Push PC on stack
WriteLong(ptrA7->s32, PC);
ptrA7->s32 -= 2; // Push SR on stack
WriteWord(ptrA7->s32, sr);
PC = ReadLong(vector * 4); // Jump to vector
pendingCycles -= CyclesException[vector];
}
void TrapVector2(int vector)
unsafe void TrapVector2(int vector)
{
Register* ptrA7 = &A[7];
short sr = (short)SR; // capture current SR.
S = true; // switch to supervisor mode, if not already in it.
A[7].s32 -= 4; // Push PPC on stack
WriteLong(A[7].s32, PPC);
A[7].s32 -= 2; // Push SR on stack
WriteWord(A[7].s32, sr);
ptrA7->s32 -= 4; // Push PPC on stack
WriteLong(ptrA7->s32, PPC);
ptrA7->s32 -= 2; // Push SR on stack
WriteWord(ptrA7->s32, sr);
PC = ReadLong(vector * 4); // Jump to vector
pendingCycles -= CyclesException[vector];
}

View File

@ -5,12 +5,50 @@ using System.Runtime.InteropServices;
namespace cpu.m68000
{
public sealed partial class MC68000 : cpuexec_data
public unsafe sealed partial class MC68000 : cpuexec_data
{
public static MC68000 m1;
// Machine State
public Register[] D = new Register[8];
public Register[] A = new Register[8];
//public Register[] D = new Register[8];
#region //指针化 D
Register[] D_src;
GCHandle D_handle;
public Register* D;
public int DLength;
public bool D_IsNull => D == null;
public Register[] D_set
{
set
{
D_handle.ReleaseGCHandle();
D_src = value;
DLength = value.Length;
D_src.GetObjectPtr(ref D_handle, ref D);
}
}
#endregion
//public Register[] A = new Register[8];
#region //指针化 A
Register[] A_src;
GCHandle A_handle;
public Register* A;
public int ALength;
public bool A_IsNull => A == null;
public Register[] A_set
{
set
{
A_handle.ReleaseGCHandle();
A_src = value;
ALength = value.Length;
A_src.GetObjectPtr(ref A_handle, ref A);
}
}
#endregion
public int PC, PPC;
private ulong totalExecutedCycles;
private int pendingCycles;
@ -69,18 +107,20 @@ namespace cpu.m68000
{
if (value == s)
return;
Register* ptrA7 = &A[7];
if (value == true) // entering supervisor mode
{
//EmuLogger.Log("&^&^&^&^& ENTER SUPERVISOR MODE");
usp = A[7].s32;
A[7].s32 = ssp;
usp = ptrA7->s32;
ptrA7->s32 = ssp;
s = true;
}
else
{ // exiting supervisor mode
//EmuLogger.Log("&^&^&^&^& LEAVE SUPERVISOR MODE");
ssp = A[7].s32;
A[7].s32 = usp;
ssp = ptrA7->s32;
ptrA7->s32 = usp;
s = false;
}
}
@ -163,8 +203,12 @@ namespace cpu.m68000
public MC68000()
{
A_set = new Register[8];
D_set = new Register[8];
//还是使用Action[]吧
BuildOpcodeTable();
InitMC68000Tables();
}
@ -201,7 +245,7 @@ namespace cpu.m68000
m = false;
InterruptMaskLevel = 7;
Interrupt = 0;
A[7].s32 = ReadOpLong(0);
(A + 7)->s32 = ReadOpLong(0);
PC = ReadOpLong(4);
}
@ -271,10 +315,14 @@ namespace cpu.m68000
//int vector = Cpuint.cpu_irq_callback(cpunum, Interrupt);
short sr = (short)SR; // capture current SR.
S = true; // switch to supervisor mode, if not already in it.
A[7].s32 -= 4; // Push PC on stack
WriteLong(A[7].s32, PC);
A[7].s32 -= 2; // Push SR on stack
WriteWord(A[7].s32, sr);
Register* ptrA7 = &A[7];
ptrA7->s32 -= 4; // Push PC on stack
WriteLong(ptrA7->s32, PC);
ptrA7->s32 -= 2; // Push SR on stack
WriteWord(ptrA7->s32, sr);
PC = ReadLong((24 + Interrupt) * 4); // Jump to interrupt vector
InterruptMaskLevel = Interrupt; // Set interrupt mask to level currently being entered
Interrupt = 0; // "ack" interrupt. Note: this is wrong.
@ -302,10 +350,12 @@ namespace cpu.m68000
//int vector = Cpuint.cpu_irq_callback(cpunum, Interrupt);
short sr = (short)SR; // capture current SR.
S = true; // switch to supervisor mode, if not already in it.
A[7].s32 -= 4; // Push PC on stack
WriteLong(A[7].s32, PC);
A[7].s32 -= 2; // Push SR on stack
WriteWord(A[7].s32, sr);
Register* ptrA7 = &A[7];
ptrA7->s32 -= 4; // Push PC on stack
WriteLong(ptrA7->s32, PC);
ptrA7->s32 -= 2; // Push SR on stack
WriteWord(ptrA7->s32, sr);
PC = ReadLong((24 + Interrupt) * 4); // Jump to interrupt vector
InterruptMaskLevel = Interrupt; // Set interrupt mask to level currently being entered
Interrupt = 0; // "ack" interrupt. Note: this is wrong.
@ -318,7 +368,7 @@ namespace cpu.m68000
// string a = Disassemble(PC).ToString().PadRight(64);
// //string a = string.Format("{0:X6}: {1:X4}", PC, ReadWord(PC)).PadRight(64);
// string b = string.Format("D0:{0:X8} D1:{1:X8} D2:{2:X8} D3:{3:X8} D4:{4:X8} D5:{5:X8} D6:{6:X8} D7:{7:X8} ", D[0].u32, D[1].u32, D[2].u32, D[3].u32, D[4].u32, D[5].u32, D[6].u32, D[7].u32);
// string c = string.Format("A0:{0:X8} A1:{1:X8} A2:{2:X8} A3:{3:X8} A4:{4:X8} A5:{5:X8} A6:{6:X8} A7:{7:X8} ", A[0].u32, A[1].u32, A[2].u32, A[3].u32, A[4].u32, A[5].u32, A[6].u32, A[7].u32);
// string c = string.Format("A0:{0:X8} A1:{1:X8} A2:{2:X8} A3:{3:X8} A4:{4:X8} A5:{5:X8} A6:{6:X8} A7:{7:X8} ", A[0].u32, A[1].u32, A[2].u32, A[3].u32, A[4].u32, A[5].u32, A[6].u32, ptrA7->u32);
// string d = string.Format("SR:{0:X4} Pending {1}", SR, pendingCycles);
// return a + b + c + d;
//}

View File

@ -2,31 +2,85 @@
namespace cpu.m68000
{
partial class MC68000
unsafe partial class MC68000
{
//sbyte ReadValueB(int mode, int reg)
//{
// sbyte value;
// switch (mode)
// {
// case 0: // Dn
// return D_ptr_reg->s8;
// case 1: // An
// return A_ptr_reg->s8;
// case 2: // (An)
// return ReadByte(A_ptr_reg->s32);
// case 3: // (An)+
// value = ReadByte(A_ptr_reg->s32);
// A_ptr_reg->s32 += reg == 7 ? 2 : 1;
// return value;
// case 4: // -(An)
// A_ptr_reg->s32 -= reg == 7 ? 2 : 1;
// return ReadByte(A_ptr_reg->s32);
// case 5: // (d16,An)
// value = ReadByte((A_ptr_reg->s32 + ReadOpWord(PC))); PC += 2;
// return value;
// case 6: // (d8,An,Xn)
// return ReadByte(A_ptr_reg->s32 + GetIndex());
// case 7:
// switch (reg)
// {
// case 0: // (imm).W
// value = ReadByte(ReadOpWord(PC)); PC += 2;
// return value;
// case 1: // (imm).L
// value = ReadByte(ReadOpLong(PC)); PC += 4;
// return value;
// case 2: // (d16,PC)
// value = ReadOpByte(PC + ReadOpWord(PC)); PC += 2;
// return value;
// case 3: // (d8,PC,Xn)
// int pc = PC;
// value = ReadOpByte((pc + GetIndex()));
// return value;
// case 4: // immediate
// value = (sbyte)ReadOpWord(PC); PC += 2;
// return value;
// default:
// throw new Exception("Invalid addressing mode!");
// }
// }
// throw new Exception("Invalid addressing mode!");
//}
sbyte ReadValueB(int mode, int reg)
{
sbyte value;
switch (mode)
{
case 0: // Dn
return D[reg].s8;
return (D + reg)->s8;
case 1: // An
return A[reg].s8;
return (A + reg)->s8;
case 2: // (An)
return ReadByte(A[reg].s32);
return ReadByte((A + reg)->s32);
case 3: // (An)+
value = ReadByte(A[reg].s32);
A[reg].s32 += reg == 7 ? 2 : 1;
{
Register* ptr = A + reg;
value = ReadByte(ptr->s32);
ptr->s32 += reg == 7 ? 2 : 1;
}
return value;
case 4: // -(An)
A[reg].s32 -= reg == 7 ? 2 : 1;
return ReadByte(A[reg].s32);
{
Register* ptr = A + reg;
ptr->s32 -= reg == 7 ? 2 : 1;
return ReadByte(ptr->s32);
}
case 5: // (d16,An)
value = ReadByte((A[reg].s32 + ReadOpWord(PC))); PC += 2;
value = ReadByte(((A + reg)->s32 + ReadOpWord(PC))); PC += 2;
return value;
case 6: // (d8,An,Xn)
return ReadByte(A[reg].s32 + GetIndex());
return ReadByte((A + reg)->s32 + GetIndex());
case 7:
switch (reg)
{
@ -53,29 +107,83 @@ namespace cpu.m68000
throw new Exception("Invalid addressing mode!");
}
//short ReadValueW(int mode, int reg)
//{
// short value;
// switch (mode)
// {
// case 0: // Dn
// return D_ptr_reg->s16;
// case 1: // An
// return A_ptr_reg->s16;
// case 2: // (An)
// return ReadWord(A_ptr_reg->s32);
// case 3: // (An)+
// value = ReadWord(A_ptr_reg->s32);
// A_ptr_reg->s32 += 2;
// return value;
// case 4: // -(An)
// A_ptr_reg->s32 -= 2;
// return ReadWord(A_ptr_reg->s32);
// case 5: // (d16,An)
// value = ReadWord((A_ptr_reg->s32 + ReadOpWord(PC))); PC += 2;
// return value;
// case 6: // (d8,An,Xn)
// return ReadWord(A_ptr_reg->s32 + GetIndex());
// case 7:
// switch (reg)
// {
// case 0: // (imm).W
// value = ReadWord(ReadOpWord(PC)); PC += 2;
// return value;
// case 1: // (imm).L
// value = ReadWord(ReadOpLong(PC)); PC += 4;
// return value;
// case 2: // (d16,PC)
// value = ReadOpWord(PC + ReadOpWord(PC)); PC += 2;
// return value;
// case 3: // (d8,PC,Xn)
// int pc = PC;
// value = ReadOpWord((pc + GetIndex()));
// return value;
// case 4: // immediate
// value = ReadOpWord(PC); PC += 2;
// return value;
// default:
// throw new Exception("Invalid addressing mode!");
// }
// }
// throw new Exception("Invalid addressing mode!");
//}
short ReadValueW(int mode, int reg)
{
short value;
switch (mode)
{
case 0: // Dn
return D[reg].s16;
return (D + reg)->s16;
case 1: // An
return A[reg].s16;
return (A + reg)->s16;
case 2: // (An)
return ReadWord(A[reg].s32);
return ReadWord((A + reg)->s32);
case 3: // (An)+
value = ReadWord(A[reg].s32);
A[reg].s32 += 2;
{
Register* ptr = A + reg;
value = ReadWord(ptr->s32);
ptr->s32 += 2;
return value;
}
case 4: // -(An)
A[reg].s32 -= 2;
return ReadWord(A[reg].s32);
{
Register* ptr = A + reg;
ptr->s32 -= 2;
return ReadWord(ptr->s32);
}
case 5: // (d16,An)
value = ReadWord((A[reg].s32 + ReadOpWord(PC))); PC += 2;
value = ReadWord((A + reg)->s32 + ReadOpWord(PC)); PC += 2;
return value;
case 6: // (d8,An,Xn)
return ReadWord(A[reg].s32 + GetIndex());
return ReadWord((A + reg)->s32 + GetIndex());
case 7:
switch (reg)
{
@ -101,6 +209,54 @@ namespace cpu.m68000
}
throw new Exception("Invalid addressing mode!");
}
//int ReadValueL(int mode, int reg)
//{
// int value;
// switch (mode)
// {
// case 0: // Dn
// return D_ptr_reg->s32;
// case 1: // An
// return A_ptr_reg->s32;
// case 2: // (An)
// return ReadLong(A_ptr_reg->s32);
// case 3: // (An)+
// value = ReadLong(A_ptr_reg->s32);
// A_ptr_reg->s32 += 4;
// return value;
// case 4: // -(An)
// A_ptr_reg->s32 -= 4;
// return ReadLong(A_ptr_reg->s32);
// case 5: // (d16,An)
// value = ReadLong((A_ptr_reg->s32 + ReadOpWord(PC))); PC += 2;
// return value;
// case 6: // (d8,An,Xn)
// return ReadLong(A_ptr_reg->s32 + GetIndex());
// case 7:
// switch (reg)
// {
// case 0: // (imm).W
// value = ReadLong(ReadOpWord(PC)); PC += 2;
// return value;
// case 1: // (imm).L
// value = ReadLong(ReadOpLong(PC)); PC += 4;
// return value;
// case 2: // (d16,PC)
// value = ReadOpLong(PC + ReadOpWord(PC)); PC += 2;
// return value;
// case 3: // (d8,PC,Xn)
// int pc = PC;
// value = ReadOpLong((pc + GetIndex()));
// return value;
// case 4: // immediate
// value = ReadOpLong(PC); PC += 4;
// return value;
// default:
// throw new Exception("Invalid addressing mode!");
// }
// }
// throw new Exception("Invalid addressing mode!");
//}
int ReadValueL(int mode, int reg)
{
@ -108,23 +264,29 @@ namespace cpu.m68000
switch (mode)
{
case 0: // Dn
return D[reg].s32;
return (D + reg)->s32;
case 1: // An
return A[reg].s32;
return (A + reg)->s32;
case 2: // (An)
return ReadLong(A[reg].s32);
return ReadLong((A + reg)->s32);
case 3: // (An)+
value = ReadLong(A[reg].s32);
A[reg].s32 += 4;
{
Register* ptr = A + reg;
value = ReadLong(ptr->s32);
ptr->s32 += 4;
}
return value;
case 4: // -(An)
A[reg].s32 -= 4;
return ReadLong(A[reg].s32);
{
Register* ptr = A + reg;
ptr->s32 -= 4;
return ReadLong(ptr->s32);
}
case 5: // (d16,An)
value = ReadLong((A[reg].s32 + ReadOpWord(PC))); PC += 2;
value = ReadLong(((A + reg)->s32 + ReadOpWord(PC))); PC += 2;
return value;
case 6: // (d8,An,Xn)
return ReadLong(A[reg].s32 + GetIndex());
return ReadLong((A + reg)->s32 + GetIndex());
case 7:
switch (reg)
{
@ -157,22 +319,41 @@ namespace cpu.m68000
switch (mode)
{
case 0: // Dn
return D[reg].s8;
return (D + reg)->s8;
case 1: // An
return A[reg].s8;
{
Register* A_ptr_reg = A + reg;
return A_ptr_reg->s8;
}
case 2: // (An)
return ReadByte(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
return ReadByte(A_ptr_reg->s32);
}
case 3: // (An)+
value = ReadByte(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
value = ReadByte(A_ptr_reg->s32);
return value;
}
case 4: // -(An)
value = ReadByte(A[reg].s32 - (reg == 7 ? 2 : 1));
{
Register* A_ptr_reg = A + reg;
value = ReadByte(A_ptr_reg->s32 - (reg == 7 ? 2 : 1));
return value;
}
case 5: // (d16,An)
value = ReadByte((A[reg].s32 + ReadOpWord(PC)));
{
Register* A_ptr_reg = A + reg;
value = ReadByte((A_ptr_reg->s32 + ReadOpWord(PC)));
return value;
}
case 6: // (d8,An,Xn)
return ReadByte(A[reg].s32 + PeekIndex());
{
Register* A_ptr_reg = A + reg;
return ReadByte(A_ptr_reg->s32 + PeekIndex());
}
case 7:
switch (reg)
{
@ -203,22 +384,42 @@ namespace cpu.m68000
switch (mode)
{
case 0: // Dn
return D[reg].s16;
return (D + reg)->s16;
case 1: // An
return A[reg].s16;
{
Register* A_ptr_reg = A + reg;
return A_ptr_reg->s16;
}
case 2: // (An)
return ReadWord(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
return ReadWord(A_ptr_reg->s32);
}
case 3: // (An)+
value = ReadWord(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
value = ReadWord(A_ptr_reg->s32);
return value;
}
case 4: // -(An)
value = ReadWord(A[reg].s32 - 2);
{
Register* A_ptr_reg = A + reg;
value = ReadWord(A_ptr_reg->s32 - 2);
return value;
}
case 5: // (d16,An)
value = ReadWord((A[reg].s32 + ReadOpWord(PC)));
{
Register* A_ptr_reg = A + reg;
value = ReadWord((A_ptr_reg->s32 + ReadOpWord(PC)));
return value;
}
case 6: // (d8,An,Xn)
return ReadWord(A[reg].s32 + PeekIndex());
{
Register* A_ptr_reg = A + reg;
return ReadWord(A_ptr_reg->s32 + PeekIndex());
}
case 7:
switch (reg)
{
@ -249,22 +450,40 @@ namespace cpu.m68000
switch (mode)
{
case 0: // Dn
return D[reg].s32;
return (D + reg)->s32;
case 1: // An
return A[reg].s32;
{
Register* A_ptr_reg = A + reg;
return A_ptr_reg->s32;
}
case 2: // (An)
return ReadLong(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
return ReadLong(A_ptr_reg->s32);
}
case 3: // (An)+
value = ReadLong(A[reg].s32);
{
Register* A_ptr_reg = A + reg;
value = ReadLong(A_ptr_reg->s32);
return value;
}
case 4: // -(An)
value = ReadLong(A[reg].s32 - 4);
{
Register* A_ptr_reg = A + reg;
value = ReadLong(A_ptr_reg->s32 - 4);
return value;
}
case 5: // (d16,An)
value = ReadLong((A[reg].s32 + ReadOpWord(PC)));
{
Register* A_ptr_reg = A + reg;
value = ReadLong((A_ptr_reg->s32 + ReadOpWord(PC)));
return value;
}
case 6: // (d8,An,Xn)
return ReadLong(A[reg].s32 + PeekIndex());
{
Register* A_ptr_reg = A + reg;
return ReadLong(A_ptr_reg->s32 + PeekIndex());
}
case 7:
switch (reg)
{
@ -296,11 +515,11 @@ namespace cpu.m68000
{
case 0: throw new Exception("Invalid addressing mode!"); // Dn
case 1: throw new Exception("Invalid addressing mode!"); // An
case 2: return A[reg].s32; // (An)
case 3: return A[reg].s32; // (An)+
case 4: return A[reg].s32; // -(An)
case 5: addr = A[reg].s32 + ReadOpWord(PC); PC += 2; return addr; // (d16,An)
case 6: return A[reg].s32 + GetIndex(); // (d8,An,Xn)
case 2: return (A + reg)->s32; // (An)
case 3: return (A + reg)->s32; // (An)+
case 4: return (A + reg)->s32; // -(An)
case 5: addr = (A + reg)->s32 + ReadOpWord(PC); PC += 2; return addr; // (d16,An)
case 6: return (A + reg)->s32 + GetIndex(); // (d8,An,Xn)
case 7:
switch (reg)
{
@ -316,32 +535,87 @@ namespace cpu.m68000
}
//void WriteValueB(int mode, int reg, sbyte value)
//{
// switch (mode)
// {
// case 0x00: // Dn
// D_ptr_reg->s8 = value;
// return;
// case 0x01: // An
// A_ptr_reg->s32 = value;
// return;
// case 0x02: // (An)
// WriteByte(A_ptr_reg->s32, value);
// return;
// case 0x03: // (An)+
// WriteByte(A_ptr_reg->s32, value);
// A_ptr_reg->s32 += reg == 7 ? 2 : 1;
// return;
// case 0x04: // -(An)
// A_ptr_reg->s32 -= reg == 7 ? 2 : 1;
// WriteByte(A_ptr_reg->s32, value);
// return;
// case 0x05: // (d16,An)
// WriteByte(A_ptr_reg->s32 + ReadOpWord(PC), value); PC += 2;
// return;
// case 0x06: // (d8,An,Xn)
// WriteByte(A_ptr_reg->s32 + GetIndex(), value);
// return;
// case 0x07:
// switch (reg)
// {
// case 0x00: // (imm).W
// WriteByte(ReadOpWord(PC), value); PC += 2;
// return;
// case 0x01: // (imm).L
// WriteByte(ReadOpLong(PC), value); PC += 4;
// return;
// case 0x02: // (d16,PC)
// WriteByte(PC + ReadOpWord(PC), value); PC += 2;
// return;
// case 0x03: // (d8,PC,Xn)
// int pc = PC;
// WriteByte(pc + PeekIndex(), value);
// PC += 2;
// return;
// default: throw new Exception("Invalid addressing mode!");
// }
// }
//}
void WriteValueB(int mode, int reg, sbyte value)
{
switch (mode)
{
case 0x00: // Dn
D[reg].s8 = value;
(D + reg)->s8 = value;
return;
case 0x01: // An
A[reg].s32 = value;
(A + reg)->s32 = value;
return;
case 0x02: // (An)
WriteByte(A[reg].s32, value);
WriteByte((A + reg)->s32, value);
return;
case 0x03: // (An)+
WriteByte(A[reg].s32, value);
A[reg].s32 += reg == 7 ? 2 : 1;
{
Register* ptr = A + reg;
WriteByte(ptr->s32, value);
ptr->s32 += reg == 7 ? 2 : 1;
}
return;
case 0x04: // -(An)
A[reg].s32 -= reg == 7 ? 2 : 1;
WriteByte(A[reg].s32, value);
{
Register* ptr = A + reg;
ptr->s32 -= reg == 7 ? 2 : 1;
WriteByte(ptr->s32, value);
}
return;
case 0x05: // (d16,An)
WriteByte(A[reg].s32 + ReadOpWord(PC), value); PC += 2;
WriteByte((A + reg)->s32 + ReadOpWord(PC), value); PC += 2;
return;
case 0x06: // (d8,An,Xn)
WriteByte(A[reg].s32 + GetIndex(), value);
WriteByte((A + reg)->s32 + GetIndex(), value);
return;
case 0x07:
switch (reg)
@ -365,32 +639,88 @@ namespace cpu.m68000
}
}
//void WriteValueW(int mode, int reg, short value)
//{
// switch (mode)
// {
// case 0x00: // Dn
// D_ptr_reg->s16 = value;
// return;
// case 0x01: // An
// A_ptr_reg->s32 = value;
// return;
// case 0x02: // (An)
// WriteWord(A_ptr_reg->s32, value);
// return;
// case 0x03: // (An)+
// WriteWord(A_ptr_reg->s32, value);
// A_ptr_reg->s32 += 2;
// return;
// case 0x04: // -(An)
// A_ptr_reg->s32 -= 2;
// WriteWord(A_ptr_reg->s32, value);
// return;
// case 0x05: // (d16,An)
// WriteWord(A_ptr_reg->s32 + ReadOpWord(PC), value); PC += 2;
// return;
// case 0x06: // (d8,An,Xn)
// WriteWord(A_ptr_reg->s32 + GetIndex(), value);
// return;
// case 0x07:
// switch (reg)
// {
// case 0x00: // (imm).W
// WriteWord(ReadOpWord(PC), value); PC += 2;
// return;
// case 0x01: // (imm).L
// WriteWord(ReadOpLong(PC), value); PC += 4;
// return;
// case 0x02: // (d16,PC)
// WriteWord(PC + ReadOpWord(PC), value); PC += 2;
// return;
// case 0x03: // (d8,PC,Xn)
// int pc = PC;
// WriteWord(pc + PeekIndex(), value);
// PC += 2;
// return;
// default: throw new Exception("Invalid addressing mode!");
// }
// }
//}
void WriteValueW(int mode, int reg, short value)
{
switch (mode)
{
case 0x00: // Dn
D[reg].s16 = value;
(D + reg)->s16 = value;
return;
case 0x01: // An
A[reg].s32 = value;
(A + reg)->s32 = value;
return;
case 0x02: // (An)
WriteWord(A[reg].s32, value);
WriteWord((A + reg)->s32, value);
return;
case 0x03: // (An)+
WriteWord(A[reg].s32, value);
A[reg].s32 += 2;
{
Register* ptr = A + reg;
WriteWord(ptr->s32, value);
ptr->s32 += 2;
}
return;
case 0x04: // -(An)
A[reg].s32 -= 2;
WriteWord(A[reg].s32, value);
{
Register* ptr = A + reg;
ptr->s32 -= 2;
WriteWord(ptr->s32, value);
}
return;
case 0x05: // (d16,An)
WriteWord(A[reg].s32 + ReadOpWord(PC), value); PC += 2;
WriteWord((A + reg)->s32 + ReadOpWord(PC), value); PC += 2;
return;
case 0x06: // (d8,An,Xn)
WriteWord(A[reg].s32 + GetIndex(), value);
WriteWord((A + reg)->s32 + GetIndex(), value);
return;
case 0x07:
switch (reg)
@ -419,27 +749,33 @@ namespace cpu.m68000
switch (mode)
{
case 0x00: // Dn
D[reg].s32 = value;
(D + reg)->s32 = value;
return;
case 0x01: // An
A[reg].s32 = value;
(A + reg)->s32 = value;
return;
case 0x02: // (An)
WriteLong(A[reg].s32, value);
WriteLong((A + reg)->s32, value);
return;
case 0x03: // (An)+
WriteLong(A[reg].s32, value);
A[reg].s32 += 4;
{
Register* ptr = A + reg;
WriteLong(ptr->s32, value);
ptr->s32 += 4;
}
return;
case 0x04: // -(An)
A[reg].s32 -= 4;
WriteLong(A[reg].s32, value);
{
Register* ptr = A + reg;
ptr->s32 -= 4;
WriteLong(ptr->s32, value);
}
return;
case 0x05: // (d16,An)
WriteLong(A[reg].s32 + ReadOpWord(PC), value); PC += 2;
WriteLong((A + reg)->s32 + ReadOpWord(PC), value); PC += 2;
return;
case 0x06: // (d8,An,Xn)
WriteLong(A[reg].s32 + GetIndex(), value);
WriteLong((A + reg)->s32 + GetIndex(), value);
return;
case 0x07:
switch (reg)
@ -485,9 +821,15 @@ namespace cpu.m68000
default: indexReg = 8; break;
}
if (da == 0)
indexReg *= size == 0 ? D[reg].s16 : D[reg].s32;
{
Register* D_ptr_reg = D + reg;
indexReg *= size == 0 ? D_ptr_reg->s16 : D_ptr_reg->s32;
}
else
indexReg *= size == 0 ? A[reg].s16 : A[reg].s32;
{
Register* A_ptr_reg = A + reg;
indexReg *= size == 0 ? A_ptr_reg->s16 : A_ptr_reg->s32;
}
return displacement + indexReg;
}
@ -513,9 +855,15 @@ namespace cpu.m68000
default: indexReg = 8; break;
}
if (da == 0)
indexReg *= size == 0 ? D[reg].s16 : D[reg].s32;
{
Register* D_ptr_reg = D + reg;
indexReg *= size == 0 ? D_ptr_reg->s16 : D_ptr_reg->s32;
}
else
indexReg *= size == 0 ? A[reg].s16 : A[reg].s32;
{
Register* A_ptr_reg = A + reg;
indexReg *= size == 0 ? A_ptr_reg->s16 : A_ptr_reg->s32;
}
return displacement + indexReg;
}

View File

@ -1,38 +1,133 @@
namespace cpu.m68000
{
partial class MC68000
{
static readonly int[,] MoveCyclesBW = new int[12, 9]
{
{ 4, 4, 8, 8, 8, 12, 14, 12, 16 },
{ 4, 4, 8, 8, 8, 12, 14, 12, 16 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 },
{ 10, 10, 14, 14, 14, 18, 20, 18, 22 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 14, 14, 18, 18, 18, 22, 24, 22, 26 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 16, 16, 20, 20, 20, 24, 26, 24, 28 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 14, 14, 18, 18, 18, 22, 24, 22, 26 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 }
};
using MAME.Core;
using System;
using System.Runtime.InteropServices;
static readonly int[,] MoveCyclesL = new int[12, 9]
namespace cpu.m68000
{
unsafe partial class MC68000
{
{ 4, 4, 12, 12, 12, 16, 18, 16, 20 },
{ 4, 4, 12, 12, 12, 16, 18, 16, 20 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 },
{ 14, 14, 22, 22, 22, 26, 28, 26, 30 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 18, 18, 26, 26, 26, 30, 32, 30, 34 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 20, 20, 28, 28, 28, 32, 34, 32, 36 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 18, 18, 26, 26, 26, 30, 32, 30, 34 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 }
void InitMC68000Tables()
{
Init_MoveCyclesBW();
Init_MoveCyclesL();
}
//static readonly int[,] MoveCyclesBW = new int[12, 9]
//{
// { 4, 4, 8, 8, 8, 12, 14, 12, 16 },
// { 4, 4, 8, 8, 8, 12, 14, 12, 16 },
// { 8, 8, 12, 12, 12, 16, 18, 16, 20 },
// { 8, 8, 12, 12, 12, 16, 18, 16, 20 },
// { 10, 10, 14, 14, 14, 18, 20, 18, 22 },
// { 12, 12, 16, 16, 16, 20, 22, 20, 24 },
// { 14, 14, 18, 18, 18, 22, 24, 22, 26 },
// { 12, 12, 16, 16, 16, 20, 22, 20, 24 },
// { 16, 16, 20, 20, 20, 24, 26, 24, 28 },
// { 12, 12, 16, 16, 16, 20, 22, 20, 24 },
// { 14, 14, 18, 18, 18, 22, 24, 22, 26 },
// { 8, 8, 12, 12, 12, 16, 18, 16, 20 }
//};
//取值范例 Columns = 9 ; i* Columns + j
const int MoveCyclesBW_len_1 = 12;
const int MoveCyclesBW_Columns = 9;
#region //指针化 MoveCyclesBW
static byte[] MoveCyclesBW_src;
static GCHandle MoveCyclesBW_handle;
public static byte* MoveCyclesBW;
public static int MoveCyclesBWLength;
public static bool MoveCyclesBW_IsNull => MoveCyclesBW == null;
public static byte[] MoveCyclesBW_set
{
set
{
MoveCyclesBW_handle.ReleaseGCHandle();
MoveCyclesBW_src = value;
MoveCyclesBWLength = value.Length;
MoveCyclesBW_src.GetObjectPtr(ref MoveCyclesBW_handle, ref MoveCyclesBW);
}
}
static void Init_MoveCyclesBW()
{
MoveCyclesBW_set = new byte[]
{
4, 4, 8, 8, 8, 12, 14, 12, 16,
4, 4, 8, 8, 8, 12, 14, 12, 16,
8, 8, 12, 12, 12, 16, 18, 16, 20,
8, 8, 12, 12, 12, 16, 18, 16, 20,
10, 10, 14, 14, 14, 18, 20, 18, 22,
12, 12, 16, 16, 16, 20, 22, 20, 24,
14, 14, 18, 18, 18, 22, 24, 22, 26,
12, 12, 16, 16, 16, 20, 22, 20, 24,
16, 16, 20, 20, 20, 24, 26, 24, 28,
12, 12, 16, 16, 16, 20, 22, 20, 24,
14, 14, 18, 18, 18, 22, 24, 22, 26,
8, 8, 12, 12, 12, 16, 18, 16, 20
};
}
#endregion
//static readonly int[,] MoveCyclesL = new int[12, 9]
//{
// { 4, 4, 12, 12, 12, 16, 18, 16, 20 },
// { 4, 4, 12, 12, 12, 16, 18, 16, 20 },
// { 12, 12, 20, 20, 20, 24, 26, 24, 28 },
// { 12, 12, 20, 20, 20, 24, 26, 24, 28 },
// { 14, 14, 22, 22, 22, 26, 28, 26, 30 },
// { 16, 16, 24, 24, 24, 28, 30, 28, 32 },
// { 18, 18, 26, 26, 26, 30, 32, 30, 34 },
// { 16, 16, 24, 24, 24, 28, 30, 28, 32 },
// { 20, 20, 28, 28, 28, 32, 34, 32, 36 },
// { 16, 16, 24, 24, 24, 28, 30, 28, 32 },
// { 18, 18, 26, 26, 26, 30, 32, 30, 34 },
// { 12, 12, 20, 20, 20, 24, 26, 24, 28 }
//};
const int MoveCyclesL_len_1 = 12;
const int MoveCyclesL_Columns = 9;
#region //指针化 MoveCyclesL
static byte[] MoveCyclesL_src;
static GCHandle MoveCyclesL_handle;
public static byte* MoveCyclesL;
public static int MoveCyclesLLength;
public static bool MoveCyclesL_IsNull => MoveCyclesL == null;
public static byte[] MoveCyclesL_set
{
set
{
MoveCyclesL_handle.ReleaseGCHandle();
MoveCyclesL_src = value;
MoveCyclesLLength = value.Length;
MoveCyclesL_src.GetObjectPtr(ref MoveCyclesL_handle, ref MoveCyclesL);
}
}
static void Init_MoveCyclesL()
{
MoveCyclesL_set = new byte[]
{
4, 4, 12, 12, 12, 16, 18, 16, 20 ,
4, 4, 12, 12, 12, 16, 18, 16, 20 ,
12, 12, 20, 20, 20, 24, 26, 24, 28 ,
12, 12, 20, 20, 20, 24, 26, 24, 28 ,
14, 14, 22, 22, 22, 26, 28, 26, 30 ,
16, 16, 24, 24, 24, 28, 30, 28, 32 ,
18, 18, 26, 26, 26, 30, 32, 30, 34 ,
16, 16, 24, 24, 24, 28, 30, 28, 32 ,
20, 20, 28, 28, 28, 32, 34, 32, 36 ,
16, 16, 24, 24, 24, 28, 30, 28, 32 ,
18, 18, 26, 26, 26, 30, 32, 30, 34 ,
12, 12, 20, 20, 20, 24, 26, 24, 28
};
}
#endregion
static readonly int[,] EACyclesBW = new int[8, 8]
{

View File

@ -2350,7 +2350,8 @@ namespace MAME.Core
}
public static void cpuexec_timeslice()
{
Atime target = EmuTimer.lt[0].expire;
//Atime target = EmuTimer.lt[0].expire;
Atime target = EmuTimer.lt._frist_Timer.expire;
Atime tbase = EmuTimer.global_basetime;
int ran;
Atime at;

View File

@ -1,85 +1,252 @@
using cpu.m6800;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using static MAME.Core.EmuTimer;
namespace MAME.Core
{
//public class EmuTimerLister
//{
// List<emu_timer> timerlist;
// public int Count = 0;
// //缓存首个元素
// public emu_timer _frist_Timer;
// public emu_timer this[int index]
// {
// get { return timerlist[index]; }
// //set { timerlist[index] = value; } //不需要set
// }
// public static void GetNewTimerLister(ref EmuTimerLister tlistObj)
// {
// //如果新旧值替换
// if (tlistObj != null)
// {
// tlistObj.ReleaseLister();
// ObjectPoolAuto.Release(tlistObj);
// tlistObj = null;
// }
// tlistObj = ObjectPoolAuto.Acquire<EmuTimerLister>();
// tlistObj.InitLister();
// }
// void InitLister()
// {
// ReleaseLister();
// //对象池产生list
// timerlist = ObjectPoolAuto.AcquireList<emu_timer>();
// Count = 0;
// _frist_Timer = null;
// }
// void ReleaseLister()
// {
// if (timerlist != null)
// {
// Clear();
// //对象池回收
// ObjectPoolAuto.Release(timerlist);
// timerlist = null;
// }
// }
// public List<emu_timer> GetSnapshotList()
// {
// return timerlist;
// }
// public void Clear()
// {
// //遍历所有timer减少引用计数后Clear
// for (int i = 0; i < Count; i++)
// timerlist[i].ReleaseRef();//timer引用计数-1
// timerlist.Clear();
// Count = 0;
// _frist_Timer = null;
// }
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void Add(emu_timer timer)
// {
// timerlist.Add(timer);
// timer.AddRef();//timer引用计数+1
// Count++;
// if (Count == 0)
// _frist_Timer = timer;
// }
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void Remove(emu_timer timer)
// {
// timerlist.Remove(timer);
// timer.ReleaseRef();//timer引用计数-1
// Count--;
// if(Count == 0)
// _frist_Timer = null;
// else if(timer == _frist_Timer)
// _frist_Timer = timerlist[0];
// }
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void Insert(int index, emu_timer timer)
// {
// timerlist.Insert(index, timer);
// timer.AddRef();//timer引用计数+1
// Count++;
// if (index == 0)
// _frist_Timer = timer;
// }
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void RemoveAt(int index)
// {
// timerlist[index].ReleaseRef();//timer引用计数-1
// timerlist.RemoveAt(index);
// Count--;
// if (index == 0)
// {
// if (Count == 0)
// _frist_Timer = null;
// else
// _frist_Timer = timerlist[0];
// }
// }
// //不考虑且禁止使用 IndexOf这种低效的使用方式
// //public int IndexOf(emu_timer timer)
// //{
// // return timerlist.IndexOf(timer);
// //}
//}
public class EmuTimerLister
{
public emu_timer this[int index]
private emu_timer[] timerArray;
private int capacity;
public int Count;
public emu_timer _frist_Timer;
public EmuTimerLister()
{
get { return timerlist[index]; }
set { timerlist[index] = value; } // 如果需要设置的话
capacity = 16;
timerArray = new emu_timer[capacity];
Count = 0;
_frist_Timer = null;
}
public static void GetNewTimerLister(ref EmuTimerLister tlistObj)
{
//如果新旧值替换
if (tlistObj != null)
{
tlistObj.ReleaseLister();
ObjectPoolAuto.Release(tlistObj);
tlistObj = null;
}
tlistObj = ObjectPoolAuto.Acquire<EmuTimerLister>();
tlistObj = new EmuTimerLister();
tlistObj.InitLister();
}
List<emu_timer> timerlist;
public List<emu_timer> GetSrcList()
{
return timerlist;
}
public int Count
{
get { return timerlist.Count; }
}
void InitLister()
public void InitLister()
{
ReleaseLister();
timerlist = ObjectPoolAuto.AcquireList<emu_timer>();
capacity = 16;
timerArray = new emu_timer[capacity];
Count = 0;
_frist_Timer = null;
}
void ReleaseLister()
public void ReleaseLister()
{
if (timerlist != null)
if (timerArray != null)
{
Clear();
ObjectPoolAuto.Release(timerlist);
timerlist = null;
timerArray = null;
}
}
public List<emu_timer> GetSnapshotList()
{
var list = new List<emu_timer>(Count);
for (int i = 0; i < Count; i++)
{
list.Add(timerArray[i]);
}
return list;
}
public void Clear()
{
emu_timer.ClearList(ref timerlist);
for (int i = 0; i < Count; i++)
{
timerArray[i].ReleaseRef();
timerArray[i] = null;
}
Count = 0;
_frist_Timer = null;
}
public emu_timer this[int index] => timerArray[index];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnsureCapacity()
{
if (Count >= capacity)
{
capacity *= 2;
Array.Resize(ref timerArray, capacity);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(emu_timer timer)
{
emu_timer.AddList(ref timerlist, ref timer);
EnsureCapacity();
timerArray[Count] = timer;
timer.AddRef();
if (Count == 0)
_frist_Timer = timer;
Count++;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Remove(emu_timer timer)
{
emu_timer.RemoveToList(ref timerlist, ref timer);
for (int i = 0; i < Count; i++)
{
if (timerArray[i] == timer)
{
RemoveAt(i);
return;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Insert(int index, emu_timer timer)
{
emu_timer.InsertToList(ref timerlist, index, ref timer);
}
public int IndexOf(emu_timer timer)
EnsureCapacity();
if (index < Count)
{
return timerlist.IndexOf(timer);
Array.Copy(timerArray, index, timerArray, index + 1, Count - index);
}
timerArray[index] = timer;
timer.AddRef();
Count++;
if (index == 0)
_frist_Timer = timer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveAt(int index)
{
emu_timer.RemoveAtToList(ref timerlist, index);
emu_timer timer = timerArray[index];
timer.ReleaseRef();
if (index < Count - 1)
{
Array.Copy(timerArray, index + 1, timerArray, index, Count - index - 1);
}
timerArray[Count - 1] = null;
Count--;
if (Count == 0)
_frist_Timer = null;
else if (index == 0)
_frist_Timer = timerArray[0];
}
}
public class EmuTimer
{
public static EmuTimerLister lt;
@ -136,7 +303,6 @@ namespace MAME.Core
static Queue<emu_timer> _readyToRelease = new Queue<emu_timer>();
static Queue<emu_timer> _timerPool = new Queue<emu_timer>();
static int outTimerAllCount = 0;
static int newTimerCount = 0;
public static emu_timer GetEmu_timerNoRef()
@ -154,7 +320,6 @@ namespace MAME.Core
outTimerAllCount++;
return obj;
}
public static void CheckReadyRelaseBeforeFrameRun()
{
if (_readyToRelease.Count < 1)
@ -174,23 +339,19 @@ namespace MAME.Core
//UnityEngine.Debug.Log($"CheckReadyRelaseAfterRun 检查数量{checkcount}| 出池数量{outTimerAllCount}其中new创建的数量{newTimerCount} 回收数量{releaseCount} ,处理前池数量{beforpoolcount},处理后池数量{_timerPool.Count}");
outTimerAllCount = 0;
newTimerCount = 0;
//_readyToRelease.Clear();
}
/// <summary>
/// 增加引用计数
/// </summary>
void AddRef()
public void AddRef()
{
//int newCount = Interlocked.Increment(ref _refCount);
_refCount++;
}
/// <summary>
/// 减少引用计数当计数为0时释放对象回池
/// </summary>
void ReleaseRef()
public void ReleaseRef()
{
//int newCount = Interlocked.Decrement(ref _refCount);
_refCount--;
@ -205,7 +366,6 @@ namespace MAME.Core
throw new InvalidOperationException("引用计数出现负数");
}
}
void ReadyToRelease()
{
if (this._inReadyQueue) return;
@ -213,7 +373,6 @@ namespace MAME.Core
this._inReadyQueue = true;
_readyToRelease.Enqueue(this);
}
/// <summary>
/// 释放资源并回池
/// </summary>
@ -245,32 +404,31 @@ namespace MAME.Core
timer = null;
}
}
public static void AddList(ref List<emu_timer> list, ref emu_timer timer)
{
list.Add(timer);
timer.AddRef();
}
internal static void InsertToList(ref List<emu_timer> list, int index, ref emu_timer timer)
{
list.Insert(index, timer);
timer.AddRef();
}
public static void RemoveToList(ref List<emu_timer> list, ref emu_timer timer)
{
list.Remove(timer);
timer.ReleaseRef();
}
internal static void ClearList(ref List<emu_timer> list)
{
for (int i = 0; i < list.Count; i++)
list[i].ReleaseRef();
list.Clear();
}
internal static void RemoveAtToList(ref List<emu_timer> list, int index)
{
list.RemoveAt(index);
}
//public static void AddList(ref List<emu_timer> list, ref emu_timer timer)
//{
// list.Add(timer);
// timer.AddRef();
//}
//internal static void InsertToList(ref List<emu_timer> list, int index, ref emu_timer timer)
//{
// list.Insert(index, timer);
// timer.AddRef();
//}
//public static void RemoveToList(ref List<emu_timer> list, ref emu_timer timer)
//{
// list.Remove(timer);
// timer.ReleaseRef();
//}
//internal static void ClearList(ref List<emu_timer> list)
//{
// for (int i = 0; i < list.Count; i++)
// list[i].ReleaseRef();
// list.Clear();
//}
//internal static void RemoveAtToList(ref List<emu_timer> list, int index)
//{
// list.RemoveAt(index);
//}
#endregion
/*
static void EnqueueObj(emu_timer obj)
@ -720,7 +878,8 @@ namespace MAME.Core
//timer_list_insert(which);
//if (lt.IndexOf(which) == 0)
if (lt[0] == which)
//if (lt[0] == which)
if (lt._frist_Timer == which)
{
if (Cpuexec.activecpu >= 0 && Cpuexec.activecpu < Cpuexec.ncpu)
{
@ -952,24 +1111,14 @@ namespace MAME.Core
{
TIME_ACT currAct = timer1.action;
int i1 = -1;
var tlist = lt.GetSrcList();
int scanCount;
int tempMaxIdx = tlist.Count - 1;
int tempMaxIdx = lt.Count - 1;
if (currAct == TIME_ACT.Cpuint_cpunum_empty_event_queue || currAct == TIME_ACT.setvector)
{
//foreach (emu_timer et in lt)
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == currAct && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
// {
// i1 = lt.IndexOf(et);
// break;
// }
//}
scanCount = 0;
while (scanCount >= tempMaxIdx)
{
emu_timer et = tlist[scanCount];
emu_timer et = lt[scanCount];
if (et.action == currAct && Attotime.attotime_compare(et.expire, global_basetime) <= 0)
{
i1 = scanCount;
@ -984,7 +1133,7 @@ namespace MAME.Core
scanCount = 0;
while (scanCount <= tempMaxIdx)
{
emu_timer et = tlist[scanCount];
emu_timer et = lt[scanCount];
if (Attotime.attotime_compare(et.expire, expire) > 0)
break;
scanCount++;
@ -1043,47 +1192,27 @@ namespace MAME.Core
{
if (timer1.action == TIME_ACT.Cpuint_cpunum_empty_event_queue || timer1.action == TIME_ACT.setvector)
{
//timer_list_remove_lt1.Clear();
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
// timer_list_remove_lt1.Add(et);
//}
//foreach (emu_timer et1 in timer_list_remove_lt1)
// lt.Remove(et1);
var tlist = lt.GetSrcList();
int tempMaxIdx = tlist.Count - 1;
int tempMaxIdx = lt.Count - 1;
while (tempMaxIdx >= 0)
{
emu_timer et = tlist[tempMaxIdx];
emu_timer et = lt[tempMaxIdx];
if (et.action == timer1.action && Attotime.attotime_compare(et.expire, timer1.expire) == 0)
lt.Remove(et);
{
lt.RemoveAt(tempMaxIdx);
}
tempMaxIdx--;
}
}
else
{
//TODO MAME.NET原来这么foreach写删除是有问题的
//foreach (emu_timer et in lt)
//foreach (emu_timer et in lt.GetSrcList())
//{
// if (et.action == timer1.action)
// {
// lt.Remove(et);
// break;
// }
//}
var tlist = lt.GetSrcList();
int tempMaxIdx = tlist.Count - 1;
int tempMaxIdx = lt.Count - 1;
int scanCount = 0;
while (scanCount <= tempMaxIdx)
{
emu_timer et = tlist[scanCount];
emu_timer et = lt[scanCount];
if (et.action == timer1.action)
{
lt.Remove(et);
lt.RemoveAt(scanCount);
break;
}
scanCount++;
@ -1128,10 +1257,13 @@ namespace MAME.Core
{
emu_timer timer;
global_basetime = newbase;
while (Attotime.attotime_compare(lt[0].expire, global_basetime) <= 0)
//while (Attotime.attotime_compare(lt[0].expire, global_basetime) <= 0)
while (Attotime.attotime_compare(lt._frist_Timer.expire, global_basetime) <= 0)
{
bool was_enabled = lt[0].enabled;
timer = lt[0];
//bool was_enabled = lt[0].enabled;
bool was_enabled = lt._frist_Timer.enabled;
//timer = lt[0];
timer = lt._frist_Timer;
if (Attotime.attotime_compare(timer.period, Attotime.ATTOTIME_ZERO) == 0 || Attotime.attotime_compare(timer.period, Attotime.ATTOTIME_NEVER) == 0)
{
timer.enabled = false;
@ -1164,6 +1296,7 @@ namespace MAME.Core
}
}
}
//public static emu_timer timer_alloc_common(TIME_ACT action, bool temp)
//{
// Atime time = get_current_time();
@ -1188,16 +1321,6 @@ namespace MAME.Core
/// <param name="temp"></param>
public static void timer_alloc_common(ref emu_timer refattr, TIME_ACT action, bool temp)
{
//Atime time = get_current_time();
//emu_timer timer = emu_timer.GetEmu_timerNoRef();
//timer.action = action;
//timer.enabled = false;
//timer.temporary = temp;
//timer.period = Attotime.ATTOTIME_ZERO;
////timer.func = func;
//timer.start = time;
//timer.expire = Attotime.ATTOTIME_NEVER;
//timer_list_insert(timer);
emu_timer timer = timer_alloc_common_NoRef(action, temp);
emu_timer.SetRefUsed(ref refattr, ref timer);
}

View File

@ -418,6 +418,12 @@ namespace MAME.Core
set_TempBuffer = new byte[0x40000];
}
public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref cpu.m68000.Register* ptr)
{
IntPtr intptr;
GetObjectPtr(srcObj, ref handle, out intptr);
ptr = (cpu.m68000.Register*)intptr;
}
public static void GetObjectPtr(this object srcObj, ref GCHandle handle, ref uint* ptr)
{
IntPtr intptr;

View File

@ -133,19 +133,31 @@
int startY = Video.offsety;
int endY = Video.offsety + Video.height;
int * bitmapcolorRect_target = &bitmapcolorRect[target_i];
if (single_step || Mame.paused)
{
byte bright = 0xa7;
for (y = startY; y < endY; y++)
{
int stepIndex = y * Video.fullwidth;
ushort* curbitmap_stepIndex = &curbitmap[stepIndex + startX];
for (x = startX; x < endX; x++, target_i++)
{
i = stepIndex + x;
red = (int)(((entry_color[curbitmap[i]] & 0xff0000) >> 16) * bright / 0xff);
green = (int)(((entry_color[curbitmap[i]] & 0xff00) >> 8) * bright / 0xff);
blue = (int)((entry_color[curbitmap[i]] & 0xff) * bright / 0xff);
bitmapcolorRect[target_i] = (int)Palette.make_argb(0xff, red, green, blue);
//i = stepIndex + x;
//red = (int)(((entry_color[curbitmap[i]] & 0xff0000) >> 16) * bright / 0xff);
//green = (int)(((entry_color[curbitmap[i]] & 0xff00) >> 8) * bright / 0xff);
//blue = (int)((entry_color[curbitmap[i]] & 0xff) * bright / 0xff);
red = (int)(((entry_color[*curbitmap_stepIndex] & 0xff0000) >> 16) * bright / 0xff);
green = (int)(((entry_color[*curbitmap_stepIndex] & 0xff00) >> 8) * bright / 0xff);
blue = (int)((entry_color[*curbitmap_stepIndex] & 0xff) * bright / 0xff);
//bitmapcolorRect[target_i] = (int)Palette.make_argb(0xff, red, green, blue);
*bitmapcolorRect_target = (int)Palette.make_argb(0xff, red, green, blue);
bitmapcolorRect_target++;
curbitmap_stepIndex++;
}
}
}
@ -155,10 +167,15 @@
for (y = startY; y < endY; y++)
{
int stepIndex = y * Video.fullwidth;
ushort* curbitmap_stepIndex = &curbitmap[stepIndex + startX];
for (x = startX; x < endX; x++, target_i++)
{
i = stepIndex + x;
bitmapcolorRect[target_i] = (int)entry_color[curbitmap[i]];
//i = stepIndex + x;
//bitmapcolorRect[target_i] = (int)entry_color[curbitmap[i]];
//*bitmapcolorRect_target = (int)entry_color[curbitmap[i]];
*bitmapcolorRect_target = (int)entry_color[*curbitmap_stepIndex];
bitmapcolorRect_target++;
curbitmap_stepIndex++;
}
}
@ -312,21 +329,34 @@
int endX = Video.offsetx + Video.width;
int startY = Video.offsety;
int endY = Video.offsety + Video.height;
int* bitmapbaseN_curbitmap_0_Ptrs = &Video.bitmapbaseN_Ptrs[Video.curbitmap][0];
int* bitmapcolorRect_Ptrunsafe_Ptr = &Video.bitmapcolorRect_Ptrunsafe[target_i];
if (single_step || Mame.paused)
{
byte bright = 0xa7;
for (y = startY; y < endY; y++)
{
int stepIndex = y * Video.fullwidth;
int* stepIndex_Ptr = &bitmapbaseN_curbitmap_0_Ptrs[stepIndex + startX];
for (x = startX; x < endX; x++, target_i++)
{
//i = y * Video.fullwidth + x;
i = stepIndex + x;
red = ((Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff0000) >> 16) * bright / 0xff;
green = ((Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff00) >> 8) * bright / 0xff;
blue = (Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff) * bright / 0xff;
//i = stepIndex + x;
//red = ((Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff0000) >> 16) * bright / 0xff;
//green = ((Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff00) >> 8) * bright / 0xff;
//blue = (Video.bitmapbaseN_Ptrs[Video.curbitmap][i] & 0xff) * bright / 0xff;
int bitmapbaseN_curbitmap_i_value = *stepIndex_Ptr;
red = ((bitmapbaseN_curbitmap_i_value & 0xff0000) >> 16) * bright / 0xff;
green = ((bitmapbaseN_curbitmap_i_value & 0xff00) >> 8) * bright / 0xff;
blue = (bitmapbaseN_curbitmap_i_value & 0xff) * bright / 0xff;
//Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)Palette.make_argb(0xff, red, green, blue);
Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)((((uint)(0xff) & 0xff) << 24) | (((uint)(blue) & 0xff) << 16) | (((uint)(green) & 0xff) << 8) | ((uint)(red) & 0xff));
//Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)((((uint)(0xff) & 0xff) << 24) | (((uint)(blue) & 0xff) << 16) | (((uint)(green) & 0xff) << 8) | ((uint)(red) & 0xff));
*bitmapcolorRect_Ptrunsafe_Ptr = (int)((((uint)(0xff) & 0xff) << 24) | (((uint)(blue) & 0xff) << 16) | (((uint)(green) & 0xff) << 8) | ((uint)(red) & 0xff));
bitmapcolorRect_Ptrunsafe_Ptr++;
stepIndex_Ptr++;
}
}
}
@ -335,11 +365,16 @@
for (y = startY; y < endY; y++)
{
int stepIndex = y * Video.fullwidth;
int* stepIndex_Ptr = &bitmapbaseN_curbitmap_0_Ptrs[stepIndex + startX];
for (x = startX; x < endX; x++, target_i++)
{
//i = y * Video.fullwidth + x;
i = stepIndex + x;
Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)(0xff000000 | (uint)Video.bitmapbaseN_Ptrs[Video.curbitmap][i]);
//i = stepIndex + x;
//Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)(0xff000000 | (uint)Video.bitmapbaseN_Ptrs[Video.curbitmap][i]);
//Video.bitmapcolorRect_Ptrunsafe[target_i] = (int)(0xff000000 | (uint)bitmapbaseN_curbitmap_0_Ptrs[i]);
*bitmapcolorRect_Ptrunsafe_Ptr = (int)(0xff000000 | (uint)*stepIndex_Ptr);
bitmapcolorRect_Ptrunsafe_Ptr++;
stepIndex_Ptr++;
}
}
}

View File

@ -42,8 +42,22 @@
{
Mame.mame_schedule_soft_reset();
}
static long LastCheckFrame;
static int frame_reset_count;
const byte maxLimitReset_everyFrame = 1;
public static void watchdog_reset()
{
if (LastCheckFrame != Video.screenstate.frame_number)
{
LastCheckFrame = Video.screenstate.frame_number;
//UnityEngine.Debug.Log($"上一帧数跳过watchdog_reset:{frame_reset_count}次");
frame_reset_count = 0;
}
frame_reset_count++;
if (frame_reset_count > maxLimitReset_everyFrame)
return;
if (!watchdog_enabled)
{
EmuTimer.timer_adjust_periodic(watchdog_timer, Attotime.ATTOTIME_NEVER, Attotime.ATTOTIME_NEVER);
@ -57,5 +71,20 @@
EmuTimer.timer_adjust_periodic(watchdog_timer, new Atime(3, 0), Attotime.ATTOTIME_NEVER);
}
}
//public static void watchdog_reset()
//{
// if (!watchdog_enabled)
// {
// EmuTimer.timer_adjust_periodic(watchdog_timer, Attotime.ATTOTIME_NEVER, Attotime.ATTOTIME_NEVER);
// }
// else if (Attotime.attotime_compare(watchdog_time, Attotime.ATTOTIME_ZERO) != 0)
// {
// EmuTimer.timer_adjust_periodic(watchdog_timer, watchdog_time, Attotime.ATTOTIME_NEVER);
// }
// else
// {
// EmuTimer.timer_adjust_periodic(watchdog_timer, new Atime(3, 0), Attotime.ATTOTIME_NEVER);
// }
//}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace MAME.Core
{

View File

@ -350,11 +350,113 @@ namespace MAME.Core
}
else
{
// 直接调用绘制函数,避免中间计算[3](@ref)
Drawgfx.common_drawgfx_m92(gfx21rom, sprite + s_ptr, colour, fx, fy,
current_x, y - i * 16, cliprect, draw_flags);
Drawgfx.common_drawgfx_m92(gfx21rom, sprite + s_ptr, colour, fx, fy,
current_x - SCREEN_WIDTH, y - i * 16, cliprect, draw_flags);
//// 直接调用绘制函数,避免中间计算[3](@ref)
//Drawgfx.common_drawgfx_m92(gfx21rom, sprite + s_ptr, colour, fx, fy,
// current_x, y - i * 16, cliprect, draw_flags);
//Drawgfx.common_drawgfx_m92(gfx21rom, sprite + s_ptr, colour, fx, fy,
// current_x - SCREEN_WIDTH, y - i * 16, cliprect, draw_flags);
//手动内联
//--start
//参数common_drawgfx_m92(byte* bb1, int code, int color, int flipx, int flipy, int sx, int sy, RECT clip, uint primask)
// 使用常量折叠和预计算[5](@ref)
int code = sprite + s_ptr;
int color = colour;
int colorbase = color << 4; // 用移位代替乘法 0x10 * color
int flipx = fx;
int flipy = fy;
RECT clip = cliprect;
uint primask = draw_flags;
const int TEMP1 = 0x10 - 1; // 15
const int TEMP3 = 0x100 - 1; // 255
const int TEMP4 = 0x200 - 1; // 511
//第1次调用
{
int sx_1st = current_x;
int sy_1st = y - i * 16;
int ox = sx_1st;
int oy = sy_1st;
int ex = sx_1st + TEMP1;
// 边界检查优化:减少分支预测错误[5](@ref)
sx_1st = sx_1st < 0 ? 0 : sx_1st;
sx_1st = sx_1st < clip.min_x ? clip.min_x : sx_1st;
ex = ex >= 0x200 ? TEMP4 : ex;
ex = ex > clip.max_x ? clip.max_x : ex;
if (sx_1st > ex)
{
}
else
{
int ey = sy_1st + TEMP1;
sy_1st = sy_1st < 0 ? 0 : sy_1st;
sy_1st = sy_1st < clip.min_y ? clip.min_y : sy_1st;
ey = ey >= 0x100 ? TEMP3 : ey;
ey = ey > clip.max_y ? clip.max_y : ey;
if (sy_1st > ey)
{
}
else
{
// 使用局部变量避免重复计算[2,4](@ref)
int ls = sx_1st - ox;
int ts = sy_1st - oy;
int dw = ex - sx_1st + 1;
int dh = ey - sy_1st + 1;
// 内联关键函数调用
Drawgfx.blockmove_8toN_transpen_pri16_m92(gfx21rom, code, 0x10, 0x10, 0x10, ls, ts, flipx, flipy, dw, dh, colorbase, sy_1st, sx_1st, primask);
}
}
}
//第2次调用
{
int sx_2nd = current_x - SCREEN_WIDTH;
int sy_2nd = y - i * 16;
int ox = sx_2nd;
int oy = sy_2nd;
int ex = sx_2nd + TEMP1;
// 边界检查优化:减少分支预测错误[5](@ref)
sx_2nd = sx_2nd < 0 ? 0 : sx_2nd;
sx_2nd = sx_2nd < clip.min_x ? clip.min_x : sx_2nd;
ex = ex >= 0x200 ? TEMP4 : ex;
ex = ex > clip.max_x ? clip.max_x : ex;
if (sx_2nd > ex) { }
else
{
int ey = sy_2nd + TEMP1;
sy_2nd = sy_2nd < 0 ? 0 : sy_2nd;
sy_2nd = sy_2nd < clip.min_y ? clip.min_y : sy_2nd;
ey = ey >= 0x100 ? TEMP3 : ey;
ey = ey > clip.max_y ? clip.max_y : ey;
if (sy_2nd > ey) { }
else
{
// 使用局部变量避免重复计算[2,4](@ref)
int ls = sx_2nd - ox;
int ts = sy_2nd - oy;
int dw = ex - sx_2nd + 1;
int dh = ey - sy_2nd + 1;
// 内联关键函数调用
Drawgfx.blockmove_8toN_transpen_pri16_m92(gfx21rom, code, 0x10, 0x10, 0x10, ls, ts, flipx, flipy, dw, dh, colorbase, sy_2nd, sx_2nd, primask);
}
}
}
//--end
}
// 优化指针更新

View File

@ -175,47 +175,192 @@ namespace MAME.Core
}
return result;
}
public static short MReadOpWord(int address)
//public static short MReadOpWord(int address)
//{
// address &= 0xffffff;
// short result = 0;
// if (address >= 0x000000 && address + 1 <= 0x00007f)
// {
// if (main_cpu_vector_table_source == 0)
// {
// result = (short)(mainbiosrom[address] * 0x100 + mainbiosrom[address + 1]);
// }
// else if (main_cpu_vector_table_source == 1)
// {
// result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
// }
// }
// else if (address >= 0x000080 && address + 1 <= 0x0fffff)
// {
// if (address >= 0x142B9 && address <= 0x142C9)
// {
// //m68000Form.iStatus = 1;
// }
// result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
// }
// else if (address >= 0x100000 && address + 1 <= 0x1fffff)
// {
// result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
// }
// else if (address >= 0x200000 && address + 1 <= 0x2fffff)
// {
// result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
// }
// else if (address >= 0xc00000 && address + 1 <= 0xcfffff)
// {
// result = (short)(mainbiosrom[address & 0x1ffff] * 0x100 + mainbiosrom[(address & 0x1ffff) + 1]);
// }
// else
// {
// result = 0;
// }
// return result;
//}
//手动优化
public unsafe static short MReadOpWord(int address)
{
address &= 0xffffff;
short result = 0;
if (address >= 0x000000 && address + 1 <= 0x00007f)
{
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + (address);
if (main_cpu_vector_table_source == 0)
{
result = (short)(mainbiosrom[address] * 0x100 + mainbiosrom[address + 1]);
return (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (main_cpu_vector_table_source == 1)
{
result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
return (short)(*ptr * 0x100 + *(ptr + 1));
}
return 0;
}
else if (address >= 0x000080 && address + 1 <= 0x0fffff)
{
if (address >= 0x142B9 && address <= 0x142C9)
{
//m68000Form.iStatus = 1;
}
result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + (address);
//if (address >= 0x142B9 && address <= 0x142C9)
//{
// //m68000Form.iStatus = 1;
//}
return (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0x100000 && address + 1 <= 0x1fffff)
{
result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
byte* ptr_0 = &Memory.mainram[0];
byte* ptr = ptr_0 + (address & 0xffff);
//result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
return (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0x200000 && address + 1 <= 0x2fffff)
{
result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + (main_cpu_bank_address + (address & 0xfffff));
//result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
return (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0xc00000 && address + 1 <= 0xcfffff)
{
result = (short)(mainbiosrom[address & 0x1ffff] * 0x100 + mainbiosrom[(address & 0x1ffff) + 1]);
byte* ptr_0 = &mainbiosrom[0];
byte* ptr = ptr_0 + (address & 0x1ffff);
return (short)(*ptr * 0x100 + *(ptr + 1));
}
else
{
result = 0;
return 0;
}
return result;
}
//public static short MReadWord(int address)
//{
// address &= 0xffffff;
// short result = 0;
// if (address >= 0x000000 && address + 1 <= 0x00007f)
// {
// if (main_cpu_vector_table_source == 0)
// {
// result = (short)(mainbiosrom[address] * 0x100 + mainbiosrom[address + 1]);
// }
// else if (main_cpu_vector_table_source == 1)
// {
// result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
// }
// }
// else if (address >= 0x000080 && address + 1 <= 0x0fffff)
// {
// if (address >= 0x142B9 && address <= 0x142C9)
// {
// //m68000Form.iStatus = 1;
// }
// result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
// }
// else if (address >= 0x100000 && address + 1 <= 0x1fffff)
// {
// if (address == 0x101410)
// {
// int i1 = 1;
// }
// result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
// }
// else if (address >= 0x200000 && address <= 0x2fffff)
// {
// result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
// }
// /*else if (address >= 0x300000 && address <= 0x300001)
// {
// result = (short)((ushort)short0 | dsw);
// }
// else if (address >= 0x300080 && address <= 0x300081)
// {
// result = short4;
// }*/
// else if (address >= 0x300000 && address <= 0x31ffff)
// {
// int add = address & 0x81;
// if (add >= 0x00 && add + 1 <= 0x01)
// {
// result = (short)((ushort)short0 | dsw);
// }
// else if (add >= 0x80 && add + 1 <= 0x81)
// {
// result = short4;
// }
// }
// else if (address >= 0x320000 && address <= 0x33ffff)
// {
// result = (short)((ushort)short3 | (ushort)((get_calendar_status() & 0x03) << 6) | (get_audio_result() << 8));
// }
// else if (address >= 0x340000 && address <= 0x35ffff)
// {
// result = short1;
// }
// else if (address >= 0x380000 && address <= 0x39ffff)
// {
// result = short2;
// }
// else if (address >= 0x3c0000 && address + 1 <= 0x3dffff)
// {
// result = (short)neogeo_video_register_r((address & 0x07) >> 1);
// }
// else if (address >= 0x400000 && address + 1 <= 0x7fffff)
// {
// result = (short)palettes[palette_bank, (address & 0x1fff) >> 1];
// }
// else if (address >= 0xc00000 && address + 1 <= 0xcfffff)
// {
// result = (short)(mainbiosrom[address & 0x1ffff] * 0x100 + mainbiosrom[(address & 0x1ffff) + 1]);
// }
// else if (address >= 0xd00000 && address + 1 <= 0xdfffff)
// {
// result = (short)(mainram2[address & 0xffff] * 0x100 + mainram2[(address & 0xffff) + 1]);
// }
// else
// {
// int i1 = 1;
// }
// return result;
//}
public static short MReadWord(int address)
{
address &= 0xffffff;
@ -224,32 +369,49 @@ namespace MAME.Core
{
if (main_cpu_vector_table_source == 0)
{
result = (short)(mainbiosrom[address] * 0x100 + mainbiosrom[address + 1]);
byte* ptr_0 = &mainbiosrom[0];
byte* ptr = ptr_0 + address;
//result = (short)(mainbiosrom[address] * 0x100 + mainbiosrom[address + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (main_cpu_vector_table_source == 1)
{
result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + address;
//result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
}
else if (address >= 0x000080 && address + 1 <= 0x0fffff)
{
if (address >= 0x142B9 && address <= 0x142C9)
{
//m68000Form.iStatus = 1;
}
result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
//if (address >= 0x142B9 && address <= 0x142C9)
//{
// //m68000Form.iStatus = 1;
//}
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + address;
//result = (short)(Memory.mainrom[address] * 0x100 + Memory.mainrom[address + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0x100000 && address + 1 <= 0x1fffff)
{
if (address == 0x101410)
{
int i1 = 1;
}
result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
//if (address == 0x101410)
//{
// int i1 = 1;
//}
byte* ptr_0 = &Memory.mainram[0];
byte* ptr = ptr_0 + (address & 0xffff);
//result = (short)(Memory.mainram[address & 0xffff] * 0x100 + Memory.mainram[(address & 0xffff) + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0x200000 && address <= 0x2fffff)
{
result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
byte* ptr_0 = &Memory.mainrom[0];
byte* ptr = ptr_0 + (main_cpu_bank_address + (address & 0xfffff));
//result = (short)(Memory.mainrom[main_cpu_bank_address + (address & 0xfffff)] * 0x100 + Memory.mainrom[main_cpu_bank_address + (address & 0xfffff) + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
/*else if (address >= 0x300000 && address <= 0x300001)
{
@ -293,16 +455,22 @@ namespace MAME.Core
}
else if (address >= 0xc00000 && address + 1 <= 0xcfffff)
{
result = (short)(mainbiosrom[address & 0x1ffff] * 0x100 + mainbiosrom[(address & 0x1ffff) + 1]);
byte* ptr_0 = &mainbiosrom[0];
byte* ptr = ptr_0 + (address & 0x1ffff);
//result = (short)(mainbiosrom[address & 0x1ffff] * 0x100 + mainbiosrom[(address & 0x1ffff) + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
else if (address >= 0xd00000 && address + 1 <= 0xdfffff)
{
result = (short)(mainram2[address & 0xffff] * 0x100 + mainram2[(address & 0xffff) + 1]);
}
else
{
int i1 = 1;
byte* ptr_0 = &mainram2[0];
byte* ptr = ptr_0 + (address & 0xffff);
//result = (short)(mainram2[address & 0xffff] * 0x100 + mainram2[(address & 0xffff) + 1]);
result = (short)(*ptr * 0x100 + *(ptr + 1));
}
//else
//{
// int i1 = 1;
//}
return result;
}
public static int MReadOpLong(int address)
@ -516,7 +684,8 @@ namespace MAME.Core
{
int i1 = 1;
}
else */if ((address & 0x01) == 1)
else */
if ((address & 0x01) == 1)
{
//watchdog_w();
//减少一次堆栈 无意义套娃
@ -1035,6 +1204,7 @@ namespace MAME.Core
MWriteLong(address, value);
}
}
const ushort prot_9a37_r_vale = 0x9a37;
public static sbyte MReadByte_mslug3(int address)
{
address &= 0xffffff;
@ -2054,61 +2224,121 @@ namespace MAME.Core
MWriteLong(address, value);
}
}
//public static byte ZReadOp(ushort address)
//{
// byte result = 0;
// if (address >= 0x0000 && address <= 0x7fff)
// {
// result = Memory.audiorom[address];
// }
// else if (address >= 0x8000 && address <= 0xbfff)
// {
// result = Memory.audiorom[audio_cpu_banks[3] * 0x4000 + address - 0x8000];
// }
// else if (address >= 0xc000 && address <= 0xdfff)
// {
// result = Memory.audiorom[audio_cpu_banks[2] * 0x2000 + address - 0xc000];
// }
// else if (address >= 0xe000 && address <= 0xefff)
// {
// result = Memory.audiorom[audio_cpu_banks[1] * 0x1000 + address - 0xe000];
// }
// else if (address >= 0xf000 && address <= 0xf7ff)
// {
// result = Memory.audiorom[audio_cpu_banks[0] * 0x800 + address - 0xf000];
// }
// else if (address >= 0xf800 && address <= 0xffff)
// {
// result = Memory.audioram[address - 0xf800];
// }
// return result;
//}
//手动优化
public static byte ZReadOp(ushort address)
{
byte result = 0;
if (address >= 0x0000 && address <= 0x7fff)
{
result = Memory.audiorom[address];
return *(Memory.audiorom + address);
}
else if (address >= 0x8000 && address <= 0xbfff)
{
result = Memory.audiorom[audio_cpu_banks[3] * 0x4000 + address - 0x8000];
return *(Memory.audiorom + (*(audio_cpu_banks + 3) * 0x4000 + address - 0x8000));
}
else if (address >= 0xc000 && address <= 0xdfff)
{
result = Memory.audiorom[audio_cpu_banks[2] * 0x2000 + address - 0xc000];
return *(Memory.audiorom + (*(audio_cpu_banks + 2) * 0x2000 + address - 0xc000));
}
else if (address >= 0xe000 && address <= 0xefff)
{
result = Memory.audiorom[audio_cpu_banks[1] * 0x1000 + address - 0xe000];
return *(Memory.audiorom + *(audio_cpu_banks + 1) * 0x1000 + address - 0xe000);
}
else if (address >= 0xf000 && address <= 0xf7ff)
{
result = Memory.audiorom[audio_cpu_banks[0] * 0x800 + address - 0xf000];
return *(Memory.audiorom + (*audio_cpu_banks * 0x800 + address - 0xf000));
}
else if (address >= 0xf800 && address <= 0xffff)
{
result = Memory.audioram[address - 0xf800];
return *(Memory.audioram + (address - 0xf800));
}
return result;
return 0;
}
//public static byte ZReadMemory(ushort address)
//{
// byte result = 0;
// if (address >= 0x0000 && address <= 0x7fff)
// {
// result = Memory.audiorom[address];
// }
// else if (address >= 0x8000 && address <= 0xbfff)
// {
// result = Memory.audiorom[audio_cpu_banks[3] * 0x4000 + address - 0x8000];
// }
// else if (address >= 0xc000 && address <= 0xdfff)
// {
// result = Memory.audiorom[audio_cpu_banks[2] * 0x2000 + address - 0xc000];
// }
// else if (address >= 0xe000 && address <= 0xefff)
// {
// result = Memory.audiorom[audio_cpu_banks[1] * 0x1000 + address - 0xe000];
// }
// else if (address >= 0xf000 && address <= 0xf7ff)
// {
// result = Memory.audiorom[audio_cpu_banks[0] * 0x800 + address - 0xf000];
// }
// else if (address >= 0xf800 && address <= 0xffff)
// {
// result = Memory.audioram[address - 0xf800];
// }
// return result;
//}
public static byte ZReadMemory(ushort address)
{
byte result = 0;
if (address >= 0x0000 && address <= 0x7fff)
{
result = Memory.audiorom[address];
result = *(Memory.audiorom + address);
}
else if (address >= 0x8000 && address <= 0xbfff)
{
result = Memory.audiorom[audio_cpu_banks[3] * 0x4000 + address - 0x8000];
result = *(Memory.audiorom + (*(audio_cpu_banks + 3) * 0x4000 + address - 0x8000));
}
else if (address >= 0xc000 && address <= 0xdfff)
{
result = Memory.audiorom[audio_cpu_banks[2] * 0x2000 + address - 0xc000];
result = *(Memory.audiorom + (*(audio_cpu_banks + 2) * 0x2000 + address - 0xc000));
}
else if (address >= 0xe000 && address <= 0xefff)
{
result = Memory.audiorom[audio_cpu_banks[1] * 0x1000 + address - 0xe000];
result = *(Memory.audiorom + (*(audio_cpu_banks + 1) * 0x1000 + address - 0xe000));
}
else if (address >= 0xf000 && address <= 0xf7ff)
{
result = Memory.audiorom[audio_cpu_banks[0] * 0x800 + address - 0xf000];
result = *(Memory.audiorom + (*audio_cpu_banks * 0x800 + address - 0xf000));
}
else if (address >= 0xf800 && address <= 0xffff)
{
result = Memory.audioram[address - 0xf800];
result = *(Memory.audioram + (address - 0xf800));
}
return result;
}

View File

@ -24,8 +24,49 @@ namespace MAME.Core
public static int main_cpu_bank_address;
public static byte main_cpu_vector_table_source;
//public static byte audio_result;
public static byte[] audio_cpu_banks;
public static byte[] mainbiosrom, /*mainram2,*/ audiobiosrom, fixedrom, fixedbiosrom, zoomyrom, /*spritesrom,*/ pvc_cartridge_ram;
//public static byte[] audio_cpu_banks;
#region //指针化 audio_cpu_banks
static byte[] audio_cpu_banks_src;
static GCHandle audio_cpu_banks_handle;
public static byte* audio_cpu_banks;
public static int audio_cpu_banksLength;
public static bool audio_cpu_banks_IsNull => audio_cpu_banks == null;
public static byte[] audio_cpu_banks_set
{
set
{
audio_cpu_banks_handle.ReleaseGCHandle();
audio_cpu_banks_src = value;
audio_cpu_banksLength = value.Length;
audio_cpu_banks_src.GetObjectPtr(ref audio_cpu_banks_handle, ref audio_cpu_banks);
}
}
#endregion
public static byte[]/* mainbiosrom, *//*mainram2,*/ audiobiosrom, fixedrom, fixedbiosrom, zoomyrom, /*spritesrom,*/ pvc_cartridge_ram;
#region //指针化 mainbiosrom
static byte[] mainbiosrom_src;
static GCHandle mainbiosrom_handle;
public static byte* mainbiosrom;
public static int mainbiosromLength;
public static bool mainbiosrom_IsNull => mainbiosrom == null;
public static byte[] mainbiosrom_set
{
set
{
mainbiosrom_handle.ReleaseGCHandle();
mainbiosrom_src = value;
mainbiosromLength = value.Length;
mainbiosrom_src.GetObjectPtr(ref mainbiosrom_handle, ref mainbiosrom);
}
}
#endregion
public static byte[] extra_ram = new byte[0x2000];
public static uint fatfury2_prot_data;
public static ushort neogeo_rng;
@ -73,7 +114,7 @@ namespace MAME.Core
public static void NeogeoInit()
{
audio_cpu_banks = new byte[4];
audio_cpu_banks_set = new byte[4];
pvc_cartridge_ram = new byte[0x2000];
Memory.Set_mainram(new byte[0x10000]);
mainram2_set = new byte[0x10000];
@ -83,7 +124,7 @@ namespace MAME.Core
fixedbiosrom = MameMainMotion.resource.sfix;
zoomyrom = MameMainMotion.resource._000_lo;
audiobiosrom = MameMainMotion.resource.sm1;
mainbiosrom = MameMainMotion.resource.mainbios;
mainbiosrom_set = MameMainMotion.resource.mainbios;
Memory.Set_mainrom(Machine.GetRom("maincpu.rom"));
Memory.Set_audiorom(Machine.GetRom("audiocpu.rom"));
fixedrom = Machine.GetRom("fixed.rom");
@ -100,7 +141,7 @@ namespace MAME.Core
{
case "irrmaze":
case "kizuna4p":
mainbiosrom = Machine.GetRom("mainbios.rom");
mainbiosrom_set = Machine.GetRom("mainbios.rom");
break;
case "kof99":
case "kof99h":

View File

@ -82,6 +82,8 @@ namespace MAME.Core
{
return 0x9a37;
}
//public const sbyte prot_9a37_r_sbyte = 0x37;
//public const short prot_9a37_r_short = -25929;
public static ushort sma_random_r()
{
ushort old = neogeo_rng;

View File

@ -88,7 +88,7 @@ namespace MAME.Core
controller_select = reader.ReadByte();
main_cpu_bank_address = reader.ReadInt32();
main_cpu_vector_table_source = reader.ReadByte();
audio_cpu_banks = reader.ReadBytes(4);
audio_cpu_banks_set = reader.ReadBytes(4);
save_ram_unlocked = reader.ReadByte();
audio_cpu_nmi_enabled = reader.ReadBoolean();
audio_cpu_nmi_pending = reader.ReadBoolean();

View File

@ -1,12 +1,51 @@
using System;
using System.Runtime.InteropServices;
namespace MAME.Core
{
public unsafe partial class Neogeo
{
public static byte[] sprite_gfx;
//public static byte[] sprite_gfx;
#region //指针化 sprite_gfx
static byte[] sprite_gfx_src;
static GCHandle sprite_gfx_handle;
public static byte* sprite_gfx;
public static int sprite_gfxLength;
public static bool sprite_gfx_IsNull => sprite_gfx == null;
public static byte[] sprite_gfx_set
{
set
{
sprite_gfx_handle.ReleaseGCHandle();
sprite_gfx_src = value;
sprite_gfxLength = value.Length;
sprite_gfx_src.GetObjectPtr(ref sprite_gfx_handle, ref sprite_gfx);
}
}
#endregion
public static uint sprite_gfx_address_mask;
public static ushort[] neogeo_videoram;
//public static ushort[] neogeo_videoram;
#region //指针化 neogeo_videoram
static ushort[] neogeo_videoram_src;
static GCHandle neogeo_videoram_handle;
public static ushort* neogeo_videoram;
public static int neogeo_videoramLength;
public static bool neogeo_videoram_IsNull => neogeo_videoram == null;
public static ushort[] neogeo_videoram_set
{
set
{
neogeo_videoram_handle.ReleaseGCHandle();
neogeo_videoram_src = value;
neogeo_videoramLength = value.Length;
neogeo_videoram_src.GetObjectPtr(ref neogeo_videoram_handle, ref neogeo_videoram);
}
}
#endregion
public static ushort[,] palettes;
public static int[] pens;
private static int neogeo_scanline_param;
@ -26,7 +65,25 @@ namespace MAME.Core
private static double[] rgb_weights_normal_bit15;
private static double[] rgb_weights_dark;
private static double[] rgb_weights_dark_bit15;
public static int[,] zoom_x_tables;
public readonly static int[,] zoom_x_tables = new int[,]
{
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 },
{ 0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0 },
{ 0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0 },
{ 0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0 },
{ 0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
{ 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 },
{ 1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0 },
{ 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,0 },
{ 1,0,1,1,1,0,1,0,1,1,1,0,1,0,1,1 },
{ 1,0,1,1,1,0,1,1,1,1,1,0,1,0,1,1 },
{ 1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
{ 1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
{ 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }
};
private static int[] transarray, bgarray;
private static int trans_color;
private static byte combine_5_weights(double[] tab, int w0, int w1, int w2, int w3, int w4)
@ -336,14 +393,16 @@ namespace MAME.Core
/// <param name="scanline"></param>
unsafe private static void draw_sprites(int iBitmap, int scanline)
{
fixed (ushort* videoramPtr = &neogeo_videoram[0])
int pixel_addr_offsety = scanline;
int pixel_addr_offsety_x_384 = pixel_addr_offsety * 384;
//fixed (byte* spriteGfxPtr = &sprite_gfx[0])
byte* spriteGfxPtr = sprite_gfx;
//fixed (ushort* videoramPtr = &neogeo_videoram[0])
ushort* videoramPtr = neogeo_videoram;
//fixed (int* bitmapbasePtr = &Video.bitmapbaseN_Ptrs[iBitmap][0])
fixed (byte* spriteGfxPtr = &sprite_gfx[0])
fixed (int* pensPtr = &pens[0])
fixed (byte* zoomyromPtr = &zoomyrom[0])
{
ushort* neogeo_videoram = videoramPtr;
//int* bitmapbase = bitmapbasePtr;
int* bitmapbase = &Video.bitmapbaseN_Ptrs[iBitmap][0];
byte* spriteGfx = spriteGfxPtr;
@ -370,7 +429,8 @@ namespace MAME.Core
}
for (max_sprite_index = 95; max_sprite_index >= 0; max_sprite_index--)
{
if (neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
//if (neogeo_videoram[sprite_list_offset + max_sprite_index] != 0)
if (*(videoramPtr + (sprite_list_offset + max_sprite_index)) != 0)
{
break;
}
@ -381,12 +441,20 @@ namespace MAME.Core
}
for (sprite_index = 0; sprite_index < max_sprite_index; sprite_index++)
{
sprite_number = neogeo_videoram[sprite_list_offset + sprite_index] & 0x1ff;
y_control = neogeo_videoram[0x8200 | sprite_number];
zoom_control = neogeo_videoram[0x8000 | sprite_number];
x_2 = neogeo_videoram[0x8400 | sprite_number];
code_2 = neogeo_videoram[sprite_number << 6];
//sprite_number = neogeo_videoram[sprite_list_offset + sprite_index] & 0x1ff;
//y_control = neogeo_videoram[0x8200 | sprite_number];
//zoom_control = neogeo_videoram[0x8000 | sprite_number];
//x_2 = neogeo_videoram[0x8400 | sprite_number];
//code_2 = neogeo_videoram[sprite_number << 6];
sprite_number = (*(videoramPtr + sprite_list_offset + sprite_index) & 0x1ff);
y_control = (ushort)(*(videoramPtr + (0x8200 | sprite_number)));
zoom_control = (ushort)(*(videoramPtr + (0x8000 | sprite_number)));
x_2 = (ushort)(*(videoramPtr + (0x8400 | sprite_number)));
code_2 = *(videoramPtr + (sprite_number << 6));
//不对👇
//sprite_number = (*(videoram + sprite_list_offset + sprite_index) & 0x1ff);
//y_control = (ushort)(*(videoram + 0x8200) | sprite_number);
//zoom_control = (ushort)(*(videoram + 0x8000) | sprite_number);
@ -420,7 +488,7 @@ namespace MAME.Core
//if (sprite_on_scanline(scanline, y, rows))
//手动内联 开始
int tempRows = rows;
if ((rows == 0) || (rows > 0x20))
if ((tempRows == 0) || (tempRows > 0x20))
tempRows = 0x20;
int max_y = (y + (tempRows * 0x10) - 1) & 0x1ff;
if (((max_y >= y) && (scanline >= y) && (scanline <= max_y)) ||
@ -452,8 +520,10 @@ namespace MAME.Core
tile ^= 0x1f;
}
attr_and_code_offs = (sprite_number << 6) | (tile << 1);
attr = neogeo_videoram[attr_and_code_offs + 1];
code = ((attr << 12) & 0x70000) | neogeo_videoram[attr_and_code_offs];
//attr = neogeo_videoram[attr_and_code_offs + 1];
attr = *(videoramPtr + attr_and_code_offs + 1);
//code = ((attr << 12) & 0x70000) | neogeo_videoram[attr_and_code_offs];
code = ((attr << 12) & 0x70000) | *(videoramPtr + attr_and_code_offs);
if (auto_animation_disabled == 0)
{
if ((attr & 0x0008) != 0)
@ -481,54 +551,78 @@ namespace MAME.Core
{
x_inc = 1;
}
int pixel_addr_offsetx, pixel_addr_offsety;
//int pixel_addr_offsetx;
if (x <= 0x01f0)
{
int i;
pixel_addr_offsetx = x + NEOGEO_HBEND;
pixel_addr_offsety = scanline;
//pixel_addr_offsetx = x + NEOGEO_HBEND;
//int* pixel_ptr = &bitmapbase[pixel_addr_offsety_x_384 + x + NEOGEO_HBEND];
int* pixel_ptr = bitmapbase + pixel_addr_offsety_x_384 + x + NEOGEO_HBEND;
//int* zoom_x_tablePtr = &zoom_x_tables[zoom_x_table_offset];
int* zoom_x_tablePtr = zoom_x_tables + zoom_x_table_offset;
//byte* spriteGfx_offset_Ptr = &spriteGfx[gfx_offset];
byte* spriteGfx_offset_Ptr = spriteGfx + gfx_offset;
for (i = 0; i < 0x10; i++)
{
//if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
if (zoom_x_tables[zoom_x_table_offset] != 0)
//if (zoom_x_tables[zoom_x_table_offset] != 0)
if (*zoom_x_tablePtr != 0)
{
//if (sprite_gfx[gfx_offset] != 0)
if (spriteGfx[gfx_offset] != 0)
//if (spriteGfx[gfx_offset] != 0)
if (*spriteGfx_offset_Ptr != 0)
{
//Video.bitmapbaseN_Ptrs[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
//bitmapbase[pixel_addr_offsety_x_384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
//*pixel_ptr = pens[line_pens_offset + *spriteGfx_offset_Ptr];
*pixel_ptr = *(pens + line_pens_offset + *spriteGfx_offset_Ptr);
}
pixel_addr_offsetx++;
//pixel_addr_offsetx++;
pixel_ptr++;
}
zoom_x_table_offset++;
gfx_offset += x_inc;
//zoom_x_table_offset++;
zoom_x_tablePtr++;
//gfx_offset += x_inc;
spriteGfx_offset_Ptr += x_inc;
}
}
else
{
int i;
int x_save = x;
pixel_addr_offsetx = NEOGEO_HBEND;
pixel_addr_offsety = scanline;
//pixel_addr_offsetx = NEOGEO_HBEND;
//int* pixel_ptr = &bitmapbase[pixel_addr_offsety_x_384 + NEOGEO_HBEND];
int* pixel_ptr = bitmapbase + pixel_addr_offsety_x_384 + NEOGEO_HBEND;
//int* zoom_x_tablePtr = &zoom_x_tables[zoom_x_table_offset];
int* zoom_x_tablePtr = zoom_x_tables + zoom_x_table_offset;
//byte* spriteGfx_offset_Ptr = &spriteGfx[gfx_offset];
byte* spriteGfx_offset_Ptr = spriteGfx + gfx_offset;
for (i = 0; i < 0x10; i++)
{
//if (zoom_x_tables[zoom_x, zoom_x_table_offset] != 0)
if (zoom_x_tables[zoom_x_table_offset] != 0)
//if (zoom_x_tables[zoom_x_table_offset] != 0)
if (*zoom_x_tablePtr != 0)
{
if (x >= 0x200)
{
//if (sprite_gfx[gfx_offset] != 0)
if (spriteGfx[gfx_offset] != 0)
//if (spriteGfx[gfx_offset] != 0)
if (*spriteGfx_offset_Ptr != 0)
{
//Video.bitmapbaseN_Ptrs[iBitmap][pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + sprite_gfx[gfx_offset]];
bitmapbase[pixel_addr_offsety * 384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
//bitmapbase[pixel_addr_offsety_x_384 + pixel_addr_offsetx] = pens[line_pens_offset + spriteGfx[gfx_offset]];
//*pixel_ptr = pens[line_pens_offset + *spriteGfx_offset_Ptr];
*pixel_ptr = *(pens + line_pens_offset + *spriteGfx_offset_Ptr);
}
pixel_addr_offsetx++;
//pixel_addr_offsetx++;
pixel_ptr++;
}
x++;
}
zoom_x_table_offset++;
gfx_offset += x_inc;
//zoom_x_table_offset++;
zoom_x_tablePtr++;
//gfx_offset += x_inc;
spriteGfx_offset_Ptr += x_inc;
}
x = x_save;
}
@ -697,6 +791,65 @@ namespace MAME.Core
// }
// }
//}
//private static void parse_sprites(int scanline)
//{
// ushort sprite_number, y_control;
// int y = 0;
// int rows = 0;
// int sprite_list_offset;
// int active_sprite_count = 0;
// if ((scanline & 0x01) != 0)
// {
// sprite_list_offset = 0x8680;
// }
// else
// {
// sprite_list_offset = 0x8600;
// }
// for (sprite_number = 0; sprite_number < 381; sprite_number++)
// {
// y_control = neogeo_videoram[0x8200 | sprite_number];
// if ((~y_control & 0x40) != 0)
// {
// y = 0x200 - (y_control >> 7);
// rows = y_control & 0x3f;
// }
// if (rows == 0)
// {
// continue;
// }
// //if (!sprite_on_scanline(scanline, y, rows))
// //手动内联 开始
// int tempRows = rows;
// if ((rows == 0) || (rows > 0x20))
// tempRows = 0x20;
// int max_y = (y + (tempRows * 0x10) - 1) & 0x1ff;
// if (!(((max_y >= y) && (scanline >= y) && (scanline <= max_y)) ||
// ((max_y < y) && ((scanline >= y) || (scanline <= max_y)))))
// //手动内联 结束
// {
// continue;
// }
// neogeo_videoram[sprite_list_offset] = sprite_number;
// sprite_list_offset++;
// active_sprite_count++;
// if (active_sprite_count == 96)
// {
// break;
// }
// }
// for (; active_sprite_count <= 96; active_sprite_count++)
// {
// neogeo_videoram[sprite_list_offset] = 0;
// sprite_list_offset++;
// }
//}
//手动优化进一步
private static void parse_sprites(int scanline)
{
ushort sprite_number, y_control;
@ -712,9 +865,12 @@ namespace MAME.Core
{
sprite_list_offset = 0x8600;
}
ushort* neogeo_videoram_sprite_list_offset = neogeo_videoram + sprite_list_offset;
for (sprite_number = 0; sprite_number < 381; sprite_number++)
{
y_control = neogeo_videoram[0x8200 | sprite_number];
//y_control = neogeo_videoram[0x8200 | sprite_number];
y_control = *(neogeo_videoram + (0x8200 | sprite_number));
if ((~y_control & 0x40) != 0)
{
y = 0x200 - (y_control >> 7);
@ -738,8 +894,11 @@ namespace MAME.Core
{
continue;
}
neogeo_videoram[sprite_list_offset] = sprite_number;
sprite_list_offset++;
//neogeo_videoram[sprite_list_offset] = sprite_number;
*neogeo_videoram_sprite_list_offset = sprite_number;
//sprite_list_offset++;
neogeo_videoram_sprite_list_offset++;
active_sprite_count++;
if (active_sprite_count == 96)
{
@ -748,8 +907,10 @@ namespace MAME.Core
}
for (; active_sprite_count <= 96; active_sprite_count++)
{
neogeo_videoram[sprite_list_offset] = 0;
sprite_list_offset++;
//neogeo_videoram[sprite_list_offset] = 0;
*neogeo_videoram_sprite_list_offset = 0;
//sprite_list_offset++;
neogeo_videoram_sprite_list_offset++;
}
}
public static void sprite_line_timer_callback()
@ -775,8 +936,16 @@ namespace MAME.Core
}
readonly static int[] pix_offsets = new int[] { 0x10, 0x18, 0x00, 0x08 };
static int[] garouoffsets = new int[32];
//private static void draw_fixed_layer(int iBitmap, int scanline)
//手动优化
private static void draw_fixed_layer(int iBitmap, int scanline)
{
//fixed (ushort* videoramPtr = &neogeo_videoram[0])
//ushort* videoramPtr = neogeo_videoram;
{
int* bitmapbase = &Video.bitmapbaseN_Ptrs[iBitmap][0];
int scanline_x_384 = 384 * scanline;
int i, j, x, y;
byte[] gfx_base;
//int[] garouoffsets = new int[32], pix_offsets = new int[] { 0x10, 0x18, 0x00, 0x08 };
@ -801,40 +970,57 @@ namespace MAME.Core
if (banked && neogeo_fixed_layer_bank_type == 1)
{
garoubank = 0;
k = 0;
//k = 0;
y = 0;
//ushort* videoramPtr = neogeo_videoram;
ushort* videoramPtr_0x7500 = neogeo_videoram + 0x7500;
ushort* videoramPtr_0x7580 = neogeo_videoram + 0x7580;
while (y < 32)
{
if (neogeo_videoram[0x7500 + k] == 0x0200 && (neogeo_videoram[0x7580 + k] & 0xff00) == 0xff00)
//if (videoramPtr[0x7500 + k] == 0x0200 && (videoramPtr[0x7580 + k] & 0xff00) == 0xff00)
if (*videoramPtr_0x7500 == 0x0200 && (*videoramPtr_0x7580 & 0xff00) == 0xff00)
{
garoubank = neogeo_videoram[0x7580 + k] & 3;
//garoubank = videoramPtr[0x7580 + k] & 3;
garoubank = *videoramPtr_0x7580 & 3;
garouoffsets[y++] = garoubank;
}
garouoffsets[y++] = garoubank;
k += 2;
//k += 2;
videoramPtr_0x7500 += 2;
videoramPtr_0x7580 += 2;
}
}
y = scanline >> 3;
int temp_yvale = 0x7500 + ((y - 1) & 31);
ushort* videoramPtr = neogeo_videoram;
ushort* videoramPtr_video_data_offset = neogeo_videoram + video_data_offset;
for (x = 0; x < 40; x++)
{
code_and_palette = neogeo_videoram[video_data_offset];
//code_and_palette = videoramPtr[video_data_offset];
code_and_palette = *videoramPtr_video_data_offset;
code = code_and_palette & 0x0fff;
if (banked)
{
y = scanline >> 3;
//y = scanline >> 3;
switch (neogeo_fixed_layer_bank_type)
{
case 1:
code += 0x1000 * (garouoffsets[(y - 2) & 31] ^ 3);
break;
case 2:
code += 0x1000 * (((neogeo_videoram[0x7500 + ((y - 1) & 31) + 32 * (x / 6)] >> (5 - (x % 6)) * 2) & 3) ^ 3);
//code += 0x1000 * (((videoramPtr[temp_yvale + 32 * (x / 6)] >> (5 - (x % 6)) * 2) & 3) ^ 3);
code += 0x1000 * (((*(videoramPtr + (temp_yvale + 32 * (x / 6))) >> (5 - (x % 6)) * 2) & 3) ^ 3);
break;
}
}
data = 0;
gfx_offset = ((code << 5) | (scanline & 0x07)) & addr_mask;
char_pens_offset = code_and_palette >> 12 << 4;
for (i = 0; i < 8; i++)
int temp_xval = scanline_x_384 + 30 + x * 8;
int* bitmapbasePtr_temp_xval = bitmapbase + temp_xval;
for (i = 0; i < 8; i++, bitmapbasePtr_temp_xval++)
{
if ((i & 0x01) != 0)
{
@ -846,12 +1032,104 @@ namespace MAME.Core
}
if ((data & 0x0f) != 0)
{
Video.bitmapbaseN_Ptrs[iBitmap][384 * scanline + 30 + x * 8 + i] = pens[char_pens_offset + (data & 0x0f)];
//bitmapbase[temp_xval + i] = pens[char_pens_offset + (data & 0x0f)];
*bitmapbasePtr_temp_xval = pens[char_pens_offset + (data & 0x0f)];
}
}
video_data_offset += 0x20;
//video_data_offset += 0x20;
videoramPtr_video_data_offset += 0x20;
}
}
}
//{
// //fixed (ushort* videoramPtr = &neogeo_videoram[0])
// ushort* videoramPtr = neogeo_videoram;
// {
// int* bitmapbase = &Video.bitmapbaseN_Ptrs[iBitmap][0];
// int scanline_x_384 = 384 * scanline;
// int i, j, x, y;
// byte[] gfx_base;
// //int[] garouoffsets = new int[32], pix_offsets = new int[] { 0x10, 0x18, 0x00, 0x08 };
// int addr_mask;
// int gfx_offset, char_pens_offset;
// byte data;
// bool banked;
// int garoubank, k, code;
// ushort code_and_palette;
// if (fixed_layer_source != 0)
// {
// gfx_base = fixedrom;
// addr_mask = fixedrom.Length - 1;
// }
// else
// {
// gfx_base = fixedbiosrom;
// addr_mask = fixedbiosrom.Length - 1;
// }
// int video_data_offset = 0x7000 | (scanline >> 3);
// banked = (fixed_layer_source != 0) && (addr_mask > 0x1ffff);
// if (banked && neogeo_fixed_layer_bank_type == 1)
// {
// garoubank = 0;
// k = 0;
// y = 0;
// while (y < 32)
// {
// if (videoramPtr[0x7500 + k] == 0x0200 && (videoramPtr[0x7580 + k] & 0xff00) == 0xff00)
// {
// garoubank = videoramPtr[0x7580 + k] & 3;
// garouoffsets[y++] = garoubank;
// }
// garouoffsets[y++] = garoubank;
// k += 2;
// }
// }
// y = scanline >> 3;
// int temp_yvale = 0x7500 + ((y - 1) & 31);
// for (x = 0; x < 40; x++)
// {
// code_and_palette = videoramPtr[video_data_offset];
// code = code_and_palette & 0x0fff;
// if (banked)
// {
// //y = scanline >> 3;
// switch (neogeo_fixed_layer_bank_type)
// {
// case 1:
// code += 0x1000 * (garouoffsets[(y - 2) & 31] ^ 3);
// break;
// case 2:
// code += 0x1000 * (((videoramPtr[temp_yvale + 32 * (x / 6)] >> (5 - (x % 6)) * 2) & 3) ^ 3);
// break;
// }
// }
// data = 0;
// gfx_offset = ((code << 5) | (scanline & 0x07)) & addr_mask;
// char_pens_offset = code_and_palette >> 12 << 4;
// int temp_xval = scanline_x_384 + 30 + x * 8;
// for (i = 0; i < 8; i++)
// {
// if ((i & 0x01) != 0)
// {
// data = (byte)(data >> 4);
// }
// else
// {
// data = gfx_base[gfx_offset + pix_offsets[i >> 1]];
// }
// if ((data & 0x0f) != 0)
// {
// bitmapbase[/*scanline_x_384 + 30 + x * 8*/temp_xval + i] = pens[char_pens_offset + (data & 0x0f)];
// }
// }
// video_data_offset += 0x20;
// }
// }
//}
private static void optimize_sprite_data()
{
sprite_gfx_address_mask = (uint)(spritesromLength * 2 - 1);
@ -948,8 +1226,10 @@ namespace MAME.Core
}
public static void video_start_neogeo()
{
sprite_gfx = new byte[spritesromLength * 2];
neogeo_videoram = new ushort[0x10000];
//sprite_gfx = new byte[spritesromLength * 2];
sprite_gfx_set = new byte[spritesromLength * 2];
//neogeo_videoram = new ushort[0x10000];
neogeo_videoram_set = new ushort[0x10000];
palettes = new ushort[2, 0x1000];
pens = new int[0x1000];
transarray = new int[384 * 264];
@ -959,7 +1239,7 @@ namespace MAME.Core
rgb_weights_normal_bit15 = new double[5] { 136.26711031260342, 63.784604843122239, 29.978764292156193, 13.626711058241233, 7.6868626613063098 };
rgb_weights_dark = new double[5] { 77.012238506947057, 36.048281863327709, 16.942692484743652, 7.7012238659431276, 4.3442801368916566 };
rgb_weights_dark_bit15 = new double[5] { 76.322306339305158, 35.725334891159271, 16.790907407744047, 7.6322306490423326, 4.3053608862660706 };
zoom_x_tables = new int[,]
/*zoom_x_tables = new int[,]
{
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0 },
@ -977,10 +1257,11 @@ namespace MAME.Core
{ 1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1 },
{ 1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }
};
};*/
Array.Clear(palettes, 0, 0x2000);
Array.Clear(pens, 0, 0x1000);
Array.Clear(neogeo_videoram, 0, 0x10000);
//Array.Clear(neogeo_videoram, 0, 0x10000);
Array.Clear(neogeo_videoram_src, 0, 0x10000);
for (int i = 0; i < 384 * 264; i++)
{
transarray[i] = trans_color;
@ -998,7 +1279,11 @@ namespace MAME.Core
}
public static void video_update_neogeo()
{
Array.Copy(bgarray, 0, Video.bitmapbaseN[Video.curbitmap], 384 * Video.new_clip.min_y, 384 * (Video.new_clip.max_y - Video.new_clip.min_y + 1));
//Array.Copy(bgarray, 0, Video.bitmapbaseN[Video.curbitmap], 384 * Video.new_clip.min_y, 384 * (Video.new_clip.max_y - Video.new_clip.min_y + 1));
Buffer.BlockCopy(bgarray, 0, Video.bitmapbaseN[Video.curbitmap],
384 * Video.new_clip.min_y * sizeof(int),
384 * (Video.new_clip.max_y - Video.new_clip.min_y + 1) * sizeof(int)
);
draw_sprites(Video.curbitmap, Video.new_clip.min_y);
draw_fixed_layer(Video.curbitmap, Video.new_clip.min_y);
}

View File

@ -617,23 +617,30 @@ namespace MAME.Core
//}
//手动内联
public unsafe void chan_calc(int c, int chnum)
//public unsafe void chan_calc(int c, int chnum)
//public unsafe void chan_calc(int c, bool chnum_is_2)
public unsafe void chan_calc(int c, bool chnum_is_2)
{
uint eg_out;
//减少寻址
int imem_To_c = imem[c];//
int imem_ToIndex_c = imem[c];
fixed (FM_SLOT* CH_c_SLOT = &CH[c].SLOT[0])//因为是引用类型,所以敢这么玩
fixed (int* out_fm_ptr = &out_fm[0])
{
FM_SLOT* cslot_0 = &CH_c_SLOT[0];
FM_SLOT* cslot_1 = &CH_c_SLOT[1];
FM_SLOT* cslot_2 = &CH_c_SLOT[2];
FM_SLOT* cslot_3 = &CH_c_SLOT[3];
//out_fm[8] = out_fm[9] = out_fm[10] = out_fm[11] = 0; //本来就是注释->m2 = c1 = c2 = mem = 0;
out_fm_ptr[8] = out_fm_ptr[9] = out_fm_ptr[10] = out_fm_ptr[11] = 0;
//set_mem(c);
if (imem_To_c == 8 || imem_To_c == 10 || imem_To_c == 11)
out_fm_ptr[imem_To_c] = CH[c].mem_value;
if (imem_ToIndex_c == 8 || imem_ToIndex_c == 10 || imem_ToIndex_c == 11)
out_fm_ptr[imem_ToIndex_c] = CH[c].mem_value;
//eg_out = volume_calc(c, 0);
eg_out = (uint)(CH_c_SLOT[0].vol_out + ((LFO_AM >> CH[c].ams) & CH_c_SLOT[0].AMmask));
eg_out = (uint)(cslot_0->vol_out + ((LFO_AM >> CH[c].ams) & cslot_0->AMmask));
int out1 = CH[c].op1_out0 + CH[c].op1_out1;
CH[c].op1_out0 = CH[c].op1_out1;
@ -655,30 +662,56 @@ namespace MAME.Core
{
out1 = 0;
}
CH[c].op1_out1 = op_calc1(CH_c_SLOT[0].phase, eg_out, (out1 << CH[c].FB));
//CH[c].op1_out1 = op_calc1(cslot_0->phase, eg_out, (out1 << CH[c].FB)); //->(uint phase, uint env, int pm)
uint p;
p = (uint)((eg_out << 3) + sin_tab[(((int)((cslot_0->phase & 0xffff0000) + (out1 << CH[c].FB))) >> 16) & 0x3ff]);
if (p >= 6656)
CH[c].op1_out1 = 0;
else
CH[c].op1_out1 = tl_tab[p];
}
//eg_out = volume_calc(c, 1);
eg_out = (uint)(CH_c_SLOT[1].vol_out + ((LFO_AM >> CH[c].ams) & CH_c_SLOT[1].AMmask));
eg_out = (uint)(cslot_1->vol_out + ((LFO_AM >> CH[c].ams) & cslot_1->AMmask));
if (eg_out < 832)
{
out_fm_ptr[iconnect3[c]] += op_calc(CH_c_SLOT[1].phase, eg_out, out_fm_ptr[8]);
//out_fm_ptr[iconnect3[c]] += op_calc(cslot_1->phase, eg_out, out_fm_ptr[8]);//--> (uint phase, uint env, int pm)
uint p;
p = (uint)((eg_out << 3) + sin_tab[(((int)((cslot_1->phase & 0xffff0000) + (out_fm_ptr[8] << 15))) >> 16) & 0x3ff]);
if (p >= 6656)
out_fm_ptr[iconnect3[c]] += 0;
else
out_fm_ptr[iconnect3[c]] += tl_tab[p];
}
//eg_out = volume_calc(c, 2);
eg_out = (uint)(CH_c_SLOT[2].vol_out + ((LFO_AM >> CH[c].ams) & CH_c_SLOT[2].AMmask));
eg_out = (uint)(cslot_2->vol_out + ((LFO_AM >> CH[c].ams) & cslot_2->AMmask));
if (eg_out < 832)
{
out_fm_ptr[iconnect2[c]] += op_calc(CH_c_SLOT[2].phase, eg_out, out_fm_ptr[9]);
//out_fm_ptr[iconnect2[c]] += op_calc(cslot_2->phase, eg_out, out_fm_ptr[9]);//--> (uint phase, uint env, int pm)
uint p;
p = (uint)((eg_out << 3) + sin_tab[(((int)((cslot_2->phase & 0xffff0000) + (out_fm_ptr[9] << 15))) >> 16) & 0x3ff]);
if (p >= 6656)
out_fm_ptr[iconnect2[c]] += 0;
else
out_fm_ptr[iconnect2[c]] += tl_tab[p];
}
//eg_out = volume_calc(c, 3);
eg_out = (uint)(CH_c_SLOT[3].vol_out + ((LFO_AM >> CH[c].ams) & CH_c_SLOT[3].AMmask));
eg_out = (uint)(cslot_3->vol_out + ((LFO_AM >> CH[c].ams) & cslot_3->AMmask));
if (eg_out < 832)
{
out_fm_ptr[iconnect4[c]] += op_calc(CH_c_SLOT[3].phase, eg_out, out_fm[10]);
//out_fm_ptr[iconnect4[c]] += op_calc(cslot_3->phase, eg_out, out_fm[10]); //-->(uint phase, uint env, int pm)
uint p;
p = (uint)((eg_out << 3) + sin_tab[(((int)((cslot_3->phase & 0xffff0000) + (out_fm[10] << 15))) >> 16) & 0x3ff]);
if (p >= 6656)
out_fm_ptr[iconnect4[c]] += 0;
else
out_fm_ptr[iconnect4[c]] += tl_tab[p];
}
CH[c].mem_value = out_fm_ptr[11];//mem;
if (CH[c].pms != 0)
{
if (((ST.mode & 0xC0) != 0) && (chnum == 2))
//if (((ST.mode & 0xC0) != 0) && (chnum == 2))
if (chnum_is_2 && ((ST.mode & 0xC0) != 0))
{
update_phase_lfo_slot(0, CH[c].pms, SL3.block_fnum[1]);
update_phase_lfo_slot(2, CH[c].pms, SL3.block_fnum[2]);
@ -692,10 +725,10 @@ namespace MAME.Core
}
else
{
CH_c_SLOT[0].phase += (uint)CH_c_SLOT[0].Incr;
CH_c_SLOT[2].phase += (uint)CH_c_SLOT[2].Incr;
CH_c_SLOT[1].phase += (uint)CH_c_SLOT[1].Incr;
CH_c_SLOT[3].phase += (uint)CH_c_SLOT[3].Incr;
cslot_0->phase += (uint)cslot_0->Incr;
cslot_2->phase += (uint)cslot_2->Incr;
cslot_1->phase += (uint)cslot_1->Incr;
cslot_3->phase += (uint)cslot_3->Incr;
}
}
}

View File

@ -934,9 +934,9 @@ namespace MAME.Core
PSG.eg_timer_overflow = 0x30000;
/* this must be done _before_ a call to ym2151_reset_chip() */
//PSG.timer_A = EmuTimer.timer_alloc_common(EmuTimer.TIME_ACT.YM2151_timer_callback_a, false);
EmuTimer.timer_alloc_common(ref PSG.timer_A,EmuTimer.TIME_ACT.YM2151_timer_callback_a, false);
EmuTimer.timer_alloc_common(ref PSG.timer_A, EmuTimer.TIME_ACT.YM2151_timer_callback_a, false);
//PSG.timer_B = EmuTimer.timer_alloc_common(EmuTimer.TIME_ACT.YM2151_timer_callback_b, false);
EmuTimer.timer_alloc_common(ref PSG.timer_B,EmuTimer.TIME_ACT.YM2151_timer_callback_b, false);
EmuTimer.timer_alloc_common(ref PSG.timer_B, EmuTimer.TIME_ACT.YM2151_timer_callback_b, false);
ym2151_reset_chip();
switch (Machine.sBoard)
{
@ -1098,8 +1098,84 @@ namespace MAME.Core
//chan_calc高频调用 单次Update 5467次 左右下级堆栈volume_calc 20000+次 op_calc 10000+次
//unsafe static void chan_calc(YM2151Operator* PSGoper, int* chanout, int* imem, int chan)
//{
// //fixed (YM2151Operator* PSGoperPtr = &PSG.oper[0])
// {
// //YM2151Operator* PSGoper = PSGoperPtr;
// uint env;
// uint AM = 0;
// //m2 = c1 = c2 = mem = 0;
// chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
// //op = PSGoper[chan * 4]; /* M1 */
// //op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
// set_mem(PSGoper, chanout, imem, chan * 4);
// if (PSGoper[chan * 4].ams != 0)
// {
// AM = PSG.lfa << (int)(PSGoper[chan * 4].ams - 1);
// }
// env = volume_calc(PSGoper, (chan * 4), AM);
// //env = volume_calc_planB(PSGoper[chan * 4], AM);
// {
// int iout = PSGoper[chan * 4].fb_out_prev + PSGoper[chan * 4].fb_out_curr;
// PSGoper[chan * 4].fb_out_prev = PSGoper[chan * 4].fb_out_curr;
// set_value1(chanout, PSGoper, chan * 4);
// PSGoper[chan * 4].fb_out_curr = 0;
// if (env < 13 * 64)
// {
// if (PSGoper[chan * 4].fb_shift == 0)
// {
// iout = 0;
// }
// PSGoper[chan * 4].fb_out_curr = op_calc1(PSGoper, (chan * 4), env, (iout << (int)PSGoper[chan * 4].fb_shift));
// }
// }
// env = volume_calc(PSGoper, (chan * 4 + 1), AM); /* M2 */
// //env = volume_calc_planB(PSGoper[chan * 4 + 1], AM);/* M2 */
// if (env < 13 * 64)
// {
// //PSGoper[chan * 4 + 1].connect += op_calc((int)(chan * 4 + 1), env, m2);
// set_value2(chanout, chan * 4 + 1, op_calc(PSGoper, (chan * 4 + 1), env, chanout[8]));// m2));
// }
// env = volume_calc(PSGoper, (chan * 4 + 2), AM); /* C1 */
// //env = volume_calc_planB(PSGoper[chan * 4 + 2], AM); /* C1 */
// if (env < 13 * 64)
// {
// //PSGoper[chan * 4 + 2].connect += op_calc((int)(chan * 4 + 2), env, c1);
// set_value2(chanout, chan * 4 + 2, op_calc(PSGoper, (chan * 4 + 2), env, chanout[9]));// c1));
// }
// env = volume_calc(PSGoper, (chan * 4 + 3), AM); /* C2 */
// //env = volume_calc_planB(PSGoper[chan * 4 + 3], AM); /* C2 */
// if (env < 13 * 64)
// {
// chanout[chan] += op_calc(PSGoper, (chan * 4 + 3), env, chanout[10]);// c2);
// }
// /* M1 */
// PSGoper[chan * 4].mem_value = chanout[11];//mem;
// }
//}
const Int32 const13_x_2_0x100 = 13 * 2 * 0x100;
//手动内联 -->//chan_calc高频调用 单次Update 5467次 左右下级堆栈volume_calc 20000+次 op_calc 10000+次
unsafe static void chan_calc(YM2151Operator* PSGoper, int* chanout, int* imem, int chan)
{
int chan_x4 = (chan * 4);
int chan_x4_add1 = (chan_x4 + 1);
int chan_x4_add2 = (chan_x4 + 2);
int chan_x4_add3 = (chan_x4 + 3);
// 预缓存操作符指针
YM2151Operator* op0 = &PSGoper[chan_x4]; /* M1 */
YM2151Operator* op1 = &PSGoper[chan_x4_add1]; /* M2 */
YM2151Operator* op2 = &PSGoper[chan_x4_add2]; /* C1 */
YM2151Operator* op3 = &PSGoper[chan_x4_add3]; /* C2 */
int* imem_chan_x4 = &imem[chan_x4]; /* C2 */
//fixed (YM2151Operator* PSGoperPtr = &PSG.oper[0])
{
@ -1110,52 +1186,120 @@ namespace MAME.Core
chanout[8] = chanout[9] = chanout[10] = chanout[11] = 0;
//op = PSGoper[chan * 4]; /* M1 */
//op.mem_connect = op.mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
set_mem(PSGoper, chanout, imem, chan * 4);
if (PSGoper[chan * 4].ams != 0)
//set_mem(PSGoper, chanout, imem, chan_x4); //-->(YM2151Operator* PSGoper, int* chanout, int* imem, int op1)
if (*imem_chan_x4 == 8 || *imem_chan_x4 == 10 || *imem_chan_x4 == 11)
{
AM = PSG.lfa << (int)(PSGoper[chan * 4].ams - 1);
chanout[*imem_chan_x4] = op0->mem_value;
}
env = volume_calc(PSGoper, (chan * 4), AM);
if (op0->ams != 0)
{
AM = PSG.lfa << (int)(op0->ams - 1);
}
//env = volume_calc(PSGoper, chan_x4, AM);
env = op0->tl + ((uint)op0->volume) + (AM & op0->AMmask);
//env = volume_calc_planB(PSGoper[chan * 4], AM);
{
int iout = PSGoper[chan * 4].fb_out_prev + PSGoper[chan * 4].fb_out_curr;
PSGoper[chan * 4].fb_out_prev = PSGoper[chan * 4].fb_out_curr;
int iout = op0->fb_out_prev + op0->fb_out_curr;
op0->fb_out_prev = op0->fb_out_curr;
set_value1(chanout, PSGoper, chan * 4);
//set_value1(chanout, PSGoper, chan_x4); //->(int* chanout, YM2151Operator* PSGoper, int op1)
if (iconnect[chan_x4] == 12)
{
chanout[9] = chanout[10] = chanout[11] = op0->fb_out_prev;
}
else
{
chanout[iconnect[chan_x4]] = op0->fb_out_prev;
}
PSGoper[chan * 4].fb_out_curr = 0;
op0->fb_out_curr = 0;
if (env < 13 * 64)
{
if (PSGoper[chan * 4].fb_shift == 0)
if (op0->fb_shift == 0)
{
iout = 0;
}
PSGoper[chan * 4].fb_out_curr = op_calc1(PSGoper, (chan * 4), env, (iout << (int)PSGoper[chan * 4].fb_shift));
//op0->fb_out_curr = op_calc1(PSGoper, chan_x4, env, (iout << (int)op0->fb_shift));//----->(YM2151Operator* PSGoper, int i1, uint env, int pm)
uint p;
int i;
i = (int)((op0->phase & 0xffff0000) + (iout << (int)op0->fb_shift));
p = (env << 3) + sin_tab[(i >> 16) & 0x3ff];
if (p >= 13 * 2 * 0x100)
{
op0->fb_out_curr = 0;
}
else
op0->fb_out_curr = tl_tab[p];
}
}
env = volume_calc(PSGoper, (chan * 4 + 1), AM); /* M2 */
//env = volume_calc(PSGoper, chan_x4_add1, AM); /* M2 */
env = op1->tl + ((uint)op1->volume) + (AM & op1->AMmask);
//env = volume_calc_planB(PSGoper[chan * 4 + 1], AM);/* M2 */
if (env < 13 * 64)
{
//PSGoper[chan * 4 + 1].connect += op_calc((int)(chan * 4 + 1), env, m2);
set_value2(chanout, chan * 4 + 1, op_calc(PSGoper, (chan * 4 + 1), env, chanout[8]));// m2));
//set_value2(chanout, chan_x4_add1, op_calc(PSGoper, chan_x4_add1, env, chanout[8]));// m2));
//--start
//参数op_calc(YM2151Operator* PSGoper, int i1, uint env, int pm)
int InParam;
uint p;
p = (env << 3) + sin_tab[(((int)((op1->phase & 0xffff0000) + (chanout[8] << 15))) >> 16) & 0x3ff];
if (p >= const13_x_2_0x100)
InParam = 0;
else
InParam = tl_tab[p];
//参数set_value2(int* chanout, int op1, int i)
if (iconnect[chan_x4_add1] == 12) { }
else
{
chanout[iconnect[chan_x4_add1]] += InParam;
}
env = volume_calc(PSGoper, (chan * 4 + 2), AM); /* C1 */
//--end
}
//env = volume_calc(PSGoper, chan_x4_add2, AM); /* C1 */
env = op2->tl + ((uint)op2->volume) + (AM & op2->AMmask);
//env = volume_calc_planB(PSGoper[chan * 4 + 2], AM); /* C1 */
if (env < 13 * 64)
{
//PSGoper[chan * 4 + 2].connect += op_calc((int)(chan * 4 + 2), env, c1);
set_value2(chanout, chan * 4 + 2, op_calc(PSGoper, (chan * 4 + 2), env, chanout[9]));// c1));
//set_value2(chanout, chan_x4_add2, op_calc(PSGoper, chan_x4_add2, env, chanout[9]));// c1));
//--start
int InParam;
uint p;
p = (env << 3) + sin_tab[(((int)((op2->phase & 0xffff0000) + (chanout[9] << 15))) >> 16) & 0x3ff];
if (p >= const13_x_2_0x100)
InParam = 0;
else
InParam = tl_tab[p];
if (iconnect[chan_x4_add2] == 12) { }
else
{
chanout[iconnect[chan_x4_add2]] += InParam;
}
env = volume_calc(PSGoper, (chan * 4 + 3), AM); /* C2 */
//--end
}
//env = volume_calc(PSGoper, (chan * 4 + 3), AM); /* C2 */
env = op3->tl + ((uint)op3->volume) + (AM & op3->AMmask);
//env = volume_calc_planB(PSGoper[chan * 4 + 3], AM); /* C2 */
if (env < 13 * 64)
{
chanout[chan] += op_calc(PSGoper, (chan * 4 + 3), env, chanout[10]);// c2);
//chanout[chan] += op_calc(PSGoper, (chan_x4_add3), env, chanout[10]);// c2); //------->(YM2151Operator* PSGoper, int i1, uint env, int pm)
uint p;
p = (env << 3) + sin_tab[(((int)((op3->phase & 0xffff0000) + (chanout[10] << 15))) >> 16) & 0x3ff];
if (p >= const13_x_2_0x100)
chanout[chan] += 0;
else
chanout[chan] += tl_tab[p];
}
/* M1 */
PSGoper[chan * 4].mem_value = chanout[11];//mem;
op0->mem_value = chanout[11];//mem;
}
}

View File

@ -282,9 +282,12 @@ namespace MAME.Core
OPN.advance_eg_channel(1);
OPN.advance_eg_channel(2);
}
OPN.chan_calc(0, 0);
OPN.chan_calc(1, 1);
OPN.chan_calc(2, 2);
//OPN.chan_calc(0, 0);
//OPN.chan_calc(1, 1);
//OPN.chan_calc(2, 2);
OPN.chan_calc(0, false);
OPN.chan_calc(1, false);
OPN.chan_calc(2, true);
{
int lt;
lt = FM.out_fm[0] + FM.out_fm[1] + FM.out_fm[2];

View File

@ -1,4 +1,5 @@

using System;
namespace MAME.Core
{
public unsafe class YM2610
@ -41,49 +42,102 @@ namespace MAME.Core
{
Sound.ym2610stream.stream_update();
}
//public void ADPCMA_calc_chan(int c)
//{
// uint step;
// byte data;
// int i;
// adpcm[c].now_step += adpcm[c].step;
// if (adpcm[c].now_step >= (1 << 16))
// {
// step = adpcm[c].now_step >> 16;
// adpcm[c].now_step &= (1 << 16) - 1;
// for (i = 0; i < step; i++)
// {
// if ((adpcm[c].now_addr & ((1 << 21) - 1)) == ((adpcm[c].end << 1) & ((1 << 21) - 1)))
// {
// adpcm[c].flag = 0;
// adpcm_arrivedEndAddress |= adpcm[c].flagMask;
// return;
// }
// if ((adpcm[c].now_addr & 1) != 0)
// {
// data = (byte)(adpcm[c].now_data & 0x0f);
// }
// else
// {
// adpcm[c].now_data = FM.ymsndrom[adpcm[c].now_addr >> 1];
// data = (byte)((adpcm[c].now_data >> 4) & 0x0f);
// }
// adpcm[c].now_addr++;
// adpcm[c].adpcm_acc += FM.jedi_table[adpcm[c].adpcm_step + data];
// if ((adpcm[c].adpcm_acc & ~0x7ff) != 0)
// {
// adpcm[c].adpcm_acc |= ~0xfff;
// }
// else
// {
// adpcm[c].adpcm_acc &= 0xfff;
// }
// adpcm[c].adpcm_step += FM.step_inc[data & 7];
// adpcm[c].adpcm_step = FM.Limit(adpcm[c].adpcm_step, 48 * 16, 0);
// }
// adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;
// }
// FM.out_adpcm[FM.ipan[c]] += adpcm[c].adpcm_out;
//}
//手动内联
public void ADPCMA_calc_chan(int c)
{
uint step;
byte data;
int i;
adpcm[c].now_step += adpcm[c].step;
if (adpcm[c].now_step >= (1 << 16))
fixed (FM.ADPCM_CH* adpcm_c = &adpcm[c])
{
step = adpcm[c].now_step >> 16;
adpcm[c].now_step &= (1 << 16) - 1;
adpcm_c->now_step += adpcm_c->step;
if (adpcm_c->now_step >= (1 << 16))
{
step = adpcm_c->now_step >> 16;
adpcm_c->now_step &= (1 << 16) - 1;
for (i = 0; i < step; i++)
{
if ((adpcm[c].now_addr & ((1 << 21) - 1)) == ((adpcm[c].end << 1) & ((1 << 21) - 1)))
if ((adpcm_c->now_addr & ((1 << 21) - 1)) == ((adpcm_c->end << 1) & ((1 << 21) - 1)))
{
adpcm[c].flag = 0;
adpcm_arrivedEndAddress |= adpcm[c].flagMask;
adpcm_c->flag = 0;
adpcm_arrivedEndAddress |= adpcm_c->flagMask;
return;
}
if ((adpcm[c].now_addr & 1) != 0)
if ((adpcm_c->now_addr & 1) != 0)
{
data = (byte)(adpcm[c].now_data & 0x0f);
data = (byte)(adpcm_c->now_data & 0x0f);
}
else
{
adpcm[c].now_data = FM.ymsndrom[adpcm[c].now_addr >> 1];
data = (byte)((adpcm[c].now_data >> 4) & 0x0f);
adpcm_c->now_data = FM.ymsndrom[adpcm_c->now_addr >> 1];
data = (byte)((adpcm_c->now_data >> 4) & 0x0f);
}
adpcm[c].now_addr++;
adpcm[c].adpcm_acc += FM.jedi_table[adpcm[c].adpcm_step + data];
if ((adpcm[c].adpcm_acc & ~0x7ff) != 0)
adpcm_c->now_addr++;
adpcm_c->adpcm_acc += FM.jedi_table[adpcm_c->adpcm_step + data];
if ((adpcm_c->adpcm_acc & ~0x7ff) != 0)
{
adpcm[c].adpcm_acc |= ~0xfff;
adpcm_c->adpcm_acc |= ~0xfff;
}
else
{
adpcm[c].adpcm_acc &= 0xfff;
adpcm_c->adpcm_acc &= 0xfff;
}
adpcm[c].adpcm_step += FM.step_inc[data & 7];
adpcm[c].adpcm_step = FM.Limit(adpcm[c].adpcm_step, 48 * 16, 0);
adpcm_c->adpcm_step += FM.step_inc[data & 7];
//adpcm_c->adpcm_step = FM.Limit(adpcm_c->adpcm_step, 48 * 16, 0);//(int val, int max, int min)
int val = adpcm_c->adpcm_step;
const int max = 48 * 16;
adpcm_c->adpcm_step = Math.Min(max, adpcm_c->adpcm_step);
adpcm_c->adpcm_step = Math.Max(0, adpcm_c->adpcm_step);
}
adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3;
adpcm_c->adpcm_out = ((adpcm_c->adpcm_acc * adpcm_c->vol_mul) >> adpcm_c->vol_shift) & ~3;
}
FM.out_adpcm[FM.ipan[c]] += adpcm_c->adpcm_out;
}
FM.out_adpcm[FM.ipan[c]] += adpcm[c].adpcm_out;
}
@ -490,6 +544,9 @@ namespace MAME.Core
}
OPN.refresh_fc_eg_chan(F2610.OPN.type, 4);
OPN.refresh_fc_eg_chan(F2610.OPN.type, 5);
int* streamoutput_0_offset_ptr = &Sound.ym2610stream.streamoutput_Ptrs[0][offset];
int* streamoutput_1_offset_ptr = &Sound.ym2610stream.streamoutput_Ptrs[1][offset];
for (i = 0; i < length; i++)
{
OPN.advance_lfo();
@ -509,10 +566,14 @@ namespace MAME.Core
OPN.advance_eg_channel(4);
OPN.advance_eg_channel(5);
}
OPN.chan_calc(1, 1);
OPN.chan_calc(2, 2);
OPN.chan_calc(4, 4);
OPN.chan_calc(5, 5);
//OPN.chan_calc(1, 1);
//OPN.chan_calc(2, 2);
//OPN.chan_calc(4, 4);
//OPN.chan_calc(5, 5);
OPN.chan_calc(1,false);
OPN.chan_calc(2,true);
OPN.chan_calc(4,false);
OPN.chan_calc(5,false);
if ((YMDeltat.DELTAT.portstate & 0x80) != 0)
{
YMDeltat.YM_DELTAT_ADPCM_CALC();
@ -537,10 +598,18 @@ namespace MAME.Core
rt += (int)((FM.out_fm[4] >> 1) & OPN.pan[9]);
lt += (int)((FM.out_fm[5] >> 1) & OPN.pan[10]);
rt += (int)((FM.out_fm[5] >> 1) & OPN.pan[11]);
lt = FM.Limit(lt, 32767, -32768);
rt = FM.Limit(rt, 32767, -32768);
Sound.ym2610stream.streamoutput_Ptrs[0][offset + i] = lt;
Sound.ym2610stream.streamoutput_Ptrs[1][offset + i] = rt;
//lt = FM.Limit(lt, 32767, -32768);
//rt = FM.Limit(rt, 32767, -32768);
lt = Math.Min(lt, 32767);
lt = Math.Max(lt, -32768);
rt = Math.Min(rt, 32767);
rt = Math.Max(rt, -32768);
//Sound.ym2610stream.streamoutput_Ptrs[0][offset + i] = lt;
*streamoutput_0_offset_ptr = lt;
streamoutput_0_offset_ptr++;
//Sound.ym2610stream.streamoutput_Ptrs[1][offset + i] = rt;
*streamoutput_1_offset_ptr = rt;
streamoutput_1_offset_ptr++;
}
}
public void ym2610b_update_one(int offset, int length)
@ -565,6 +634,7 @@ namespace MAME.Core
OPN.refresh_fc_eg_chan(F2610.OPN.type, 3);
OPN.refresh_fc_eg_chan(F2610.OPN.type, 4);
OPN.refresh_fc_eg_chan(F2610.OPN.type, 5);
for (i = 0; i < length; i++)
{
OPN.advance_lfo();
@ -588,12 +658,18 @@ namespace MAME.Core
OPN.advance_eg_channel(4);
OPN.advance_eg_channel(5);
}
OPN.chan_calc(0, 0);
OPN.chan_calc(1, 1);
OPN.chan_calc(2, 2);
OPN.chan_calc(3, 3);
OPN.chan_calc(4, 4);
OPN.chan_calc(5, 5);
//OPN.chan_calc(0, 0);
//OPN.chan_calc(1, 1);
//OPN.chan_calc(2, 2);
//OPN.chan_calc(3, 3);
//OPN.chan_calc(4, 4);
//OPN.chan_calc(5, 5);
OPN.chan_calc(0, false);
OPN.chan_calc(1, false);
OPN.chan_calc(2, true);
OPN.chan_calc(3, false);
OPN.chan_calc(4, false);
OPN.chan_calc(5, false);
if ((YMDeltat.DELTAT.portstate & 0x80) != 0)
{
YMDeltat.YM_DELTAT_ADPCM_CALC();
@ -622,8 +698,12 @@ namespace MAME.Core
rt += (int)((FM.out_fm[4] >> 1) & OPN.pan[9]);
lt += (int)((FM.out_fm[5] >> 1) & OPN.pan[10]);
rt += (int)((FM.out_fm[5] >> 1) & OPN.pan[11]);
lt = FM.Limit(lt, 32767, -32768);
rt = FM.Limit(rt, 32767, -32768);
//lt = FM.Limit(lt, 32767, -32768);
//rt = FM.Limit(rt, 32767, -32768);
lt = Math.Min(lt, 32767);
lt = Math.Max(lt, -32768);
rt = Math.Min(rt, 32767);
rt = Math.Max(rt, -32768);
Sound.ym2610stream.streamoutput_Ptrs[0][offset + i] = lt;
Sound.ym2610stream.streamoutput_Ptrs[1][offset + i] = rt;
}

View File

@ -100,25 +100,29 @@ public class UniSoundPlayer : MonoBehaviour, ISoundPlayer /*, AxiAudioPull*/
}
}
void OnAudioFilterRead(float[] data, int channels)
unsafe void OnAudioFilterRead(float[] data, int channels)
{
if (!UMAME.bInGame) return;
int step = channels;
for (int i = 0; i < data.Length; i += step)
int length = data.Length;
fixed (float* dataptr = &data[0])
{
float* dataptr_index = &dataptr[0];
for (int i = 0; i < length; i += step)
{
float rawFloat = lastData;
float rawData;
if (_buffer.TryRead(out rawData))
{
rawFloat = rawData;
for (int fill = 0; fill < step; fill++)
{
*dataptr_index = rawFloat;
dataptr_index++;
}
data[i] = rawFloat;
for (int fill = 1; fill < step; fill++)
data[i + fill] = rawFloat;
lastData = rawFloat;
}
}
}
public void SubmitSamples(byte[] buffer, int samples_a)
{