PDA

View Full Version : Game Boy



Pages : 1 [2] 3 4 5

glVertex3f
September 7th, 2004, 07:42
Only worked on the emu a few hours in the past week or so, times run short now that university has begun, but I will try to find time here and there :P

Heres some screens :P

I despise you...
:P

Nice work, I only hope to one day have your skill :party:

EDIT:

Yeah I finally got color going on my emu too...

http://img14.exs.cx/img14/9355/forestbrix.jpg

hehe :P

aprentice
September 18th, 2004, 23:47
This thread seems to have died, anyone still working on their gb emu? :P

zenogais
September 19th, 2004, 04:18
I am from time to time, but right now I'm working on an emulation framework so I can simplify the process of getting them up-and-running. I've only just started, but basically I hope to have the following:


Logging and Error Handling Facilities.
Premade GUI classes for Windows.
GUI facilities for toolbars, status bars, and tooltips.
Lots of helper functions and macros.
Video, Sound, Controller, and Memory emulation facilities.
Possibly dynamic recompilation facilities.


It'll be distributed in DLL form, so it should be quite efficient. I'll post more soon, and if anyone would like to help just ask. Also I might consider making it more cross-platform compatible once I have the windows version working.

EDIT: Oh btw, Here's a little teaser screenshot of what I've got thus far. This is a basic windows application created through the framework as you can see it only takes one line of code:

http://www.zenogais.net/Temp/emu_framework---snap.png (http://www.zenogais.net/Temp/emu_framework.png)

bcrew1375
September 20th, 2004, 06:31
I haven't quite given up on mine yet. I just have some tedious bugs to work out that I haven't quite worked up the stamina to smash. For instance, I have a bug with the new build of my emu that wasn't in my old build. So now I have to go through the entire source comparing the old and new one to see what's the same and what's different -_-.

retroK
September 20th, 2004, 11:43
I am from time to time, but right now I'm working on an emulation framework so I can simplify the process of getting them up-and-running.

It'll be distributed in DLL form, so it should be quite efficient. I'll post more soon, and if anyone would like to help just ask. Also I might consider making it more cross-platform compatible once I have the windows version working.



Hi zenogais,

the author of the NES emulator Nessie wants to do a similar thing. Maybe you could join forces on this!

Here is the thread on Nessie Forum: http://nessie.emubase.de/forum/viewtopic.php?t=34

glVertex3f
September 20th, 2004, 18:41
Zenogais, what version of MSVC++ is that?

zenogais
September 21st, 2004, 01:03
retroK:
This is really just a project for myself, in order to speed up development and design change, as I find that most of the time when I write an emulator I spend about 80% of the time working on a lot of the same components. Also the Nessie author is merely creating his in order to load NES games, this is just going to be a general framework so that I can get the basic, time-consuming components out of the way leaving a lot more time for actually creating the emulator.
Basically that is why I've stopped work on my game boy emulator/PSX emulator is so that I can get this project done and finally have an easy way to set up my emulators.


glVertex3f:
I'm running Microsoft Visual C++ .NET

bcrew1375
September 23rd, 2004, 08:36
aprentice, I need to ask you a question. Are you having compatibility issues with any of these games:

Donkey Kong
A Boy and His Blob
DragonBall Z - Goku Hishouden
DragonBall Z - Goku Gekitouden(Not sure if that's the correct name :P).
Any Final Fantasy Legend
Home Alone
T2 - The Arcade Game
Super Mario Land 1 or 2
Toy Story

If you have compatibility issues with any of those, could you please tell me what kind of problems they are.

BTW, I found the problem in my new code, it now has the same compatibility as my old code with some improvements :bouncy:. It was the Subtract with carry instruction. I was subtracting the C Flag from the register and then subtracting that value from register A. I should have been adding the C flag and the register together and subtracting THAT value -_-.

aprentice
September 24th, 2004, 02:48
aprentice, I need to ask you a question. Are you having compatibility issues with any of these games:

Donkey Kong
A Boy and His Blob
DragonBall Z - Goku Hishouden
DragonBall Z - Goku Gekitouden(Not sure if that's the correct name :P).
Any Final Fantasy Legend
Home Alone
T2 - The Arcade Game
Super Mario Land 1 or 2
Toy Story

If you have compatibility issues with any of those, could you please tell me what kind of problems they are.

BTW, I found the problem in my new code, it now has the same compatibility as my old code with some improvements :bouncy:. It was the Subtract with carry instruction. I was subtracting the C Flag from the register and then subtracting that value from register A. I should have been adding the C flag and the register together and subtracting THAT value -_-.

I havent been able to test dbz and toy story, but the rest of the games you mentioned work in my emu with the exception of super mario land 2, which crashes on the tunnel selection screen. My emu does seem to have some problems with a few select gb games, which I'm having trouble figuring out though, like for example, wave race. Are you able to get that game showing anything?

I'm still in the process of a complete recode, some new bugs creeping out though :\

bcrew1375
September 24th, 2004, 05:32
Hmm, I'm not sure exactly what the problem is yet. It seems most games have a problem recognizing button presses (T2, Super Mario Land 2, DBZ games, Final Fantasy Legends, A Boy and his Blob, Mortal Kombat). Donkey Kong freezes after the first level, Toy Story doesn't show any sprites, A few games work fine, but run through some jumbled, distorted graphics before reaching the title. Super Mario Land 2 seems to go into an endless loop after Start is pressed. I'll update this post after I try Wave Race.

This screen is all I can get from Wave Race with my emulator in its current state.

aprentice
September 24th, 2004, 21:29
I get that same exact image in wave race if i disable the LCDC interrupts, otherwise its just a white screen. If you figure out what causes this, feel free to share as I'll do the same.

Your controller issue has to do with a bug in the cpu core, I've had the same problem until i fixed this "magical" bug :P

Also, some games didnt show sprites in my emu either, so i just temporarily disabled the sprite enable check

bcrew1375
September 25th, 2004, 00:47
Would you mind telling me this 'magical bug', oh Wise One :P? I'm really at a loss as to what it could be :/. Hmm, I'll try messing around with the interrupts and see if I can get something else out of Wave Race.

aprentice
September 25th, 2004, 06:47
Would you mind telling me this 'magical bug', oh Wise One :P? I'm really at a loss as to what it could be :/. Hmm, I'll try messing around with the interrupts and see if I can get something else out of Wave Race.

I don't recall what the bug was, I've rewritten my cpu core 3 times, everytime i get frustrated i scrap code and redo it, in hopes of not making the same mistake again :P

I would make sure your ADC, SBC, and rotate opcodes are setting flags right, these are common opcodes for mistakes :P

bcrew1375
September 26th, 2004, 00:23
Yes, I would suspect the same ones. the ADC instuctions were messing up alot of games simply because of a tiny problem with the carry flag. Unfortunately, I've already fixed that a while ago, and games still don't work. Eh, maybe I'll re-write like you did.

zenogais
October 6th, 2004, 05:29
Well, seeing as how this thread has kind of died, I figured I'd respur it with news about my emulation framework. I don't really think its worth starting a new thread for...yet :p Anyway, I've consolidated all the individual frameworks into a single framework which spits out "EFramework.dll". Right now I've finished creating facilities for the following:


Generic exception for error handling (Check Here For More Information (http://www.zenogais.net/projects/Tutorials/Groundwork.html))
Generic logging framework which allows for the creation and management of multiple log files.
System versioning class which allows for management and comparison of versions as well as a few other things.
Class which allows one to trace the execution of a program.
Generic save states class and two derived class, one which allows for basic binary file output, and a second which uses zlib to produce a compressed save state file. Basically allows the programmer to decide how their program saves states, without the need to modify more than a few lines of code.
A class for loading, managing, and retrieving of methods from plugin DLLs. It is also almost completely cross-platform.

Thats about it for now, while I haven't released any source code or anything yet, I am hoping to make a release in the future once I have the system for creating and managing emulator components laid out and completely implemented.

Doomulation
October 6th, 2004, 08:27
That's cool.
Say, if it gets finished, I could test this for the chip8 emulator I did. How's the work going, then? Any idea on what's left and when it "might" be finished?

zenogais
October 7th, 2004, 04:45
No estimates yet, I'm currently retooling the GUI framework to work the the Windows Template Library (WTL) instead of MFC. Basically this would be come the new version of WinMain using the framework:



int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

// Create our WTL class management instance.
EFWindowApplication< MainWindow > WTLStuff;

// Display our window and process message until closing.
return WTLStuff.Run();
}

Doomulation
October 7th, 2004, 08:19
Err, just if you do that, you can't use MFC? Baaaad.
I was going to try this though, by rewriting the chip8 emulator a little with it.
Hmm well, I'll wait until you give word that some intresting is about to happen :) :evil:

zenogais
October 8th, 2004, 00:18
Err, just if you do that, you can't use MFC? Baaaad.
I was going to try this though, by rewriting the chip8 emulator a little with it.
Hmm well, I'll wait until you give word that some intresting is about to happen :) :evil:

Not really, I've had too many headaches trying to distribute plugins that used MFC, the Windows Template Library in addition to having a smaller footprint than MFC and less dependencies (the dependencies were the cause of the problems btw), just seems to be the right balance between pure, ugly Win32 and the bloated MFC, also it has a few nice features built-in that MFC and Win32 certainly don't have.

Doomulation
October 8th, 2004, 12:47
Still, everything - all the classes that MFC provides that makes programming easier, what about these? But I'll take your word for it. If it's easy to use then it'll certainly be good. I'd like to test this framework sometime, too.

zenogais
October 9th, 2004, 03:56
Still, everything - all the classes that MFC provides that makes programming easier, what about these? But I'll take your word for it. If it's easy to use then it'll certainly be good. I'd like to test this framework sometime, too.

Well...have you looked at the windows template library? From using it I can tell you that it has all of the things I used to incorporate into my windowing classes, including tooltips and all the predefined helper classes. Often times it also makes the components a bit easier to use. Anyway thanks for taking my word on it and, if you'd like to test it if you can just drop me an email I can send you a copy of the latest framework, plus the sources so you can get an idea and possibly start working with it and telling me if it simplifies creating an emulator or improving a prebuilt one, anyway I suppose I should get back to working on it :P

UPDATE:

Here is the basic list of the Emulation Framework I have so far:


Plugin Management
Save State Support For Both Binary Files and ZIP Files
Cross-Platform Size-Guaranteed Types (uint8_t will always be 8-bits)
Support For Simple Singleton Creation
Simple Classes For Versioning Of The Framework And Your Emulator
WTL Application Module Wrapper
Windows Register I/O Wrapper
Dynamic Logging With Support For Creation And Management Of Multiple Log Files
Special Exception Class
Program Execution Tracing Class


That's about it for now.

aprentice
November 28th, 2004, 05:57
anyone from this thread still working on a gameboy emu, or have you all moved onto gamecube emulation?


(ps: just kidding about the gamecube emulation).

bcrew1375
November 29th, 2004, 07:14
Still working on it, just not often. I'm still bug hunting though :/.

aprentice
November 29th, 2004, 08:02
Still working on it, just not often. I'm still bug hunting though :/.

Same here, i work on it at least once a week, bug hunting as well, with no luck might i add. I've also started a nes emu, its up to the stage where it should show gfx but i didnt fully implement interrupts, so nothing shows right now. Theres only about 4 days of work i put into the nes project since i've been working on it sunday nights only.

Doomulation
November 29th, 2004, 12:40
Still no word from my co-programmers. Too lazy to work on it, been doing other stuff.

bcrew1375
November 30th, 2004, 05:29
Same here, i work on it at least once a week, bug hunting as well, with no luck might i add. I've also started a nes emu, its up to the stage where it should show gfx but i didnt fully implement interrupts, so nothing shows right now. Theres only about 4 days of work i put into the nes project since i've been working on it sunday nights only.

Oh, NES? Got any good information on it? Everything I found was junk. :/

aprentice
November 30th, 2004, 05:37
Oh, NES? Got any good information on it? Everything I found was junk. :/

Good info is hard to find for the nes, too much old stuff and junk in between the docs unlike the gameboy. I have a collection of docs with data scattered between that I've been collecting since 2001. You might need to stare at the docs a bit to get use to em first :P

bcrew1375
December 1st, 2004, 19:45
Thanks. That's better info than I've been able to find. Those mappers look kind of intimidating though.

Edit: Oh, made these stickies, huh? Sweet. :bouncy:

aprentice
January 4th, 2005, 02:29
Has anyone reached up to emulating tile/sprite priorities?

"Bit 7 BG-to-OAM Priority (0=Use OAM priority bit, 1=BG Priority)

When Bit 7 is set, the corresponding BG tile will have priority above all OBJs (regardless of the priority bits in OAM memory). There's also an Master Priority flag in LCDC register Bit 0 which overrides all other priority bits when cleared."

I can't really figure out how to implement this efficiently, considering my gfx routine is split into 3 functions, Background display, window display, and sprite display.

I could read the oam memory every tile and compare priorities, but this doesnt sound that efficient does it? Any advice? :P

edit: oh btw, hows your emu going bccrew?

edit2: Thanks for all the replies (just kidding), figured it out on my own, i set up a pointer that pointed directly to the video memory buffer for that pixel and it works out perfectly. This pretty much puts my gb/gbc gfx emulation at 100% complete, leaves more time now to focus on the hardware aspect :)

bcrew1375
January 8th, 2005, 08:50
I haven't even concerned myself with the priorities yet. I'm still trying to crack out bugs -_-. Ive tried tracing several games. Everytime I get close to pinpointing a problem, it seems to split off into hundreds of other problems. I've fixed a few bugs, my emulator is now slightly more compatible. Anyway, I haven't given up. If I can't get a gameboy emulator more compatible than this, I'll never make it with other emulators :P.

aprentice
January 9th, 2005, 00:28
I haven't even concerned myself with the priorities yet. I'm still trying to crack out bugs -_-. Ive tried tracing several games. Everytime I get close to pinpointing a problem, it seems to split off into hundreds of other problems. I've fixed a few bugs, my emulator is now slightly more compatible. Anyway, I haven't given up. If I can't get a gameboy emulator more compatible than this, I'll never make it with other emulators :P.

I know how you feel, i'm kinda in the same situation, i managed to creep out a couple major bugs at the expense of long (days) hardcore debugging, my gameboy mono compat is about 95% now, but my gameboy color emulation suffers some some unknown bugs, so i estimate gameboy color compat to be about between 40-50%, im sure its just one or two bugs causing all the damage. I'm having trouble with timing, i redid my timing exactly as specified in the gameboy documents, but it appears to still be off. Bad timing = sprites not visible in a few select games (i current overcome that by disabling the sprite disabling code but that can't possibly be good even though I havent seen any bad effects from this yet) :P

Btw, if you notice any glitches in some games, it may be because of lack of sprite (or tile in gbc) priorities, after adding the priorities, all these "glitches" disppeared :P

I'm glad you havent given up bccrew, persistance is always rewarded, im sure with time you'll figure out whats wrong, it's just a matter of time.

Also, does mario land 2 have any anti-emulator code or something, this game is impossible to get working! Would be nice if there was a gameboy emu author on the boards to ask, but it seems we are on our own :P

bcrew1375
January 9th, 2005, 08:50
Pffh, I haven't even got Mario Land 2 past the title screen :P. I compared my timings to another Gameboy emulator's. Assuming the other's is correct, mine appears to be off a little. When the other emulator's LY was at around 0xCD, mine was around 0xAB.

aprentice
January 9th, 2005, 16:39
Pffh, I haven't even got Mario Land 2 past the title screen :P. I compared my timings to another Gameboy emulator's. Assuming the other's is correct, mine appears to be off a little. When the other emulator's LY was at around 0xCD, mine was around 0xAB.

I can't get it past the title screen either. And i thought LY wraps at 153 or am I wrong?

bcrew1375
January 9th, 2005, 16:56
Oh heh heh, whoops. I was really tired when I posted that. I meant the TIMA register. :blush:

Trotterwatch
January 9th, 2005, 17:06
Found this on Mario Land 2; very vague and don't think it'll be any help but I'll post it anyways (just in case):


I fixed some condition register results that were incorrect for a couple of opcodes, which fixed up several games so that they actually run...Super Mario Land 2 responds to input after this fix, but crashes itself at the save slot screen.
http://www2.hawaii.edu/~dereksmi/wip/log.html

aprentice
January 10th, 2005, 07:45
Not what i'm looking for trotter, thanks though :P

After lots of debugging and such (and fixed a few bugs in the process) i've tracked down my gbc incompatability to the HDMA routines, but in what way I dont know. It looks like its copying the data correctly, so the problem could be anything from bad timing in the emulator to me not making the routine use cycle time.

Timing/HDMA info is hard to find and whatever is available seems uninformative. There must be a secret society for gb dev out there, cause some emus emulate stuff theres no docs out there for...

bcrew1375
January 11th, 2005, 07:12
aprentice, did you ever have any MBC problems? Remember that distorted screen problem I had as a game was starting, when it showed all the garbage? Well, I've noticed it only seems to happen in games that use an MBC. Unfortunately, it happens with MBC1 and 2(which are the only ones I have emulated at the moment).

Edit: Hmm, seems I have this problem with Donkey Kong, DBZ - Goku Hishouden, and DBZ - Gekitouden. 2 use MBC1, 1 uses MBC2, and all three have battery backup. None of them appear to use Ram banks.

rcgamer
January 11th, 2005, 08:23
sorry to interupt this thread but i had to say that you all deserve kudos. it is very inspiring to read all your trials and errors. congrats to the ones who got it done already and i hope the ones that havent got it yet are still trying.

tip of the cap to you all.

aprentice
January 12th, 2005, 02:45
work in progress of my debugger, hopefully this could help me find out why some games dont work.... I'll probably expand on this debugger later, but the screen shot pretty much shows the framework. A possibly feature could be tracing backwards, but i'd imagine that would take an insane amount of memory :P Also ideas for the future would be detection of "irregularities", like games trying to do impossible things (possibly emulator detection code).

Anyway, ideas, improvements, comments, post em here :P

http://darkengine.net/gb/debugger.gif

BGNG
January 12th, 2005, 03:05
That looks rather intuitive. Well done. I myself am basing (albeit for NES) a debugger window mostly off of the no$gmb one, which displays each of the following:

Disassembly
Hex Dump
CPU Memory Map (values of addresses as returned by the LD command)
Register Values
Status Register Flags (as check boxes)
File Header Dump (no$ does this in the disassembly window)

However, I notice you also have some additional displays like interrupts, bank controllers and I/O registers.
__________

Something which no$gmb allows you to do which may be useful in your application, is the way it lets you change the values of the registers and memory. If you can spoof some values at a breakpoint to see if it operates correctly, you could probably use it to debug even the emulator.

aprentice
January 12th, 2005, 03:50
Something which no$gmb allows you to do which may be useful in your application, is the way it lets you change the values of the registers and memory. If you can spoof some values at a breakpoint to see if it operates correctly, you could probably use it to debug even the emulator.

Hmm, that may be a pretty good idea, I'll consider adding it once all current implementations are complete. Hows progress on your nes emulator?

BGNG
January 12th, 2005, 04:20
It's in more or less the same spot it was when I posted the source in that "Incredulous Undertaking" thread. What I've done since then is modify the memory framework to accomodate for a variable number of ROM, VROM and Cart RAM banks, as well as updated the iNES header loader. I am also, as I mentioned, constructing a debugger window which will let you change things right down to the instructions in the PRG-ROM, although not change the size of the ROM. I'll have to do some thinking on that.

Outside the emulator realm, I've been compiling a technical document of various sources on the NES, and I've been researching things like the various mappers games use, Game Genie code format, etc. I even found mention that the NMOS 6502 architecture has a bug for Indirect addressing mode, which I have yet to implement in the emulator.

I don't know if this link was posted yet in this thread (I'm too lazy to look), but a comprehensive document covering the Game Boy (Super and Color too) quite thoroughly is the Pan Docs, which has contributions from Martin Korth (author of no$gmb)... Game Genie and GameShark codes are described. You can find that at the below address:

http://work.typo3.work.de/nocash/pandocs.htm

aprentice
January 14th, 2005, 02:50
Ok, finally came up with the "final" design for the debugger (and pretty much fully functional). It probably won't change much from this, if even. I don't want to spend too much time coding a debugger :P

http://darkengine.net/gb/debuggerv2.gif

BGNG
January 14th, 2005, 04:13
It certainly is helpful for display of information, but it doesn't appear to be able to change anything. I recommend putting in at least the ability to change processor registers (including status flags) and RAM values. That will make it very easy for you to pinpoint bugs in both a ROM (if you're developing one) and the emulator.

Other than that, it looks good. The only thing I would change is make the displays use a fixed-width font like Courier New or Fixedsys. The way the hex dump in the disassembler looks, it's as though someone layed them all down on a table and aligned them with the edges of his hands.

aprentice
January 14th, 2005, 05:12
It certainly is helpful for display of information, but it doesn't appear to be able to change anything. I recommend putting in at least the ability to change processor registers (including status flags) and RAM values. That will make it very easy for you to pinpoint bugs in both a ROM (if you're developing one) and the emulator.

Thats what the modify register button is for, it pops up another window that lets you modify the registers, I didn't want to clutter the debugger even more.


Other than that, it looks good. The only thing I would change is make the displays use a fixed-width font like Courier New or Fixedsys. The way the hex dump in the disassembler looks, it's as though someone layed them all down on a table and aligned them with the edges of his hands.

Thanks for the interesting comparison. I haven't had a chance to port the cpu listbox to a listview control yet (like the box with the gameboy physical memory output), right now its just using a standard listbox which explains the misalignments. However, its still readable, thats all that matters to me right now :P

Thanks for the input.

Doomulation
January 14th, 2005, 10:22
Cool debugger, aprentice. Looks nice :)

BGNG
January 14th, 2005, 17:41
Ah, yes. I missed that button.

And indeed: it is your project. What do you care if others find it pretty to look at? Though if you plan for people to use it after its release, it may be a good idea to spruce it up a bit. Mainly by making a fixed-width display. The classic example is "iiiii" versus "WWWWW"... Five characters each, one significantly wider than the other. Even if they were aligned in a ListView control, that would still be the case unless every character of the font was the same width.

aprentice
January 14th, 2005, 18:54
ok, so hows this one look?

http://darkengine.net/gb/debuggerv3.gif

BGNG
January 14th, 2005, 19:11
Now THAT looks very good. There seems to be a bug in the ASCII display of the hex dump, though. All printable characters appear to be followed by a space.

zenogais
January 15th, 2005, 19:51
Very nice debugger apprentice :)

bcrew1375
January 17th, 2005, 08:45
Ah, the problem I originally thought was caused by the MBCs actually seems to be caused by games that are SGB/CGB capable. I'm guessing they're incorrectly detecting an SGB/CGB instead of an original GB. Now I just need to figure out how to fix it :/.

BGNG
January 17th, 2005, 22:05
To detect Super Game Boy, the values of SGB Flag and Old Licensee Code must be set in the cartridge header. In detail, that would mean that the value of $0146 is $03 and the value of $014B is $33.

To detect Game Boy Color, use the value of the CGB Flag in the cartridge header. If the value of $0143 is $80, then the game should be compatible with both normal and color Game Boy models. If it is $C0, then it should only work with Game Boy Color.

Additionally, some games check the value of the Accumulator directly after startup. If the value is $01, then the hardware is either Super Game Boy or normal Game Boy. If it is $FF, then the hardware is either Super Game Boy 2 or Game Boy Pocket. If it is $11, then it is either Game Boy Color or Game Boy Advance.

Lastly, you can detect if the game is on a Game Boy Advance by checking bit 0 of the B register directly after startup. If it is cleared, it is a Game Boy Color. If it is set, it is a Game Boy Advance.
__________

Note: The Super Game Boy 2 was little more than a Super Game Boy with a link cable port in it. Some games do detect this, however, like Tetris DX, which will display a different border for Super Game Boy and Super Game Boy 2.

EDIT:
Here is a list of examples for games which detect seperate combinations of hardware configurations:

Normal only: Tetris
Normal or Super: Pokémon
Normal, Super or Color: Game & Watch Gallery 2, Game & Watch Gallery 3
Normal, Super, Color or Super2: Tetris DX
Color only: Super Mario Bros. DX
Advance: The Legend of Zelda: Oracle of Ages, The Legend of Zelda: Oracle of Seasons

bcrew1375
January 17th, 2005, 22:23
Well, what I'm saying is I think the games are incorrectly detecting they are on a Super Gameboy, and so are trying to use its features. I'm only emulating an original Gameboy. To my knowledge, the startup register values for the original Gameboy are:

AF = 0x01B0
BC = 0x0013
DE = 0x00D8
HL = 0x014D

BGNG
January 17th, 2005, 22:32
The program code for the games detect which Game Boy they are on using the bytes I mentioned above. If for some reason they are indeed improperly detecting a different Game Boy, then something in your emulator is giving them different values for the above than it should.

EDIT:
Whoop. Looks like a new page. Consider "Above" as "In my last post"

aprentice
January 18th, 2005, 00:01
bccrew: those values are correct, the games shouldn't be detecting a super gameboy with those values, how have you come to this conclusion?

Is your stack pointer pointing at 0xFFFE ?
And note the gameboy starts in vblank mode, scanline 144, don't know if that will help. Do you have any more info on the problem so I can help you track it down?

edit: Also, do you talk like that in real life as well bgng? It sounds quite funny :P

bcrew1375
January 18th, 2005, 01:13
Um, BGNG, those bytes are part of the ROM. They're not variable. How could the game use information in its own ROM to determine the system type? I believe the Gameboy uses that information to determine how to run the game.

