What's new

-

Danny

Programmer | Moderator
So, it's barely been a year since I started working on GBA emulation, but already I'm at the final steps of getting a fully functional emulator up and running. By functional, I mean just that, it'll run without exploding. The last major area to tackle is sound. The GBA basically copies the original GB sound very closely, so I'm reusing previous code I wrote for GB/GBC emulation. The real fun starts when I tackle the two digital FIFO audio channels. Hopefully by April, things will be more or less complete.

Nice work!
Have any screenshots to share with us? Always helps with motivation :)
 

Shonumi

EmuTalk Member
Not much to visually demonstrate when it comes to sound :p But yeah, I recently finished work on the GBA's special effects (brightness increase/decrease and alpha blending). It's not 100% done, but it hits the most common cases in games. While actually changing the color of the pixels themselves was easy (the formula is well documented) there were surprisingly a lot of rules about when and where to apply special effects. Here are some before and after pictures of things not working/working

  Spoiler:

iSiDwQuBJguKu.png

iZEZxTluDBjbV.png

i3Lz0lw5eNRJB.png

ifjO7LrzoskTx.png

itiUIbxoEeMie.png

ibaikwBcD4pKHn.png



A prerequisite for proper special effects handling is emulation of the GBA's so called "windows". They're basically regions of the screen where certain layers (including sprites) can be dynamically enabled or disabled inside or outside the box. Sprites can even act as masks for special effects to in OBJ Window mode, which is how you get many of the status effects in Pokemon RSE and FR/LG. LCD processing eats up a lot of CPU cycles on my machine, so I was worried that many games would choke when I added special effects, but that was not the case. My emulator still isn't optimized (I'm running a 3.8GHz i5-2500K, and many games don't break 200%) but speed will come later. Gotta focus on core emulation right now.
 

Danny

Programmer | Moderator
Not much to visually demonstrate when it comes to sound :p But yeah, I recently finished work on the GBA's special effects (brightness increase/decrease and alpha blending). It's not 100% done, but it hits the most common cases in games. While actually changing the color of the pixels themselves was easy (the formula is well documented) there were surprisingly a lot of rules about when and where to apply special effects. Here are some before and after pictures of things not working/working

  Spoiler:

iSiDwQuBJguKu.png

iZEZxTluDBjbV.png

i3Lz0lw5eNRJB.png

ifjO7LrzoskTx.png

itiUIbxoEeMie.png

ibaikwBcD4pKHn.png



A prerequisite for proper special effects handling is emulation of the GBA's so called "windows". They're basically regions of the screen where certain layers (including sprites) can be dynamically enabled or disabled inside or outside the box. Sprites can even act as masks for special effects to in OBJ Window mode, which is how you get many of the status effects in Pokemon RSE and FR/LG. LCD processing eats up a lot of CPU cycles on my machine, so I was worried that many games would choke when I added special effects, but that was not the case. My emulator still isn't optimized (I'm running a 3.8GHz i5-2500K, and many games don't break 200%) but speed will come later. Gotta focus on core emulation right now.

Very nice! Looking really good.
Keep us updated, nice to see some life in these stickies.

I've been on hiatus with my emulator project (Space invaders) for a while, too much programming at work has worn me out... Want to get back to it though.
Thanks for the inspiration :D
 

shutterbug2000

New member
Very nice! Looking really good.
Keep us updated, nice to see some life in these stickies.

I've been on hiatus with my emulator project (Space invaders) for a while, too much programming at work has worn me out... Want to get back to it though.
Thanks for the inspiration :D

How much progress have you made, just out of curiosity? I haven't made much progress(haven't really had time), but I have 10-20 opcodes done.
 

Danny

Programmer | Moderator
How much progress have you made, just out of curiosity? I haven't made much progress(haven't really had time), but I have 10-20 opcodes done.

I've implemented 50 (afaik) opcodes (the 50 (afaik) opcodes that space invaders uses). When I say implemented, I mean around 70% in total. Still a lot to do.
 
Last edited:

Rüdiger

New member
Shonumi:
That is some impressive progress, keep it up. :)

I'm still working on the second iteration of my Gameboy emulator (optimized for speed, should run on that 180MHz ARM board).
The CPU itself is done and passes all instruction tests, but the timers still have some weird issues. My new interrupt system is
much more efficient than the old one, but makes all the cycle-accurate calculations even more complicated, so debugging is
even more !!Fun!! :whistling .

