Skip to content

About

A gameboy (CGB & DMG) emulator written in dotnet core 3.1 C#8 with SDL/NAudio

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Build Status Code Coverage

Gameboy Emulator in C# 8

Gameboy (DMG & CGB) emulator written in C#8 (dotnet core 3.1) as an educational exercise (not as a production emulator). Uses SDL2 for windowing & graphics and NAudio for playing raw audio samples.

State

  • Passing test roms section at bottom of readme
  • Most DMG games are playable, most CGB games have graphical glitches although DX style games are typically ok
  • MBC1,2,3,5 all implemented and tested

TODO

Fixes

  • Lots of test failures specified in the table below
  • Aladdin screwed up video after boot
  • Sound channel 4 is screwed up (1 & 2 seem ok if badly aliased)
  • Sounds start during copyright screen of tetris, so I've misunderstood something regarding how sounds are turned on/off. Think I need to rewrite the sound channels to call out the DAC as a separate unit

Specific

  • Complete adding integration tests for all known test roms
  • Add HDMA transfer tests
  • Test timer subsystem
  • Prevent pressing multiple buttons (just direction keys?) at a time
  • RTC for MBC3 pretends to exist but doesn't really
  • Fully update debugging spreadsheets for CGB and Audio

Ideas/Future

  • Display FPS using SDL text rendering?
  • Native debugger with winforms/wpf?
  • SGB support
  • Dot renderer rather than full line renderer
  • Proper configurable serial port support
  • IR port configuration

Known Tests

