Giter Club home page Giter Club logo

magenboy's Introduction

MagenBoy

A GameBoy emulator developed by me.

The main goal of this project is to be able to play Pokemon on my own emulator.

Implemented Cartridges Types

  • Rom (No MBC controller)
  • MBC1
  • MBC3
  • MBC5

More will be added if neccessary (and by neccessary I mean if games I want to play will require them)

Building

Install cargo-make

cargo install cargo-make

verify you have docker or podman installed

Desktop

cargo make sdl

or with more configuration options:

cargo build --release --package magenboy_sdl --features [optional_features]

Optional features:

  • static-sdl - will link statically to sdl2, On by default
  • sdl-resample - Use the audio resampler from sdl2 library and a manual one I wrote
  • push-audio - Use a push methododlogy instead of pull for the delivery of the sound samples to sdl2
  • u16pixel - pixels are represented by 16 bits and not 32 bits

Note to turn off on by default features pass --no-default-features when building

Key bindings:

Joypad Keyboard
A X
B Z
Start S
Select A
Dpad Up Up arrow
Dpad Down Down arrow
Dpad Left Left arrow
Dpad Right Right arrow

(WIP) Raspberry Pi Baremetal (with ili9341 display and gpio buttons)

Edit the relevant settings in configuration.rs install arm-none-eabi-gcc and then run:

cargo make -e [rpi_revision] rpibm 

This command will do the folowing:

  1. Install the rust source to compile for toolchain armv7a-none-eabihf:
rustup +nightly component add rust-src

Unfurtuantly armv7a-none-eabihf is a tier3 target for the Rust compiler so building for it requires the nightly toolchain - source

Notice We install the armv7a-none-eabihf target and not the armv7a-none-eabi target, as the later doesn't have support for hardware floats.

  1. Install Cargo Binutils:
cargo install cargo-binutils
rustup component add llvm-tools-preview
  1. Builds the image

Libretro

See - LibretroDocs

Running

Desktop

magenboy [path_to_rom] [other_optional_flags]

Raspberry Pi Desktop with peripherals

See - RealMagenBoy

Optional flags

  • --file-audio - Saves the audio to a file
  • --full-screen - Full screen mode
  • --no-vsync - Disable vsync
  • --bootrom [path to bootrom file] - Specify the path for a bootrom (If not specified the emualtor will look for dmg_boot.bin at the cwd)
  • --rom-menu [path to roms folder] - Opens an interactive dialog uopn start to choose the rom from the folder Choose a game with the Joypad bindings (Dpad and A to confirm)
  • --mode [mahcine mode] - Override the auto machine detection for the game (mode can be: CGB - Gameboy color | DMG - Original Gameboy | ANY - default)
  • --shutdown-rpi - Requires rpi feature, shutdown the RPi upon shutdown of the program

Raspberry Pi Baremetal

Currently only Raspberry Pi 4 is supported using the following instructions:

  • Format a sd card and make a single FAT32 partition called boot
  • Copy the file config.txt to the root dir of the sd card
  • Copy the following files from the Raspberry Pi firmware repo onto the SD card:
  • Copy kernel7.img onto the SD card
  • Connect all the peripherals (ili9341 display and gpio buttons)
  • Insert the SD card to the RPI4 and boot it

Note: Should it not work on your RPi4, try renaming start4.elf to start.elf (without the 4) on the SD card.

QEMU

Currently Qemu doesn't support RPI4 in 32 bit mode, so in order to test it I added support for RPI2 mapping. To change to RPI2 mode build with the rpi2 feature and not the default rpi4 feature.

running with qemu:

qemu-system-arm.exe -M raspi2b -serial null -serial mon:stdio -kernel path_to_elf

Note Qemu takes the path to the elf generated by cargo not the image generated by binutils the UART output will be written to the console.

I think that not all the peripherals I use are implemented in QEMU so I used this mainly to debug boot and CPU initialization problems

GameBoy

Development Status

Games Tested

  • Pokemon Red
  • Tetris
  • Super Mario World
  • The Legend of Zelda: A Link to the Past

GameBoy Color

Developement Status

Games Tested

  • Pokemon Yellow
  • Tetris DX

Resources

Gameboy

RaspberryPi

BareMetal RaspberryPi

magenboy's People

Contributors

alloncm avatar dependabot[bot] 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

Watchers

 avatar  avatar  avatar

magenboy's Issues

Cycle accurate emulation

Currently the PPU is almost ready (line based not pixel based)
The CPU is not ready and once is ready needs to pass the passed cycles to the PPU

Note to self:

Once ready fix the MMU to block VRAM and OAM

Refactor the DMA controller

Right now the dma is inside the gb_mmu, mainly because it needs access the mmu and needs to be under the io_bus in order to expose its memory interface to the mmu.

I think that by making another bus for regular memory (addresses 0x0 - 0xFDFF) we can separate the dma implementation to its own independent structure.

Hopefully it wont harm performance :)

Improve performance

