Skip to content

Commit b05c37b

Browse files
committed
parse enough opcodes for boot ROM
0 parents  commit b05c37b

File tree

10 files changed

+364
-0
lines changed

10 files changed

+364
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.bin
2+
*.pdf
3+
/target

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "gameboy-disassembler"]
2+
path = gameboy-disassembler
3+
url = [email protected]:ericwoude/gameboy-disassembler.git

Cargo.lock

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "rustyboi"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
byteorder = "1.4.3"
10+
serde = { version = "1.0", features = ["derive"] }
11+
serde_json = "1.0"

NOTES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Boor ROM obtained from:
2+
https://gbdev.gg8.se/files/roms/bootroms/
3+
4+
# List of opcodes
5+
https://gbdev.io/gb-opcodes/optables/
6+
7+
# List of instruction semantics
8+
https://rgbds.gbdev.io/docs/v0.6.1/gbz80.7/

gameboy-disassembler

Submodule gameboy-disassembler added at edc7be7

src/instructions.rs

Whitespace-only changes.

src/main.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use std::fmt;
2+
3+
use opcodes::{decode_next_instruction, DecodedInstruction};
4+
5+
pub mod opcodes;
6+
7+
impl fmt::Display for DecodedInstruction {
8+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9+
write!(f, "0x{:02X} {:?}", self.address, self.instruction)
10+
}
11+
}
12+
13+
fn main() {
14+
let boot_ROM_bytes = std::fs::read("dmg_boot.bin").unwrap();
15+
let mut pc: usize = 0;
16+
while (pc < boot_ROM_bytes.len()) {
17+
let decoded = decode_next_instruction(pc as u16, &boot_ROM_bytes[pc..]);
18+
pc += decoded.instruction_size as usize;
19+
println!("{}", decoded)
20+
}
21+
}

src/memory_map.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
enum MemoryMapType {
2+
ROMBank00,
3+
SwitchableROMBank,
4+
VRAM,
5+
ExternalRAM,
6+
FixedWRAM,
7+
SwitchableWRAM,
8+
EchoRAM,
9+
SpriteAttributeTable,
10+
Unusable,
11+
IORegisters,
12+
HRAM,
13+
InterruptEnableRegister,
14+
}