Test Pass Notes
Blargg - cpu_instrs ✅
Blargg - instr_timing ✅
Blargg - interrupt_time ✅
Blargg - mem_timing ✅
Blargg - mem_timing2 ✅
Blargg - cgb_sound ❌ All bar one fail, but this would fail on a DMG so doesn't matter overly
Blargg - dmg_sound ❌ All 12 fail, but this also fails on a CGB console so doesn't matter too much
Blargg - halt_bug ❌ Fails but no attempt to implement this bug
Blargg - oam_bug ❌ Fails but no attempt to implement this bug
Mooneye - MBC1 - bits_bank1 ✅
Mooneye - MBC1 - bits_bank2 ✅
Mooneye - MBC1 - bits_mode ✅
Mooneye - MBC1 - bits_ramg ✅
Mooneye - MBC1 - ram64kb ✅
Mooneye - MBC1 - ram256kb ✅
Mooneye - MBC1 - rom512kb ✅
Mooneye - MBC1 - rom1Mb ✅
Mooneye - MBC1 - rom2Mb ✅
Mooneye - MBC1 - rom4Mb ✅
Mooneye - MBC1 - rom8Mb ✅
Mooneye - MBC1 - rom16Mb ✅
Mooneye - MBC2 - bits_ramg ✅
Mooneye - MBC2 - bits_romb ✅
Mooneye - MBC2 - bits_unused ✅
Mooneye - MBC2 - ram ✅
Mooneye - MBC2 - rom1Mb ✅
Mooneye - MBC2 - rom2Mb ✅
Mooneye - MBC2 - rom512kb ✅
Mooneye - MBC5 - rom512kb ✅
Mooneye - MBC5 - rom1Mb ✅
Mooneye - MBC5 - rom2Mb ✅
Mooneye - MBC5 - rom4Mb ✅
Mooneye - MBC5 - rom8Mb ✅
Mooneye - MBC5 - rom16Mb ✅
Mooneye - MBC5 - rom32Mb ✅
Mooneye - MBC5 - rom64Mb ✅
Mooneye - BITS - mem_oam ✅
Mooneye - BITS - reg_f ✅
Mooneye - BITS - unused_hwio-GS ✅
Mooneye - Instr - daa ✅
Mooneye - Interrupts - ie_push ❌ Subtle bug relating to interrupt causing the PC to get put into the interrupt flag, not emulated
Mooneye - OAM_DMA - basic ✅
Mooneye - OAM_DMA - reg_read ✅
Mooneye - OAM_DMA - sources-GS ❌ Not supposed to pass on CGB, not really clear what this actually does
Mooneye - PPU - hblank_ly_scx_timing-GS ❌ Just says that the test fails without details, we do take SCX into account so this is a bit surprising
Mooneye - PPU - intr_1_2_timing-GS ❌ Register values way off what they should be
Mooneye - PPU - intr_2_0_timing ✅
Mooneye - PPU - intr_2_mode0_timing ✅
Mooneye - PPU - intr_2_mode0_timing_sprites ❌ TEST #00 FAILS
Mooneye - PPU - intr_2_mode3_timing ✅
Mooneye - PPU - intr_2_oam_ok_timing ✅
Mooneye - PPU - lcd_on_timing ❌ LY=1 when it should be 0 - maybe a more serious bug than the timing issues we know about
Mooneye - PPU - lcdon_write_timing ❌ Loads of bad assumptions cause this failure
Mooneye - PPU - stat_irq_blocking ❌ Unknown reason
Mooneye - PPU - stat_lyc_onoff ❌ Fail r1 step 1 reason unknown
Mooneye - PPU - vblank_stat_intr-GS ✅
Mooneye - Timer - div_write ✅
Mooneye - Timer - rapid_toggle ❌ "the timer circuit design causes some unexpected timer increases" - unsure what this means in the test source so likely the cause of failure
Mooneye - Timer - tim00 ✅
Mooneye - Timer - tim01 ✅
Mooneye - Timer - tim10 ✅
Mooneye - Timer - tim11 ✅
Mooneye - Timer - tim00_div_trigger ❌ Precise implementation of counts and interesting behavior of div register setting values in timer required to do this and following
Mooneye - Timer - tim01_div_trigger ❌
Mooneye - Timer - tim10_div_trigger ❌
Mooneye - Timer - tim11_div_trigger ❌
Mooneye - Timer - tima_reload ✅
Mooneye - Timer - tima_write_reloading ❌ Fails, requires non-atomic CPU ops
Mooneye - Timer - tma_write_reloading ❌ Fails, requires non-atomic CPU ops
Mooneye - General - add_sp_e_timing ✅
Mooneye - General - boot_div-dmg0 ❌ Only passes on specific model of device
Mooneye - General - boot_div-dmgABCmgb ❌ Only passes on specific model of device
Mooneye - General - boot_div-S ❌ Only passes on specific model of device
Mooneye - General - boot_div2-S ❌ Only passes on specific model of device
Mooneye - General - boot_hwio-dmg0 ❌ Only passes on specific model of device
Mooneye - General - boot_hwio-dmgABCmgb ❌ Only passes on specific model of device
Mooneye - General - boot_hwio-S ❌ Only passes on specific model of device
Mooneye - General - boot_regs-dmg0 ❌ Only passes on specific model of device
Mooneye - General - boot_regs-dmgABC ❌ Only passes on specific model of device
Mooneye - General - boot_regs-mgb ❌ Only passes on specific model of device
Mooneye - General - boot_regs-sgb ❌ Only passes on specific model of device
Mooneye - General - boot_regs-sgb2 ❌ Only passes on specific model of device
Mooneye - General - call_cc_timing ✅
Mooneye - General - call_cc_timing2 ✅
Mooneye - General - call_timing ✅
Mooneye - General - call_timing2 ✅
Mooneye - General - div_timing ✅
Mooneye - General - di_timing-GS ✅ Passes in both DMG/CGB mode when it should only pass in DMG
Mooneye - General - ei_sequence ✅
Mooneye - General - ei_timing ✅
Mooneye - General - halt_ime0_ei ✅
Mooneye - General - halt_ime0_nointr_timing ✅
Mooneye - General - halt_ime1_timing ✅
Mooneye - General - halt_ime1_timing2-GS ❌ Fails on CGB device, not sure why it fails on emulator though
Mooneye - General - if_ie_registers ✅
Mooneye - General - intr_timing ✅
Mooneye - General - jp_cc_timing ✅
Mooneye - General - jp_timing ✅
Mooneye - General - ld_hl_sp_e_timing ✅
Mooneye - General - oam_dma_restart ✅
Mooneye - General - oam_dma_start ❌ Something isn't quite right with restarting DMA?
Mooneye - General - oam_dma_timing ✅
Mooneye - General - pop_timing ✅
Mooneye - General - push_timing ✅
Mooneye - General - rapid_di_ei ✅
Mooneye - General - reti_intr_timing ✅
Mooneye - General - reti_timing ✅
Mooneye - General - ret_cc_timing ✅
Mooneye - General - ret_timing ✅
Mooneye - General - rst_timing ✅

About

A gameboy (CGB & DMG) emulator written in dotnet core 3.1 C#8 with SDL/NAudio

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages