Skip to content

DaveTCode/GBADotnet

Repository files navigation

Gameboy Advanced Emulator - C#

This is a WIP Gameboy Advanced emulator which is nowhere near something you'd want to play actual games on.

Projects

Within this repository there are a number of projects:

  1. GameboyAdvanced.Arm.SourceGenerators - Roslyn source generators to template our various common operations in the ARM core
  2. GameboyAdvanced.CompatibilityChecker - A console application which runs the emulator against all roms in a directory and outputs 1 image per rom along with a github flavour markdown doc showing compatibility
  3. GameboyAdvanced.Core.Benchmarks - A (mostly unused) project to generate benchmarks of low level parts of the emulator
  4. GameboyAdvanced.Core.Tests - A small handful of unit tests written whilst validating the CPU. Not really used any more as test roms are more useful
  5. GameboyAdvanced.Core - The fundamental core of the emulator which provides a Device class that takes a gamepak and allows single/frame stepping
  6. GameboyAdvanced.Headless - A dotnet console application which allows running the core without a UI but has debugging commands
  7. GameboyAdvanced.Sdl2 - An SDL2 based UI for emulator which provides no features beyond running the application
  8. GameboyAdvanced.Web - A SignalR based websockets implementation of the emulator which runs the emulator on the server and passes frames to a web ui which includes some debugging information

Architecture

The core question for any low level emulator is what granularity it steps the various components. This can be done in a number of ways but the most common are:

  • 1 step per instruction
  • 1 step per memory access
  • 1 step per master clock cycle

Typically good 8 bit system (NES/GB) emulators will act at the master clock cycle level but this can be prohitibitively expensive to once working on more modern devices.

This emulator aims to step all of the components of a GBA at the master clock cycle speed, specifically it aims to accurately emulate the various signals in/out of the arm7tdmi core. Some effort has been taken to ensure that the correct signals appear on the rising/falling edge of each cycle but since the core is stepped once per master clock cycle rather than once for each of the rising/falling edge this is not reliably accurate. I don't believe that it impacts accuracy of the overarching system emulation.

The various components are then listed below with links to the code handling their step function:

Scheduler or not?

All good GBA emulators make use of a scheduler instead of single stepping components which don't need running each cycle (e.g. timers). This emulator does not have a scheduler although it's likely that I'll need to add one at some point to resolve the performance issues tracked here: #48.

Low level coding decisions

Q. Why use source generators? A. C# sadly doesn't come with a macro/preprocessor/templating system and so our only options here for e.g. ALU operations are either to write functions with loads of branches (bad performance), pre-generate a bunch of copy paste functions (even worse than what I've done) or bastardise a macro system out of source generators.

Q. Why is the code so bad it makes my eyes hurt? A. To be clear, I would slap anyone who submitted this to me for code review. Generally this emulator makes the concious decision to prioritise performance over readable code. So e.g. there's almost no inheritance or properties. I've also prioritised practicality over good practice. So everything is public scoped in order to make serializing data easy for use by the web based UI and save/load state functionality.

Test Rom Status

