Files
scripts/cpp/chip8_disasm.cpp
2019-05-26 11:57:05 +03:00

222 lines
5.6 KiB
C++

#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <filesystem>
template<typename T>
std::uint8_t get_nibble(T value, int nr) {
return ((value >> (nr * 4)) & 0xF);
}
template<typename T>
std::vector<T> get_file_vector(std::ifstream& file_stream) {
file_stream.seekg(0, std::ios::end);
const std::size_t file_size = file_stream.tellg();
file_stream.seekg(0, std::ios::beg);
std::vector<T> file_contents(file_size);
file_stream.read((char*)&file_contents[0], file_size);
return file_contents;
}
void disassemble(const std::vector<std::uint16_t>& program) {
for (auto inst : program) {
if (inst == 0) {
break;
}
switch (get_nibble(inst, 3)) {
case 0x0:
if (inst == 0x00E0) {
printf("CLS\n");
} else if (inst == 0x00EE) {
printf("RET\n");
} else {
printf("SYS %03x\n", inst & 0xFFF);
} break;
case 0x1:
printf("JMP %03x\n", inst & 0xFFF);
break;
case 0x2:
printf("CALL %03x\n", inst & 0xFFF);
break;
case 0x3:
printf("SE V%X, %02x\n", get_nibble(inst, 2), inst & 0xFF);
break;
case 0x4:
printf("SNE V%X, %02x\n", get_nibble(inst, 2), inst & 0xFF);
break;
case 0x5:
printf("SE V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x6:
printf("LD V%X, %02x\n", get_nibble(inst, 2), inst & 0xFF);
break;
case 0x7:
printf("ADD V%X, %02x\n", get_nibble(inst, 2), inst & 0xFF);
break;
case 0x8:
switch (inst & 0xF) {
case 0x0:
printf("LD V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x1:
printf("OR V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x2:
printf("AND V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x3:
printf("XOR V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x4:
printf("ADD V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x5:
printf("SUB V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x6:
printf("SHR V%X {, V%X}\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0x7:
printf("SUBN V%X V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
case 0xE:
printf("SHL V%X {, V%X}\n", get_nibble(inst, 2), get_nibble(inst, 1));
break;
default:
break;
} break;
case 0x9:
if (get_nibble(inst, 0) == 0) {
printf("SNE V%X, V%X\n", get_nibble(inst, 2), get_nibble(inst, 1));
} break;
case 0xA:
printf("LD I, %03x\n", inst & 0xFFF);
break;
case 0xB:
printf("JP V0, %03x\n", inst & 0xFFF);
break;
case 0xC:
printf("RND V%X, %02x\n", get_nibble(inst, 2), inst & 0xFF);
break;
case 0xD:
printf("DRW V%X, V%X, %x\n", get_nibble(inst, 2), get_nibble(inst, 1), get_nibble(inst, 0));
break;
case 0xE:
switch (inst & 0xFF) {
case 0x9E:
printf("SKP V%X\n", get_nibble(inst, 2));
break;
case 0xA1:
printf("SKNP V%X\n", get_nibble(inst, 2));
break;
default:
break;
} break;
case 0xF:
switch (inst & 0xFF) {
case 0x07:
printf("LD V%X, DT\n", get_nibble(inst, 2));
break;
case 0x0A:
printf("LD V%X, K\n", get_nibble(inst, 2));
break;
case 0x15:
printf("LD DT, V%X\n", get_nibble(inst, 2));
break;
case 0x18:
printf("LD ST, V%X\n", get_nibble(inst, 2));
break;
case 0x1E:
printf("ADD I, V%X\n", get_nibble(inst, 2));
break;
case 0x29:
printf("LD F, V%X\n", get_nibble(inst, 2));
break;
case 0x33:
printf("LD B, V%X\n", get_nibble(inst, 2));
break;
case 0x55:
printf("LD [I], V%X\n", get_nibble(inst, 2));
break;
case 0x65:
printf("LD V%X, [I]\n", get_nibble(inst, 2));
default:
break;
} break;
default:
break;
}
}
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cout << "Usage: " << argv[0] << " [CHIP8 ROM]" << std::endl;
return 1;
}
const std::string file_path = argv[1];
if (!std::filesystem::exists(file_path)) {
std::cout << "Could not find file." << std::endl;
return 1;
}
std::ifstream file_stream(file_path, std::ios::binary);
if (!file_stream) {
std::cout << "Could not open file." << std::endl;
return 1;
}
const auto file_contents = get_file_vector<std::uint16_t>(file_stream);
disassemble(file_contents);
}