aprentice, I am assuming this is the problem because other games use the same things as some of the SGB games, but only the SGB games have the distortion problem when the game loads. I have the problem with Donkey Kong, both DBZ games, and Tetris Attack. All of these games have SGB support and I have the same problem with all of them. Other games that use the same hardware, but do not have SGB support, do not have this problem.

aprentice
January 18th, 2005, 01:37
Um, BGNG, those bytes are part of the ROM. They're not variable. How could the game use information in its own ROM to determine the system type? I believe the Gameboy uses that information to determine how to run the game.

aprentice, I am assuming this is the problem because other games use the same things as some of the SGB games, but only the SGB games have the distortion problem when the game loads. I have the problem with Donkey Kong, both DBZ games, and Tetris Attack. All of these games have SGB support and I have the same problem with all of them. Other games that use the same hardware, but do not have SGB support, do not have this problem.

What do you have at memory location 0xFF26? its IO register NR52 (sound register) and it should have the value 0xF1 for gameboy and 0xF0 for sgb on cpu initialization. That could be a way the rom detects if you have a super gameboy or not. I have no issues with these games, so your problem must be here..

bcrew1375
January 18th, 2005, 01:52
It was indeed set to 0xF0. Unfortunately, it seems to have no effect on the games :(.

BGNG
January 18th, 2005, 02:28
Ah, yes. I forgot how to post hardware detection of Super Game Boy. My appologies.

Super Game Boy programs write to the Joypad register at $FF00 in order to communicate with the Super Game Boy. For a non-Super Game Boy system, anything written to this register should be ignored.

Sending command $11 through this register (which requires a special SGB protocol which I will not document here) will pass a MLT_REQ command to the Super Game Boy, which is used for multiple joypads plugged into the SNES, which can be 1, 2 or 4. If this command is successful, then data can be read from each of those joypads. If it is not successful, then the hardware is not a Super Game Boy.

So simply ignore any data that is written to register $FF00 and it is therefore impossible for a ROM to detect that it is being used in a Super Game Boy.
__________

Simply checking the Accumulator will resolve Color/Advance Game Boy presence.

bcrew1375
January 18th, 2005, 02:37
You have to allow writes to 0xFF00, even for an original Gameboy. The Gameboy can only get the status of 4 keys at a time. You have to write to 0xFF00 to tell it which keys to get. I also saw something about writing a 3 to 0xFF00 and reading it back to get the Gameboy type. This doesn't seem to make much sense.

aprentice
January 18th, 2005, 03:49
So simply ignore any data that is written to register $FF00 and it is therefore impossible for a ROM to detect that it is being used in a Super Game Boy.

Thats great advice if you don't want your emulator to ever have joypad support :P

BGNG
January 18th, 2005, 03:58
Right, right. I said what I didn't mean. I MEANT to say to ignore any SGB functions to be written to the register.

HyperHacker
January 20th, 2005, 05:34
Alright, so I finally decided to start working on an emulator of my own. :P I've got the basic CPU emulation done, all opcodes except DAA and that sub-set 0xCB, working good so far. I'm not sure how I should go about doing interrupts, though. I'm starting with VBlank/LCDC status. I'm not sure exactly how to determine how many cycles to go before changing the LCDC mode.

Also, does anyone know what the values of the CPU and I/O registers are right when it boots up, before the bootROM is executed?

BTW, aprentice, your debugger would look a lot better if you used spaces instead of zeros for 1 and 2-byte opcodes, like this:
0150 00 .. .. NOP
0151 E0 D3 .. LDH ($FFD3),A
0153 CD 34 12 CALL $1234
except I've used periods instead of spaces because repeated spaces won't show up. :P

aprentice
January 20th, 2005, 06:22
BTW, aprentice, your debugger would look a lot better if you used spaces instead of zeros for 1 and 2-byte opcodes, like this:
0150 00 .. .. NOP
0151 E0 D3 .. LDH ($FFD3),A
0153 CD 34 12 CALL $1234
except I've used periods instead of spaces because repeated spaces won't show up. :P

I disagree, I think it would look messy and more hard to follow if it looked like that :P

Also in your sig "There are 11 types of people in the world: Those who can count in Binary and those who can't." i'm guessing you're the people who can't count in binary cause "11" = 3 :P

bcrew1375
January 20th, 2005, 09:43
LOL, stop messing with him aprentice :p. Anyway, for the Gameboy, this will be your best friend: http://work.typo3.work.de/nocash/pandocs.htm. For the startup values, goto Power Up Sequence. It should also have the timings for the Stat Flag. Also, I'd have to disagree on the debugger as well. I think it looks fine the way it is.

HyperHacker
January 20th, 2005, 18:38
Heh, I thought that doc was just the same as the text file I had, but apparently not. Thanks!

Also in your sig "There are 11 types of people in the world: Those who can count in Binary and those who can't." i'm guessing you're the people who can't count in binary cause "11" = 3 :P
That's the idea. It combines a few old jokes. :P

bcrew1375
January 24th, 2005, 09:45
Well, I think I already said it, but a big mistake I made when writing my graphics code was to draw the screen all at once, instead of scanline by scanline. *Waits for everyone to point and laugh* :blush:. So, now I'm kinda stumped as to how I should draw the background. I've got the window and sprites down fine, I just can't find a decent way to draw the background. BTW, aprentice, did you ever get my PM :whistling?

aprentice
January 24th, 2005, 13:28
Well, I think I already said it, but a big mistake I made when writing my graphics code was to draw the screen all at once, instead of scanline by scanline. *Waits for everyone to point and laugh* :blush:. So, now I'm kinda stumped as to how I should draw the background. I've got the window and sprites down fine, I just can't find a decent way to draw the background. BTW, aprentice, did you ever get my PM :whistling?

Yeah, I started writing out a reply and then had to leave for a few hours, when I got back someone closed the window already and I completely forgot about it until now :blush: Replying to that pmsg now..

HyperHacker
January 28th, 2005, 03:55
Bleh, how are you guys handling video exactly? I've just been doing SetPixel() in a loop whenever the game modifies a tile (to draw that tile on the buffer), and drawing the screen using BitBlt (copy from the tile buffer)... Of course it's ridiculously slow. :P Variable-size screen is a big problem especially, since the only way I know how to do it is with StretchBlt() which is so slow it's a joke.

aprentice
January 28th, 2005, 04:20
Bleh, how are you guys handling video exactly? I've just been doing SetPixel() in a loop whenever the game modifies a tile (to draw that tile on the buffer), and drawing the screen using BitBlt (copy from the tile buffer)... Of course it's ridiculously slow. :P Variable-size screen is a big problem especially, since the only way I know how to do it is with StretchBlt() which is so slow it's a joke.

I have no clue what you are talking about, did you mean to post this in the chip8 forum? :P

HyperHacker
January 28th, 2005, 22:00
No... I'm talking about re-drawing the screen. How are you translating the GB's VRAM and tile map into an image scaled to the size of the window without massive slowdown?

Also just for comparison's sake, what kinds of CPU speeds are you all getting? I'm averaging around 250% with just the CPU core (IE no video, sound etc).

aprentice
January 29th, 2005, 04:56
No... I'm talking about re-drawing the screen. How are you translating the GB's VRAM and tile map into an image scaled to the size of the window without massive slowdown?

Also just for comparison's sake, what kinds of CPU speeds are you all getting? I'm averaging around 250% with just the CPU core (IE no video, sound etc).

The screen is rendered line by line, no scaling or stretching needed.
As for speed, it can greatly vary depending on your system specs and video card. My emu (with the graphics on) runs at 1400fps on someones pc who has a high end gfx card, while it runs like 700fps on mine with my crappy geforce3. Probably without the video it would run at like 3000 fps or something :P Before you go thinking your cpu is slow, i just want to say that mine is super optimized, I milked it for all its worth, I spent two weeks optimizing it (no joke).

On the side note, i started to attempt sound, i'm not exactly sure how to handle it really so its going to be a slow process. I already emulated the sound registers so its a matter of generating sound using the raw waveform pattern in memory. What baffles me is how to play sound, and how to use notifications via streaming in directsound.

zenogais
January 29th, 2005, 06:22
Sound is tricky, but direct sound does have a raw waveform mode. So its just a matter of using the callback to load the latest sound data into DirectSound for playing. My guess is its probably a little more involved than that, but thats the basic gist of it from what I can gather.

aprentice
January 29th, 2005, 06:26
Sound is tricky, but direct sound does have a raw waveform mode. So its just a matter of using the callback to load the latest sound data into DirectSound for playing.

do you have any resources on its waveform mode? Not many sound tutorials on the web (not interested in openal or fmod tutorials).

zenogais
January 29th, 2005, 06:39
well, for the WAVEFORMATEX structure you probably wanna use WAVE_FORMAT_PCM with two channels. That should get you started. Now I'm not an expert on this stuff, but since it has only two channels of sound it shouldn't be terribly difficult to emulate.

bcrew1375
January 31st, 2005, 01:50
HyperHacker, could you make yourself more clear? Are you talking about making the screen bigger than 160x144? Like scaling it to 2 or 3 times bigger? If so, you would just draw a rectangle instead of a single pixel. I'm not sure if that's what you're talking about or not :P.

aprentice
January 31st, 2005, 01:54
HyperHacker, could you make yourself more clear? Are you talking about making the screen bigger than 160x144? Like scaling it to 2 or 3 times bigger? If so, you would just draw a rectangle instead of a single pixel. I'm not sure if that's what you're talking about or not :P.

hey bcrew, how'd that line by line implementation go? also, have you looked into sound?

bcrew1375
February 2nd, 2005, 08:00
I wish I could say I have it working, but my brain just doesn't seem to want to work right now :/. I can't get myself to comprehend the code at the moment. I rewrote my background code basing it on yours, but I'm still missing something, probably something really simple. I just can't figure out what. As far as sound, I'm not touching it until I get some of the other kinks worked out.

aprentice
February 2nd, 2005, 20:52
I wish I could say I have it working, but my brain just doesn't seem to want to work right now :/. I can't get myself to comprehend the code at the moment. I rewrote my background code basing it on yours, but I'm still missing something, probably something really simple. I just can't figure out what. As far as sound, I'm not touching it until I get some of the other kinks worked out.

send me your code for the drawing routine and i'll have a look and point you in the right direction

HyperHacker
February 4th, 2005, 09:02
HyperHacker, could you make yourself more clear? Are you talking about making the screen bigger than 160x144? Like scaling it to 2 or 3 times bigger? If so, you would just draw a rectangle instead of a single pixel. I'm not sure if that's what you're talking about or not :P.
Yeah, I figured that much out. Still only getting ~70% speed though. (Yes, my video card does suck a lot. :P) The real problem is updating the tile graphics when a game writes to them, it seems to be causing some major slowdown. I finally got it to actually do something, Tetris gets to the title screen, w00t w00t. The biggest problem is I can't seem to work out this one damn graphic bug. On each tile, the right-most pixels are always drawn in colour 0. http://www.emutalk.net/images/smilies/angry.gif

Here's my crappy tile-updating code, you give it the tile # (just the address being modified \ 0x10, I call it whenever the game writes to the tile data).

void UpdateTile(unsigned int TileNum)
{
unsigned int Addr = (TileNum << 4);
if(LogInstructions) printf("UpdateTile %04X %02X, ---- - - -- --",Addr,TileNum);
int x,y,c;
for(y=0;y<8;y++)
{
for(x=0;x<8;x++)
{
if(LogInstructions) printf("##############%04X %01X %01X %02X %02X",Addr,x,y,GFX0[Addr],GFX0[Addr + 1]);
c = ((GFX0[Addr + (y << 1)] >> x) & 1) |
((GFX0[(Addr + (y << 1)) + 1] >> (x-1)) & 2);
SetPixel(TileDC,(7 - x) + (TileNum << 3), y, Colour[BGColourIndex[c]]);
}
}
if(LogInstructions) printf(" B");
for(x=0;x<10;x++)
{
BitBlt(MainDC,0,x << 3,160,8,TileDC,x*160,0,SRCCOPY);
}
if(LogInstructions) printf(" OK\n");
}
(Small note: On the line that prints "##############", the #s are actually supposed to be backspace characters. I couldn't get the escape code to work so I just manually inserted them. Isn't TextPad great? :P)
The problem seems to be with the algorithm just before SetPixel. Somehow the right-most pixel is always coming up as color 0. (Also, yes, at the moment it's written to dump all the tiles to the screen instead of display the actual output, which is what that BitBlt loop at the end is for.)

Anyone else working on one of these, here's a tip: Instruction 0xCB is a lot more important than you'd think. :P

[edit] Hmm, I think I might know what's going on... X >> -1 = 0, rather than X << 1 like you would think. :blink:

bcrew1375
February 4th, 2005, 09:13
I'm not sure about the color 0 thing, but I think you might be making the same mistake I did. You don't want to update the screen whenever the tile data changes. You need to update the screen using LY(memory location 0xFF44). When the LY changes, you draw the pieces of the tiles that are on that specific line, you don't want to draw the tiles all at once. I'm guessing this is the reason I have problems in Donkey Kong, Legend of Zelda, and Super Mario Land. You should have a routine to draw one scanline instead of one tile.

HyperHacker
February 4th, 2005, 09:18
Interesting... I had just had it drawing the entire screen when it hits vblank. The problem isn't really re-drawing the screen, it's drawing each individual tile onto a buffer.

Is there a faster method than SetPixel/BitBlt though?

aprentice
February 4th, 2005, 13:56
Interesting... I had just had it drawing the entire screen when it hits vblank. The problem isn't really re-drawing the screen, it's drawing each individual tile onto a buffer.

Is there a faster method than SetPixel/BitBlt though?

If you render the whole screen at vblank, you WILL have problems, and also remember there are dynamic scrolling registers. I think your code is slow cause you are rendering "per tile", how often is this routine called?

HyperHacker
February 5th, 2005, 01:56
There are 2 different routines. One draws each individual tile onto a buffer, this is called whenever the game writes to the tile data in order to update the buffer (it re-draws whatever tile was modified). The other copies each tile to the screen as specified in VRAM and is called every time it enters Vblank. I am going to change it to draw per scanline instead of all at once though. (I'd completely forgotten about the scroll registers. ^_^; )

bcrew1375
February 12th, 2005, 04:34
You know, I finally got my scrolling code to work, thanks to VBA's source. I couldn't seem to grasp it until I looked there. The only thing is now I kinda feel like a theif because my graphics code is heavily based on VBA's. :plain: BTW, thanks for your help, aprentice. Now I can concentrate on the CPU bugs :).

aprentice
February 12th, 2005, 07:04
You know, I finally got my scrolling code to work, thanks to VBA's source. I couldn't seem to grasp it until I looked there. The only thing is now I kinda feel like a theif because my graphics code is heavily based on VBA's. :plain: BTW, thanks for your help, aprentice. Now I can concentrate on the CPU bugs :).

no problem, cpu bugs are the easy part to fix, timing is a huge pain :P
I cant get the timing right in my emu, its killing compat :plain:

Dark Stalker
February 15th, 2005, 05:28
Hi!

I've been lurking around the outskirts of these forums for some years now, looks like quite a few interesting things have been happening here lately.

Y'all got me throwing away the last few weeks starting my own cross-platform gb emu. I've gotten to the point where things start to look like something playable. I've been spending the night implementing MBC1, which seems to do fairly well (Zelda looks quite playable except for the obvious lack of sprites). I guess I'll be looking at sprites next if I get some more time on my hands.


Screenies:
Big Scroller Demo
http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde119.png http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde1111.png

Super Mario Land
http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde117.png

Link's Awakening
http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde115.png http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde114.png

bcrew1375
February 15th, 2005, 09:40
Nice work, Dark Stalker. You'll be caught up with me soon :P.

aprentice
February 15th, 2005, 17:25
nice work indeed, its good to see more people who read this thread successfully attempting their own gameboy emu.

Have you completed the timing for your emulator yet?

Dark Stalker
February 15th, 2005, 22:59
I've still got ways to go before I (if ever) catch up to you guys I think. Sprites are coming along nicely though. Zelda's been complaining about some weird drawing problem I have, effectively killing the bottom-screen menu. Is this an issue with the window-drawing you think? The menu won't show if the start button is pressed either for that matter. I've got a few games acting similarly grumpy too, though I haven't done a lot of testing yet.

http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde1113.png http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde1112.png


As for timing, I've got the timer and divider registers presumably working, and I'm generating all the interrupts except for input which doesn't seem to make any difference to any rom I've tested yet anyway. I'm also supposedly drawing every line at the correct time, but I'm only setting vsync and hsync modes (will setting the other ones do anything for compatibility?). Additionally, I think I've got the wrong cycle-numbers for some of the conditional opcodes, and probably a few of the others too. There's probably more aspects to timing that I haven't even begun to think of yet.

refraction
February 15th, 2005, 23:13
that was a question i was going to ask, now im actually working on the development of a GB emu (yes i know i said i started ages ago, but i gave up on programming for a bit :P)

The timing seems to be a big factor in compatability, and now ive written the Z80 core from scratch, i would like someone to explain (aprentice this is where you jump in!) how the time works, what it triggers, where is it kept to be counted etc..

If its mentioned in some docs tell me which n ill have a look, but ive got so many now i dont know which one to look at!

bcrew1375
February 16th, 2005, 04:47
The menu problem is definitely something to do with the window. I can pretty much guarantee that. You should look into your window drawing code for problems.

refraction: The time counter is kept at 0xFF05. It goes from 0-255. When it exceeds 255, it is loaded with the value at 0xFF06. The timer on/off switch and the frequency is kept at 0xFF07.

refraction
February 16th, 2005, 10:06
The menu problem is definitely something to do with the window. I can pretty much guarantee that. You should look into your window drawing code for problems.

refraction: The time counter is kept at 0xFF05. It goes from 0-255. When it exceeds 255, it is loaded with the value at 0xFF06. The timer on/off switch and the frequency is kept at 0xFF07.


is it incremented by the number of cpu cycles each opcode takes? or by one every cycle?

bcrew1375
February 16th, 2005, 13:38
It's incremented according to the frequency. So, if the frequency is set at 4096 Hz, then the time counter is incremented 4096 times a second. To get the number of cycles, you would take the total cycles ran a second and divide by the times the time is updated per second. So, if you use the machine speed(1.048576 MHz, I think), 1048576 / 4096 = 256. Not entirely sure this is correct. Can you back me up aprentice? :P

refraction
February 16th, 2005, 13:47
i see, but what i mean is with the CPU cycles, as each one takes a certain number of cycles, say one takes 4 and another takes 3 cycles, what would i do to implement them?

i understand what you mean tho, divider set to 4096, clock speed is 1.436395634mhz or whatever lol (just slapped a load of numbers) and the divided number is the amount of opcodes it runs per second yes?

actually what do i do with my result number? :P

where is aprentice when you need him!!

Dark Stalker
February 16th, 2005, 16:48
I'm just do this every 455th cpu-cycle (one line is drawn every 455 cycle, which I wouldn't want to miss), so the precision is limited to that. Each opcode processed by the cpu subtracts from the CycleCounter.

const Uint32 timaClock[4]={ 1024, 16, 64, 256 };
for(;;) {
z80.process();
if(CycleCounter<=0) {
CycleCounter+=455;
...
...
if(memory.read(0xFF07)&4)
updateTima(timaClock[(memory.read(0xFF07)&3)]);
...
}
}
//Updates TIMA register according to cycles passed and frequency given by TAC reg. Requests interrupt if overflow
inline void GameBoy::updateTima(const Uint32 &timaClock) {
//Increases timaCounter by cycles passed.
timaCounter+=455;
//temp is set to cycles passed divided by cycles required to pass per update.
temp=timaCounter/timaClock;
//If the TIMA reg is about to overflow, reset to value in TMA reg (and adds back overflowed value) and request interrupt.
if((memory.read(0xFF05)+temp)&256) {
memory.write(0xFF05)=memory.read(0xFF06) +((memory.read(0xFF05)+temp)%256);
memory.write(0xFF0F)|=4;
}
else //Increment TIMA by cycles passed divided by cycles required to pass pr update.
memory.write(0xFF05)+=temp;
//Find number of cycles left to use for future calculations.
timaCounter-=temp*timaClock;
}
EDITed in update on progress, and a bit context for my code :whistling :
I finished implementing sprites (except x-position priority) yesterday, and was a bit reluctant to implement yflip since it got sort of hilarious looking at link swinging his sword by the wrong end when faced north :P. Additionally I added regular saveram support, and support for pressing all buttons at once (so I can actually get to the savescreen in zelda :P). I did some testing and a few games surprisingly seem to work with hardly any flaws at all.

http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde11112.png
http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde1115.png http://home.tussa.com/iaamaas/screenshots/lameboy/skjermbilde1117.png

refraction
February 16th, 2005, 16:55
explaining it woulda been nicer instead of having to decypher your code :P

but i get the general idea cheers. Aprentice? can you give you take on timing?

Dark Stalker
February 16th, 2005, 17:25
I don't have the time to explain further right now, but I edited my previous post to add some more context for my code. I guess aprentice would know better anyway though :P

bcrew1375
February 16th, 2005, 22:44
refraction, you should create a variable to hold the number of cycles until the timer is updated(which is machine speed / timer frequency. example: 1048576 / 4096 = 256) and subtract the opcode's cycles from that. When it is lower than or equal to 0, increment 0xFF05. When 0xFF05 exceeds 255, load it with the contents of 0xFF06. Hope that is what you're talking about.

refraction
February 16th, 2005, 23:36
refraction, you should create a variable to hold the number of cycles until the timer is updated(which is machine speed / timer frequency. example: 1048576 / 4096 = 256) and subtract the opcode's cycles from that. When it is lower than or equal to 0, increment 0xFF05. When 0xFF05 exceeds 255, load it with the contents of 0xFF06. Hope that is what you're talking about.

now THAT made sense, a variable holding the result of that equasion depending on the divider, so a number of opcodes run, subtracting the number of cpu cylces it takes from that figure each time until it reaches zero, at which point 0xFF05 is filled with 0xFF06 and a timer interrupt is called yes?

Dark Stalker
February 17th, 2005, 00:53
Note that timing is a much bigger issue than just taking care of the tima register, in case that wasn't clear.

bcrew1375
February 17th, 2005, 03:27
now THAT made sense, a variable holding the result of that equasion depending on the divider, so a number of opcodes run, subtracting the number of cpu cylces it takes from that figure each time until it reaches zero, at which point 0xFF05 is filled with 0xFF06 and a timer interrupt is called yes?

Only after 0xFF05 has exceeded 255(It is reset to 0, by the way) should it be loaded with 0xFF06 and the interrupt called. Otherwise, yes, but as Dark Stalker said, there's a bit more. You need to limit the number of cycles the emulation can run per second, or you could limit it by screen updates.

aprentice
February 17th, 2005, 04:48
yeah, timing is a pretty big issue, which i myself haven't got working accurately yet.

basically you have to execute 70,224 cycles per frame.

in my emu i have pretty much estimated the oam transfer mode to be 80 cycles, the hblank to last 204 cycles, the transfer to be 172 cycles and vblank to last 4560 cycles. basically every scanline has to be 456 cycles, and although the gameboy mono isnt too timing sensative, a handful of games wont work if its not done right.

Not sure how accurate my timing is, but its causing me problems in a lot of games like sprites not showing up in some gameboy mono and hdma transfers happening at the wrong times (and locations) in some color gameboy.

bccrew is right about the DIV, and tima stuff, heres my code on how i did the div, incase the other code examples given were too confusing.


void inc_div(int cycles)
{
cpu.div_counter+=cycles;
if(cpu.div_counter>=256)
{
cpu.div_counter-=256;
DIV++;
}
}


if anyone makes any breakthroughs on timing, let me know :P

refraction
February 17th, 2005, 11:59
ok so i see its something people havent perfected yet, well if i manage to fluke the ultimate soluition (haha) then ill let you know :P

aprentice
February 17th, 2005, 20:37
ok so i see its something people havent perfected yet, well if i manage to fluke the ultimate soluition (haha) then ill let you know :P

actually thats true, but i have errors in my own timing as well :P

refraction
February 17th, 2005, 22:42
actually thats true, but i have errors in my own timing as well :P

well nobody is perfect :)

ill have a look around see if i can find anything more in depth about timing, most documents just say "the DIV register is updated 16355 times a second, if any value is written to this it becomes 00"

thats kinda confusing, but im assuming it means it increments itself so many times a second, BUT if something else tries to write to it, it resets to 00 yeh?

aprentice
February 17th, 2005, 23:04
well nobody is perfect :)

ill have a look around see if i can find anything more in depth about timing, most documents just say "the DIV register is updated 16355 times a second, if any value is written to this it becomes 00"

thats kinda confusing, but im assuming it means it increments itself so many times a second, BUT if something else tries to write to it, it resets to 00 yeh?

yep, writing any value to this register would reset its value and
it incraments every 256 cycles on its own.

refraction
February 17th, 2005, 23:06
yep, writing any value to this register would reset its value and
it incraments every 256 cycles on its own.


ah good, so i dont have to touch that then? im sure i saw someone in here with a loop round their main function to do something every 256 cycles :plain:

aprentice
February 17th, 2005, 23:12
ah good, so i dont have to touch that then? im sure i saw someone in here with a loop round their main function to do something every 256 cycles :plain:

by on its own, i mean the hardware does it, and your the one emulating the hardware :P

refraction
February 17th, 2005, 23:21
by on its own, i mean the hardware does it, and your the one emulating the hardware :P


now your trying to confuse me :P right so i need a routine incrementing that and checking it for overflow got it.

thats the DIV register that increments right?

TIMA increments in 1/4 the time of DIV if TAC is set to 4096 (which is 1/4 the number of times DIV updates)

that sound right to you?

thisd be so much easier if you could contact me on msn :P

aprentice
February 18th, 2005, 00:29
now your trying to confuse me :P right so i need a routine incrementing that and checking it for overflow got it.

thats the DIV register that increments right?

TIMA increments in 1/4 the time of DIV if TAC is set to 4096 (which is 1/4 the number of times DIV updates)

that sound right to you?

thisd be so much easier if you could contact me on msn :P

you dont need to check for overflow with div's, it can wrap around by itself. tima is a different story though, i posted my div function above, very easy to follow code :P

to figure out how many cycles to incrament TIMA its 4194304 / TAC frequency.

Dark Stalker
February 18th, 2005, 02:11
I just started setting all the modes (presumably at the right time), and now many games just work.
I also fixed my Zelda-problem. Zelda sets wx to 6, and in gamboy logic 6-7=0 apparently. As opposed to my result of 255, which might not be quite natural to most people anyway though :P


edit: Just forgot to satisfy my boasting needs :P:

http://home.tussa.com/iaamaas/screenshots/lameboy/zelda.png http://home.tussa.com/iaamaas/screenshots/lameboy/ffl3.png

http://home.tussa.com/iaamaas/screenshots/lameboy/mario2.png http://home.tussa.com/iaamaas/screenshots/lameboy/wario1.png

http://home.tussa.com/iaamaas/screenshots/lameboy/donkey1.png http://home.tussa.com/iaamaas/screenshots/lameboy/mm4.png

bcrew1375
February 18th, 2005, 05:01
As I said before, you probably just blew me out of the water. I still can't get SML2 to run. :P You must be a great programmer to get it done so quickly. Congrats!

aprentice
February 18th, 2005, 06:23
super mario land 2 wont go in game for me either, i have no idea why...
also, does wave race run for you dark stalker?

hap
February 18th, 2005, 15:32
Good to see so many people working on GB emulation, maybe I'll join in later... much later, stubborn NES emu ;-)

Dark Stalker
February 18th, 2005, 17:00
Wave Race obviously won't run, since I haven't bothered to implement mbc2 support yet.
Super mario land 2 even works in my old versions, from before I fixed my lcd-mode timing. So I guess the issue you have with it lies elsewhere.

Out of the mbc1 games I've tested (which aren't really that many), these seems to have issues:
Kirby's dreamland 2
Final Fantasy Legend II and III