Group Test Status Notes
DenSinH Arm Data Processing ✔️
DenSinH Arm Any ✔️
DenSinH Thumb Data Processing ✔️
DenSinH Thumb Any ✔️
DenSinH EEPROM test ✔️ EEPROM implemented
DenSinH Flash test ✔️ Fixed banking issues and now works
Open bus Open Bus Bios Misaligned ✔️ Implemented open bus for bios and passed this and jsmolka bios tests
Marie Open Bus Bios Fixed top 4, wrong with THM but so is mgba so not that big a deal
Marie Retaddr ✔️
Fleroviux Openbuster 1/144 - smashed it (mostly because I haven't written a proper open bus rotate for LDRH)
Dead_Body cpu_test ✔️ Passes after ensuring that the rotates on the data bus are handled for misaligned reads
Wrestler arm-wrestler-fixed ✔️ Mode 0 enabled this to run. Fixed all LDR/STR/LDM/STM operations now that shifter treats RRX properly and register writebacks happen on the correct cycle. FIQ banking support required for MRS/MSR tests
JSMolka arm ✔️ Passes all tests now
JSMolka thumb ✔️ Passes everything after some shenanigans with LDM/STM special cases
JSMolka memory ✔️ Passes all memory mirror tests after implementing mirroring of relevant regions
JSMolka nes ✔️ Passed first time
JSMolka hello ✔️
JSMolka shades ✔️ Amusingly reads beyond the end of the provided ROM (w/ pipelining) so that needed fixing before it passed
JSMolka stripes ✔️
JSMolka bios ✔️
JSMolka unsafe ✔️ According to readme doesn't pass on real hardware so this is not a great test to be passing!
Panda panda ✔️
PeterLemon 3DEngine ✔️
PeterLemon Hello World ✔️ Required SWI, DMA channel 3 immediate, transparent palette color 0 and multiple palettes in same BG
PeterLemon BGMode0 ✔️ Requires "BG Tile Offset = 0, Enable Mosaic, Tiles 8BPP, BG Map Offset = 26624, Map Size = 64x64 Tiles"
PeterLemon BGMode7 ✔️ Affine backgrounds
PeterLemon BGRotZoomMode2 ✔️ Working except unimplemented mosaic
PeterLemon BGRotZoomMode3 ✔️ Works now I have affine bg backgrounds
PeterLemon BGRotZoomMode4 ✔️
PeterLemon BGRotZoomMode5 ✔️
PeterLemon OBJRotZoom4BPP ✔️ 32*64 sprite is wrong, rest are correct
PeterLemon OBJRotZoom8BPP ✔️ 8bpp sprites fixes made this work (except mosaic which is tracked elsewhere)
PeterLemon Fast Line ✔️ Ran on first attempt
PeterLemon Fast Line Clip ✔️ Ran on first attempt
PeterLemon Cylinder Map ✔️ Ran on first attempt, not clear what it showcases
PeterLemon Myst ✔️ Looks good to me although only let it play for 30s or so
PeterLemon BigBuckBunny ✔️ Fixing bg affine backgrounds made this display properly in full screen
PeterLemon BIOS - ArcTan ✔️ Passes after lots of work on timers
PeterLemon BIOS - Div ✔️ Passes after lots of work on timers
PeterLemon BIOS - Sqrt ✔️ Passes after lots of work on timers
PeterLemon Timers ✔️ Passes after implementing timer register byte reads
mgba suite See Notes.md for detailed breakdown of pass/fail
TONC Bigmap ✔️ Requires byte wide writes to PPU registers which isn't implemented
TONC Blddemo ✔️ Blending appears to work compared against mgba
TONC BM Modes ✔️ Looks weird but tested against other emulators
TONC Brin Demo ✔️ Passes with proper support for multi size tilemaps
TONC CBB Demo ✔️ mgba was wrong, I'm now right after fixing the default sprite height/width
TONC DMA Demo ✔️ Interesting hackery using HBLANK DMA to create a round window effect
TONC First ✔️ First passing test case!
TONC Hello ✔️ Calls an SWI from Thumb and then ends up executing beyond where it should in bios. Haven't checked what's happening precisely.
TONC IRQ Demo ✔️ Looking good, compared completely against mgba and correct
TONC Key Demo ✔️ Working first time it was tested
TONC M3 Demo ✔️
TONC M7 Demo ✔️ Affine backgrounds working nicely but goes blank if I rotate the screen past half way (fixed by correctly using signed 16 bit ints)
TONC M7 Demo MB ✔️ Requires affine backgrounds
TONC M7 Demo Ex ✔️ Required affine backgrounds with mid frame changes to Dmx/Dmy
TONC Mos Demo Requires mosaic
TONC OA Combo ✔️ Sprites don't appear in quite the right place, affine sprites not quite right
TONC Obj Aff ✔️ Good affine sprite test rom
TONC Obj Demo ✔️ I think this is working properly
TONC Octtest ✔️ Required affine backgrounds and sprites but now works
TONC Pageflip ✔️ Requires LYC to behave vaguely sensibly and page flipping (obviously) so those are vaguely tested
TONC Prio Demo ✔️
TONC Sbb Aff ✔️ Requires affine background
TONC Sbb Reg ✔️ Requires large backgrounds
TONC Second ✔️ fixed with bug fixes around SWI return/MSR/MRS
TONC SWI Demo ✔️ Required a really interesting interaction with PC and a load instruction which was bugged for ages
TONC SWI VSync ✔️ Tests sprite rotations based on vsync in some way
TONC Tmr Demo ✔️ Tests countdown timers by displaying as a clock, seems to work although I'm sure timer values aren't 100% correct
TONC TTE Demo ✔️ Full test of all sorts of things
TONC Txt Obj ✔️ Letters bouncing properly, looks like sprite rendering working here well
TONC Txt SE1 ✔️ Looks identical to mgba
TONC Txt SE2 ✔️ Quite tight timings to pass this
TONC Win demo ✔️ Window implemented and working (but no OBJ window bits)
beeg beeg.gba ✔️ With scanline renderer this is now fine
AGB AGB_CHECKER_TCHK10 Passes all tests on first screen but the graphics after that are all over the place
zayd prefetch abuse All wrong values, still don't have a good handle on the prefetch module
zayd dmaslow One cycle off on 3 prefetch tests so far
zayd dmamedium One cycle off on 3 prefetch tests so far
zayd dmamedium2 One cycle off on 3 prefetch tests so far
zayd dmafast ✔️
NBA IRQ Delay Was working but now displays wrong lol irq lines compared to hardware since fixes for issue #82
NBA DMA - Burst into tears ✔️ Required fixing the DMA timing to not trigger prefetch
NBA DMA - Latch ✔️
NBA DMA - Start Delay ✔️ 20 on real GBA and 20 here, fixed by getting write cycles correct
NBA Haltcnt ✔️ Pass direct and cpuset but fail on iwram and rom by 1 cycle in each case
NBA PPU - Basic Timing ✔️ HDMA doesn't bloody stop when HBlank turns off. FFS. Idiot.
NBA Timer - Start Stop ✔️ Fixed by adding 1 cycle delay from register write to stopping timer
NBA Timer - Reload ✔️ Requires a cycle delay latching more than just start bit (countup etc need the same cycle delay).

About

A C#/net core GBA emulator

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published