feat(core): add SUPER-CHIP/XO-CHIP extended opcodes
This commit is contained in:
1 parent
40cebbe0dc
commit
17a8befb8d
1 file changed
+165
@@ -0,0 +1,165 @@
|
||||
namespace Chip8.Core;
|
||||
|
||||
public sealed partial class Machine
|
||||
{
|
||||
bool executeExtended(ushort opcode, int x, int y, int n, byte nn, ushort nnn)
|
||||
{
|
||||
switch (opcode & 0xF000)
|
||||
{
|
||||
case 0x0000:
|
||||
return executeSystem(opcode, n);
|
||||
|
||||
case 0x5000:
|
||||
if (platform == Platform.XoChip && n == 0x2)
|
||||
{
|
||||
storeRange(x, y);
|
||||
return true;
|
||||
}
|
||||
if (platform == Platform.XoChip && n == 0x3)
|
||||
{
|
||||
loadRange(x, y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case 0xD000:
|
||||
v[0xF] = (byte)(video.drawSprite(memory, i, v[x], v[y], n, planeMask, !quirks.clipSprites) ? 1 : 0);
|
||||
drawPending = true;
|
||||
return true;
|
||||
|
||||
case 0xF000:
|
||||
return executeExtendedMisc(opcode, x, nn);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool executeSystem(ushort opcode, int n)
|
||||
{
|
||||
if ((opcode & 0xFFF0) == 0x00C0)
|
||||
{
|
||||
video.scrollDown(n, planeMask);
|
||||
drawPending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((opcode & 0xFFF0) == 0x00D0)
|
||||
{
|
||||
video.scrollUp(n, planeMask);
|
||||
drawPending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x00E0:
|
||||
video.clear(planeMask);
|
||||
drawPending = true;
|
||||
return true;
|
||||
case 0x00FB:
|
||||
video.scrollRight(Video.scrollStep, planeMask);
|
||||
drawPending = true;
|
||||
return true;
|
||||
case 0x00FC:
|
||||
video.scrollLeft(Video.scrollStep, planeMask);
|
||||
drawPending = true;
|
||||
return true;
|
||||
case 0x00FD:
|
||||
exited = true;
|
||||
pc -= 2;
|
||||
return true;
|
||||
case 0x00FE:
|
||||
video.setResolution(false);
|
||||
drawPending = true;
|
||||
return true;
|
||||
case 0x00FF:
|
||||
video.setResolution(true);
|
||||
drawPending = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool executeExtendedMisc(ushort opcode, int x, byte nn)
|
||||
{
|
||||
if (platform == Platform.XoChip && opcode == 0xF000)
|
||||
{
|
||||
i = (ushort)((memory[pc] << 8) | memory[pc + 1]);
|
||||
pc += 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (platform == Platform.XoChip && (opcode & 0xF0FF) == 0xF001)
|
||||
{
|
||||
planeMask = x & 0x3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (platform == Platform.XoChip && opcode == 0xF002)
|
||||
{
|
||||
for (int b = 0; b < audioPattern.Length; b++)
|
||||
{
|
||||
audioPattern[b] = memory[(i + b) & (memory.Length - 1)];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (nn)
|
||||
{
|
||||
case 0x30:
|
||||
i = (ushort)(bigFontStart + (v[x] & 0xF) * FontSet.bigGlyphBytes);
|
||||
return true;
|
||||
case 0x3A:
|
||||
if (platform != Platform.XoChip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
audioPitch = v[x];
|
||||
return true;
|
||||
case 0x75:
|
||||
for (int r = 0; r <= (x & 0xF); r++)
|
||||
{
|
||||
rplFlags[r] = v[r];
|
||||
}
|
||||
return true;
|
||||
case 0x85:
|
||||
for (int r = 0; r <= (x & 0xF); r++)
|
||||
{
|
||||
v[r] = rplFlags[r];
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void storeRange(int x, int y)
|
||||
{
|
||||
int step = x <= y ? 1 : -1;
|
||||
int addr = i;
|
||||
for (int r = x; ; r += step)
|
||||
{
|
||||
memory[addr++ & (memory.Length - 1)] = v[r];
|
||||
if (r == y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadRange(int x, int y)
|
||||
{
|
||||
int step = x <= y ? 1 : -1;
|
||||
int addr = i;
|
||||
for (int r = x; ; r += step)
|
||||
{
|
||||
v[r] = memory[addr++ & (memory.Length - 1)];
|
||||
if (r == y)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user