What's new

Hi, I ran into a problem while building a GB emulator and need some help...

LinkOfTime

New member
Hi
I am building an emulator of the old GameBoy system.
Now, while trying to run a game (Tetris - Rom only), I ran into a problem. There is a "call (FFB6H)" instruction in the code (in address 247H - part of the ROM).Now, in that called procedure (in address FFB6H), there is the value 0, meaning, instruction "nop" and there isn't a ret instuction somewhere near that address to take the CPU back from the procedure... and that's impossible...
So I compared the values that are supposed to be at that address (FFB6H) and at the 247H address with a different, working emulator that I downloaded...
Well, the "call (FFB6H)" instruction is there in the right place, but, in address FFB6H there are different values that, in Assembly code, actually make sense...
Well, those values aren't loaded to that address (FFB6H - which is, by the way, in the internal RAM memory space) from the beginning, they are put there some when but I don't know how or when...
I hope you understand my problem and could find a solution to it and help me with it...
Thanks in advance for trying to help me :)
 

bcrew1375

New member
First, there is a Gameboy thread, and you should ask there. Second, you can delete your posts. Third, I have no idea where you are getting that instruction from. When I looked at Tetris, the instruction at 0x247 was "ld hl, 0xFF26", opcode number 0x21.
 
OP
L

LinkOfTime

New member
Sorry for the double posting, I have deleted my older message...
Anyway, you are right, the instruction number isn't 0247H, it's 0254H but that doesn't change anything, I just wrote it from memory so I got it wrong, my emu does this jump at address 0254H as it should, but, there still is the "nop" instruction in address FFB6H that shouldn't be there...
Now, I was thinking, is there something that copies instructions to those address in the internal RAM (FFB6H and a bit before\after) that has nothing to do with the program's code that I am not aware of?
Well, thanks for trying to help so far... :) but, I am still stuck so more help would be welcomed :p
 

ZeroEffect

New member
If it is a NOP (0x00) instruction at that address and you are initializing your memory to zero when the class/struct is created then it is very likely that there is a Load instruction not being handled (or handled incorrectly).
 

bcrew1375

New member
Okay, I'm sure the game should NEVER jump into that section. It is restricted memory(except maybe on the Gameboy Color). When I look at that 0x254 in the ROM, I see a ld (2000), a instruction, which would be ROM bank switching. You've either got a bad ROM, or interpreting the opcode number as something it isn't. It could also be that you're not correctly loading the ROM into memory.
 
Last edited:
OP
L

LinkOfTime

New member
Well, I have compared my emu's results with other, working emus...
Here are a few screen shots from VBA running Tetris...
See what I mean, in address FFB6 in my emu there is the value 00 when that procedure is called...
Might it have anything to do with the fact that I haven't emulated the DMA device yet? :)
 

Pontifice

Learning
FF80-FFFE High RAM (HRAM)
and
FF46 - DMA - DMA Transfer and Start Address (W)
Writing to this register launches a DMA transfer from ROM or RAM to OAM memory (sprite attribute table). The written value specifies the transfer source address divided by 100h, ie. source & destination are:
Source: XX00-XX9F ;XX in range from 00-F1h
Destination: FE00-FE9F


It takes 160 microseconds until the transfer has completed (80 microseconds in CGB Double Speed Mode), during this time the CPU can access only HRAM (memory at FF80-FFFE). For this reason, the programmer must copy a short procedure into HRAM, and use this procedure to start the transfer from inside HRAM, and wait until the transfer has finished:
ld (0FF46h),a ;start DMA transfer, a=start address/100h
ld a,28h ;delay...
wait: ;total 5x40 cycles, approx 200ms
dec a ;1 cycle
jr nz,wait ;4 cycles


Most programs are executing this procedure from inside of their VBlank procedure, but it is possible to execute it during display redraw also, allowing to display more than 40 sprites on the screen (ie. for example 40 sprites in upper half, and other 40 sprites in lower half of the screen).


This is important:

during this time the CPU can access only HRAM (memory at FF80-FFFE). For this reason, the programmer must copy a short procedure into HRAM, and use this procedure to start the transfer from inside HRAM, and wait until the transfer has finished