Kirby2 just shows a black screen. Final Fantasy Legend II goes to unknown opcodes in the rom after a few seconds, regardless of if I start the intro or not. Final Fantasy Legend III works, but is a bit unstable in that it goes to unknown opcodes every few minutes on a random basis.

Shpongled
February 18th, 2005, 17:11
Does anyone happen to know a really old black-and-white gameboy game which you could pick either a rabbit or a penguin or a walrus and you had to roll balls across a table so the other player couldn't block it?

Thanks :)

aprentice
February 18th, 2005, 18:33
Wave Race obviously won't run, since I haven't bothered to implement mbc2 support yet.
Super mario land 2 even works in my old versions, from before I fixed my lcd-mode timing. So I guess the issue you have with it lies elsewhere.

Out of the mbc1 games I've tested (which aren't really that many), these seems to have issues:
Kirby's dreamland 2
Final Fantasy Legend II and III

Kirby2 just shows a black screen. Final Fantasy Legend II goes to unknown opcodes in the rom after a few seconds, regardless of if I start the intro or not. Final Fantasy Legend III works, but is a bit unstable in that it goes to unknown opcodes every few minutes on a random basis.

how is the ram page handling in your emulator done?
i'm still not 100% sure mine is correct, wouldn't be surprised if this is whats breaking mario land 2

