Code Monkey home page Code Monkey logo

binjgb's Introduction

Github CI Status

binjgb

A simple GB/GBC emulator.

Features

  • Runs in the browser using WebAssembly
  • Hacky-but-passable CGB support!
  • Mostly-there Super GB support!
  • Cycle accurate, passes many timing tests (see below)
  • Supports MBC1, MBC1M, MMM01, MBC2, MBC3, MBC5 and HuC1
  • Save/load battery backup
  • Save/load emulator state to file
  • Fast-forward, pause and step one frame
  • Rewind and seek to specific cycle
  • Disable/enable each audio channel
  • Disable/enable BG, Window and Sprite layers
  • Convenient Python test harness using hashes to validate
  • (WIP) Debugger with various visualizations (see below)

DMG Screenshots

Bionic Commando Donkey Kong Kirby's Dreamland 2 Mole Mania Mario's Picross Trip World Wario Land Game Boy Wars Is That a Demo in Your Pocket?

CGB Screenshots

Dragon Warrior Hamtaro Metal Gear Solid It Came From Planet Zilog Survival Kids Aevilia Toki Tori Wario 3

SGB Screenshots

Donkey Kong Kirby's Dreamland 2 Mole Mania

Debugger Screenshots

Debugger OBJ Map Tile Data Breakpoints

Embedding binjgb in your own web page

Copy the folowing files to your webserver:

  • docs/binjgb.js
  • docs/binjgb.wasm
  • docs/simple.html
  • docs/simple.js
  • docs/simple.css
  • your .gb or .gbc file

simple.html will fill the entire page, so if you don't want that, you should put it into an iframe.

The emulator will also display an on-screen gamepad if the device supports touch events.

You can configure the emulator by editing simple.js:

Constant name Description
ROM_FILENAME The path to your .gb or .gbc file
ENABLE_REWIND Whether to enable rewinding with the backspace key
ENABLE_PAUSE Whether to enable pausing with the space bar
ENABLE_SWITCH_PALETTES Whether to enable switching palettes with [ and ]
OSGP_DEADZONE How wide to make the deadzone for the onscreen gamepad, as a decimal between between 0 and 1
CGB_COLOR_CURVE How to tint the CGB colors so they look more like a real CGB.
  • 0: none
  • 1: Use Sameboy's "Emulate Hardware" colors
  • 2: Use Gambatte/Gameboy Online colors
DEFAULT_PALETTE_IDX Which palette to use by default, as an index into PALETTES
PALETTES An array of built-in palette IDs, between 0 and 83. Useful if you only want the player to switch between a few of the built-in palettes

See simple.js for more info.

Cloning

Use a recursive clone, to include the submodules:

$ git clone --recursive https://github.com/binji/binjgb

If you've already cloned without initializing submodules, you can run this:

$ git submodule update --init

Building

Requires CMake and SDL2. Debugger uses dear imgui, (included as a git submodule).

Building (Linux/Mac)

If you run make, it will run CMake for you and put the output in the bin/ directory.

$ make
$ bin/binjgb foo.gb

You can also just use cmake directly:

$ mkdir build
$ cd build
$ cmake ..
$ make

Building (Windows)

When building on Windows, you'll probably have to set the SDL2 directory:

> mkdir build
> cd build
> cmake .. -G "Visual Studio 15 2017" -DSDL2_ROOT_DIR="C:\path\to\SDL\"

Then load this solution into Visual Studio and build it. Make sure to build the INSTALL target, so the exectuables are built to the bin directory.

Building WebAssembly

You can build binjgb as a WebAssembly module. You'll need an incoming build of emscripten. See https://github.com/kripken/emscripten/wiki/WebAssembly and http://kripken.github.io/emscripten-site/docs/building_from_source/index.html#installing-from-source.

Put a symlink to Emscripten in the emscripten directory, then run make.

$ ln -s ${PATH_TO_EMSCRIPTEN} emscripten
$ make wasm

Or set Makefile variables via command line:

$ make wasm EMSCRIPTEN_CMAKE="/path/to/Emscripten.cmake"