Unfortunalety, most of my free time this month got replaced by unexpected work. Orginally, the plan was to have a working
prototype by the end of the month :down: .
 

Shonumi

EmuTalk Member
Interesting updates everyone. Keep working on stuff when you have the time. Eventually, all the effort absolutely becomes worth it. It's just amazing to me to be able to play my favorite games in a program I built up from scratch (well, not the APIs like SDL, but you get the idea). When I got into emulation a decade ago, I never dreamed I'd be making my own emulators like this. It always seemed like some dark magic.

For the GBA, I got Sounds 1-2 done, and Sound 3 is coming along nicely. I scrapped my idea of basing sound output on cycles. It was just overly complicated trying to find a way to make SDL's call-back audio functions match up to GBA cycles, so I stuck to the old method of generating samples based on seconds (as determined by the host computer). As long as fullspeed is maintained, audio+video should not desync, and at worse, the game will slowdown but the audio will keep playing at fullspeed. I don't think the DMA channels will play at its intended speed if the CPU slows down (the game won't generate the necessary samples fast enough) but I that's not an issue at this point. I'll figure out time-stretching later. Sound 4 will be easy to do, and after that I'll tackle the DMA channels.

Some games have partial sound, but GBA games relied heavily on digital samples rather than the GB style sound channels. Can't wait to hear all of my favorite tunes again (looking at you, Golden Sun).
 

Shonumi

EmuTalk Member
[MENTION=110839]Flerovium[/MENTION] - Sorry to hear about your depression. I hope you're feeling better now. Let me know if I can help in any way if you need it :)

Just finished up Sound 3 finally (implemented 64-sample waveforms, proper bank switching, proper frequency calculations). Let me just say that most of the documentation on what the output frequency should be is ridiculous. If I hadn't already done a bunch of probing of the GBC, I'd still be scratching my head. I'll post these here for anyone else who scratched their heads over this:

Code:
Output frequency of Sound 3 with 32-samples -> (131072 / (2048 - X)) / 2
X is the value of bits 0 - 10 of SOUND3CNT_X


Output frequency of Sound 3 with 64-samples -> (131072 / (2048 - X)) / 4
X is the value of bits 0 - 10 of SOUND3CNT_X

That's how many times per-second the waveform is generated and played back by the hardware. Sure was hard to get a straight answer from any source I looked at.
 
F

Fanatic 64

Guest
Unfortunaly I suffered some sort of depression the last months which made it impossible to me to make big progress on my projects :(
Just in case, if you ever feel like ending your life, please call this number: 1-800-273-8255
 

Exophase

Emulator Developer
Cool thread :D

Super Mario Advance: Displays something now (was a black screen). Complains about corrupted saves; EEPROM emulation necessary.

Do you want any advice with EEPROM? I can try to explain it in a way that's clearer than GBATEK did (although this would also be a reinterpretation of gpSP code I wrote 9 years ago)

I'm still working on the second iteration of my Gameboy emulator (optimized for speed, should run on that 180MHz ARM board).

That's quite ambitious - I assume this is a Cortex-M4 board?

gpSP didn't really generally run that well on the old ARM9 GP2X clocked at 200MHz, outside of maybe some low demand games like Sonic Advance 1. But, there were many optimizations left on the table for gpSP. And it's hard to say how that compares with an M4 CPU that probably has a lot more very fast tightly integrated SRAM rather than just 16KB + 16KB L1 cache connected to relatively slow SDRAM. I'd love to talk more about optimizing GBA emulators if you or anyone else here is interested.
 

Shonumi

EmuTalk Member
Exophase said:
Do you want any advice with EEPROM? I can try to explain it in a way that's clearer than GBATEK did (although this would also be a reinterpretation of gpSP code I wrote 9 years ago)

Thanks for the offer :) I actually got EEPROM emulation working quite a while ago, around the end of November. I think the problem I had with GBATEK was that it didn't explicitly lay out what the EEPROM bitstreams looked like. I kept thinking it was more like the bitstreams used by some of the BIOS decompression functions (specifically Huffman), but the bitstream before DMA is essentially composed of halfwords, and only Bit 0 of each halfword is used for the stream. GBATEK was never explicit about this (at least not when I read it) so I had to do some digging. Now I can happily play Super Mario Advance and I can save in games like Lunar Legend.

Currently, I'm done with GBA Sound Channels 1-4. I'm in the process of emulating the 16-byte FIFO buffers. After that, it should be straightforward to output the samples through SDL. Hopefully within the next week, most games will have full sound :D
 

Exophase

Emulator Developer
Oh cool, congrats on your progress. Sound always feels kind of annoying. Especially if you're like me and forget to take off headphones while testing a totally broken first implementation.

You mentioned BIOS, are you HLEing it? I never even bothered with gpSP, but I was pretty much forced to with DraStic (my DS emulator). Well, not HLE really, more of a custom replacement BIOS. At the same time, Normmatt wrote one for GBA. It's included in ReGBA (a GBA emulator for MIPS based off of gpSP) in case anyone wants to use it: https://github.com/Nebuleon/ReGBA

I've thought about refactoring DraStic into a new GBA emulator and spent a few days working on that before I didn't really want to anymore. But maybe I'll come back to it. Mostly just for kicks, although I do think it'd be nice to have an optimized GBA emulator that can emulate 2+ GBAs locally for netplay emulation.
 

Shonumi

EmuTalk Member
For the moment, I'm HLEing the BIOS. I can run the actual dumps, but it's for show. It'll go through the logo intro, but nothing else. At the time, going HLE was easier than figuring out how to do SWIs the correct way, but now much of the infrastructure in GBE+ (my GBA emulator) can easily handle doing LLE SWIs. It's just a matter of not being lazy ;) I'll check out that GBA BIOS replacement you linked to. Looks very interesting, thanks for that.

