4
It’s been a long time since I wanted to start in the world of emulators, I decided to stop trying to make an emulator of a complex system and start with a very basic one, a CHIP-8 emulator, which is what many indicate in emulation forums. Well we go in pieces:
First operation I don’t see the point:
std::uint16_t opcode = m_Memory[reg.PC] << 8 | m_Memory[reg.PC + 1];
Basically 1 CHIP-8 option is worth 2 bytes, but the rom is 8 bits, first I access the Std array::uint8_t which I call m_Memory which I used to store the ROM and font set at the Program Counter position which is started as 0x200 which is where most CHIP-8 programs/games start, then 8 more zeros are added, which is easy to understand, 1 byte = 8 bits, so 2 bytes is 16 bits, but then the confusion starts, if you already got the opcode then why mask a 16 bits value with 8? and why use the rom itself but advancing the position of the pc?
Here we go to the second part of my problem:
switch (opcode & 0xF000) {
...
}
In a discussion I started on a Reddit forum about emulators people told me that they mask the opcode with 0xF000 to get the real opcode, but what I didn’t understand is how they came to the conclusion that they should mask and why with this value.
The final part:
Utilise that documentation where I and many others are guided, first we go to the opcode 0x6000 or 6xkk or LD V x , byte:
//LD Vx, byte
case 0x6000:
reg.Vx[(opcode & 0x0F00) >> 8] = (opcode & 0x00FF);
reg.PC += 2;
std::cout << "OPCODE LD Vx, byte executado." << std::endl;
break;
The CHIP-8 has 16 8-bit registers I called Vx, let’s go:
reg. Vx[(opcode & 0x0F00) >> 8]
First I converted the opcode 0x6000 into binary and performed the operation and:
0110 0000 0000 0000 //0x6000
0000 1111 0000 0000 //0x0F00
-------------------
0000 0000 0000 0000 //0x0
Afterward >> 8
moves 8 bits right which would 0000 0000
that is, the Vx index 0, after = (opcode & 0x00FF)
which remains:
0110 0000 0000 0000 //0x6000
0000 0000 1111 1111 //0x00FF
-------------------
0000 0000 0000 0000 //0x0
So why not just do reg.Vx[0] = 0;
?
Remembering that I’ve never had to do Bit to Bit operations before on any project, I just know what the books told me about Operation AND, OR, XOR, NOT etc...
I wish I could understand this logic that people use to be able to use in future projects.
Some related things: https://answall.com/q/175345/101, https://answall.com/q/201392/101, https://answall.com/q/178733/101, https://answall.com/q/205163/101, https://answall.com/q/213615/101, https://answall.com/q/268467/101 e https://answall.com/q/9497/101
– Maniero