Reputation: 13
I thougth I knew Python enough to program a basic chip8 emulator, but it seems I was wrong.
I'm basically having problems to read/write bytes to and from memory. At a certain point in the program, I need to read to a variable a single byte I've already read from a file and stored in a list. This is how I read from the file:
byte = rom.read(1)
memory.append(byte)
while byte:
byte = rom.read(1)
memory.append(byte)
rom.close()
At a certain point in the program, I need to get a byte from memory, AND it with 0x80 shifted by certain numbers (to extract single bits), so I use:
for i in range(h):
p = ord(memory[addressI + i])
for j in range(8):
if(p & (0x80 >>j)) != 0:
...
It works fine for a while but then I get this error out of nowhere:
(...)p = ord(memory[addressI + i])
TypeError: ord() expected string of length 1, but int found
If I simply don't use the ord funcion I get this error, as expected:
TypeError: unsupported operand type(s) for &: 'str' and 'int'
I think I get this error because at some point in the program I store the BCD of a stored value in in the memory. I guess it replaces the byte type previously stored for an int one.
data = registers[sNum>>8]
memory[addressI] = data/100
memory[addressI + 1] = (data/10) % 10
memory[addressI + 2] = data % 10
Possible solutions are: 1 - properly store the int calculated as a single byte in the list that "emulate" the chip8 memory 2 - use a function or a miracle instead of ord() that gets whatever the data is and stores it as a single byte
Any help would be appreciated. By the way, I'm using windows and tested this code in both Python 2.7.2 and 3.2.2.
Upvotes: 1
Views: 1586
Reputation: 208475
I think it makes the most sense to keep the type in your list consistent, which you can do fairly easily by passing the integers that your are calculating into the chr()
function (which is the reverse of ord()
):
data = registers[sNum>>8]
memory[addressI] = chr(data/100)
memory[addressI + 1] = chr((data/10) % 10)
memory[addressI + 2] = chr(data % 10)
However here is an alternative, which is to create a function that returns the right thing whether the argument is an int
or a byte.
ord_ = lambda c: c if isinstance(c, int) else ord(c)
and then change the line in your for loop to this:
p = ord_(memory[addressI + i])
So now if that item in the list is an integer, ord_(memory[addressI + i])
will return it unchanged, but if it is a byte then it will return the result of ord()
.
edit: The empty string in your list may be there because of your read loop, try changing it to the following:
byte = rom.read(1)
while byte:
memory.append(byte)
byte = rom.read(1)
This should prevent the situation where the last time through the loop rom.read(1)
returns an empty string and then immediately appends it to memory
before checking the while
condition.
Upvotes: 1