In order to run on weaker hardware I want to improve performance as much as I can.

In order to do that I opened a new branch called feature/mt, a PR will be opened soon.

In this branch I will convert the program to 2 threads (or maybe 3) in order to move the IO from the logic thread.
When doing this I need to figure out how to draw properly without busy waiting in the IO thread for new frame buffer from the emulation thread while not making the window unresponsive in case the PPU is turned off.

This be achievable with blocking function that has a timeout, when the timeout is set the function will update the UI (accept new events) and than block again for the amount of time.

Improve boot time on the RaspberryPi

Currently the setup described the RaspberryPi section takes about 15 seconds to boot, I want to cut it to 1-3 seconds to achieve an authentic feeling as much as I can.

I believe running bare metal could help achieve this goal.

This issue depends on this #123 and is used to collect all the resources in one place

Implement a FIFO PPU

This will give a better emulation accuracy and I'm believe a faster emulation too.

Allow RealMagenBoy to load new roms from a uart port

The emulator will have a port for "technician" which will allow to read logs from the uart and when choose upload new rom in the menu will allow the user to upload a rom to the gameboy.

Perhaps there will be a program from the other side which will stream the rom and communicate with the emulator

Solve the performance issue

The emulator barely runs at 120 fps without the sound implemented.

After the sound it will barely run at 60 fps (on an I7 machine)

Add quick saves

Add the option to save the state of a game anywhere I want (also support for saves in games that do not support it).

Add support for gameboy color

In order to do that there are a few areas that will need to change

  • Detect rom target machine (CGB/DMG)
  • CPU - support double speed mode, including enable and disable double speed mode
  • PPU -
    • Support the CGB pallets
    • Object priority changes in CGB mode (place in OAM memory and not X value)
    • BG map priority table
  • MMU
    • Support the expanded vram and ram
    • Support the new vram dma contoller
    • Support the CGB bootrom

Fetch the opcodes faster

I think could be done with two matches ine for the to get opcode type enum and one to run the the specific enum with the func pointer

code improvements

  • use trait default implementation in the mbc
  • try use impl instead if dyn when passing the Memory trait to the opcodes

Choose rom option

Add an folder that the user could add roma to and upon start could choose to be prompt with a menu to select a game.

Could use the dialoguer lib

Sound accuracy

Current state

The sound gets de-synced from the video over time.

In order to solve this every time Im pushing new sound to the sound device (right now to SDL) Im blocking until the samples queue is almost empty and only than pushing the buffer.

Reasons

I believe the de-syncing happens for 2 reasons:

  • Right now Im calculating the ratio of Emulator samples per actual sample with the original GB frequency.
    The problem is that since Im not stepping this amount of cycles per second but slightly more (since Im running at 60 fps and not 59.7... fps like the original GB) Im producing more samples than I have time to output.
  • Another reason for this is that Im saving the amount of samples to skip as an integer and no floating point, cause of that I might lose precision when skipping samples and could have more samples than necessary.

Proper solution

Running the emulator at the correct original fps and using float to calculate the samples to skip.

Pull audio segfaults on linux

I had those two errors on RPI linux:
When using the manual resampler:

malloc(): invalid size (unsorted)

When using sdl resampler:

free(): invalid pointer

when activating the push-audio feature the error will no longer occur

Save MBC state

The idea

In order to save the state of the game some games have an battery packed MBC that allow them to save the sate of the game to the MBC.

I want to support that and for this Ill need some way of access to the MBC from outside the gameboy (that should be multi platform).

Solution

I can drop the gameboy as the program receive close signal and only pass the MBC as & mut so Ill still have access to it after.

Screen tearing

The problem

The screen is tearing

The frame isnt being drawn in the end, but all over the place (not LY = 153 but all kinds of LY's).

Solutions

  • Accurate emulation could solve it, only the amount of opcodes needed would run until the screen would be drawn.
  • Double buffering could help with the tearing, switch the buffers only when finishing to draw.
  • Fetching the buffer only when finishing the PPU finishes to draw.

Blargg's test 11 bugs

Sound sync

Sync the sound using the callback api of sdl and not the push api.

It will grant a better performance at the cost of another thread.

Finish Raspberry pi baremetal port

There are still uncompleted tasks:

  • Merge the rpi_gpio module to the baremetal project to create a RPI project with feature to run baremetal (the peripherlas are really look alike in the code base)
  • Add support for roms-folder from the image sd card
  • Support proper shutdown from software side
  • Add support for saves
  • Support other rpi's and cpu's, currently the code is only tested on cortex-a72 (and some code assumes it compiled only for this cpu) so add support for other cpu's and arrange the code for that
    • replace the target-feature=+virtualization with target-cpu=cpu for the compiled cpu
    • Add .ifdef where necessary to add support for coretx-a53 and more
    • Add a rendering core that will handle the rendering to boost performance - Not sure if necessary (on RPI4 its not but might be on zero2)
  • More testing on hardware (hopefully get another rpi zero2)

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.