Dark Stalker
February 18th, 2005, 19:34
This is roughly how I handle mbc1 ram for now:
If the rom writes to 0x4000-0x5FFF and ram is enabled, and the rom is in rambank-mode, I make the rom write the rambank number (only caring about the 2 ls bits of course) to a variable (and set the bool rambankchange=1).

Then the next time the rom tries to read or write to ram (and rambankchange is true), I swap rambanks right before giving it access. Meaning I basically copy the contents of the active ram to the previous rambank, and then copy the contents of the new rambank to active ram.

(This array represents my rambanks: "Uint8 rambankdata[4][0x2000];" which I copy back and forth from/to.)

I hope this is what you wanted to know.

zenogais
February 18th, 2005, 23:04
I have a request to those who have working emus, it would be cool if you guys would make occassional releases (executable releases) just so those of use who don't have working emu's yet can check out your progress.

Dark Stalker
February 19th, 2005, 00:47
Heh :P

http://home.tussa.com/iaamaas/screenshots/lameboy/waverace.png http://home.tussa.com/iaamaas/screenshots/lameboy/waverace1.png


edit: update :saint:,
I just toyed around a bit with mbc3, and it seems to work, except my rtc currently follows actual time while the rest of my emu is based on clock cycles. I'll probably reimplement it according to clock cycles later.

:P:P:P
http://home.tussa.com/iaamaas/screenshots/lameboy/pokeblue1.png http://home.tussa.com/iaamaas/screenshots/lameboy/warioland2.png
(no pun intended)


final(?) edit:
I just went ahead and threw in support for mbc5 too when I was at it (what? what is it? no, I'm not spamming :P):

http://home.tussa.com/iaamaas/screenshots/lameboy/dw2-2.png


As for releases, I really don't think I want to do any before I've at least made a half-decent user interface (currently command-line only). I'll probably GPL it too, so I don't want my code to be too ugly. It's nice that someone is interested though. How is your emu doing Zenogais? Previous posts from you indicate you're writing a whole OS around your emulator :P
I guess that means you've done all those things I haven't even started to think about yet :blush: and probably more at that.

aprentice
February 19th, 2005, 06:03
This is roughly how I handle mbc1 ram for now:
If the rom writes to 0x4000-0x5FFF and ram is enabled, and the rom is in rambank-mode, I make the rom write the rambank number (only caring about the 2 ls bits of course) to a variable (and set the bool rambankchange=1).

Then the next time the rom tries to read or write to ram (and rambankchange is true), I swap rambanks right before giving it access. Meaning I basically copy the contents of the active ram to the previous rambank, and then copy the contents of the new rambank to active ram.

(This array represents my rambanks: "Uint8 rambankdata[4][0x2000];" which I copy back and forth from/to.)

I hope this is what you wanted to know.

opps, i wasnt thinking right when i wrote that, i meant sram not wram :blushing:

Setting up sram pages is pretty odd, since some roms have less sram than a a full bank (eg. 2kb instead of 8kb).

basically right now i set up the 2kb one like
mem.rampage[0]=(mem.sram+(0*0x800));
and the 8kb one like:
mem.rampage[0]=(mem.sram+(0*0x2000));

Dark Stalker
February 19th, 2005, 06:31
What is this sram you speak of? :P I don't really handle sram very much at all. I've been going around the problem for now by just backing up all rambanks. (Actually my docs haven't mentioned a whole lot on sram). I just treat all my mbc1 ram as 4 arrays of 0x2000 bytes. For mbc5 I just use 16 arrays. I'll be looking at doing sram correctly later. :blush:

I tried to point out that I don't perform the bank swap until the game actually wants to access the ram (this goes for rom-swapping too). Not doing this breaks things for me (probably because the rom is changing modes meanwhile or something). This might be obvious for all I know though. :P

zenogais
February 19th, 2005, 07:11
I suppose we can let the cat out of the bag...

Refraction and I have been working on NeoGameboy now for about 2-3 weeks, and we've already gotten quite alot done. I've been mostly working on getting the GUI up and running so we have the frontend set up and all we have to do is code the backend. Refraction has been working on CPU/Timing emulation for a while now, and I'm slotted to go over it tommorow and basically "refactor" it in order to make the code more managable.

Check out some screenies of what we've got HERE (http://www.zenogais.net/projects/series/images.htm)

P.S. Don't try to keep up on source releases, they change 2-3 times a day :P

aprentice
February 19th, 2005, 07:18
What is this sram you speak of? :P I don't really handle sram very much at all. I've been going around the problem for now by just backing up all rambanks. (Actually my docs haven't mentioned a whole lot on sram). I just treat all my mbc1 ram as 4 arrays of 0x2000 bytes. For mbc5 I just use 16 arrays. I'll be looking at doing sram correctly later. :blush:

I tried to point out that I don't perform the bank swap until the game actually wants to access the ram (this goes for rom-swapping too). Not doing this breaks things for me (probably because the rom is changing modes meanwhile or something). This might be obvious for all I know though. :P

are you physically moving the memory or controlling a pointer? I really hope your not physically moving the memory :P

srams external memory, located in the cartridge :P

refraction
February 19th, 2005, 13:32
I suppose we can let the cat out of the bag...

Refraction and I have been working on NeoGameboy now for about 2-3 weeks, and we've already gotten quite alot done. I've been mostly working on getting the GUI up and running so we have the frontend set up and all we have to do is code the backend. Refraction has been working on CPU/Timing emulation for a while now, and I'm slotted to go over it tommorow and basically "refactor" it in order to make the code more managable.

Check out some screenies of what we've got HERE (http://www.zenogais.net/projects/series/images.htm)

P.S. Don't try to keep up on source releases, they change 2-3 times a day :P

gah party pooper :P yes its true, hence all the timing questions, hopefully we will get something showing within the next week or so, even if its just minimal emulation

Dark Stalker
February 19th, 2005, 14:45
are you physically moving the memory or controlling a pointer? I really hope your not physically moving the memory :P

srams external memory, located in the cartridge :P
I've only been talking about external memory all the time, so I guess we've got some kind of misunderstanding going. At least I thought all rambanks were located in the cartridge (no, I don't mean the GameBoy's internal work ram at C000h-DFFFh). I've been lazy about it for now, so I'm actually copying the memory in and out of address space and haven't seen very much of an overhead anyway (according to my profiler, my swapping function uses 0.01 % cputime :P).

bcrew1375
February 20th, 2005, 05:57
RAM banks are extra memory for the cartridge. The SRAM is Save or Shadow RAM. It is what the game's save data is recorded on, aka the battery backup. Anyway, I've been controlling RAM banks pretty much the same as Dark Stalker, yet I still have problems with SML2. :plain:

zenogais
February 21st, 2005, 04:12
Progress update on NeoGameboy - CPU refactoring is about 25% complete, I'm trying to make the code a lot more readable and maintainable, despite that being somewhat of an oxymoron, it seems, when talking about the gameboy. The GUI is pretty much finished, though I'd like to add a ROM browser once ROM loading and emulating is taken care of. Nice to see your incredible progress Dark Stalker, seems like you really know your stuff :)

Dark Stalker
February 21st, 2005, 18:39
I've mostly been bug-fixing lately and I've worked a lot on timing. Regression testing was hell, but I think I've finally just about hit the spot (or pretty close to it, since new surprises have been appearing all the time up until now). During this I came across a few things that may be relevant to some of your problems (bcrew/aprentice).

For super mario land 2 to work, you need to allow execution of vblank-interrupts when the display is disabled.

For waverace to work, you need to do lyc-compare during vblank (note that if you don't take some precations, this will break other games).

aprentice
February 21st, 2005, 20:26
I've mostly been bug-fixing lately and I've worked a lot on timing. Regression testing was hell, but I think I've finally just about hit the spot (or pretty close to it, since new surprises have been appearing all the time up until now). During this I came across a few things that may be relevant to some of your problems (bcrew/aprentice).

For super mario land 2 to work, you need to allow execution of vblank-interrupts when the display is disabled.

For waverace to work, you need to do lyc-compare during vblank (note that if you don't take some precations, this will break other games).

The lyc compare during vblank definately fixed waverace, brilliant find dude :)
Im not sure what you mean by execution of vblank when the display is disabled though. I dont really emulate turning off the display though yet, dunno if that makes a difference even. Btw, how are you handling the timing for the lcd modes?

Dark Stalker
February 21st, 2005, 21:01
The lyc compare during vblank definately fixed waverace, brilliant find dude :)
Im not sure what you mean by execution of vblank when the display is disabled though. I dont really emulate turning off the display though yet, dunno if that makes a difference even. Btw, how are you handling the timing for the lcd modes?
If you're not disabling display according to the LCDC register you'll have problems getting past the title screen (and a lot of other games will break too). It's just not very well documented exactly what gets disabled when the lcd is off. I had to try lots of combinations to find a solution that didn't break anything. Just ask if you want to know how I've implemented it.

Timing lcd-modes can be a bit strange. Some documentation claim that mode3 is set longer according to the number of sprites on the the line being drawn, which in turn makes mode0 shorter. I implemented that, but it gave me a flashing line in Mega Man 5, so I've backed down to setting fixed intervals again for now.
When the LY-register has been incremented, I set mode2 for 80 cpu cycles (20 machine cycles) and check if I should request an oam lcdstat interrupt. Then mode3 is set for 172 cpu cycles. When mode3 is done, I draw the line, set mode0, and check if hsync lcdstat interrupt should be requested. Mode0 is staying set for 204 cpu cycles. After that LY is incremented, and mode2 will be set again.

When LY reaches 144 I set mode1 and request v-blank interrupt (and lcdstat if apropriate). Vblank should then last for 4560 cpu cycles.

refraction
February 21st, 2005, 21:10
this is all i could find on the lcd thing


Stopping LCD operation (bit 7 from 1 to 0) must
be performed during V-blank to work properly. Vblank
can be confirmed when the value of LY is
greater than or equal to 144.

The Mode Flag goes through the values 0, 2,
and 3 at a cycle of about 109uS. 0 is present
about 48.6uS, 2 about 19uS, and 3 about 41uS.
This is interrupted every 16.6ms by the VBlank
(1). The mode flag stays set at 1 for about 1.08
ms. (Mode 0 is present between 201-207 clks, 2
about 77-83 clks, and 3 about 169-175 clks. A
complete cycle through these states takes 456
clks. VBlank lasts 4560 clks. A complete screen
refresh occurs every 70224 clks.)

aprentice
February 21st, 2005, 23:22
If you're not disabling display according to the LCDC register you'll have problems getting past the title screen (and a lot of other games will break too). It's just not very well documented exactly what gets disabled when the lcd is off. I had to try lots of combinations to find a solution that didn't break anything. Just ask if you want to know how I've implemented it.

Timing lcd-modes can be a bit strange. Some documentation claim that mode3 is set longer according to the number of sprites on the the line being drawn, which in turn makes mode0 shorter. I implemented that, but it gave me a flashing line in Mega Man 5, so I've backed down to setting fixed intervals again for now.
When the LY-register has been incremented, I set mode2 for 80 cpu cycles (20 machine cycles) and check if I should request an oam lcdstat interrupt. Then mode3 is set for 172 cpu cycles. When mode3 is done, I draw the line, set mode0, and check if hsync lcdstat interrupt should be requested. Mode0 is staying set for 204 cpu cycles. After that LY is incremented, and mode2 will be set again.

When LY reaches 144 I set mode1 and request v-blank interrupt (and lcdstat if apropriate). Vblank should then last for 4560 cpu cycles.

okay, thats exactly what im doing timing wise, not sure why sprites aren't showing in some games. Hmmm.

Dark Stalker
February 21st, 2005, 23:56
That might be because you shouldn't be changing mode-values while the display is disabled. :P
I think some games choose to disable the display to write sprite data.

aprentice
February 22nd, 2005, 00:07
That might be because you shouldn't be changing mode-values while the display is disabled. :P
I think some games choose to disable the display to write sprite data.

edit: scrap all i just said, MARIO LAND 2 works!!!
you were right about the lcd disabled thing, thanks dude :)

<bragging>
http://www.darkengine.net/gb/marioland2.gif
http://www.darkengine.net/gb/marioland2_tree.gif
</bragging>

mario land 2 with vsync enabled :P

only problem is the sprites issue wasnt fixed and super mario land 4 (jap hack) broke and all the hardware test demos :P

Dark Stalker
February 22nd, 2005, 01:18
Congrats! Must feel good to finally get that annoyance out of your life :P

Yep, things break once something else works, I've gotten used to that by now. It took me an unpleasant amount of guesswork and experimenting to get it all (hopefully) working together.

aprentice
February 22nd, 2005, 01:23
Congrats! Must feel good to finally get that annoyance out of your life :P

Yep, things break once something else works, I've gotten used to that by now. It took me an unpleasant amount of guesswork and experimenting to get it all (hopefully) working together.

so when bit 7 is set in lcdc, all you do is execute 70224 cycles and nothing more? (besides interrupt execution)

Dark Stalker
February 22nd, 2005, 02:06
so when bit 7 is set in lcdc, all you do is execute 70224 cycles and nothing more? (besides interrupt execution)Pretty much everything not related to drawing runs as normal until the display is enabled again. I had to deny LCDC interrupt execution for Street Fighter 2 to be satisfied, but that may be the result of something else of course. Also LY should be set to 0, and mode to 0 it seems. The order in which you do things and how often you do them can also affect compatibility greatly btw.

aprentice
February 22nd, 2005, 02:30
Pretty much everything not related to drawing runs as normal until the display is enabled again. I had to deny LCDC interrupt execution for Street Fighter 2 to be satisfied, but that may be the result of something else of course. Also LY should be set to 0, and mode to 0 it seems. The order in which you do things and how often you do them can also affect compatibility greatly btw.

ok, setting mode to 0 fixed the games that stopped working as a result of this change :P

zenogais
February 22nd, 2005, 03:52
Seeing those pics or Mario Land 2 brings back alot of memories. You guys rock! :)
I've still got a long ways to go, but I've finished the CPU stuff and now I'm working on video.