You fail to load the loop in HRAM, it is related to DMA but the problem is not in the DMA routine
Taken from

http://www.work.de/nocash/pandocs.htm
 
Last edited:
OP
L

LinkOfTime

New member
Well, I guess that's what's been making the problem then... :p
Thanks for all of the help... :)

One question though, when it says that "the programmer must copy a short procedure to the HRAM space", it means that the GB game programmer must copy it there right, not the emulator's\GB machine programmer...
Now, the question is, if the GB game's program code is supposed to copy the procedure to those addresses using instructions that I have already emulated (ld instructions), how come that procedure isn't in the right address (FFB6H) when it is called?

Thanks again for the help :)
 
Last edited:

bcrew1375

New member
Whoops, sorry about that FFB6 thing, you can write there, I was tired at the time :p. Anyway, have you made sure to emulate the 0xFFxx specific instructions? There's an instruction like "ld (xxxx), a", and there's also one like "ld (FFxx), a". Most programmers would probably use that since it uses less cycles.
 
OP
L

LinkOfTime

New member
It's ok, everyone can make a mistake when they are tired :p ...
Anyway, yeap, I have emulated those instructions... and I have built the emulator in the kind of way that if an instruction is missing, it would prevent it from going on to the next instruction so the instructions in the GB code must be emulated before it can go on to the next ones... :)
 

bcrew1375

New member
Have you solved your problem yet? If not, have you checked to see if there any instructions at all in the FF80-FFFE area? Is it just FFB6 that is empty? Have you tried setting breakpoints if that specific area is written to?
 
OP
L

LinkOfTime

New member
Nope, haven't really solved it yet, but you are right, the whole area is empty, not just that address...
Anyway, I just copied the procedure that is supposed to be there manually (made the emulator copy it there) since I have checked it with another rom and the same procedure is there too, I just assumed that procedure is supposed to be there. :p
 
OP
L

LinkOfTime

New member
I write to the memory at the beginning of the game, when I read the file. I read addresses 0000-FFFF + I force the emu to copy the procedure I used to have a problem with in address FFB6 to that address (and those near it) since I saw it is the same in each game...
Then, the rest of the writes are being done by the CPU emulation (the ASM commands of the game).
 

bcrew1375

New member
Yes, but you shouldn't have to manually copy that procedure into memory. That could lower your compatibility. I'm saying is that after the game starts, is there something that could possibly be keeping the game from writing to the FF80-FFFE section? Like when something writes to memory, do you have a routine that decides what to do when that area is written to? For instance "if (address == 0xFF44) *address = 0", so if 0xFF44 is written to, it resets to 0. If you do, maybe it is keeping you from writing into the FF80-FFFE section. I've done that a few times accidentally.
 
OP
L

LinkOfTime

New member
Nope, I don't think I have anything like that in the emulator.
Access to that area of RAM is completly free...
 

HyperHacker

Raving Lunatic
I don't see any technical reason this shouldn't be working; it seems like that area of memory is being corrupted. I would look at the memory-handling routines to make sure they're not messing it up. I managed to get Tetris to run (crappy as it is without sprites :p) and I don't recall having to do anything unusual for it.
 

bcrew1375

New member
Okay, I notice the first time Tetris writes to address 0xFFB6, it IS a NOP instruction. In fact, the whole area is filled with a data value of 0x00. The second time Tetris writes to 0xFFB6, it is 0x3E, which is "LD A, nn" Have you gotten any graphical results from Tetris?
 
Last edited:
OP
L

LinkOfTime

New member
No, the only graphical results I received in my emu were the tiles of the game Super Mario Land (I tried it before Tetris) and in uncorrect order and some were messy... Oh, I also got a game I created on my own to run almost perfectly (without sprites) but it doesn't have any complicated things in it... Actually, you can barely call it a game, it just draws tiles on screen :p

By the way, what address is the writing instruction at?
 
Last edited:

bcrew1375

New member
The first time it is at 0x290, and it is a "LD (HL), A", the second time it is at 0x29c, and it is "LD (FF00 + C), A".
 

Top