forked from sin365/AxibugEmuOnline
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f53fcbfee0 | |||
| 79ada55c3c | |||
| 7ecd7d45a0 | |||
| a3e5f75694 | |||
| 1e3cf56675 | |||
| 7f20da42e6 | |||
| bb32fd3736 | |||
| a806deed55 | |||
| c1ad639f7a | |||
| 212810384e | |||
| 382ee2d1b9 | |||
| 96039886f4 | |||
| 4914db1b54 | |||
| 0009a2d00e | |||
| 898353b652 | |||
| e41c910496 | |||
| e394d38e27 | |||
| 6edb3b5400 | |||
| f49f7fef00 | |||
| 48c7fe00eb | |||
| 4649149103 | |||
| d7322d8e91 |
@ -2,7 +2,8 @@
|
||||
{
|
||||
public partial class CGBAudio
|
||||
{
|
||||
public class CGBWave : Wave, IDMGAudioChannel
|
||||
//本身wave就继承了IDMGAudioChannel
|
||||
public class CGBWave : Wave//, IDMGAudioChannel
|
||||
{
|
||||
public override void Reset()
|
||||
{
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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)];
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
@ -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;
|
||||
//}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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]
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MAME.Core
|
||||
{
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
// 优化指针更新
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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":
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user