Update:

Picture page updated here (http://www.zenogais.net/projects/series/images.htm)

Doomulation
February 22nd, 2005, 08:21
Hey you guys, anyone care posting a source? :P
I need one to see how to do all these fuggin' stuff. The gb is, like, well, a machine to me. Heh, I don't know much 'bout the interior workings of them.
I must try to kick that emulator off for a good start at the gb eme which my *cough* co-workers *cough* seems to have abandoned. I'm all by myself now =(

bcrew1375
February 22nd, 2005, 08:27
I could give you mine, but it's not nearly as compatible as aprentice or Dark Stalker's code. I also tend not to use the fastest code, so I can understand my own code(I don't understand alot of speed techniques in programming just yet.).

hap
February 22nd, 2005, 15:27
How are all of you doing cpu-useage-wise then ?
My chip8 emu uses 0-1% on my athlon 2ghz :) and my (yet unoptimized) nes emu uses about 50% :(

zenogais
February 22nd, 2005, 15:51
The leap from Chip8 to NES is a giant one, and 50% doesn't sound at all unreasonable. Although doubtless your code probably could be optimized.

Dark Stalker
February 22nd, 2005, 20:25
I just redid my memory code and cleaned up my cpu. Quite magically I've got near 100% compatibility with all my games. :P
Only flaws I can think of is that the menu in FFA has some issues, Street Fighter II has some visual annoyances, and Escape from Camp Deadly has a problem when you "lose".

refraction
February 22nd, 2005, 23:00
I just redid my memory code and cleaned up my cpu. Quite magically I've got near 100% compatibility with all my games. :P
Only flaws I can think of is that the menu in FFA has some issues, Street Fighter II has some visual annoyances, and Escape from Camp Deadly has a problem when you "lose".

thats simple, your emu is a sore loser :P

Doomulation
February 23rd, 2005, 08:22
I could give you mine, but it's not nearly as compatible as aprentice or Dark Stalker's code. I also tend not to use the fastest code, so I can understand my own code(I don't understand alot of speed techniques in programming just yet.).
Oh yeah well who cares about speed?! =) The main objective is to get it working now. I'll see if I can do some own optimizations as well.
I just need to know how to emulate things, not copy code! Heh. I just want to see how it is emulated, so I can write my own code. =)

bcrew1375
February 23rd, 2005, 08:52
Hmm, as far as speed, task manager claims my emulator takes over 95% of the CPU time. Though, I seriously doubt that's correct because no other programs are slowing down.

Doomulation
February 23rd, 2005, 08:57
Doesn't matter if it runs at 10% or 90%, it still might not slow down other programs because windows shares processor power will all apps.

bcrew1375
February 23rd, 2005, 09:01
Well anyway, if you want source that badly... Don't say I didn't warn you...

Dark Stalker
February 24th, 2005, 11:58
I got some time yesterday and implemented cgb support. Most games seem to run just fine, a few end in a black screen though. I guess I've got some tweaking to look forward to. :P My palette is off by quite a bit as you might see, I'll try to find some more detailed information on how the gbc interprets colour values.


http://home.tussa.com/iaamaas/screenshots/lameboy/zeldadx.png http://home.tussa.com/iaamaas/screenshots/lameboy/warioland3.png
http://home.tussa.com/iaamaas/screenshots/lameboy/dw3-2.png http://home.tussa.com/iaamaas/screenshots/lameboy/pokemonsilver.png

Doomulation
February 24th, 2005, 12:47
Well anyway, if you want source that badly... Don't say I didn't warn you...
Oh gee, very nice! Very clean code and such.
Ah, don't worry... it will be my little reference source if I don't know how something works =)
Just one question 'bout your source, though... why do you put the definitions in the .c file?

aprentice
February 24th, 2005, 15:02
I got some time yesterday and implemented cgb support. Most games seem to run just fine, a few end in a black screen though. I guess I've got some tweaking to look forward to. :P My palette is off by quite a bit as you might see, I'll try to find some more detailed information on how the gbc interprets colour values.

http://www.darkengine.net/gb/zeldacolor.gif

In my emu, any game that uses hdma screws up at one point or another. I dont know exactly why but it does dma's from wrong locations or bad locations sometimes.

Dark Stalker
February 24th, 2005, 20:17
Hdma seems to be fine in my emu, there's something else screwing up I think. Zelda oracle games just show the very first screen, then go white. Warioland 2 just stays black, and Mega Man Xtreme shows the first screen and goes black too. I think that's all the roms that haven't worked for now, but I haven't really tested that many yet.

aprentice
February 24th, 2005, 20:54
you need to emulate the sound registers for the zelda oracle series games to work

http://www.darkengine.net/gb/oracle1.gif

bcrew1375
February 25th, 2005, 04:34
Just one question 'bout your source, though... why do you put the definitions in the .c file?

I don't know. It's just the way I've always been. I like to lump things into one file rather than splitting them up. I'm weird :P. I'm sure you'll find some parts that aren't quite so neat :P.

Oh, just to let you know, the window drawing code is broken right now, and it's not nearly as compatible as aprentice's or Dark Stalker's, but it should help you get started.

Doomulation
February 25th, 2005, 10:16
Hmm. Alright. But you do know that include files exist for the purpose of definitions right? It's pretty much the basic reason they exist. As for me, I hate it when files get so large =)

aprentice
February 25th, 2005, 18:26
Hmm. Alright. But you do know that include files exist for the purpose of definitions right? It's pretty much the basic reason they exist. As for me, I hate it when files get so large =)

same here, i have have .c/cpp and header for every category, i personally find the code more maintainable

Kronox!
February 26th, 2005, 01:20
i've read all the post and all that i can say is Wooooooow you guys are really great programmers...
i'm interested in emulation and programming but i don't have the skills (yet) maybe when i take a course (or two ) i will start my own emualation proyect

Keep up the good work

(as for my crappy english .... we speak spanish here ...Saludos desde Chile!! )

bcrew1375
February 26th, 2005, 05:25
If you want to learn programming, I'd start with C, C++ has alot of functionality you won't need for simplistic programs. In fact, most emulators are written in C. Also, aside from punctuation, your English is just fine :P.

zenogais
February 26th, 2005, 07:08
Actually, I'd recommend just the opposite, C++. C is an antiquated language, and C++ has a lot of advanced functionality which can simplify programming of just about anything, including emulators. Most people simply don't take advantage of, or are unaware of these constructs. Most colleges anymore teach C++ as it is a vast improvement over C in many areas, and the only reason "most" emulators are written in C is because that is the language their authors learned in college or feel they are most comfortable with for various reasons. Finally, if you know c++ you already know c, however if you know c you do not know c++.

Kronox!
February 26th, 2005, 09:15
MMm Makes sense... thanks , i'm learning c but i think i'm going to learn step by step
First C
then i will advance to c++ ... cause' it's too much Info! just start with c++
i would like to know the basics first... to feel a bit more confortable with the language

Kronox

bcrew1375
February 27th, 2005, 05:37
Well, after getting an FPS display implemented(thanks zenogais), I think my emu is pretty slow :P. With graphics display, I get about 80-90 FPS. Without graphics display, but with GB graphics code, I get about 400-500 FPS. With only the CPU I get 800-900 FPS. This is on a 2.4 GHz Celeron, so... yeah. :P

zenogais
February 27th, 2005, 05:53
Well, after getting an FPS display implemented(thanks zenogais), I think my emu is pretty slow :P. With graphics display, I get about 80-90 FPS. Without graphics display, but with GB graphics code, I get about 400-500 FPS. With only the CPU I get 800-900 FPS. This is on a 2.4 GHz Celeron, so... yeah. :P

Ahem, this is one of the big quarrels most people have with FPS as a measurement system. 80-90 FPS is more than adequate, most 3D games (Half-Life 2 for instance) run quite decent at 40-60 FPS.

bcrew1375
February 27th, 2005, 06:35
Yes, it runs at full speed, but it's not very optimized. That can't be a good speed for a Gameboy emu on a 2+ GHz computer. :P I wonder what the performance on slower computers would be?

zenogais
February 27th, 2005, 09:27
Yes, it runs at full speed, but it's not very optimized. That can't be a good speed for a Gameboy emu on a 2+ GHz computer. :P I wonder what the performance on slower computers would be?

Probably equal or only slightly worse would be my guess.

ShizZy
March 4th, 2005, 21:52
Howdy. I'd like to say great job to all of you - very awesome work. I'm a C programmer as well, although I'm somewhat new to the emulation field. I'm going to give a go at a GB emulator, I've been inspired by everything that I've seen here. Hopefully it'll go smoothly! :bouncy:

