summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jones <admin@danieljon.es>2020-08-19 16:29:58 +0930
committerDaniel Jones <admin@danieljon.es>2020-08-19 16:30:13 +0930
commit26653bc8ac93cb748b46dae933b60fa755e400b1 (patch)
tree0820482c21f76c8db44899f3e742ad4ddd8582d7
parentd64874fc4e50f22ecb5aa669abfe5d5a7931255a (diff)
downloadchip8-26653bc8ac93cb748b46dae933b60fa755e400b1.tar.gz
chip8-26653bc8ac93cb748b46dae933b60fa755e400b1.zip
instructions and debugging features
added some more instructions, particularly calling and returning from subroutines using the stack. also added stepping through the program using the '.' key to advance one cycle
-rw-r--r--chip8.c25
-rw-r--r--main.c46
2 files changed, 59 insertions, 12 deletions
diff --git a/chip8.c b/chip8.c
index 1d8de29..f005de8 100644
--- a/chip8.c
+++ b/chip8.c
@@ -133,7 +133,7 @@ chip8_beep()
void
unknown_opcode(uint16_t bad_opcode)
{
- fprintf(stderr, "unknown opcode: 0x%02X at 0x%02X\n", bad_opcode, PC);
+ fprintf(stderr, "unknown opcode: 0x%02X at 0x%02X\n", bad_opcode, PC-2); // minus 2 because we increment PC by 2 at the start of decoding
}
void
chip8_cycle()
@@ -145,7 +145,7 @@ chip8_cycle()
/*
* the opcode is a 2 byte value, while our memory is 1 byte
* so to get our opcode we need to combine 2 bytes located at PC and PC+1
- * we right shift the first byte by 8 (1 byte) to place it in the high byte
+ * we left shift the first byte by 8 (1 byte) to place it in the high byte
* and we store the second byte in the lower byte
*/
opcode = (memory[PC] << 8) | memory[PC+1];
@@ -155,7 +155,8 @@ chip8_cycle()
uint8_t x = (opcode >> 8) & 0x000F; // lower 4 bits of the high byte, we discard the low byte by right shifting it out
uint8_t y = (opcode >> 4) & 0x000F; // upper 4 bits of the low byte, so we need to discard the lower 4 bits
uint8_t kk = opcode & 0x00FF; // lowest 8 bits
-
+ printf("parsing at 0x%03X\n", PC);
+ PC += 2; // TODO: remove
switch (opcode & 0xF000)
{
/*
@@ -172,17 +173,32 @@ chip8_cycle()
draw_flag = 1;
break;
case 0x00EE: /* ret (return from subroutine) */
+ // TODO: test, check for out of bounds?
+ PC = stack[--SP];
break;
default: unknown_opcode(opcode);
}
break;
}
+ case 0x1000: /*JP addr (jump to memory address nnn) */
+ PC = nnn;
+ break;
+ case 0x2000: /* CALL addr (call subroutine at addr, increment SP and put current PC on top of stack, set PC to nnn) */
+ // TODO: test, bounds check?
+ stack[SP++] = PC;
+ PC = nnn;
+ break;
case 0x6000: /* LD Vx, byte (load byte in register x) */
{
V[x] = kk;
break;
}
-
+ case 0x7000: /* ADD Vx, byte (add byte to Vx and store result in Vx) */
+ V[x] = V[x] + kk;
+ break;
+ case 0x8000: /* LD Vx, Vy (load Vy into Vx register) */
+ V[x] = V[y];
+ break;
default: unknown_opcode(opcode);
}
@@ -194,5 +210,4 @@ chip8_cycle()
chip8_beep();
sound_timer--;
}
- PC += 2;
}
diff --git a/main.c b/main.c
index f58edf7..3b8183e 100644
--- a/main.c
+++ b/main.c
@@ -10,9 +10,11 @@
* http://mattmik.com/files/chip8/mastering/chip8.html (lots of info)
* http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#0.1
* http://www.emulator101.com/chip-8-sprites.html
+ * https://slack-files.com/T3CH37TNX-F3RKEUKL4-b05ab4930d?nojsmode=1
*/
#define VIDEO_SCALE 5
+#define STEPPING 1 // set to 1 to step manually through program
SDL_Window *window;
SDL_Renderer *renderer;
@@ -29,6 +31,8 @@ void handle_key_up(int keycode);
uint8_t get_chip8_key(int keycode);
void print_registers();
+int step_cycle = 0;
+
extern uint32_t video[WIDTH*HEIGHT];
extern int draw_flag;
extern uint8_t key[KEY_SIZE];
@@ -38,6 +42,7 @@ extern uint16_t PC;
extern int8_t SP;
extern uint8_t delay_timer;
extern uint8_t sound_timer;
+extern uint16_t stack[STACK_SIZE];
void
usage(char *program)
@@ -86,13 +91,21 @@ toggle_pixel(int x, int y)
void
print_registers()
{
- puts("REGISTER DUMP");
+ puts("DUMP");
puts("--------------------------");
for (int reg = 0; reg < REGISTER_COUNT; reg++)
{
printf("V[0x%01X] = 0x%02X\n", reg, V[reg]);
}
- printf("PC = 0x%03X\nI = 0x%03X\nSP = 0x%02X\ndelay_timer = 0x%02X\nsound_timer = 0x%02X\n", PC, I, SP, delay_timer, sound_timer);
+ // minus 2 on PC because we increment PC by 2 at the start of decoding
+ printf("PC = 0x%03X\nI = 0x%03X\nSP = 0x%02X\ndelay_timer = 0x%02X\nsound_timer = 0x%02X\n", PC-2, I, SP, delay_timer, sound_timer);
+ puts("STACK:");
+ for (int i = 0; i < 16; i++)
+ {
+ printf("[%d] = 0x%03X", i, stack[i]);
+ if (i == 7) puts("");
+ }
+ puts("");
puts("--------------------------");
}
@@ -103,6 +116,7 @@ handle_key_down(int keycode)
{
/* detect interpreter debug keys */
case SDLK_p: print_registers(); break;
+ case SDLK_PERIOD: step_cycle = 1; break;
default: break;
}
@@ -191,7 +205,7 @@ int main(int argc, char *argv[])
init_video();
- const int fps = 2;
+ const int fps = 1;
const int frame_delay = 1000/fps;
uint32_t frame_start;
uint32_t frame_time;
@@ -232,12 +246,30 @@ int main(int argc, char *argv[])
// logic
do_quit = handle_sdl_events();
- chip8_cycle();
+ if (STEPPING)
+ {
+ if (step_cycle == 1)
+ {
+ chip8_cycle();
+
+ if (draw_flag)
+ {
+ update_video();
+ draw_flag = 0;
+ }
- if (draw_flag)
+ step_cycle = 0;
+ }
+ }
+ else
{
- update_video();
- draw_flag = 0;
+ chip8_cycle();
+
+ if (draw_flag)
+ {
+ update_video();
+ draw_flag = 0;
+ }
}
frame_time = SDL_GetTicks() - frame_start;