Changing the Build Configuration

If you change the build config (e.g. update the submodules), you may need to run CMake again. The simplest way to do this is to remove the out/ directory.

$ rm -rf out/
$ make

Running

$ bin/binjgb <filename>
$ bin/binjgb-debugger <filename>

Keys:

Action Key
DPAD-UP
DPAD-DOWN
DPAD-LEFT
DPAD-RIGHT
B Z
A X
START Enter
SELECT Tab
Quit Esc
Save state F6
Load state F9
Toggle fullscreen F11
Disable audio channel 1-4 1-4
Disable BG layer B
Disable Window layer W
Disable OBJ (sprites) O
Fast-forward Lshift
Rewind Backspace
Pause Space
Step one frame N

INI file

Binjgb tries to read from binjgb.ini on startup for configuration. The following keys are supported:

# Load this file automatically on startup
autoload=filename.gb

# Set the audio frequency in Hz
audio-frequency=44100

# Set the number of audio frames per buffer
# lower=better latency, more pops/clicks
# higher=worse latency, fewer pops/clicks
audio-frames=2048

# Set to the index of a builtin palette
# (valid numbers are 0..82)
builtin-palette=0

# Force the emulator to run in DMG (original gameboy) mode.
# 0=Don't force DMG
# 1=Force DMG
force-dmg=0

# The number of video frames to display before storing a full dump of
# the emulator state in the rewind buffer. Probably best to leave this
# alone
rewind-frames-per-base-state=45

# The number of megabytes to allocate to the rewind buffer.
# lower=less memory usage, less rewind time
# higher=more memory usage, more rewind time
rewind-buffer-capacity-megabytes=32

# The speed at which to rewind the game, as a scale.
# 1=rewind at 1x
# 2=rewind at 2x
# etc.
rewind-scale=1.5

# How much to scale the emulator window at startup.
render-scale=4

# What to set the random seed to when initializing memory. Using 0
# disables memory randomization.
random-seed=0

# Whether to display the SGB border or not.
# 0=Don't display SGB border
# 1=Display SGB border, even if it doesn't exist.
sgb-border=0

The INI file is loaded before parsing the command line flags, so you can use the command line to override the values in the INI file.

Running tests

Run scripts/build_tests.py to download and build the necessary testsuites. This works on Linux and Mac, not sure about Windows.

scripts/tester.py will only run the tests that match a filter passed on the command line. Some examples:

# Run all tests
$ scripts/tester.py

# Run all tests mooneye tests
$ scripts/tester.py mooneye

# Run all gpu tests
$ scripts/tester.py gpu

Test status

See test results

binjgb's People

Contributors

anders-stripe avatar basxto avatar bbbbbr avatar binji avatar daid avatar h3nnn4n avatar pau-tomas avatar surma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

binjgb's Issues

Segmentation fault when trying to run on OSX

[anders/fix_compile_errors_on_osx] % ./bin/binjgb ~/Projects/blarggs-tests/cpu_instrs/source/test.gb
title: ""
cgb flag: CGB_FLAG_SUPPORTED
sgb flag: SGB_FLAG_NONE
cart type: CART_TYPE_MBC1
rom size: ROM_SIZE_32K
ext ram size: EXT_RAM_SIZE_NONE
header checksum: 0x66 [OK]
GL_VERTEX_SHADER ERROR: ERROR: 0:1: '' :  version '130' is not supported
ERROR: 0:2: '' :  #version required and missing.
ERROR: 0:2: 'attribute' : syntax error: syntax error

zsh: segmentation fault  ./bin/binjgb ~/Projects/blarggs-tests/cpu_instrs/source/test.gb

It appears to originate in the hard coding of the GL_VERTEX_SHADER version: https://github.com/binji/binjgb/blob/master/src/host-ui-imgui.cc#L116

However bumping that to version 150 which I believe is the current version available on my machine moves the error to an attribute syntax error:

GL_VERTEX_SHADER ERROR: ERROR: 0:2: 'attribute' : syntax error: syntax error