refraction
March 4th, 2005, 22:41
Howdy. I'd like to say great job to all of you - very awesome work. I'm a C programmer as well, although I'm somewhat new to the emulation field. I'm going to give a go at a GB emulator, I've been inspired by everything that I've seen here. Hopefully it'll go smoothly! :bouncy:


if youve never made an emulator before, id really advise you do the chip8 project a go first to give you the overall idea of how it works, chip8 to GB is a big enough step, nothing to GB is even bigger.

bcrew1375
March 5th, 2005, 04:33
if youve never made an emulator before, id really advise you do the chip8 project a go first to give you the overall idea of how it works, chip8 to GB is a big enough step, nothing to GB is even bigger.

I second that, if you've never done anything emulation related, you have no idea what you're getting yourself into. I tried doing a Gameboy emulator first, there were alot of concepts I simply couldn't grasp until I did a Chip-8 emu. If you understand assembly, registers, the stack, input/output ports, cycle counting, and the way the CPU handles instructions, then go for it.

refraction
March 5th, 2005, 12:55
I second that, if you've never done anything emulation related, you have no idea what you're getting yourself into. I tried doing a Gameboy emulator first, there were alot of concepts I simply couldn't grasp until I did a Chip-8 emu. If you understand assembly, registers, the stack, input/output ports, cycle counting, and the way the CPU handles instructions, then go for it.


not forgetting interrupts, DMA transfers and timers :P

bcrew1375
March 5th, 2005, 13:25
Thought I was forgetting something, but it was late :P. Interrupts and timers yes, but DMA transfer is nothing more than a for loop or a memcpy for most people :P.

refraction
March 5th, 2005, 13:30
Thought I was forgetting something, but it was late :P. Interrupts and timers yes, but DMA transfer is nothing more than a for loop or a memcpy for most people :P.


yeh i think thats all ive done lol, if im not mistaken the DMA register stores the first 8bits of the 16bit address yes? example if it stores 0x01 the address starts at 0x0100 (or 0x100 however you wanna write it)

bcrew1375
March 5th, 2005, 13:46
Yep, that's right. Just copy it from that address to 0xFE00. BTW, I found a really dumb bug in my code :P. In some cases, when switching MBC1 models, the correct rom bank wasn't copied in :plain:. Unfortunately, it seemed to do squat for compatibility.

aprentice
March 5th, 2005, 23:56
Yep, that's right. Just copy it from that address to 0xFE00. BTW, I found a really dumb bug in my code :P. In some cases, when switching MBC1 models, the correct rom bank wasn't copied in :plain:. Unfortunately, it seemed to do squat for compatibility.

so is mario land 2 running for you yet? :P

bcrew1375
March 6th, 2005, 02:48
Nope, like I said, it seemed to do squat for compatibility :plain:. Mario Land 2 seems to jump into the rom bank space at one point when there is nothing but 0's in it. I was hoping the bug I mentioned was the cause of this, but nope :(.

aprentice
March 6th, 2005, 03:41
Nope, like I said, it seemed to do squat for compatibility :plain:. Mario Land 2 seems to jump into the rom bank space at one point when there is nothing but 0's in it. I was hoping the bug I mentioned was the cause of this, but nope :(.

So what DarkStalker mentioned didn't fix it for you?

bcrew1375
March 6th, 2005, 05:56
Nope, I had already been doing that, if you mean allowing the interrupt when the display is disabled. I don't even make it past the title screen. It's fine until I press start.

aprentice
March 6th, 2005, 06:14
Nope, I had already been doing that, if you mean allowing the interrupt when the display is disabled. I don't even make it past the title screen. It's fine until I press start.

oh okay, I had the same exact problem and it fixed it for me. Have you checked through every single opcode with a fine needle?

Too bad that there isnt a diagnostic rom that does this :P

bcrew1375
March 6th, 2005, 06:39
No, but I plan to. Hehe, I was thinking the same thing about the diagnostics rom until I realized it wouldn't run if the opcodes weren't correct anyways :P.

Hehe, found a really, REALLY dumb bug. Because of some certain variables, I was denying rom bank switches in ROMS with MBC3, MBC4, and MBC5. That of course doesn't fix Mario Land 2. I also found another bug in Earthworm Jim. When you first start the game, Jim instantly dies, and the stage restarts.

ShizZy
March 7th, 2005, 02:25
Thanks for the advise bcrew and refraction, this really is a much bigger project than I had initially expected. Though so far, I havn't ran into anything which has slowed me down too much. I spent every waking minute this weekend coding my emulator, and I have the basic core completed. I have about 95% of the opcodes included, and about half of them have basic functionality (mostly a lot of the basic arithmetic and logical functions).

For some reason though, it's crashing on me when I try to load the ROM... I'm willing to bet it's some minescule little error in my code that's throwing everything off. I'm going to pick at it tonight, hopefully I'll have something to show for it in a few days :P

ShizZy
March 7th, 2005, 22:18
After mangling my code and such, here's where I spotted the bug... What I did was log the Opcodes for Link's Awakening (original, not the DX version). Here is what it spit out...

The first 6 Opcodes are as follows, with the functions I call...
Opcode = 0 NOP
Opcode = c3 Non-conditional JP
Opcode = cd Non-conditional CALL
Opcode = f0 LD register A with 0xFF00 + 8bit immediate value
Opcode = e0 LD 8bit immediate value + the value at 0xFF00 into register A
Opcode = cb

Following this, the following three opcodes were spit out in what seems to be an infinite loop...
Opcode = f0 (same as above)
Opcode = fe CP an 8bit immediate value with register A
Opcode = 20 (same as above)

Now, I used bcrew's source and edited his logging function to spit the op codes as well. The same first 6 ops are loaded, followed by the f0 - fe - 20 loop. But, what appears to be about a thousand opcodes in (I didn't count :P), it hits op E6. I don't think I ever get to this one, but if I do - I'd call an AND 8bit immediate value to register A.

Any one have any thoughts? Am I doing something blatantely wrong here?

refraction
March 8th, 2005, 01:03
in a wild stab in the dark, that would be an Interrupt call ;)

ShizZy
March 8th, 2005, 01:17
How wild is that stab? I'm pretty sure that I'm calling it right /sideways look/
:P

bcrew1375
March 8th, 2005, 04:53
After mangling my code and such, here's where I spotted the bug... What I did was log the Opcodes for Link's Awakening (original, not the DX version). Here is what it spit out...

The first 6 Opcodes are as follows, with the functions I call...
Opcode = 0 NOP
Opcode = c3 Non-conditional JP
Opcode = cd Non-conditional CALL
Opcode = f0 LD register A with 0xFF00 + 8bit immediate value
Opcode = e0 LD 8bit immediate value + the value at 0xFF00 into register A
Opcode = cb

Following this, the following three opcodes were spit out in what seems to be an infinite loop...
Opcode = f0 (same as above)
Opcode = fe CP an 8bit immediate value with register A
Opcode = 20 (same as above)

Now, I used bcrew's source and edited his logging function to spit the op codes as well. The same first 6 ops are loaded, followed by the f0 - fe - 20 loop. But, what appears to be about a thousand opcodes in (I didn't count :P), it hits op E6. I don't think I ever get to this one, but if I do - I'd call an AND 8bit immediate value to register A.

Any one have any thoughts? Am I doing something blatantely wrong here?

I had that same problem when I was starting out. The infinite loop is caused because you are not incrementing the LY register at 0xFF44. You need to increment it approx. every 456 clock cycles(114 machine cycles). Reset it to 0 when it passes 153. Do that, and you should make it through that loop.

Also, my old source has two small bugs in it you might want to fix. First is the SRL command function, change "if (*reg & BIT_1)" to "if (*reg & BIT_0)" Second, in the WriteMemory function, goto the if for addresses 0x4000 to 0x5FFF and move the code that says "Switch in the current ROM bank" above the if statement. I'll probably repost the fixed source in a while. I've changed a few things since then, but I don't know if it's caused any new bugs.

ShizZy
March 8th, 2005, 15:32
Big thanks bcrew. I'll check that out when I get home - hopefully it'll fix my problem. I also seemed to not be handling the v-bank interrupt properly, but I think that error should be fixed now.

ShizZy
March 8th, 2005, 22:06
Hmmm.. I'm incrementing it now. Problem is, I'm still getting that ugly crash that occurs when an infinite loop cycles improperly. It shouldn't crash like that regardless of the LY increment though, enless maybe it wasn't calling the v-bank interrupt. But I can't see how it isn't. Maybe I'm not looking hard enough :blush: Very frustrating.

aprentice
March 8th, 2005, 23:18
crashes dont happen cause of bugs in opcodes, they happen cause of you accessing protected memory :P

bcrew1375
March 9th, 2005, 04:49
Hmmm.. I'm incrementing it now. Problem is, I'm still getting that ugly crash that occurs when an infinite loop cycles improperly. It shouldn't crash like that regardless of the LY increment though, enless maybe it wasn't calling the v-bank interrupt. But I can't see how it isn't. Maybe I'm not looking hard enough :blush: Very frustrating.

Is it the same loop, or a different one? Can you post the log again? Oh, and you do realize that you are supposed to call the interrupts, not the program?

