-
Notifications
You must be signed in to change notification settings - Fork 9
ROM disassembler #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
danirod
wants to merge
8
commits into
devel
Choose a base branch
from
disasm
base: devel
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
ROM disassembler #29
Changes from 1 commit
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2ed8500
Add initial prototype for ROM dumper
danirod 18fe607
Ignore binary disassembler file
danirod 2525e35
Implement opcode decompiling
danirod 7b5fb61
Fix Makefile.am
danirod c30ce24
Minimal instruction fixes
hugomartin89 740c103
Merge pull request #30 from hugomartin89/fix/disasm
danirod 421c48b
Use getopt for input parameters
danirod 995f353
Use different output modes
danirod File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,195 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
|
||
#define OPCODE_P(opcode) (opcode >> 12) | ||
#define OPCODE_X(opcode) ((opcode & 0xF00) >> 8) | ||
#define OPCODE_Y(opcode) ((opcode & 0xF0) >> 4) | ||
#define OPCODE_N(opcode) (opcode & 0xF) | ||
#define OPCODE_NNN(opcode) (opcode & 0xFFF) | ||
#define OPCODE_KK(opcode) (opcode & 0xFF) | ||
|
||
static void | ||
to_instruction_0(unsigned short opcode, char* out) | ||
{ | ||
if (opcode == 0x00E0) { | ||
snprintf(out, 20, "EXIT"); | ||
} else if (opcode == 0x00EE) { | ||
snprintf(out, 20, "RET"); | ||
} else { | ||
snprintf(out, 20, "SYS %x", OPCODE_NNN(opcode)); | ||
} | ||
} | ||
|
||
static void | ||
to_instruction_1(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "JP %x", OPCODE_NNN(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_2(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "CALL %x", OPCODE_NNN(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_3(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "SE V[%x], %x", OPCODE_X(opcode), OPCODE_KK(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_4(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "SNE V[%x], %x", OPCODE_X(opcode), OPCODE_KK(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_5(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "SE V[%x], V[%x]", OPCODE_X(opcode), OPCODE_Y(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_6(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "LD V[%x], %x", OPCODE_X(opcode), OPCODE_KK(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_7(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "AND V[%x], %x", OPCODE_X(opcode), OPCODE_KK(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_8(unsigned short opcode, char* out) | ||
{ | ||
int x = OPCODE_X(opcode), y = OPCODE_Y(opcode), n = OPCODE_N(opcode); | ||
switch (n) { | ||
case 0: | ||
snprintf(out, 20, "LD V[%x], V[%x]", x, y); | ||
break; | ||
case 1: | ||
snprintf(out, 20, "OR V[%x], V[%x]", x, y); | ||
break; | ||
case 2: | ||
snprintf(out, 20, "AND V[%x], V[%x]", x, y); | ||
break; | ||
case 3: | ||
snprintf(out, 20, "XOR V[%x], V[%x]", x, y); | ||
break; | ||
case 4: | ||
snprintf(out, 20, "ADD V[%x], V[%x]", x, y); | ||
break; | ||
case 5: | ||
snprintf(out, 20, "SUB V[%x], V[%x]", x, y); | ||
break; | ||
case 6: | ||
snprintf(out, 20, "SHR V[%x]", x); | ||
break; | ||
case 7: | ||
snprintf(out, 20, "SUBN V[%x], V[%x]", x, y); | ||
break; | ||
case 0xE: | ||
snprintf(out, 20, "SHL V[%x]", x); | ||
break; | ||
} | ||
} | ||
|
||
static void | ||
to_instruction_9(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "SNE V[%x], V[%x]", OPCODE_X(opcode), OPCODE_Y(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_A(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "LD I, %x", OPCODE_NNN(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_B(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "JP V[0], %x", OPCODE_NNN(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_C(unsigned short opcode, char* out) | ||
{ | ||
snprintf(out, 20, "RND V[%x], %x", OPCODE_X(opcode), OPCODE_KK(opcode)); | ||
} | ||
|
||
static void | ||
to_instruction_D(unsigned short opcode, char* out) | ||
{ | ||
int x = OPCODE_X(opcode), y = OPCODE_Y(opcode), n = OPCODE_N(opcode); | ||
snprintf(out, 20, "DRW %x, %x, %x", x, y, n); | ||
|
||
} | ||
|
||
static void | ||
to_instruction_E(unsigned short opcode, char* out) | ||
{ | ||
if (OPCODE_KK(opcode) == 0x9E) { | ||
snprintf(out, 20, "SKP V[%x]", OPCODE_X(opcode)); | ||
} else if (OPCODE_KK(opcode) == 0xA1) { | ||
snprintf(out, 20, "SKNP V[%x]", OPCODE_X(opcode)); | ||
} | ||
} | ||
|
||
static void | ||
to_instruction_F(unsigned short opcode, char* out) | ||
{ | ||
switch (OPCODE_KK(opcode)) { | ||
case 0x07: | ||
snprintf(out, 20, "LD V[%x], DT", OPCODE_X(opcode)); | ||
break; | ||
case 0x0A: | ||
snprintf(out, 20, "LD V[%x], K", OPCODE_X(opcode)); | ||
break; | ||
case 0x15: | ||
snprintf(out, 20, "LD DT, V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x18: | ||
snprintf(out, 20, "LD ST, V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x1E: | ||
snprintf(out, 20, "ADD I, V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x29: | ||
snprintf(out, 20, "LD F, V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x33: | ||
snprintf(out, 20, "LD B, V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x55: | ||
snprintf(out, 20, "LD [I], V[%x]", OPCODE_X(opcode)); | ||
break; | ||
case 0x65: | ||
snprintf(out, 20, "LD V[%x], [I]", OPCODE_X(opcode)); | ||
break; | ||
} | ||
} | ||
|
||
typedef void (*to_instr) (unsigned short opcode, char* out); | ||
|
||
static to_instr instructions[] = { | ||
&to_instruction_0, &to_instruction_1, &to_instruction_2, &to_instruction_3, | ||
&to_instruction_4, &to_instruction_5, &to_instruction_6, &to_instruction_7, | ||
&to_instruction_8, &to_instruction_9, &to_instruction_A, &to_instruction_B, | ||
&to_instruction_C, &to_instruction_D, &to_instruction_E, &to_instruction_F | ||
}; | ||
|
||
static void | ||
to_instruction(unsigned short opcode, char* out) | ||
{ | ||
int p = OPCODE_P(opcode); | ||
// Fallback. In case instructions array fail to print for some reason. | ||
snprintf(out, 20, "%04x", opcode); | ||
instructions[p](opcode, out); | ||
} | ||
|
||
static int | ||
load_rom_file(const char* filename, unsigned char** buf) | ||
{ | ||
|
@@ -38,9 +227,12 @@ main(int argc, char** argv) | |
|
||
unsigned char* buffer; | ||
int length = load_rom_file(argv[1], &buffer); | ||
char output[20]; | ||
|
||
for (int byte = 0; byte < length; byte += 2) { | ||
printf("%02x%02x\n", buffer[byte], buffer[byte + 1]); | ||
unsigned short opcode = buffer[byte] << 8 | buffer[byte + 1]; | ||
to_instruction(opcode, output); | ||
printf("%03x %04x %s\n", (0x200 + byte), opcode, output); | ||
} | ||
|
||
free(buffer); | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be ADD instead of AND
http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#7xkk