What's new

GBA emulator in C#

gladius

New member
I was playing around with C# 2.0 a year or so ago and put together a GBA emulator in it to see what kind of speed it could get. It runs full speed w/ sound on my Athlon 64 3200, but much less than that and it will probably not be 60 fps :). All graphics functionality is emulated, but there is no gb sound channel emulation, only direct sound. The cpu core is pretty good, but there are still a few bugs lurking.

The source is released, which is why I post it here as I hope it's a relatively clean example of how to build an emulator for a decently powerful system (16Mhz Arm7, up to 4 backgrounds with alpha blending and 256 rot/scale sprites).

Check it out here:
http://www.forwardcoding.com/projects/gbaemu.html.

You will need to install managed directx runtime as well, just download the newest directx runtime and run it with: dxsetup /installmanageddx.

Edit: old webpage went down (it stayed up for 6 years!)
 
Last edited:

synch

New member
Nice! As a detail, one of the versions of my gameboy mono emulator runs on C++ managed, and is really slower than the unmanaged one, even if the latter is not optimized for my cpu, and the managed should :p
 

Doomulation

?????????????????????????
And microsoft actually thinks the .NET Framework can beat unmanaged code, as they state? What nonsense! The framework can't produce better code than if written unmanaged it appears!
 
OP
G

gladius

New member
ShizZy said:
Wow awesome - very nice work! How long did this project take you?

Thanks, it took me about 3 months working on&off on it.

As for the managed vs. unmanaged speed differential, well emulators are one place where unmanaged can *really* take advantage of it's benefits. Bounds checking on the array access for my register store&memory is actually a significant cost for example.

It's doable though, which is basically all I was trying to find out :).
 

zAlbee

Keeper of The Iron Tail
Haha, hey Gary. As soon as I saw GBA and C# I knew it was you. Glad to see you completed it, congrats. :)

By the way, I think your site just recently went down. Getting a 404 now.
 
OP
G

gladius

New member
Hey Albert! Didn't know you were interested in the emulation scene, cool stuff :).

Yeah, my old webpage seems to have gone down. Apparently I was ad-blocking (without even knowing it). Anyhow, this is the impetus for me to register my own domain, but until that's all set up the code is stored temporarily on the pocketspc page.

Edit: okay, new domain is up and running now.
 
Last edited:

refraction

PCSX2 Coder
well done! maybe you should announce this on some emulation sites ;) if you think its good enough for release, you can never have enough emus :D well, maybe N64 has enough :bouncy:
 
OP
G

gladius

New member
Hehe, this emulator has very limited mass appeal, the specs are way too high. VBA/No$GBA are something like 5-6x faster. Of course, it is the only GBA emulator with pixel shader support for rendering the screen ;). (Which in fact runs slower than software rendering currently :p)
 

refraction

PCSX2 Coder
well maybe you could work on a bit of optimisation to make it good enough for release, itll definately get you known in the community ;)
 

swtrse

New member
managed and unmanaged things related to the Emu

Doomulation said:
And microsoft actually thinks the .NET Framework can beat unmanaged code, as they state? What nonsense! The framework can't produce better code than if written unmanaged it appears!

First of all: English is not my native language so I'm sure there are some sentences that are not right or clumsy combined with some keyboarderrors ^^ it must be horrible for someone who talks english but oversee that fact. Please :(

I created an account just do comment this post ^^ so be proud :bouncy: .

If you are not interresting in boring explations how the framework works jump to ---MAIN PART


Since I use the .NET framework at work I know nealy everything worth of knowing in the Frameworks 1.0, 1.1, 2.0. You do not have to belive me, but you should think about what I am trying to tell you.
The framework is able to beat unmanaged code but there are some requrements for the statement to be true.

First of all if you think about how JIT-Compilers work JIT compiled code has to be as fast or faster then native code. Just to remember native code is machinecode that was generated once and then published. This machinecode has to be compatible to many systems and therefore can not take advantages of special features on some systems. The JIT compiler (on the system where the application runs) takes an intermediatecode and generates the macinecode just in time optimized for the system where the application is running (there is no need to be compatible to other systems). The machinecode is normaly only generated once (fist use of app or if the system changed) then stored and executed. The time is only lost when starting the app because if the application is running the source is the generated machinecode that should be as fast or faster.
Just to be complete there is no JIT compiler that supports special chipsets (MMX, SSE, SSE2, 3DNOW,..). If they are upraded someday to support that chipsets they generate faster code than now with now additional work for programmers (what are realy an good thing if I think about add MMX support to an programm...brrr)