Vsync bug

Since commit number b18c9ac (Synchronize video to the monitor refresh rate) committed on Mar/20/2017, the Windows build runs much faster than it should.

I have tried your released binaries and I have also compiled the source code myself. Have run them on my machine and also on a virtual machine. Happens all the time.

If you haven't seen it on Linux or Mac, I'm guessing that this only happens when using the Windows build of SDL 2.

Unmatched malloc/free in `emulator_delete`

In the latest revision in function emulator_delete, file_data_delete is called to release ROM data.

binjgb/src/emulator.c

Lines 5050 to 5056 in 1e67a75

void emulator_delete(Emulator* e) {
if (e) {
xfree(e->audio_buffer.data);
file_data_delete(&e->file_data);
xfree(e);
}
}

The data is created outside the emulator, but it's released inside it, which causes unmatched malloc/free. There should be a way that allows a programmer to indicate whether the memory of ROM data is managed by emulator or its caller.

Joypad interrupt does not fire

The Lawnmower Man for Game Boy reportedly will not start unless joypad interrupts are implemented.

To reproduce:

  1. Download and unzip the attached test ROM "Telling LYs?" tellinglys-for-binjgb.zip
  2. In binjgb, load and run the ROM
  3. Press any button

Observed behavior:

Title screen does not disappear; the test cannot progress.

Expected behavior:

Display advances from title screen to conversation, and pressing other buttons advances the conversation.

(If you do issue joypad interrupts, but you don't vary the LY when they're issued, you'll get a different error message.)

Missing Z flag after add operation

I think I spotted a bug. :) Please take a look at A value and flags after add a,a at 0x01f7:

A:80 F:---- BC:0000 DE:c205 HL:0260 SP:fffc PC:01ec (cy: 548) ppu:+3 |[00]0x01ec: 18 09     jr +9          
A:80 F:---- BC:0000 DE:c205 HL:0260 SP:fffc PC:01f7 (cy: 560) ppu:+3 |[00]0x01f7: 87        add a,a        
A:00 F:---C BC:0000 DE:c205 HL:0260 SP:fffc PC:01f8 (cy: 564) ppu:+3 |[00]0x01f8: 38 08     jr c,+8        
A:00 F:---C BC:0000 DE:c205 HL:0260 SP:fffc PC:0202 (cy: 576) ppu:+3 |[00]0x0202: 28 ea     jr z,-22       
A:00 F:---C BC:0000 DE:c205 HL:0260 SP:fffc PC:0204 (cy: 584) ppu:+3 |[00]0x0204: 01 02 00  ld bc,2        

Carry is set but Zero is missing so instead making conditional jump at 0x0202 it goes straight to 0x0204 which is wrong. I checked it in BGB before opening an issue and it sets Z--C so the result is as expected. Above output is from binjgb-tester.exe win64. This is really handy util BTW!

OAM priority calculation

As per these gbdev.io docs, when it comes to drawing an OAM pixel, the Gameboy first calculates which of 2 overlapping objects has higher priority; and THEN considers the winning object's BG priority bit. This can be exploited to "mask" objects (see INTERACTION WITH "BG OVER OBJ" FLAG in the article.)

Currently on binjgb, this behavior does not occur; it calculates the BG priority bit of all objects and renders whatever is on top.

On my local version of binjgb, I was able to fix this by inserting the following lines to emulator.c:
image
image
image
which seems like a hacky solution, but you can see a working version on my demo GB game.

I'm unable to open a pull request as I'm unable to create a branch but this is the issue and a potential solution!

Huge RAM usage.

I was playing "Super Mario Bros. Deluxe (USA, Europe)" using the emulator in the website and noticed that it's using lots of RAM

SDL_INIT_EVERYTHING is not needed

Calling SDL_Init(SDL_INIT_EVERYTHING) is not needed and will fail on some systems that doesn't have all SDL components installed.

Graphics bug in Sagaia

When you fly down the screen, there is a spot where the window fills the entire screen. The issue is that the LY=LYC interrupt should be firing, but isn't. The strange thing is that normally the code sets the LYC value to something below the current LY value. When it screws up, it sets LYC to the current LY value. This should fire an interrupt, but it seems to be blocked by the internal STAT interrupt flag already being set (see stat_irq_blocking in mooneye-gb). Maybe I'm setting it wrong.

Force DMG mode?

I couldn't find it documented, so I thought I'd ask: Is there any way to force DMG mode? I'm trying to use your emulator's tracing to see where my emulator diverges, but I'm not currently aiming for CGB support.

Cube Raider doesn't work as expected

Description

When Cube Raider tries to load, it loads, but it's not correctly viewed.
This is a behavior encountered with other emus too.

Steps

Could we do something to fix this behaviour?
TBH I don't know if we can do anything for it, but it would be nice to have it working.

Incorrect CGB sprite priority

In CGB mode, sprite priority is determined by OAM address (sprite #00 being topmost, #3F being bottommost). binjgb currently uses the DMG behavior of priority being assigned by X position.

Fatass Tracker doesn't work

Description

When Fatass Tracker tries to load, it doesn't work.
It says "File size too small" and freezes.
However, with other emulators, that rom perfectly works!

Steps

  1. Go here: https://hh.gbdev.io/game/fatass
  2. Open web console
  3. It says "File size too small (required 524288, got 425984)"
  4. (optional) to test yourself, download the rom, download mgba. It works.

Could we do something to fix this behaviour?

"Black" screen in debugger

Hi,
I have a trouble: when I launch binjgb-debugger nothing happens. There is music from Game, but screen is black (gray).
When I press some keys there are some responds, but screen stays in black.

Lost Save Files

Hi there!

Let me begin by again THANKING you for helping me get this up and running on my site!

I did just run into one issue though. On Chromebooks the save file sometimes fails to load, which forces one to restart their game from the start.

Do you think you know why this is happening, and could you possibly add a patch that would allow one to save their save state as a .sav file that could be played on other emulators (or even sent to other computers)?

Thanks and let me know :D

Support CGB

  • model new registers
  • speed switch
  • banked vram
  • banked wram
  • hdma
  • new palettes (bg/obj)
  • new PPU renderer
  • try to keep it under 5k lines still!

Other stuff too, I'm sure. But this is a good start.

Browser Pre-Load Rom

Hi! I want to use this to embed an emulator on my HTML page and have it pre-load a rom of my choice.

Could you guide me as to how to do this? Thanks!

Feature request: add a .sav import/export feature

I tried by different means to download the 'db' indexedDB data.
I was able to see the base64-encoded screenshot, but the 'extram' blob, despite having a size of 131072, was always empty.

Is there anything special to do in order to import or export .sav files?

thx

Implement debug messages

GBG knows two kinds of debug messages that can be used to trace what the program is doing. They're described in the manual.

In the first kind, the message is embedded in the instructions

    ld d, d ; signals a debug message
    jr .enddebugmsg
	; the next 4 instructions specify the kind of mesage
    ld h, h
    ld h, h
   	dw $0000
    db "my message"
.enddebugmsg

The second kind loads a zero-terminated string from an address, which can be useful for dynamic messages that include runtime values.

    ld d, d
    jr .enddebugmsg
    ; the next 4 instructions specify the kind of mesage
    ld h, h
    ld h, h
    dw $0001
    dw address
    dw bank
.enddebugmsg

In BGB, these messages are displayed in a separate window.

image

This would be a nice feature, I think.

[Improvement] Capability to logging by pressing key

Hi Ben,

Could you make some change in your emulator to you can enable/disable logging by pressing a key? I mean then I run emulator with '-t' flag it starts to write in trace log, but I need to get trace log in specific time in the game. It would be nice to enable or disable logging to file by pressing a key.

Run Boot Rom

Is there a way to run the DMG Boot Rom? I am developing an emulator on a Mac and the debugger looks great but I can't find a way to run the boot rom to compare my own emulator with.

Rejects ROMs as invalid

334B is the minimum size needed. 334th Byte is the header checksum, which is the last header byte touched by the bootrom. Global checksum doesn't get verified. SIERPINSKIBOY should therefore have everything, the bootrom needs.

$ bin/binjgb testrom/sierpinskiboy.smol.cgb
/tmp/binjgb/src/emulator.c:4847: File size (334) should be a multiple of minimum rom size (32768).

TINYMIRRORBOY has the correct first half of the Nintendo logo and a correct header checksum. That's everything CGB needs to boot.

$ bin/binjgb testrom/tinymirrorboy.mirrored.32k.cgb
/tmp/binjgb/src/emulator.c:1178: Invalid ROM.

These ROMs work on Sameboy, Emulicious and BGB. And they also boot with EVERDRIVE GB X3 on my CGB-D.

make fails because of the ImGui

I cloned the repository and run make. Make failed because imgui was not present, i cd into third_party/ and cloned the imgui (https://github.com/ocornut/imgui.git). Then i run make again. This time it started to compile but it exited with these errors:


/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc: In member function ‘bool Debugger::Init(const char*, int, int, int, bool, u32, u32, bool)’:
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:127:21: error: ‘ImGuiConfigFlags_DockingEnable’ was not declared in this scope; did you mean ‘ImGuiConfigFlags_None’?
  127 |   io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                     ImGuiConfigFlags_None
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:128:6: error: ‘struct ImGuiIO’ has no member named ‘ConfigDockingWithShift’
  128 |   io.ConfigDockingWithShift = false;
      |      ^~~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc: In member function ‘void Debugger::Run()’:
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:241:18: error: ‘DockBuilderGetNode’ is not a member of ‘ImGui’
  241 |       if (ImGui::DockBuilderGetNode(dockspace_id) == nullptr) {
      |                  ^~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:242:16: error: ‘DockBuilderRemoveNode’ is not a member of ‘ImGui’
  242 |         ImGui::DockBuilderRemoveNode(dockspace_id);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:243:16: error: ‘DockBuilderAddNode’ is not a member of ‘ImGui’
  243 |         ImGui::DockBuilderAddNode(dockspace_id, ImGui::GetIO().DisplaySize);
      |                ^~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:249:16: error: ‘DockBuilderSplitNode’ is not a member of ‘ImGui’
  249 |         ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.333f, &left,
      |                ^~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:251:16: error: ‘DockBuilderSplitNode’ is not a member of ‘ImGui’
  251 |         ImGui::DockBuilderSplitNode(left, ImGuiDir_Up, 0.666f, &left_top,
      |                ^~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:253:22: error: ‘DockBuilderSplitNode’ is not a member of ‘ImGui’
  253 |         mid = ImGui::DockBuilderSplitNode(mid, ImGuiDir_Left, 0.5f, nullptr,
      |                      ^~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:255:16: error: ‘DockBuilderSplitNode’ is not a member of ‘ImGui’
  255 |         ImGui::DockBuilderSplitNode(mid, ImGuiDir_Up, 0.5f, &mid_top,
      |                ^~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:258:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  258 |         ImGui::DockBuilderDockWindow(s_emulator_window_name, left_top);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:259:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  259 |         ImGui::DockBuilderDockWindow(s_audio_window_name, left_bottom);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:260:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  260 |         ImGui::DockBuilderDockWindow(s_rewind_window_name, left_bottom);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:261:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  261 |         ImGui::DockBuilderDockWindow(s_obj_window_name, mid_top);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:262:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  262 |         ImGui::DockBuilderDockWindow(s_tiledata_window_name, mid_top);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:263:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  263 |         ImGui::DockBuilderDockWindow(s_map_window_name, mid_bottom);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:264:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  264 |         ImGui::DockBuilderDockWindow(s_disassembly_window_name, right);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:265:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  265 |         ImGui::DockBuilderDockWindow(s_memory_window_name, right);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:266:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  266 |         ImGui::DockBuilderDockWindow(s_io_window_name, right);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:267:16: error: ‘DockBuilderDockWindow’ is not a member of ‘ImGui’
  267 |         ImGui::DockBuilderDockWindow(s_rom_window_name, right);
      |                ^~~~~~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:268:16: error: ‘DockBuilderFinish’ is not a member of ‘ImGui’
  268 |         ImGui::DockBuilderFinish(dockspace_id);
      |                ^~~~~~~~~~~~~~~~~
/home/ucak/Projects/emulator/binjgb/src/debugger/debugger.cc:271:14: error: ‘DockSpace’ is not a member of ‘ImGui’
  271 |       ImGui::DockSpace(dockspace_id);
      |              ^~~~~~~~~
make[3]: *** [CMakeFiles/binjgb-debugger.dir/build.make:232: CMakeFiles/binjgb-debugger.dir/src/debugger/debugger.cc.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:171: CMakeFiles/binjgb-debugger.dir/all] Error 2
make[1]: *** [Makefile:130: all] Error 2
make: *** [Makefile:15: debug] Error 2

Implement proper mode3 behavior

I think I know how this works now, partly via Nitty gritty VRAM doc, and partly from the sprite tests in mooneye-gb. I don't think I'll have to implement the full pipeline behavior, because it's not observable outside the fetches from VRAM. (Though maybe that's not observable?)

Read sym file

The rgbds toolchain (https://github.com/rednex/rgbds) can output a .sym file, where all labels used in the assembler code are given with their location. It looks something like this.

; this is a comment
; the format is
; bank:address label
00:08f4 Start.mainloop
00:09b0 memcpy
00:09b4 memcpy.repeat
00:09b7 memcpy.start

The bgb emulator reads the file if it has the same name as the rom file (except the file extension is .sym) and displays the labels in the disassembly, which looks like this:

image

The labels are very helpful while debugging and it would be awesome if binjgb could support it.

Scaling is uneven

The scaling is uneven, possibly because of the 1-pixel black border around the screen.

Steps to reproduce

  1. Download gb240p.gb from 240p-test-mini v0.20
  2. In binjgb, load and run gb240p.gb
  3. On the second page of the menu, open Full screen stripes
  4. Set magnification to 2x or 3x
  5. Press X (bound to the A Button) several times to rotate the stripes

Observed behavior:

One stripe about 1/4th of the way from each side is one pixel narrower than the others.

Expected behavior:

All stripes have the same thickness.

sound buffer underflow at start

Don't call SDL_PauseAudio(0) until there is more data available.

Some other underflows happen occasionally too, maybe those are from locking on the audio thread? Need to investigate.

Skip audio frames while audio context is suspended

I was seeing an audio latency issue on a page with the emulator embedded, in cases when the audio context starts out in "suspended" state.

As you know, Web Audio API has an autoplay policy which can require a user gesture, such as click or keypress event, and calling resume() on the audio context, before it's in a "running" state.

The issue was that, because I'm starting the emulator immediately upon page load, audio buffers were being created while the audio context was still suspended. This happens in the Audio class, the method pushBuffer(). Every time Audio.ctx.createBuffer is called, it produces a console warning:

An AudioContext was prevented from starting automatically. It must be created or resumed after a user gesture on the page.

Then, when the audio context is "resumed" after a user gesture, it apparently starts processing all the buffered audio, causing significant audio latency in the emulator.

The solution was to avoid creating an audio buffer when the audio context is suspended.

Before this condition:

if (this.startSec >= nowSec) {
  const buffer = Audio.ctx.createBuffer(2, AUDIO_FRAMES, this.sampleRate)
  ...
}

I added a line:

if (Audio.ctx.state !== 'running') return

This is probably too small for a pull request, but I thought it could be a possible improvement for the emulator.


Just wanted to add, I'm thoroughly enjoying the emulator and its code base. Such wonderful work!

Fix DMA access rules

They're trickier than I have currently: e.g. if you DMA from VRAM to OAM, it shouldn't block the CPU (read this somewhere, can't remember where...)

Also, it should be possible to restart a DMA, so access to FF46 should be legal during DMA.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.