What's new

Game Boy

aprentice

Moderator
zenogais said:
Well, the curent timer implementation I've written does reset it to zero after it reaches 153, but I may just try removing that or making it a compiler option. Thanks for the heads up bcrew. :)

I also have a question I was just pondering. Right now I am thinking of writing the video system so that each pixel written to my screenBuffer takes up two bits which denote its color. Then as I draw the data onto the screen during VBlank I read through each byte from the screenBuffer and draw 4 pixels from that, each of the specified color. Is this how you guys are doing it, and would this even work?

why don't you just make an array that holds the real color in 32bit? Reading through the video screen array would kill some speed, i use to have it like that ages ago, then when i changed it to write directly to video memory the speed up was huge.

edit:
examples

PHP:
unsigned long palette[4];
unsigned long gb_bgpal[4], gb_spr_pal[2][4];

void set_palette_dept(int bits)
{
	if(bits==16)
	{
		palette[0]=((0xFF/8)<<11)|((0xFF/4)<<5)|(0xFF/8);
		palette[1]=((0x8D/8)<<11)|((0x8D/4)<<5)|(0x8D/8);
		palette[2]=((0x69/8)<<11)|((0x69/4)<<5)|(0x69/8);
		palette[3]=((0x00/8)<<11)|((0x00/4)<<5)|(0x00/8);

		gb_bgpal[0]=gb_spr_pal[0][0]=gb_spr_pal[1][0]=palette[0];
		gb_bgpal[1]=gb_spr_pal[0][1]=gb_spr_pal[1][1]=palette[1];
		gb_bgpal[2]=gb_spr_pal[0][2]=gb_spr_pal[1][2]=palette[2];
		gb_bgpal[3]=gb_spr_pal[0][3]=gb_spr_pal[1][3]=palette[3];
	}
	else if(bits==24 || bits==32)
	{
		palette[0]=0xFFFFFF;
		palette[1]=0x8D8D8D;
		palette[2]=0x696969;
		palette[3]=0x000000;

		gb_bgpal[0]=gb_spr_pal[0][0]=gb_spr_pal[1][0]=palette[0];
		gb_bgpal[1]=gb_spr_pal[0][1]=gb_spr_pal[1][1]=palette[1];
		gb_bgpal[2]=gb_spr_pal[0][2]=gb_spr_pal[1][2]=palette[2];
		gb_bgpal[3]=gb_spr_pal[0][3]=gb_spr_pal[1][3]=palette[3];
	}

	if(bits==16) main.pixelwidth=2;
	else if(bits==24) main.pixelwidth=3;
	else main.pixelwidth=4;
}
 
Last edited:

Dark Stalker

New member
aprentice said:
DarkStalker: how are you so effectively tracking the bugs, can you share a few tips with the rest of us? and what obvious solutions?
There seems to be lots of tiny details all over the place. The thing is, I can't be perfectly sure I'm doing things right, as there are still strange issues, so I don't want to claim something to be the right way of doing things until I'm quite certain. (Besides if I told you everything you'd all catch up/pass me, wouldn't you? :p.) As for tracking the bugs, I'm basically just trying things to see what affects them, so as to narrow down which area it's connected to. Then I try probable solutions, and see if they fix anything.

Just now, wrt Altered Space, I got the impression that the LCDC Status register flags that enable the individual lcdc status interrupts are priority-based. So that if "LYC=LY Concidence Interrupt" is enabled, "Mode 2 OAM Interrupt" won't be executed even if enabled and so on with mode1 and mode2 (the higher bits take precedence over the lower bits), but again don't take my word on it (still looking for regressions). I wasn't really sure if some of you might consider these things "spoilers", in case you wanted to figure out everything on your own. Good luck to you all though. I just want to make it clear that I've got no absolute answers, as I've largely been doing a whole lot of guesswork.
 
Last edited:

Dark Stalker

