Add special addressing functions for X, Y, N, etc
This commit is contained in:
parent
5d82b8ee40
commit
67b3e37c72
1 changed files with 63 additions and 44 deletions
107
src/emu.cpp
107
src/emu.cpp
|
@ -32,6 +32,31 @@ void EmulatorState::reset() {
|
||||||
draw_dirty = true;
|
draw_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reads 0x0NNN
|
||||||
|
uint16_t readAddress(const uint16_t opcode) {
|
||||||
|
return opcode & 0x0fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads 0x00NN
|
||||||
|
uint8_t readNN(const uint16_t opcode) {
|
||||||
|
return opcode & 0x00ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads 0x000N
|
||||||
|
uint8_t readN(const uint16_t opcode) {
|
||||||
|
return (opcode & 0x000f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads 0x0X00
|
||||||
|
uint8_t readX(const uint16_t opcode) {
|
||||||
|
return (opcode & 0x0f00) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads 0x00Y0
|
||||||
|
uint8_t readY(const uint16_t opcode) {
|
||||||
|
return (opcode & 0x00f0) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
typedef void (*cpu_func)(const uint16_t opcode);
|
typedef void (*cpu_func)(const uint16_t opcode);
|
||||||
|
|
||||||
void null_func(const uint16_t opcode) {
|
void null_func(const uint16_t opcode) {
|
||||||
|
@ -91,24 +116,23 @@ void operation0(const uint16_t opcode) {
|
||||||
|
|
||||||
// 1NNN
|
// 1NNN
|
||||||
void operation1(const uint16_t opcode) {
|
void operation1(const uint16_t opcode) {
|
||||||
const uint16_t nnn = opcode & 0x0fff;
|
const auto nnn = readAddress(opcode);
|
||||||
|
|
||||||
state.PC = nnn;
|
state.PC = nnn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2NNN
|
// 2NNN
|
||||||
void operation2(const uint16_t opcode) {
|
void operation2(const uint16_t opcode) {
|
||||||
const uint16_t nnn = opcode & 0x0fff;
|
const auto nnn = readAddress(opcode);
|
||||||
|
|
||||||
state.stack[state.stack_pointer] = state.PC;
|
state.stack[state.stack_pointer++] = state.PC;
|
||||||
state.stack_pointer++;
|
|
||||||
state.PC = nnn;
|
state.PC = nnn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3XNN
|
// 3XNN
|
||||||
void operation3(const uint16_t opcode) {
|
void operation3(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t nn = opcode & 0x00ff;
|
const auto nn = readNN(opcode);
|
||||||
|
|
||||||
if(state.v[x] == nn)
|
if(state.v[x] == nn)
|
||||||
state.PC += 4;
|
state.PC += 4;
|
||||||
|
@ -118,8 +142,8 @@ void operation3(const uint16_t opcode) {
|
||||||
|
|
||||||
// 4XNN
|
// 4XNN
|
||||||
void operation4(const uint16_t opcode) {
|
void operation4(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t nn = opcode & 0x00ff;
|
const auto nn = readNN(opcode);
|
||||||
|
|
||||||
if(state.v[x] != nn)
|
if(state.v[x] != nn)
|
||||||
state.PC += 4;
|
state.PC += 4;
|
||||||
|
@ -129,28 +153,26 @@ void operation4(const uint16_t opcode) {
|
||||||
|
|
||||||
// 6XNN
|
// 6XNN
|
||||||
void operation6(const uint16_t opcode) {
|
void operation6(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t nn = opcode & 0x00ff;
|
const auto nn = readNN(opcode);
|
||||||
|
|
||||||
state.v[x] = nn;
|
state.v[x] = nn;
|
||||||
|
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// &XNN
|
// &XNN
|
||||||
void operation7(const uint16_t opcode) {
|
void operation7(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t nn = opcode & 0x00ff;
|
const auto nn = readNN(opcode);
|
||||||
|
|
||||||
state.v[x] += nn;
|
state.v[x] += nn;
|
||||||
|
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8XY0
|
// 8XY0
|
||||||
void op8_func0(const uint16_t opcode) {
|
void op8_func0(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
state.v[x] = state.v[y];
|
state.v[x] = state.v[y];
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
|
@ -158,8 +180,8 @@ void op8_func0(const uint16_t opcode) {
|
||||||
|
|
||||||
// 8XY1
|
// 8XY1
|
||||||
void op8_func2(const uint16_t opcode) {
|
void op8_func2(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
state.v[x] = state.v[x] & state.v[y];
|
state.v[x] = state.v[x] & state.v[y];
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
|
@ -167,8 +189,8 @@ void op8_func2(const uint16_t opcode) {
|
||||||
|
|
||||||
// 8XY3
|
// 8XY3
|
||||||
void op8_func3(const uint16_t opcode) {
|
void op8_func3(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
state.v[x] = state.v[x] ^ state.v[y];
|
state.v[x] = state.v[x] ^ state.v[y];
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
|
@ -176,8 +198,8 @@ void op8_func3(const uint16_t opcode) {
|
||||||
|
|
||||||
// 8XY4
|
// 8XY4
|
||||||
void op8_func4(const uint16_t opcode) {
|
void op8_func4(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
// TODO: implement tests
|
// TODO: implement tests
|
||||||
if(state.v[y] < (0xFF - state.v[x]))
|
if(state.v[y] < (0xFF - state.v[x]))
|
||||||
|
@ -191,8 +213,8 @@ void op8_func4(const uint16_t opcode) {
|
||||||
|
|
||||||
// 8XY5
|
// 8XY5
|
||||||
void op8_func5(const uint16_t opcode) {
|
void op8_func5(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
// TODO: implement tests
|
// TODO: implement tests
|
||||||
if(state.v[y] > state.v[x])
|
if(state.v[y] > state.v[x])
|
||||||
|
@ -206,7 +228,7 @@ void op8_func5(const uint16_t opcode) {
|
||||||
|
|
||||||
// 8XY6
|
// 8XY6
|
||||||
void op8_func6(const uint16_t opcode) {
|
void op8_func6(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
state.v[0xF] = (state.v[x] & 1);
|
state.v[0xF] = (state.v[x] & 1);
|
||||||
state.v[x] >>= 1;
|
state.v[x] >>= 1;
|
||||||
|
@ -230,8 +252,8 @@ void operation8(const uint16_t opcode) {
|
||||||
|
|
||||||
// 9XY0
|
// 9XY0
|
||||||
void operation9(const uint16_t opcode) {
|
void operation9(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
|
|
||||||
if(state.v[x] != state.v[y])
|
if(state.v[x] != state.v[y])
|
||||||
state.PC += 4;
|
state.PC += 4;
|
||||||
|
@ -241,7 +263,7 @@ void operation9(const uint16_t opcode) {
|
||||||
|
|
||||||
// ANNN
|
// ANNN
|
||||||
void operationA(const uint16_t opcode) {
|
void operationA(const uint16_t opcode) {
|
||||||
const uint16_t nnn = opcode & 0x0fff;
|
const auto nnn = readAddress(opcode);
|
||||||
|
|
||||||
state.I = nnn;
|
state.I = nnn;
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
|
@ -249,8 +271,8 @@ void operationA(const uint16_t opcode) {
|
||||||
|
|
||||||
// CXNN
|
// CXNN
|
||||||
void operationC(const uint16_t opcode) {
|
void operationC(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t nn = opcode & 0x00ff;
|
const auto nn = readNN(opcode);
|
||||||
|
|
||||||
srand(time(nullptr));
|
srand(time(nullptr));
|
||||||
state.v[x] = (rand() % 0xFF) & nn;
|
state.v[x] = (rand() % 0xFF) & nn;
|
||||||
|
@ -259,9 +281,9 @@ void operationC(const uint16_t opcode) {
|
||||||
|
|
||||||
// DXYN
|
// DXYN
|
||||||
void operationD(const uint16_t opcode) {
|
void operationD(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
const uint8_t y = (opcode & 0x00f0) >> 4;
|
const auto y = readY(opcode);
|
||||||
const uint8_t n = opcode & 0x000f;
|
const auto n = readN(opcode);
|
||||||
|
|
||||||
const uint8_t x_pos = state.v[x];
|
const uint8_t x_pos = state.v[x];
|
||||||
const uint8_t y_pos = state.v[y];
|
const uint8_t y_pos = state.v[y];
|
||||||
|
@ -295,7 +317,7 @@ void operationD(const uint16_t opcode) {
|
||||||
|
|
||||||
// EX9E & EXA1
|
// EX9E & EXA1
|
||||||
void operationE(const uint16_t opcode) {
|
void operationE(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
switch(opcode & 0x00ff) {
|
switch(opcode & 0x00ff) {
|
||||||
case 0x9E:
|
case 0x9E:
|
||||||
|
@ -319,7 +341,7 @@ void operationE(const uint16_t opcode) {
|
||||||
|
|
||||||
// FX07
|
// FX07
|
||||||
void opF_func7(const uint16_t opcode) {
|
void opF_func7(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
state.v[x] = state.delay_timer;
|
state.v[x] = state.delay_timer;
|
||||||
|
|
||||||
|
@ -328,7 +350,7 @@ void opF_func7(const uint16_t opcode) {
|
||||||
|
|
||||||
// FX0A
|
// FX0A
|
||||||
void opF_funcA(const uint16_t opcode) {
|
void opF_funcA(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
for(int i = 0; i < 16; i++) {
|
for(int i = 0; i < 16; i++) {
|
||||||
if(state.keys[i] != 0) {
|
if(state.keys[i] != 0) {
|
||||||
|
@ -340,7 +362,7 @@ void opF_funcA(const uint16_t opcode) {
|
||||||
|
|
||||||
// FX55/FX65 & FX15
|
// FX55/FX65 & FX15
|
||||||
void opF_func5(const uint16_t opcode) {
|
void opF_func5(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
switch((opcode & 0x00F0) >> 4) {
|
switch((opcode & 0x00F0) >> 4) {
|
||||||
case 0x6:
|
case 0x6:
|
||||||
|
@ -377,25 +399,23 @@ void opF_func5(const uint16_t opcode) {
|
||||||
|
|
||||||
// FX18
|
// FX18
|
||||||
void opF_func8(const uint16_t opcode) {
|
void opF_func8(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
state.sound_timer = state.v[x];
|
state.sound_timer = state.v[x];
|
||||||
|
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FX29
|
// FX29
|
||||||
void opF_func9(const uint16_t opcode) {
|
void opF_func9(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
state.I = state.v[x] * 0x5;
|
state.I = state.v[x] * 0x5;
|
||||||
|
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FX1E
|
// FX1E
|
||||||
void opF_funcE(const uint16_t opcode) {
|
void opF_funcE(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
if((state.I + state.v[x]) > 0xFFF)
|
if((state.I + state.v[x]) > 0xFFF)
|
||||||
state.v[15] = 1;
|
state.v[15] = 1;
|
||||||
|
@ -403,13 +423,12 @@ void opF_funcE(const uint16_t opcode) {
|
||||||
state.v[15] = 0;
|
state.v[15] = 0;
|
||||||
|
|
||||||
state.I += state.v[x];
|
state.I += state.v[x];
|
||||||
|
|
||||||
state.PC += 2;
|
state.PC += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FX33
|
// FX33
|
||||||
void opF_func3(const uint16_t opcode) {
|
void opF_func3(const uint16_t opcode) {
|
||||||
const uint8_t x = (opcode & 0x0f00) >> 8;
|
const auto x = readX(opcode);
|
||||||
|
|
||||||
int decimal_rep = state.v[x];
|
int decimal_rep = state.v[x];
|
||||||
|
|
||||||
|
|
Reference in a new issue