I'm really hoping to tackle the DS after this. I wrote an article way back on internal resolution in DS emulators, and it's actually become a sort of goal of mine. I know I was saying I'd make my own DS emulator as sort of tongue-in-cheek comment, but now I'm actually serious. The GBC and GBA have been stepping stones towards it. I think I've got some goo momentum going though :p
 

Exophase

Emulator Developer
For the moment, I'm HLEing the BIOS. I can run the actual dumps, but it's for show. It'll go through the logo intro, but nothing else. At the time, going HLE was easier than figuring out how to do SWIs the correct way, but now much of the infrastructure in GBE+ (my GBA emulator) can easily handle doing LLE SWIs. It's just a matter of not being lazy ;) I'll check out that GBA BIOS replacement you linked to. Looks very interesting, thanks for that.

All the more power to you if that's what works for you. I'm kind of surprised you'd have seen it that way at the time, since emulating SWI isn't much different than emulating interrupts.

The thing that really puts me off a complete HLE solution for GBA (or DS) is the syscalls that wait for interrupts. Those will call the game's interrupt handler, then the game has to return to the syscall handler. It's not even going to use a return from interrupt instruction (like movs pc) because it's returning to the BIOS's interrupt dispatcher. So anything that looks like a normal indirect branch (technically a direct branch back into the BIOS could also work, but no game would do that) needs to be handled in a special way as an alternate non-SWI entry point. Then the exit from the SWI goes back to where the code was.

Supporting this is a lot more complex than the simple model of just having the SWI handler call a function on the spot and maybe count away some emulated CPU cycles.

I know VBA didn't actually HLE this, instead opting to have a custom function in the BIOS area that handled it. But the hex was hard-inserted as an array in the code. I'd much rather load such a thing from a file I can assemble and users can replace, at which point it made more sense to just do the whole BIOS. I'd opt to HLE some functions if there was a big performance incentive to do so, though. In gpSP I did eventually HLE the division syscall, which was by far the most frequently used one (and on PSP I could use actual division instructions to implement it) but even in games that used it the most there wasn't a real performance benefit to it.

I'm really hoping to tackle the DS after this. I wrote an article way back on internal resolution in DS emulators, and it's actually become a sort of goal of mine. I know I was saying I'd make my own DS emulator as sort of tongue-in-cheek comment, but now I'm actually serious. The GBC and GBA have been stepping stones towards it. I think I've got some goo momentum going though :p

Good luck with that! I think most other DS emulator authors have also done a GBA emulator first, it definitely helps. It's also a lot more work, but I think you know that.

If it's any indication, it took me about 3 months to get the first version of a GBA emulator out and 15 months for DS (on Pandora, more like 20 months for Android version). But both emulators were attempting to be optimized for low performance mobile platforms, and that dramatically impacted the effort needed. Especially for DS, where there's a lot more that needs to be optimized and I optimized everything a lot more thoroughly.

Cydrak on the other hand took much less time both for his work on GBA emulation in higan and DS emulator dasShiny. I don't remember exactly, but I don't think more than a few months for the latter. It helps a lot that he was very familiar with DS, coming from a homebrew background.

I remember your old internal resolution article. I'm actually working on resolution enhancement for DraStic currently. We'll see how much punishment mobile devices can take, being all software rendered. The enhancement part itself wasn't hard, the challenge is in compositing the low-res 2D with the high-res 3D, and coming up with some kind of a solution to pass high-res through capture so dual-screen 3D, multi-frame 3D and so on don't have resolution shifts.
 

Shonumi

EmuTalk Member
Exophase said:
All the more power to you if that's what works for you. I'm kind of surprised you'd have seen it that way at the time, since emulating SWI isn't much different than emulating interrupts.

Well, at the time, I had barely just gotten VBlank interrupts to work (and badly too). That was around October when the goal was to boot a commercial game as fast as I could. I didn't feel like implementing BIOS loading, so to me HLE was the more straight-forward approach. I know in many cases LLE is, but for me it was more work to get things running.

Exophase said:
The thing that really puts me off a complete HLE solution for GBA (or DS) is the syscalls that wait for interrupts. Those will call the game's interrupt handler, then the game has to return to the syscall handler. It's not even going to use a return from interrupt instruction (like movs pc) because it's returning to the BIOS's interrupt dispatcher. So anything that looks like a normal indirect branch (technically a direct branch back into the BIOS could also work, but no game would do that) needs to be handled in a special way as an alternate non-SWI entry point. Then the exit from the SWI goes back to where the code was.

Supporting this is a lot more complex than the simple model of just having the SWI handler call a function on the spot and maybe count away some emulated CPU cycles.

That's interesting to hear. I've only implemented VBlankIntrWait, but it was relatively simple to do so. As soon as the emulated CPU hits the SWI instruction, it calls the HLE'd function, and from there it basically runs the emulated hardware cycle-by-cycle (I try to run most things cycle-by-cycle, not DMAs because I have not gone over the timings + it makes no noticeable difference so far). Once the emulated LCD triggers a VBlank interrupt, the main loop jumps to interrupt handling, then eventually jumps back out and puts the PC right where it should be (after the SWI instruction). I guess other emulators are structured differently, so I won't say it's easy for anyone's project (or hard for that matter), but I didn't have too much trouble. That, and I was really, really determined to get Super Dodgeball Advance to run. :)

Exophase said:
If it's any indication, it took me about 3 months to get the first version of a GBA emulator out and 15 months for DS (on Pandora, more like 20 months for Android version). But both emulators were attempting to be optimized for low performance mobile platforms, and that dramatically impacted the effort needed. Especially for DS, where there's a lot more that needs to be optimized and I optimized everything a lot more thoroughly.

