Timeliness
Rather unfortunately, a lot of work has been done since the last devlog due to yesterday’s hackatime outage.
Let’s get started!
House of Memories
As I mentioned in the last devlog, the next step was to create a program counter (pc, marks where in the program we are) and the memory bus (with all the instructions we have been emulating for the GB to run, and others)
Bite the Code
The instructions are not stored as plain text of enums, they are stored as bytes, one byte for each combination of instruction and target. I thus have to map each bytecode to each instruction that I have added so far.
Not English Class! Anything but English!
There are much more than 256 different bytecodes; there are actually nearly 512. To accomplish this and still have memory be 1 byte, there is a bytecode prefix, 0xcb, which tells the chip that the real instruction is the next one, and to look it up on a different table.
PCMR
To go through each instruction, I added a step function:
fn step(&mut self) {
let (instruction_byte, prefixed) = {
let temp_byte = self.bus.read_byte(self.pc);
if temp_byte == 0xcb {
(self.bus.read_byte(self.pc + 1), true)
} else {
(temp_byte, false)
}
};
let next_pc = if let Some(instruction) = Instruction::from_byte(instruction_byte, prefixed)
{
self.execute(instruction)
} else {
panic!("Unknown instruction found for: 0x{:x}", instruction_byte);
};
self.pc = next_pc;
}
As you can see, execute returns the next pc value, something it didn’t do before. So, I had to go and make all the match arms blocks that do their associated action and also return self.pc.wrapping_add(1) for non-0xcb functions and self.pc.wrapping_add(2) for 0xcb functions, since no function that modifies the pc has been added yet.
Next is added yet more instructions! See y’all next time!
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.