Now to the .NET framework (and partitially to the JAVA framework).
Garbage colection (GC) only frees memory if there is enougth time (no heavy cpu load) or when it is realy need. (<-should be faster that freeing every time an object is not needed anymore)
So the question is why is the framework slower than native code even when JIT compiling is faster and GC is faster...
The answeres are:
1) GC needs more memory to work efficient. Machines that run frameworks with GC should at least have 1GB Ram better are to. If there is less ram available te GC has to free memory more often and the speed gets down. (Note: .NET GC use Stackcopy the JAVA GC Refereces, both methods have there benefites stackcopy is the saver (and newer) one. Also the .NET GC is working more efficient than the JAVA GC (no wonder if you think that there are 3 years of technology in between (can change after each new Java Version))
2) There are some things that slows the .NET Framwork down that have there reasons in the fact that there are two (incompatible) technologies side by side (Lets call it: Framework with GC / Win32(native)).

And point 2) is the main reason while managed code is "slower" than native code. (Notice: That changed with the Win2003 kernel and will be completly reversed with the VISTA core).
So you can call unmanaged (native) code from within the Framework. Therefor an wrapper is needed for most parts the wrapper can be generated automaticly, only some special wrappers are written by hand (Ex: ManagedDirectX). The automaticly generated wrappers are 10-20 Times slower that the native call of native APIs(all Win32-APIs, unmanaged dlls,...).
As you see time gets lost everytime an Windows API is called. For frequently used APIs (EX: IO Data on the screen) MS included "handwritten" wrappers that are much faster than the automaticaly generated one (x1-x1.5 times slower).
In windows 2003 Kernel .NET runtime runs in kernel mode so no wrappers are needed for API calls (that are in the .NET kernel part). This cals are as fast as there native counterparts. Whats left are the native APIs that are calle from managed code. In VISTA core the only kernelmode thats left is .NET, native code is still suportet but like .NET now in VISTA a wrapper is needet for native code to access the VISTA APIs (10-20 slower than managed calls now)
Ok enouth of the future, it's also not for sure that there will no native kernel APIs VISTA. MS can change that everytime they like better wait for the release to be sure (the betas do not have nativ APIs even when this fact is hidden).

---MAIN PART
Ok now to the main part of this post all other things are just introduction...
I studied the sourcecode of the Emulator and found some parts that slows down the emulator.
But before: gladius you did realy a great work with the emu, so what comes is nothing personal maybe you can get a few hints to make some parts faster.

As described bevore calls of unmanaged APIs are slow ergo -> [DllImport("Kernel32.dll")] <- all calls to funktions of that API are slow
The problem here is that there is not realy an other way, the only "managed" solution that could also work (not tested only thinking about) is Environment.TickCount that should (except for Win98 where one ticks 1 ms) me accurate enouth for the Timer (in WinXP 64 10000 ticks are 1 ms).

The code calles the managed directX APIs. The APIs are .NET 1.1 your code is .NET 2.0. If there is no 1.1 Framework installed the code is running in compatibiliy mode what can cost some speed. (not realy much, I don't know if it's realy noticeable ore not). If .NET 1.1 is installed the 1.1 apis are called for the Interface a small Wrapper 2.0 to 1.0 is made (cost of speed is less than if .NET 1.1 is not installed, not noticeble at all).
The best way would be to use managed DirectX APIs for .NET 2.0 -> Problem they does not exist till DX10 are out.

The memory and cpu classes are not coded for optimal performance I will now give you a few examples of some new features in .NET 2.0 that allow some codeconstructs that could be speed up the classes. Maybe it is usefull.
For fast CPU Register access think about this (works in 1.1 too) (C# code)
The Attributes are located in System.Runtime.InteropServices and can used for struct and classes (im not sure if realy working for classes but using an embeded structure is no problem)
[StructLayout(LayoutKind.Explicit, Size = 2)]
private unsafe struct Registers
{
[FieldOffset(0)]
public ushort AF;
[FieldOffset(1)]
public byte A;
[FieldOffset(0)]
public byte F;
}

For fast access memory its possible to use...(C# code)
(only works in .NET 2.0).
The Attributes are located in System.Runtime.InteropServices and can used for struct and classes (im not sure if realy working for classes but using an embeded structure is no problem)
This code need to be in an unsafe context (note that unsafe is not unmanaged that fact and the differences can be discuss if requested)
[StructLayout(LayoutKind.Explicit, Size = 0xFFFF)]
public unsafe struct Memory
{
[FieldOffset(0)]
public fixed byte complete[0xFFFF];
[FieldOffset(0)]
public fixed sbyte signedComplete[0xFFFF];
}
 
Last edited:

Doomulation

?????????????????????????
Well, I should be honored if you signed up just for that. But I still hold grudges against the Network and the fact that it will continue to run slow for some forseeable future (since many people won't even be able to upgrade to Vista because of it's outrageous requirements, plus the fact this it will probably cost lots and lots).
Pure old and c++ programming the way for me.
 

swtrse

New member
Well, I agree that in the near future there is realy nothing that beats c++ (i was an c++ programmer before).
However sooner or later unmanaged APIs are gone, just look on how many people still use Win98 (I'm one ^^ so count me in).
The main benefit you get, if you can write full managed code (only call APIs that are located in the framework) is (the Emu is an bad example thats why I'm not refering it originaly) that with existing .NET frameworks on other platforms you can run the Software in Linux(mono), Unix(mono), BSD(Rotor), MacOS(Rotor). DirectX APIs are not available at other OS than Windows so it's not realy an option for the emu but if (maybe sometimes) the DX APIs are ported to Linux, BSD and what ever there is outside too .net the emu would be very portable (with no aditional work from the programming point of view).

WindowsForm and Console applications are already 100% protable. (Except for some exotic not implemented but normlay not used functions in Mono.NET). And that is the main benefit of a framwork with JIT compiling and the reason why I code exclusively in .NET (mainly C#) in an multi OS environment since the Beta of 1.0 was out, must be over 5 years now.
 
Last edited:

Doomulation

?????????????????????????
C# has become something I despise, as well as the Network in itself, as it sacrifices power for RAD. Anyhow, Pre-Vista (and 2003 as you say), native APIs are the ones that doninate and so shall it forbee. That probably means that in Vista, everything will run 10-20x slower because microsoft throws away the native system.
Backwards compability? What's that?
Keep in mind that most programs are written with native and the Framework puts a stop to lots of things you are used to in C++, so boo to that.
 

swtrse

New member
The framework puts no stop on thinks, they just work different (and have to be code different). Backwarcompatibilty is given over the wrappers but compatibility is slow ;). That most programms are written in native code is also clear just like the step from 8bit to 16bit to 32bit to 64bit applications, always the same ^^. New technologies needs time to be etablished.
There also existing an C# native compiler from some company I can't remeber jet.
Maybe we should not discus this any furter here, looks like we get to much off topic :unsure:. Also this is discussed enougth all over the web, I will not change my mind and you wont either :flowers:.
 

Doomulation

?????????????????????????
You are correct, of course, but I will explain what you missed there. The framework puts stop to advanced coding, such as memory manipulating. You can use and cast pointers and even overwrite memory where that pointer leads to, which in short, you can't do with the framework objects. It puts a stop to such, which I do not like.

As for the backwards compability, why would you want to buy Vista when everything is still native? Vista is such a resource hog PLUS it will run all the current (okay, most of the current) programs slow due to the lack of a native win32 API. I mean, gee, HELLO? Vista puts a stop to advanced programming - when Vista becomes a must, we can all go back to Visual Basic and forget C++.
 

swtrse

New member
This is an typesafe Pointercast in C# (other ways are also possible)

public unsafe struct Memory
{
[FieldOffset(0)]
public fixed byte complete[0xFFFF];
[FieldOffset(0)]
public fixed sbyte signedComplete[0xFFFF];
}

PLZ look in your PM for furter information.

Maybe I should start writing en GB Emulator ^^
 

Toasty

Sony battery
I'm not a big fan of Microsoft or Vista, but I kind of like C# in certain situations because it's easy to write and can be used to develop certain types of programs much quicker than other languages. That said, I agree with Doomulation that it is definitely not the best-suited language for developing emulators. While C# does have some limited memory manipulation techniques, (unsafe code, pointers,) C/C++'s ability to throw in inline assembly when you need it and do special tricks with low-level processor instructions really help a lot when developing emulators. With emulators, you really need to be able to 'speak' directly to hardware to get some things done fast, and languages like C# and Java are designed to avoid just that, in the interest of making things simple and quick to develop. I still think this project is pretty neat, though, as it's an original idea and it proves that you can develop an emulator in just about any language. I bet some optimizations could improve speed a bit, too, though I can't see it competing with native emulators any time soon.
 

Top