New member
Dark Stalker said:
Just now, wrt Altered Space, I got the impression that the LCDC Status register flags that enable the individual lcdc status interrupts are priority-based. So that if "LYC=LY Concidence Interrupt" is enabled, "Mode 2 OAM Interrupt" won't be executed even if enabled and so on with mode1 and mode2 (the higher bits take precedence over the lower bits), but again don't take my word on it (still looking for regressions).
Seems this gave me a grand total of 2 regressions (of some 100 roms). Backing it down to just denying mode0 interrupts when mode2 interrupts are enabled seems to keep everyone happy for now. I'm pretty sure mode2 interrupts combined with lyc interrupt isn't good though, as they currently do effectively the same thing, so the game might perceive it as a successful lyc each line (unless it checks lyc in it's interrupt routine of course, or the lyc is provoked by changing the lyc value in the middle of a line).
 

bcrew1375

New member
Ah, found out a nice little piece of info. Apparently, some games require the STAT register be set to 0x80 when the display is disabled. I found this out with Earthworm Jim :p. It is supposed to start out initialized to 0x80, but for some reason it's getting turned off for me. I didn't think bit 7 was important, but apparently every other bit should be set to 0 :p.
 
Last edited:

Dark Stalker

New member
bcrew1375 said:
Ah, found out a nice little piece of info. Apparently, some games require the STAT register be set to 0x80 when the display is disabled. I found this out with Earthworm Jim :p. It is supposed to start out initialized to 0x80, but for some reason it's getting turned off for me. I didn't think bit 7 was important, but apparently every other bit should be set to 0 :p.
AFAIK it isn't. I think you should simply be unsetting the read-only bits of the STAT register when the display is disabled. In other words do memory[0xFF41]&=0xF8; when disabling the display.
 

zenogais

New member
Whee, status update. Finished CPU rewrite except for a few loose ends, all the correct cycle timings have, hopefully, been factored in. I'm currently working on a simple SDL video implementation. Projects section of my website redesigned, check out the NeoGameBoy section. Hopefully I'll get stuff working since I have this whole week off :D
 
Last edited:

ShizZy

Emulator Developer
Nice job Zenogais. So far, I have about half of my interpreter coded, although I have a really nice shell setup. A nice debugger (including logging and a console), a GUI, using a clean SDL hack to get it in a regular window, as well as rom loading and what not. Unfortunetly, all the easy stuff :p Anyways, I'm making so many silly mistakes - it's going to be a wonder if I can ever figure them all out when it comes time to get it all working.

I'll post source sometime tomarrow or wednesday once I get a bit more coded. Ahso... anyone know of any good refferences for coding the asm commands? I'm having trouble with a couple of things, such as:

Code:
void z80_PUSH_r16(unsigned int *reg16)
{
	/* push 16bit reg onto the stack, decrement twice */
	reg.SP-=2;
	MemoryWriteTo(reg.SP,&*reg16);

	/* add the cycles */
	cpu.cycles+=4;	
}

Which, correct me if I'm wrong - I have the right idea, but I'm going about it wrong? Would something like this work instead:

Code:
void z80_PUSH_r16(unsigned int *reg16)
{
	/* push 16bit reg onto the stack, decrement twice */
	reg.SP--;
	MemoryWriteTo(reg.SP,&(*reg16&0xFF00));
	reg.SP--;
	MemoryWriteTo(reg.SP,&(*reg16&0x00FF));

	/* add the cycles */
	cpu.cycles+=4;	
}
Where I am decrementing between each byte? Anyways, things like this... I'm a tad clueless on how I should go about with the syntax. Trial and error maybe? Yes, like I said... if anyone has any good refferences on this, please share. Thanks!
 
Last edited:

Pontifice

Learning
Code:
void z80_PUSH_r16(unsigned int *reg16)
{
	/* push 16bit reg onto the stack, decrement twice */
	reg.SP--;
	MemoryWriteTo(reg.SP,&(*reg16&0xFF00));
	reg.SP--;
	MemoryWriteTo(reg.SP,&(*reg16&0x00FF));

	/* add the cycles */
	cpu.cycles+=4;	
}

I think the first one should be
Code:
MemoryWriteTo(reg.SP,&((*reg16&0xFF00)>>8));

Because you will write 0x00

And i think &(*reg16&0x????) will return something unknown, because you are not changing reg16 but you want reg16&0x???? and take the pointer to an unchanged reg16 ( i don't know if i am clear enough ).

If you want to write to memory you must think about passing argument by value not pointers, because you aren't going to change ( in that case ) the reg16 value.

So:

1.- If &(*reg16&0x????) returns a pointer to reg16 it will pointing to reg16 value not reg16&0x????. But i think &(*reg16&0x????) will return something unknown, because *reg16&0x???? it is not "stored" in memory, is only a temp value, so you can't get its address

2.- If i'm wrong with (1) anyway in the first write you will be writting 0x00 because you don't shift 0x??00 right and i suppouse you write only a byte from parameter
 
Last edited:

ShizZy

Emulator Developer
Thanks guys! Okay, I think I gotcha Pontifice... While the pointer is useless in this function - it still is pointing to the same address, so I don't see why it wouldn't work - but I fixed it anyways. So, revised, my function would be:

Code:
void z80_PUSH_r16(unsigned int reg16)
{
	/* push 16bit reg onto the stack, decrement twice */
	MemoryWriteTo(reg.SP,&((reg16&0xFF00)>>8));
	reg.SP--;
	MemoryWriteTo(reg.SP,&((reg16&0x00FF)>>8));
	reg.SP--;

	/* add the cycles */
	cpu.cycles+=4;	
}
My only question being, why do I need to shift it right?
 
Last edited:

Soccr743

Cubed Member
Basically add a MemoryWriteByte function to the code. Then you want to change what you put there to this:

Code:
void z80_PUSH_r16(unsigned int reg16)
{
	/* push 16bit reg onto the stack, decrement twice */
	MemoryWriteByte(reg.SP--, (char)(reg16 >> 8));
	MemoryWriteByte(reg.SP--, (char)(reg16 & 0x00FF));

	/* add the cycles */
	cpu.cycles += 4;	
}

The first write function call shifts the 16 bit integer over 8 bits so you end up with the high byte.

The second write function causes the high byte to be 0 so that you end up with the lower byte.

I type cast both of them to char so that they are not still of the int type when you send them to the function.

-----Soccr743-----

EDIT: Pontifice thanks for pointing that out. I completely forgot to take those reference things out.
 
Last edited:

Pontifice

Learning
What i tried to say before is that &((char)(reg16 >> 8))); will fail to compile because you can't get address for something that is not a variable and (reg16 >> 8) it is not a variable.


P.D. you can get the address from more things than variables ( functions, classes, structs ) but you can't get it from an "intermediate" value
 
Last edited:

ShizZy

Emulator Developer
Thanks Soccr.. that makes sense now. And of course you write the upper byte first, because the gb cpu is high-endian, correct?
 

Soccr743

Cubed Member
zenogais said:
doesn't matter what order you write it in as long as you read it out the same way ;)

A gameboy rom could push many values onto the stack in the memory and then choose to load one byte from the memory into a register. If that byte was part of one of the ones pushed, then it would matter how you write it in. The developer of such as game would be expecting to get a certain value in that register.

-----Soccr743-----
 
Last edited:

HyperHacker

Raving Lunatic
A lot of games use the stack for faster memory access in fact. I know some Pokémon games use it to copy data into VRAM by adjusting the stack pointer. It wouldn't work very well if you wrote it in the wrong order there...
 

bcrew1375

New member
ShizZie said:
Thanks Soccr.. that makes sense now. And of course you write the upper byte first, because the gb cpu is high-endian, correct?

It's little-endian, or low-byte first. So, 0x7280 would be written into memory as the hex bytes 80 72

Whoops, I think I made a mistake with the decrementing. SP IS supposed to be decremented before writing the value. Sorry about that ShizZie :blush:. So, basically what Soccr said(but wouldn't that function write to the same spot twice?).
 
Last edited:

Soccr743

Cubed Member
SP is not supposed to decrement before writing to the memory. SP points to the top of the stack and that is where you write your data to. You do not want to put it one byte from where the stack should be.

It doesnt write to the same place. You probably just missed the reg.SP-- when I call the MemoryWriteByte function. Which means it decrements SP by one after something else happens (In this case the function call). When you have --reg.SP then you are decrementing before something else happens.

The second part is useful for popping the data off the stack as you want to read from ++reg.SP both times.

-----Soccr743-----
 

Top