Well, in my opinion, you're a very speedy coder :D I saw how quickly you got things running for your PC-Engine emulator a few years ago. It took me two years to "conquer" GB/GBC emulation, but I guess that was due to a lack of focus. I flirted with GBA emulation last April, but serious work began in September. I'm much farther ahead than I expected (I used to think it'd be great if I could have games booting around this time), but I don't think I could push something with mostly working graphics + sound in a few months. I dunno, emu-programming is one of those things I have to pace myself with. If I do everything at once, I get obsessed with the project, lose sight of everything else. My GB to DS emulation timeline is 5 years, so...

About DS emulation, I know Desmume X432R has already accomplished one of my dreams, but there's still room to push things. Arbitrary internal resolutions, shaders, custom textures/tiles, free look features, widescreen hacks(?), music and graphics dumping, Wiimote as touchscreen pointer, and a better system to use mouse input. And that's not even some of the crazy, pie-in-the-sky stuff I'd like to see happen (connecting to Dolphin for DS-Wii wireless communication emulation, DS-DS wifi emulation, 3D support). Not saying I'll get to all of those, but it's something to aim for. Having used Dolphin for so long, I've seen how polished an emulator can be. I'd like to make a DS emulator of that same caliber.

Good luck implementing internal resolution in DraStic. I wonder how far you can push ARM and low-power Intel devices. That'll be fun to watch.
 

Exophase

Emulator Developer
That's interesting to hear. I've only implemented VBlankIntrWait, but it was relatively simple to do so. As soon as the emulated CPU hits the SWI instruction, it calls the HLE'd function, and from there it basically runs the emulated hardware cycle-by-cycle (I try to run most things cycle-by-cycle, not DMAs because I have not gone over the timings + it makes no noticeable difference so far). Once the emulated LCD triggers a VBlank interrupt, the main loop jumps to interrupt handling, then eventually jumps back out and puts the PC right where it should be (after the SWI instruction). I guess other emulators are structured differently, so I won't say it's easy for anyone's project (or hard for that matter), but I didn't have too much trouble. That, and I was really, really determined to get Super Dodgeball Advance to run. :)

The problem here is, what happens if a non-vblank interrupt occurs after VBlankIntrWait is called? You need to have logic somewhere that determines, after the interrupt returns, whether or not it needs to keep waiting for interrupts, and that's normally part of the SWI handler in the BIOS. I can't think of any outcome with this approach except the interrupt getting suppressed or the SWI returning earlier than it was supposed to, both of which have high potential of breaking the game. It's possible games worked if they didn't have other interrupts enabled or didn't have any that ever fired during that time period but I definitely wouldn't count on that always being the case. Hblank and v-count interrupts would be the biggest offenders, plus some games use DMA or timer interrupts for audio (Sword of Mana IIRC)

Regarding DMA timing, I never handled it in gpSP - that is, DMAs were effectively zero cycle. Usually this won't be a problem because the CPU's locked during DMAs. The only game I know of that needed DMA timing to work properly was GTA Advance, or at least that's what appeared to be breaking it (some race condition where things would go bad if it came out of the DMA handler before vblank or something like that). I tried implementing it at some point but it broke hblank effects with some things, so I don't think I did it right...

Well, in my opinion, you're a very speedy coder :D I saw how quickly you got things running for your PC-Engine emulator a few years ago. It took me two years to "conquer" GB/GBC emulation, but I guess that was due to a lack of focus. I flirted with GBA emulation last April, but serious work began in September. I'm much farther ahead than I expected (I used to think it'd be great if I could have games booting around this time), but I don't think I could push something with mostly working graphics + sound in a few months. I dunno, emu-programming is one of those things I have to pace myself with. If I do everything at once, I get obsessed with the project, lose sight of everything else. My GB to DS emulation timeline is 5 years, so...

Thanks ;) I don't think I'm that fast though. I was frustrated at how long Temper felt like it was taking to get anywhere. IIRC about 3 weeks before I saw anything from a commercial game, which is about the same amount of time it took with gpSP. GBA should have been a much bigger challenge since it's more complex and it was my first real emulator, but on the other hand it was much better documented and there were more emulators with debuggers to compare it against. It sounds like it only took you a couple months to reach a decent compatibility level on your GBA emulator so I don't think I was really faster than you, since 2 months is about where I switched to writing the recompilers (although I did have a fairly optimized video renderer from the start, and that bloated development time somewhat).

But, with gpSP I worked on it constantly. It was between years at grad school and I didn't have a job so I poured a ton of time into it, maybe 10+ hours a day on average. So I don't know if it's a great benchmark for anything. I never worked on anything so constantly since, what with having a job and some actual social contact.

I did a GB emulator once for a competition, got it "ready" after 24 hours straight coding (the criteria was getting a particular 5 games working properly) but I ended up having to steal the audio code from gpSP to get it to sound right. At that point we just called a draw on the competition. If you went back and did GB again now I'm sure you could do it in a similar timeframe, if you have the focus to stay up that long coding anyway. I probably no longer do.

DS was 15-20 man months for first release, but that was spread out over a long time. Like, one period roughly August 2009 to April 2010 (when I broke my wrist.. real momentum killer) and another period roughly August 2012 to February 2013 for the Pandora release, and August 2013 for the Android one. But if you don't really care about performance it shouldn't be that bad, especially if you already have a good understanding of how its 3D works. Then again, if you're too indifferent to performance it won't even run full speed on a PC.. mine didn't with the interpreter on my desktop machine (~1.8GHz Core 2 class Pentium) and that was before 3D was even implemented.

If your GBA emulator runs around 120FPS on your desktop machine now then I'd say your DS emulator will probably have to be more efficient than it is. I'd estimate that a DS emulator of similar efficiency will cost you somewhere around 6x what a GBA emulator does, both running intensive games.

About DS emulation, I know Desmume X432R has already accomplished one of my dreams, but there's still room to push things. Arbitrary internal resolutions, shaders, custom textures/tiles, free look features, widescreen hacks(?), music and graphics dumping, Wiimote as touchscreen pointer, and a better system to use mouse input. And that's not even some of the crazy, pie-in-the-sky stuff I'd like to see happen (connecting to Dolphin for DS-Wii wireless communication emulation, DS-DS wifi emulation, 3D support). Not saying I'll get to all of those, but it's something to aim for. Having used Dolphin for so long, I've seen how polished an emulator can be. I'd like to make a DS emulator of that same caliber.

Sounds interesting. Good luck with all that. Maybe we could support the same custom texture format if it takes off.

Good luck implementing internal resolution in DraStic. I wonder how far you can push ARM and low-power Intel devices. That'll be fun to watch.

Probably not so far on x86 any time soon.. the x86 recompiler isn't nearly as optimized as the ARM one and the ARM version has a bunch of hand-optimized SIMD ASM that the x86 version lacks. The latter is especially critical since it heavily impacts 3D rendering performance.

From what I've seen so far I'm pretty confident that high end mobile ARM devices (like quad core Cortex-A15, maybe higher clocked Kraits) can handle at least a lot of games with 2x2 resolution enhancement w/o frameskip. But I don't want to commit to that just yet.
 
Last edited:

Shonumi

EmuTalk Member
Exophase said:
The problem here is, what happens if a non-vblank interrupt occurs after VBlankIntrWait is called? You need to have logic somewhere that determines, after the interrupt returns, whether or not it needs to keep waiting for interrupts, and that's normally part of the SWI handler in the BIOS. I can't think of any outcome with this approach except the interrupt getting suppressed or the SWI returning earlier than it was supposed to, both of which have high potential of breaking the game. It's possible games worked if they didn't have other interrupts enabled or didn't have any that ever fired during that time period but I definitely wouldn't count on that always being the case. Hblank and v-count interrupts would be the biggest offenders, plus some games use DMA or timer interrupts for audio (Sword of Mana IIRC)

I guess I'm still having trouble seeing where the difficulty is in emulating what you've described, because I'm fairly sure I've implemented SWIs in a way that handles that case properly. For VBlankIntrWait, all I do is call a function that clocks hardware components (LCD, Timers, etc) until a VBlank interrupt is generated. This is a tight while loop, that keeps checking for the correct bit in IF, so other interrupts can be fired at this time, but it will only break for VBlanks. Once the VBlank interrupt is fired, it returns to main() (this is where the CPU runs fetch(), decode(), and execute() functions for the GBA pipeline). After execute() has done the HLE'd SWI, handle_interrupt() is immediately called, and from there the CPU begins processing the VBlank interrupt (any other interrupts generated during the previous VBlankIntrWait call are ignored because VBlank interrupts always have the highest priority).

The VBlank interrupt does its thing and returns the CPU back to the PC after the original SWI call. At this point, the SWI's done and so is the VBlank interrupt. Any additional interrupts that want to happen can do so on the instruction immediately after the SWI. Most games will clear the VBlank's flag in IF, so VBlank interrupts shouldn't happen twice (once for VBlankIntrWait, then again after the SWI). Any interrupts besides VBlank that are fired during VBlankIntrWait have to be "ignored" or "put on hold" since the GBA enters HALT mode, and it will only escape upon generating the interrupt it's looking for. But there isn't anything particularly fancy I do to get to trigger those pending interrupts. They've already been fired, so the first chance my emulator gets to run them (after the HLE'd SWI + VBlank interrupt) it jumps on it.

Exophase said:
Thanks I don't think I'm that fast though. I was frustrated at how long Temper felt like it was taking to get anywhere. IIRC about 3 weeks before I saw anything from a commercial game, which is about the same amount of time it took with gpSP. GBA should have been a much bigger challenge since it's more complex and it was my first real emulator, but on the other hand it was much better documented and there were more emulators with debuggers to compare it against. It sounds like it only took you a couple months to reach a decent compatibility level on your GBA emulator so I don't think I was really faster than you, since 2 months is about where I switched to writing the recompilers (although I did have a fairly optimized video renderer from the start, and that bloated development time somewhat).

But, with gpSP I worked on it constantly. It was between years at grad school and I didn't have a job so I poured a ton of time into it, maybe 10+ hours a day on average. So I don't know if it's a great benchmark for anything. I never worked on anything so constantly since, what with having a job and some actual social contact.

Well, I had code laying around when I started on September 20-ish, but it didn't run anything. It was very foundational though, a lot of "grunt work" necessary for getting things off the ground. First game to work was Super Dodge Ball Advance on October 9th of last year. That's almost 3 weeks, but I had been working on it before that, on and off again stuff whenever I got bored with GBC emulation. My personal goal is to make at least 1 useful commit everyday. I didn't want to go hardcore and tackle something like FLASH or EEPROM support all in one day (I think you can see how I spread it over a weekend in my commit history). Keeps me active but obsessive about the project. I have a job + I'm constantly working on a writing project that requires me to make a new chapter every week (~3.5K word count on average) so emu programming has to be a light hobby by necessity :D

Exophase said:
DS was 15-20 man months for first release, but that was spread out over a long time. Like, one period roughly August 2009 to April 2010 (when I broke my wrist.. real momentum killer) and another period roughly August 2012 to February 2013 for the Pandora release, and August 2013 for the Android one. But if you don't really care about performance it shouldn't be that bad, especially if you already have a good understanding of how its 3D works. Then again, if you're too indifferent to performance it won't even run full speed on a PC.. mine didn't with the interpreter on my desktop machine (~1.8GHz Core 2 class Pentium) and that was before 3D was even implemented.

If your GBA emulator runs around 120FPS on your desktop machine now then I'd say your DS emulator will probably have to be more efficient than it is. I'd estimate that a DS emulator of similar efficiency will cost you somewhere around 6x what a GBA emulator does, both running intensive games.

My GBA emulator is already a CPU-cycle slurping monster. There are some cases where even my 3.8 GHz i5-2500K can't maintain fullspeed. Only a few games come close to 120 FPS. I haven't even gotten to optimization yet (or recompilation for that matter). I'm going to get this to "just run" first, then worry about performance. Only a few games would run close to fullspeed on something low-spec like my mini-PC that has a Celeron 1035U (VBam/mednafen run just fine). Guess that means I just have my work cut out for me. I'm running just a basic interpreter (no ASM anywhere) and everything is run atomically based on CPU cycles (that is to say I have a clock() function that runs constantly during instruction execution and calls emulated components to do their thing for 1 cycle) which probably explains a lot as well.
 
Last edited:

Shonumi

EmuTalk Member
Glad to see you back at work Flerovium :D Keep up with the progress. Since I largely have fully-functional GBA emulator (can play through most games start to finish with minor graphical/sound issues) I'd be happy to come up with a host of test ROMs. I know I said I'd work on that before, but now that I have a better understanding of the GBA hardware and some extra time, I think I can start working on tests again. Let me know if you have anything in particular in mind.

Last night, I finally got the DMA sound channels working (have not pushed the latest commits yet to GitHub). It's not perfect but it definitely sounds like it's on the right track. Now I can focus on the GUI and integrating and refactoring my GB/GBC code. There are still plenty of sound issues to tackle, but the my main focus for March was to get it working in a playable capacity.
 

Exophase

Emulator Developer
I guess I'm still having trouble seeing where the difficulty is in emulating what you've described, because I'm fairly sure I've implemented SWIs in a way that handles that case properly. For VBlankIntrWait, all I do is call a function that clocks hardware components (LCD, Timers, etc) until a VBlank interrupt is generated. This is a tight while loop, that keeps checking for the correct bit in IF, so other interrupts can be fired at this time, but it will only break for VBlanks. Once the VBlank interrupt is fired, it returns to main() (this is where the CPU runs fetch(), decode(), and execute() functions for the GBA pipeline). After execute() has done the HLE'd SWI, handle_interrupt() is immediately called, and from there the CPU begins processing the VBlank interrupt (any other interrupts generated during the previous VBlankIntrWait call are ignored because VBlank interrupts always have the highest priority).

The VBlank interrupt does its thing and returns the CPU back to the PC after the original SWI call. At this point, the SWI's done and so is the VBlank interrupt. Any additional interrupts that want to happen can do so on the instruction immediately after the SWI. Most games will clear the VBlank's flag in IF, so VBlank interrupts shouldn't happen twice (once for VBlankIntrWait, then again after the SWI). Any interrupts besides VBlank that are fired during VBlankIntrWait have to be "ignored" or "put on hold" since the GBA enters HALT mode, and it will only escape upon generating the interrupt it's looking for. But there isn't anything particularly fancy I do to get to trigger those pending interrupts. They've already been fired, so the first chance my emulator gets to run them (after the HLE'd SWI + VBlank interrupt) it jumps on it.

What you're doing is making it so that the interrupt handler never gets called for non-vblank interrupts that happen during the wait. It's not enough that those interrupts are fired, they need to actually call the interrupt handler (if the interrupt's enabled anyway). Otherwise they won't happen until it's too late.

For example, say you have an hblank IRQ interrupt handler that does something to the scanlines like scrolls them for a wavy background effect. The normal game loop runs then calls VBlankIntrWait while the screen is still in the middle of being rendered. If you sit in a tight loop until vblank hits all of those hblanks were something should have happened are going to be missed. They may be serviced along with the vblank interrupt but by then it's too late.

If you look at 0x34C in the GBA BIOS you'll see that after coming out of a CPU halt it checks to see if the right interrupt was triggered, and if not it goes back to waiting. Nowhere does it disable other interrupts. If your emulator doesn't do this it's not doing things correctly and there are some games that will definitely break - maybe not a ton, but they're out there.

Well, I had code laying around when I started on September 20-ish, but it didn't run anything. It was very foundational though, a lot of "grunt work" necessary for getting things off the ground. First game to work was Super Dodge Ball Advance on October 9th of last year. That's almost 3 weeks, but I had been working on it before that, on and off again stuff whenever I got bored with GBC emulation. My personal goal is to make at least 1 useful commit everyday. I didn't want to go hardcore and tackle something like FLASH or EEPROM support all in one day (I think you can see how I spread it over a weekend in my commit history). Keeps me active but obsessive about the project. I have a job + I'm constantly working on a writing project that requires me to make a new chapter every week (~3.5K word count on average) so emu programming has to be a light hobby by necessity :D

That's a good work ethic. Just one commit a day can get a lot more done and keep you from losing momentum and stagnating. I wish I could always maintain at least that much.

My GBA emulator is already a CPU-cycle slurping monster. There are some cases where even my 3.8 GHz i5-2500K can't maintain fullspeed. Only a few games come close to 120 FPS. I haven't even gotten to optimization yet (or recompilation for that matter). I'm going to get this to "just run" first, then worry about performance. Only a few games would run close to fullspeed on something low-spec like my mini-PC that has a Celeron 1035U (VBam/mednafen run just fine). Guess that means I just have my work cut out for me. I'm running just a basic interpreter (no ASM anywhere) and everything is run atomically based on CPU cycles (that is to say I have a clock() function that runs constantly during instruction execution and calls emulated components to do their thing for 1 cycle) which probably explains a lot as well.

Well, you hardly need recompilation to run a DS emulator okay on a high end desktop, much less a GBA emulator. But yeah, not interleaving everything's state machine every single is a reasonable start.

Getting things to just work first without thinking about optimization is almost always the best path. Just with an emulator, you may find yourself rewriting big chunks of it later if the speed isn't enough; some parts can be hard to really improve incrementally.
 

Exophase

Emulator Developer
There was an earlier question in this thread if anyone decoded Thumb to ARM, right?

I never did this for GBA, but DraStic did it from the start so at least I can attest that it's a workable approach.

BUT, you have to be aware that some Thumb instructions can't be done in ARM directly. bl is internally split into two distinct instructions, which you have to emulate separately because some games use the sub-instructions independently (eg Golden Sun), and neither of these can be expressed as ARM instructions. In DraStic I got around this by re-encoding them in some of the unused instruction space (you probably want to make sure you're in Thumb mode if these instructions are encountered, otherwise actual invalid ARM instructions will look like them.. but I think those hang the GBA anyway...)

Also, the ldr[pc, ...] and add rd, pc, imm instructions are relative to a PC that has the second-least significant bit cleared, so you have to communicate that somehow to the ARM core (or some other way of handling it properly) rather than just using the PC as-is.
 

Top