Reading binary file in C++ skips 0s?

Started by
15 comments, last by mentor 7 years, 6 months ago

Yep, done that already. I don't know why you're talking about masking bytes actually, but I was wrong about shift operator. "<<" is correct here. Still, I have no idea why my emulator doesn't work.

Advertisement
memory[pc] << 8 | memory[pc+1];
That part looks correct to me...

- Operator precedence for << is higher than |: CHECK
- << is signed/unsigned agnostic: CHECK
- Big endian byte order: CHECK

You *might* be experiencing automatic promotion of signed values to larger integer types, but that shouldn't turn your 0C into 20.

So where is the 0x20 coming from?

Since you're using C++, I suggest putting a data breakpoint on that element of the array to see what's setting it to 0x20.

That's totally strange, but the value of this variable is always: 12 '\f'. I mean, always after the value is written into from buffer. I never used breakpoints and debugger before, but I think I did properly.

12 in decimal is C in hex, so that's OK. Does the "6B20" problem still happen?

Unfortunately, yes. Also I might be missing something. Variable memory is declared like this:


unsigned char memory[4096];

Chip 8 memory is 4K and Chip 8 program (.ch8 file) starts at 0x200. So the variable I'm looking here for is memory[0x203], right?:


memory[0x200] = 22
memory[0x201] = FC
memory[0x202] = 6B
memory[0x203] = 0C (should be, but console window shows 20)

Please, take a look at the screenshot attached. I think that values shown by debugger (on the left in Dev-cpp window) are correct, but opcodes in console window aren't really that correct. I added watches on two following opcodes (from 0x204 to 0x207) which aren't shown in console window, but debugger shows them correctly also. For the record, this very same problem happened when I was using VS2010, so I don' think that's an issue anyhow related to Dev-cpp.

It kinda seems like the problem lies with this line:


opcode = memory[pc] << 8 | memory[pc+1];

Because values in memory are correct, so I cannot think of anything else, but still this line is exactly the same as in tutorial's source code. So I really don't know what could be causing this problem.

You need to debug everything between the point where memory[...] appears to be correct and where it's being printed incorrectly, not just the loading code.

for example, the following program with known-good values prints the expected result:

int main()
{
  unsigned char c1 = 0x6C;
  unsigned char c2 = 0x0C;
  unsigned int opcode = c1 << 8 | c2; // int, unsigned short, and short all work here as well.  What is your opcode type, anyway?

  printf("%04X", opcode); // prints 6C0C

   return 0;
}
so my suspicion is that something is wrong between your loading code and the line that assigns opcode = ...


It's most likely one of the following:
- Your memory malloc isn't large enough and other allocations occupy its space later on.
- Buffer overrun.
- Stack corruption.
- "if (memory[x] == 0x6C && memory[x+1] = 0x20)" (single-equals-in-condition-expression bug)
- memory[x] with a typo in how x is calculated

Since it always happens on the same location, if something is actually modifying the memory array, you can find this extremely quickly by using a data breakpoint.

In visual studio:

- Set a normal breakpoint on the line after 'memory' is allocated.
- Calculate the effective address of memory[0x203]. (put "&memory[0x203]" in the watch window and use the address it shows)
- Make a 1-byte data breakpoint at that address. https://msdn.microsoft.com/en-us/library/350dyxd0(v=vs.100).aspx
- Resume the program.

You should see the program stop at the exact statement which writes to that memory address (including your loader and any bugs that might exist). From there you can figure out what's happening and fix it.

I finally figured out what was wrong. First opcode is 22FC which calls subroutine at address 2FC. So after my emulator executed this instruction my program counter (pc) was set to 2FC (and not 201), so the next opcode would be 6B20, not 6B0C (because emulator "jumped" to a different place in memory) and that's ok. The problem was with implementation of another opcode which had a typo I totally missed and that caused my emulator's strange behaviour.

I'm just surprised I didn't notice this typo before, but now Pong works correctly. I'll later check emulator with other programs, but everything should be fine now. Thank you all for all your help!

This topic is closed to new replies.

Advertisement