ChaosBlade
March 9th, 2005, 23:48
Wow. Thats basicly what i have to say after reading this whole thread :p
I havent read any of the GB docs yet (care to tell me which ones you're mostly using ? id like to weed out some useless ones before i might even consider starting a gb emu project) and based on what ive read in this thread, I think i might wait a bit before taking the step from something supremely simple as the chip8 to something immensly complex (in my eyes right now BEFORE reading ANY gb hardware\inner-working material) as the gameboy.

Since i dont believe in jumping in blindly (translating the docs to code really) before i understand, i guess ill wait. One other request i have is, if someone can shortly expline how to deal with timing (considering a PC is far more capable then the gb's cpu), and a few general tips could help aswell.

Thanks in advance :) (wheh, long post.)

(General Note to other people: i do believe i have adaqute programming skills, and ive coded up my chip8emu 95% on my own with little help from others, so im positive i understand it completely.)

bcrew1375
March 10th, 2005, 00:04
As far as I know, this is what everyone's been using: http://www.work.de/nocash/pandocs.htm

As far as timing, you simply count the cycles for each instruction and simply tie the interrupts and IO registers to that.

ChaosBlade
March 10th, 2005, 00:24
I understood that much from reading the thread and from zenogais, but it seems to me that its too simple just being that. Timing is a serious issue when emulating, and ive seen people comment about spending hours and even days just to fix timing, which seems odd if its just that. I could be wrong though (refer to my last post as to why :p).

bcrew1375
March 10th, 2005, 05:01
Well, there's the timing of the emulator program, and then there's the timing of the emulated system. The emulator program needs to be restricted to running only the number of cycles per second that the original CPU would allow. The Gameboy has a timer that programs use to call code at specific intervals. They are 4096, 16384, 65536, and 262144 Hertz. That means they interrupt 4096, 16384, 65536, and 262144 times per second, respectively. As far as I know, the Gameboy has a machine speed of 1.048576 MegaHertz(4.194304 Megahertz clock speed). So, you would take 1048576 / Timer frequency, and that would give you the number of cycles you need to run before calling the interrupt. Hope that's clear :P.

HyperHacker
March 10th, 2005, 05:53
Interesting how this thread (http://www.emutalk.net/showthread.php?t=13868) popped up in Similar Threads. O_o Anyway, what exactly are you supposed to do with the memory at FEA0-FEFF?

aprentice
March 10th, 2005, 07:10
Interesting how this thread (http://www.emutalk.net/showthread.php?t=13868) popped up in Similar Threads. O_o Anyway, what exactly are you supposed to do with the memory at FEA0-FEFF?

Learn to use http://www.work.de/nocash/pandocs.htm :P

HyperHacker
March 10th, 2005, 07:23
Yes, but all that says is "unusable"; what does that mean? Would it read as 00 or FF or what, and what would happen if it were written to?

bcrew1375
March 10th, 2005, 07:49
Yes, but all that says is "unusable"; what does that mean? Would it read as 00 or FF or what, and what would happen if it were written to?

It means just that, unusable. If you write to the area, it won't be written at all. If you read from it, you will get undefined data, which means the data is unknown.

Dark Stalker
March 10th, 2005, 09:00
Well, there's the timing of the emulator program, and then there's the timing of the emulated system. The emulator program needs to be restricted to running only the number of cycles per second that the original CPU would allow. The Gameboy has a timer that programs use to call code at specific intervals. They are 4096, 16384, 65536, and 262144 Hertz. That means they interrupt 4096, 16384, 65536, and 262144 times per second, respectively. As far as I know, the Gameboy has a machine speed of 1.048576 MegaHertz(4.194304 Megahertz clock speed). So, you would take 1048576 / Timer frequency, and that would give you the number of cycles you need to run before calling the interrupt. Hope that's clear :P.Not to mention video modes, lyc, serial transfer, sound, dma, rtc etc. Strict timers are simple, since it's pretty clear when to do them.

bcrew1375
March 10th, 2005, 09:55
Yeah, I always forget to mention the guts of it. And, um, I don't think you worry about the time for the DMA. You use it by writing to memory, the OAM data is copied to memory in a few microseconds, but the game waits for that to be completed before continuing. You shouldn't need to worry about timing the DMA.

ChaosBlade
March 10th, 2005, 10:27
Considering i havent worked with timing issues before im expecting trouble whenever ill grab this project up :p

Dark Stalker
March 10th, 2005, 10:29
Dma takes a certain number of clock cycles that need to be accounted for, if you are to believe the docs that insist that the cpu halts until the transfers are done. At least for hdma and gdma. Still, doing that seemed to break things, so I suspect that either the docs are wrong and the cpu doesn't halt, or they just fail to mention that everything else halts too, so that it doesn't really matter. Gnuboy hackers question dma timings too, as seen on their front page (http://gnuboy.unix-fu.org/).

Also, interestingly, some of the the video modes exist strictly for timing purposes, as the game boy screen doesn't really have a physical hblank time.

HyperHacker
March 10th, 2005, 13:33
You don't have to time the actual DMA transfer, but it has to leave the memory inaccessible for ~160 emulated microseconds and set the 'DMA complete' flag. Most games go into a tight loop in the FF80-FFFE area (the only area accessible during DMA) that waits exactly this long.

Dark Stalker
March 10th, 2005, 14:03
Yes, that's basically quoting the docs on regular oam dma transfers :P

edit: Wait a minute, there is an oam dma complete flag to set? I thought the reason the games loop for a set number of cycles was because there is no feedback on when the oam dma transfer is complete.

ShizZy
March 10th, 2005, 14:29
Yeah bcrew, it's the same loop. But, there are still a lot of things that I'm not quite sure about, so I think that I am going to do a little more work on my Chip8 emulator, and then come back to this project. I am hoping that it'll give me a firming grasp on the whole concept of emulator programming.

ChaosBlade
March 10th, 2005, 14:40
It will certaintly help - Im saying this from personal experince.

ZeroEffect
March 11th, 2005, 02:33
I'm having a little difficulty with the 8-bit ALU instructions involving HL (eg ADD A, HL). Maybe I'm just over-complication...

Is this as straight forward as adding the low 8-bits of HL to A and setting the flag appropritely (where a carry occurs on bit 7)? I've read in several places that AF is in some cases used as a 16-bit register, would this be one of those situations, and if not, what would be an example of where AF is used.

bcrew1375
March 11th, 2005, 05:04
If it's "ADD A, (HL)" that you are talking about, it means to add the memory contents at address HL to register A.

refraction
March 11th, 2005, 11:28
If it's "ADD A, (HL)" that you are talking about, it means to add the memory contents at address HL to register A.


it will be that, i know no gameboy opcode that tries to cram a 16bit register into an 8 bit one lol.

you want something like register.A = memory(register.HL);

depending on how youve laid it out

ZeroEffect
March 11th, 2005, 14:16
So anytime an ALU opcode indicates (HL) in the docs, (HL) is an address. Thx :)

Pontifice
March 11th, 2005, 16:15
all "(number)" refers to memory[number]

I'm searching a simple rom to debug a GB emulator someone knows about one ???

gunder
March 11th, 2005, 17:18
Check out www.zophar.net for some freeware roms .. also you can check www.pdroms.com. You won't find any commercial roms on either of those sites, just public domain ones. Hope this helps.

-gunder

ChaosBlade
March 11th, 2005, 18:49
Might seem like a silly question, was looking at that GB tech PDF, the $ signs account for memory addresses ? $FF00 would be 0xFF00 ?

smcd
March 11th, 2005, 19:19
Might seem like a silly question, was looking at that GB tech PDF, the $ signs account for memory addresses ? $FF00 would be 0xFF00 ?
Yup

ZeroEffect
March 13th, 2005, 00:32
Is there an contradiction in the Gameboy CPU Manual (aka Everything you always wanted to know about the GameBoy...)?

From the I/O Registers section for TMA($FF06), the doc indicates "When TIMA overflows, this data will be loaded"

Whereas in the Timer section, the document mentions that TMA is used to divide the value of the clock set in TIMA.

In Otaku's cribsheet DIV($FF04) is indicated as the Timer Divider register.

What is the correct use of these registers?

Pontifice
March 16th, 2005, 12:03
Now i get something ---> some sprites

http://usuarios.lycos.es/pontifice/gb/gl-gb.JPG

Ufff i rewrote the cpu core two times and the bug was in the drawing routine, first i wasn't drawing anything, second i made a 10x zoom.


Thanks bcrew1375 your sources clarified many things about gb to me

bcrew1375
March 16th, 2005, 19:31
Glad they helped, just don't take them as completely accurate :P.

ChaosBlade
March 18th, 2005, 14:17
Well, update, i guess ill have to wait with this project for now. started boot camp this week, so no time to program and my muscles are in no state to code :p

Nice to see all of you guys progress tho, im waiting to see your names in some upcoming next-gen cool emnlation project ;)

LinkOfTime
March 19th, 2005, 00:40
I have a question about a GB emu I am making...
How do you draw the pixels of the GB to the screen?
For now I use the DirectDraw DrawBox method for each pixel but screen refresh is waaaaayyy too long using that method (about 0.3 fps)...
Note that I want to be able the change the screen's size, hence, the pixels size...
Thanks for the help :)

zenogais
March 19th, 2005, 03:10
You draw during VBlank interrupt so that your emulator doesn't run so slow, and until the VBlank interrupt you merely draw the scanlines out to video memory allocated by your emulator. When the VBlank interrupt occurs you loop through that buffer and draw all of the data in it.

LinkOfTime
March 19th, 2005, 11:20
Well, that's more or less what I have been doing... I made it draw the screens every 70244 (more or less, don't remember the exact number) clock cycles... Meaning, every VBlank interrupt...

bcrew1375
March 20th, 2005, 00:27
Well, that's more or less what I have been doing... I made it draw the screens every 70244 (more or less, don't remember the exact number) clock cycles... Meaning, every VBlank interrupt...

What kind of computer do you have? CPU Speed, RAM, etc...

LinkOfTime
March 20th, 2005, 08:17
Well, I don't think the speed of the computer has much to do with the speed of the emulator because today's computers should be fast enough to run those the old Gameboy's emulators, but anyway... My computer is a Pentium 3 - 1000 MHz, 256 MB of ram, 64 MB of video ram... Well, hope I wrote everything important :)

zenogais
March 20th, 2005, 23:56
I would say find a different method than DrawBox as thats probably a very slow method for drawing rectangles.

bcrew1375
March 21st, 2005, 07:29
I apparently just "fixed" a big bug. However, it seems to contradict what I have read on the system. When the LY register passes 153, I was resetting it to 0. Just for the heck of it, I decided to remove the part that resets it to 0. For some reason that fixed the instant dying bug in Earthworm Jim, and made Pokemon Gold and Silver (partially) playable. So, my question is, do you guys reset the LY register yourself when it passes 153, or is the game supposed to do it?

BTW, aprentice, this still hasn't fixed Mario Land 2 for me :P. However, it did change the errors that are occuring, and it doesn't freeze my emulator now.

zenogais
March 21st, 2005, 07:44
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?

bcrew1375
March 21st, 2005, 07:53
You're welcome :P. I'd really like to know how Dark Stalker and aprentice are handling the LY register. About the drawing, I've just been using the numbers 0-3. I look at the two bits, get the palette index, and store the number in the palette in my screenbuffer. So, 0, 1, 2, and 3 are the colors white, light grey, dark grey, and black, respectively.

Hmm, this is weird. An extract from my log of Mario Land 2:



PC = 350 SP = a8fb AF = 3370 BC = 0 DE = 2be5 HL = 2be5 Interrupts = 1 FF80 = 0
PC = 352 SP = a8fb AF = 3370 BC = 0 DE = 2be5 HL = 2be5 Interrupts = 1 FF80 = 0
PC = 354 SP 8HL = a8fd Interrupts = 1 FF80 = 0
PC = 54dc SP = a8fd AF = 20 BC = c4f9 DE = 9a08 HL = a8fd Interrupts = 1 FF80 = 0
PC = 54dd SP = a8fd AF = c400 BC = c4f9 DE = 9a08 HL = a8fd Interrupts = 1 FF80 = 0


Notice the "hiccup"? I call a function to write to the log that is just a bunch of "fprintf"'s. Why would it suddenly cut that section? Nothing else is called. Would this be a Windows problem?

zenogais
March 21st, 2005, 08:01
It can sometimes happen if you print some weird non-character value such as delete or backspace. All depends on how you're fprintf'ing though. Definately unusual. As for the drawing I thinking your system would make it easier to do both GameBoy and ColorGameboy drawing, so I think I'll use that :) And for anyone who cares, a NeoGameBoy status update - I'm currently rewriting major chunks, and am almost done. The rewriting was a necessity in order to integrate NeoGameBoy with Neologism (An API for simplifying emulator creation) and because timing/interrupts weren't implemented properly and would have required major rewrites anyway. Hopefully we can join you guys who have graphics working soon :icecream:

Dark Stalker
March 21st, 2005, 12:24
So, my question is, do you guys reset the LY register yourself when it passes 153, or is the game supposed to do it?
I think you can be pretty certain that the hardware wraps LY around after 153.

Update on progress:
I haven't had as much time lately, but I've been fixing minor bugs when I've had the time. Most games seem to work flawlessly, with som very rare exceptions. At least one game known only to run on kigb runs on my emu :P. I've still got some open questions wrt timing, as some things are imprecisely documented. I could get just about every game running perceivingly perfectly with a few game-specific hacks, but I really want to do things right. Namely the game Altered Space is a very weird one, I can easily get it to run correctly with a few changes, but that's at the expense of other games (EDIT: I think I just solved it :P ).
You're definitly up for a few surprises if you go for the obvious solutions according to doc. I don't think I'll be looking at sound until I've investigated this a bit further.

http://home.tussa.com/iaamaas/screenshots/lameboy/zeldaooa1.png http://home.tussa.com/iaamaas/screenshots/lameboy/mmx_1.png
http://home.tussa.com/iaamaas/screenshots/lameboy/dkc_1.png http://home.tussa.com/iaamaas/screenshots/lameboy/warioland2_2.png

ShizZy
March 21st, 2005, 17:52
Very nice shots.

I've done some more research, and finished up my chip8 emulator... I'm going take a second stab at the GB project. My old source code is very messy, so I've decided to redo most of it. So far I have a much cleaner frame up, the api initialized, the rom loader, a nice debugger, and most of the needed memory and registers declared. A lot of fluff, but a good start to begin actually implementing the emulation and testing it. Hopefully it'll go well...

Question.. or curiousity rather: Does anyone have sound emulated? It's the only thing that I really don't have much of an idea of where to begin with. Any links to useful information on it?

aprentice
March 21st, 2005, 18:33
bccrew: are you executing 153 before you reset it?

DarkStalker: how are you so effectively tracking the bugs, can you share a few tips with the rest of us? and what obvious solutions?

aprentice
March 21st, 2005, 18:37
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



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;
}

Dark Stalker
March 21st, 2005, 21:26
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.

Dark Stalker
March 21st, 2005, 23:19
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).

aprentice
March 22nd, 2005, 00:59
nothings a spoiler, we are here to share info :P

bcrew1375
March 25th, 2005, 09:29
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.

Dark Stalker
March 25th, 2005, 15:58
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.

bcrew1375
March 25th, 2005, 20:05
Yeah, I realize that now, but it doesn't break anything, so I'm going to leave it in, just in case.

zenogais
March 28th, 2005, 09:41
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 (http://www.zenogais.net/projects) section of my website redesigned, check out the NeoGameBoy (http://www.zenogais.net/projects/NeoGameBoy) section. Hopefully I'll get stuff working since I have this whole week off :D

ShizZy
March 29th, 2005, 05:51
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:


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:


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!

bcrew1375
March 29th, 2005, 06:06
I think that would work, and I also think you should be decrementing SP after writing the values.

Pontifice
March 29th, 2005, 11:03
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



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

ShizZy
March 29th, 2005, 15:57
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:


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?

Soccr743
March 29th, 2005, 16:23
Basically add a MemoryWriteByte function to the code. Then you want to change what you put there to this:



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.

Pontifice
March 29th, 2005, 16:30
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

ShizZy
March 29th, 2005, 18:42
Thanks Soccr.. that makes sense now. And of course you write the upper byte first, because the gb cpu is high-endian, correct?

zenogais
March 29th, 2005, 22:29
doesn't matter what order you write it in as long as you read it out the same way ;)

Soccr743
March 30th, 2005, 03:48
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-----

HyperHacker
March 30th, 2005, 05:31
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
March 30th, 2005, 07:27
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?).

Soccr743
March 30th, 2005, 14:27
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-----