src/opcodes.rs

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#[derive(Debug)]
2+
#[allow(non_camel_case_types)]
3+
pub enum Instruction {
4+
ADC_A_B,
5+
ADC_A_C,
6+
ADC_A_d8,
7+
ADD_A__HL_,
8+
ADD_A_E,
9+
AND_L,
10+
CALL_a16,
11+
CALL_Z_a16,
12+
CP__HL_,
13+
CP_C,
14+
CP_d8,
15+
CP_E,
16+
DEC_A,
17+
DEC_B,
18+
DEC_BC,
19+
DEC_C,
20+
DEC_D,
21+
DEC_E,
22+
EI,
23+
Illegal(u8),
24+
INC_A,
25+
INC_B,
26+
INC_BC,
27+
INC_C,
28+
INC_DE,
29+
INC_H,
30+
INC_HL,
31+
INC_SP,
32+
JR_NZ_r8,
33+
JR_r8,
34+
JR_Z_r8,
35+
LD__a16__A,
36+
LD__a16__SP,
37+
LD__C__A,
38+
LD__HL__A,
39+
LD__HL__E,
40+
LD_A__DE_,
41+
LD_A_B,
42+
LD_A_d8,
43+
LD_A_E,
44+
LD_A_H,
45+
LD_A_L,
46+
LD_B_D,
47+
LD_B_d8,
48+
LD_C_A,
49+
LD_C_d8,
50+
LD_D_A,
51+
LD_D_d8,
52+
LD_DE_d16,
53+
LD_E_d8,
54+
LD_H__HL_,
55+
LD_H_A,
56+
LD_H_E,
57+
LD_HL_d16,
58+
LD_HL_minus_A,
59+
LD_HL_plus_A,
60+
LD_L__HL_,
61+
LD_L_d8,
62+
LD_SP_A,
63+
LDH__a8__A,
64+
LDH_A__a8__,
65+
NOP,
66+
Prefix,
67+
PUSH_BC,
68+
RET_NZ,
69+
RET,
70+
RETI,
71+
RLA,
72+
SBC_A_A,
73+
SBC_A_C,
74+
SUB_B,
75+
XOR_A,
76+
}
77+
78+
/*
79+
0x00 LD SP, 0xFFFE
80+
0x03 XOR A
81+
0x04 LD HL, 0x9FFF
82+
0x07 LD (HL-), A
83+
0x08 BIT 7, H
84+
0x0A JR NZ, 0xFB
85+
0x0C LD HL, 0xFF26
86+
0x0F LD C, 0x11
87+
0x11 LD A, 0x80
88+
0x13 LD (HL-), A
89+
0x14 LD (C), A
90+
0x15 INC C
91+
92+
00000000 31 fe ff af 21 ff 9f 32 cb 7c 20 fb 21 26 ff 0e
93+
00000010 11 3e 80 32 e2 0c 3e f3 e2 32 3e 77 77 3e fc e0
94+
95+
*/
96+
97+
#[derive(Debug)]
98+
pub struct DecodedInstruction {
99+
pub address: u16,
100+
pub instruction: Instruction,
101+
pub instruction_size: u8,
102+
}
103+
104+
pub fn decode_next_instruction(address: u16, slice_at_program_counter: &[u8]) -> DecodedInstruction {
105+
let (i, s) = match slice_at_program_counter[0] {
106+
0x00 => (Instruction::NOP, 1),
107+
0x03 => (Instruction::INC_BC, 1),
108+
0x04 => (Instruction::INC_B, 1),
109+
0x05 => (Instruction::DEC_B, 1),
110+
0x06 => (Instruction::LD_B_d8, 2),
111+
0x08 => (Instruction::LD__a16__SP, 3),
112+
0x0B => (Instruction::DEC_BC, 1),
113+
0x0C => (Instruction::INC_C, 1),
114+
0x0D => (Instruction::DEC_C, 1),
115+
0x0E => (Instruction::LD_C_d8, 2),
116+
0x11 => (Instruction::LD_DE_d16, 3),
117+
0x13 => (Instruction::INC_DE, 1),
118+
0x15 => (Instruction::DEC_D, 1),
119+
0x16 => (Instruction::LD_D_d8, 2),
120+
0x17 => (Instruction::RLA, 1),
121+
0x18 => (Instruction::JR_r8, 2),
122+
0x1A => (Instruction::LD_A__DE_, 1),
123+
0x1D => (Instruction::DEC_E, 1),
124+
0x1E => (Instruction::LD_E_d8, 2),
125+
0x20 => (Instruction::JR_NZ_r8, 2),
126+
0x21 => (Instruction::LD_HL_d16, 3),
127+
0x22 => (Instruction::LD_HL_plus_A, 1),
128+
0x23 => (Instruction::INC_HL, 1),
129+
0x24 => (Instruction::INC_H, 1),
130+
0x28 => (Instruction::JR_Z_r8, 2),
131+
0x2E => (Instruction::LD_L_d8, 2),
132+
0x31 => (Instruction::LD_SP_A, 3),
133+
0x32 => (Instruction::LD_HL_minus_A, 1),
134+
0x33 => (Instruction::INC_SP, 1),
135+
0x3C => (Instruction::INC_A, 1),
136+
0x3D => (Instruction::DEC_A, 1),
137+
0x3E => (Instruction::LD_A_d8, 2),
138+
0x42 => (Instruction::LD_B_D, 1),
139+
0x4F => (Instruction::LD_C_A, 1),
140+
0x57 => (Instruction::LD_D_A, 1),
141+
0x63 => (Instruction::LD_H_E, 1),
142+
0x66 => (Instruction::LD_H__HL_, 1),
143+
0x67 => (Instruction::LD_H_A, 1),
144+
0x6E => (Instruction::LD_L__HL_, 1),
145+
0x73 => (Instruction::LD__HL__E, 1),
146+
0x77 => (Instruction::LD__HL__A, 1),
147+
0x78 => (Instruction::LD_A_B, 1),
148+
0x7B => (Instruction::LD_A_E, 1),
149+
0x7C => (Instruction::LD_A_H, 1),
150+
0x7D => (Instruction::LD_A_L, 1),
151+
0x83 => (Instruction::ADD_A_E, 1),
152+
0x86 => (Instruction::ADD_A__HL_, 1),
153+
0x88 => (Instruction::ADC_A_B, 1),
154+
0x89 => (Instruction::ADC_A_C, 1),
155+
0x90 => (Instruction::SUB_B, 1),
156+
0x99 => (Instruction::SBC_A_C, 1),
157+
0x9F => (Instruction::SBC_A_A, 1),
158+
0xA5 => (Instruction::AND_L, 1),
159+
0xAF => (Instruction::XOR_A, 1),
160+
0xB9 => (Instruction::CP_C, 1),
161+
0xBB => (Instruction::CP_E, 1),
162+
0xBE => (Instruction::CP__HL_, 1),
163+
0xC1 => (Instruction::RET_NZ, 1),
164+
0xC9 => (Instruction::RET, 1),
165+
0xCB => match slice_at_program_counter[1] {
166+
_ => {
167+
(Instruction::Prefix, 2) // 1 for prefix, 1 for extension?
168+
// println!("TODO: CB-prefixed opcode 0x{:x}", slice_at_program_counter[1]);
169+
// todo!()
170+
}
171+
},
172+
0xC5 => (Instruction::PUSH_BC, 1),
173+
0xCC => (Instruction::CALL_Z_a16, 3),
174+
0xCD => (Instruction::CALL_a16, 3),
175+
0xCE => (Instruction::ADC_A_d8, 2),
176+
0xD9 => (Instruction::RETI, 1),
177+
0xE0 => (Instruction::LDH__a8__A, 2),
178+
0xE2 => (Instruction::LD__C__A, 1),
179+
0xEA => (Instruction::LD__a16__A, 3),
180+
0xF0 => (Instruction::LDH_A__a8__, 2),
181+
0xFB => (Instruction::EI, 1),
182+
0xFE => (Instruction::CP_d8, 2),
183+
b => (Instruction::Illegal(b), 1),
184+
};
185+
DecodedInstruction {
186+
instruction: i,
187+
instruction_size: s,
188+
address,
189+
}
190+
}
191+
192+
impl Instruction {
193+
// /// Returns the number of cycles to execute this [`Instruction`].
194+
// pub fn get_cycles(self: &Instruction) -> i8 {
195+
// match self {
196+
// Instruction::LD_SP_A => todo!(),
197+
// Instruction::XOR_A => todo!(),
198+
// Instruction::LD_HL_d16 => todo!(),
199+
// Instruction::LD_HL_minus_A => todo!(),
200+
// Instruction::Prefix => todo!(),
201+
// Instruction::EI => todo!(),
202+
// Instruction::LD_C_d8 => todo!(),
203+
// Instruction::LD_A_d8 => todo!(),
204+
// Instruction::LD__C__A => todo!(),
205+
// }
206+
// }
207+
}

0 commit comments

Comments
 (0)