Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebuilt WasmBoy Debugger on top of PhosphorJS #228

Merged
merged 81 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
45b49b7
Got a working rollup workflow for the debugger rebuild
torch2424 Dec 22, 2018
6009830
Moved around some files and scripts
torch2424 Dec 22, 2018
3d2cc02
Removed old preact-cli deps
torch2424 Dec 22, 2018
43b7d2f
Got phosphor working!
torch2424 Dec 23, 2018
985be0d
Added some more test changes, everything looking great!
torch2424 Dec 23, 2018
c1d97d4
Added some cleanup to debugger builds
torch2424 Dec 23, 2018
927818b
Started adding some actual usage
torch2424 Dec 23, 2018
3df549b
Got everything a lot more organized
torch2424 Dec 23, 2018
6a78272
Started allowing to load files
torch2424 Dec 23, 2018
f9016d1
Got notifications working
torch2424 Dec 23, 2018
bb9df66
Finished notifications
torch2424 Dec 24, 2018
ed92b33
Added Google Analytics
torch2424 Dec 24, 2018
15a6f25
Need to make a wasmboy component now to config wasmboy
torch2424 Dec 24, 2018
8ae8554
Got Wasmboy Playing
torch2424 Dec 25, 2018
8b5a2f6
CLeaned up CSS on the player
torch2424 Dec 25, 2018
698035e
Made the modal, but didn't test it :joy:
torch2424 Dec 25, 2018
a29281f
Working on modal css
torch2424 Dec 26, 2018
e9adec9
Tried to code, but already sleepy haha!
torch2424 Dec 26, 2018
889d088
Fixed modal styling, and player contain
torch2424 Dec 28, 2018
6448788
Moved over all of our old assets
torch2424 Dec 28, 2018
0cd384c
Fixed images, and more open source ROM styling
torch2424 Dec 28, 2018
a75223b
Got some re-rendering for the controls
torch2424 Dec 28, 2018
68ba7dc
Added google drive support
torch2424 Dec 29, 2018
79f9956
Started widget management
torch2424 Dec 29, 2018
5a6bc22
Added save and restore to widget manager
torch2424 Dec 29, 2018
9cb0c9f
Got dynamically adding / hiding widgets
torch2424 Dec 30, 2018
e3c8f23
Moved the wasmboy options into the wasmboy file
torch2424 Dec 30, 2018
a4ee88a
Tons of awesome stuff, options, and serialization
torch2424 Dec 31, 2018
2e22d2b
Made a CPU Value Table
torch2424 Dec 31, 2018
4238cc1
Got opcode stepping working great
torch2424 Jan 2, 2019
46b4d44
Finished up the CPU Control component logic
torch2424 Jan 2, 2019
ff8b743
Made Basic State Components for all other GB Elements
torch2424 Jan 2, 2019
4172d41
Almost forgot memory
torch2424 Jan 2, 2019
e172b2c
Got all the state components set up
torch2424 Jan 2, 2019
485c97d
Started testing the HomebrewHub API
torch2424 Jan 3, 2019
bbe5562
Added some more functionality
torch2424 Jan 3, 2019
2227ed2
Skeleton'd the background map
torch2424 Jan 3, 2019
c03f7df
Added the background map
torch2424 Jan 4, 2019
a84c5f3
Fixed canvas stylinh
torch2424 Jan 4, 2019
1162554
Started the tile data component
torch2424 Jan 4, 2019
2aeffd9
Fixed Sourcemaps, and finally got tile data working
torch2424 Jan 5, 2019
6fb74e8
Solved the autoplay dillemma
torch2424 Jan 5, 2019
f8eddfb
Added loading spinners for control based components
torch2424 Jan 6, 2019
98e6e1a
refacotred style importing
torch2424 Jan 6, 2019
c2bc916
Finished up the help and about components
torch2424 Jan 6, 2019
49bc1dd
Mentioned how to resize widgets
torch2424 Jan 6, 2019
037683d
Stated some mobile stuff
torch2424 Jan 6, 2019
c9b3f69
Fixed lib setCanvas
torch2424 Jan 6, 2019
5a6c151
Added the touchpad inputs
torch2424 Jan 6, 2019
dcedbbe
More mobile UI Stuff done
torch2424 Jan 7, 2019
c84c4d4
Some more small fixes
torch2424 Jan 7, 2019
6231a74
Removed extra space
torch2424 Jan 7, 2019
b65b1b9
Final about fixes
torch2424 Jan 7, 2019
1258768
Started the canvas on load overlay
torch2424 Jan 7, 2019
d617b52
more mobile ui stuff
torch2424 Jan 7, 2019
de02d87
Fnished up the beginning mobile container
torch2424 Jan 7, 2019
036ee9f
Abstracted the google drive picker
torch2424 Jan 7, 2019
7c7589d
Finished mobile UI
torch2424 Jan 7, 2019
fb8b394
Standardized padding in widgets
torch2424 Jan 9, 2019
f400a3e
More general fixes for stability
torch2424 Jan 9, 2019
e71845c
Added a on loaded and started analytics
torch2424 Jan 9, 2019
ba087eb
Finished up our analytics implementation
torch2424 Jan 9, 2019
e6a9aab
Added closure for prod builds
torch2424 Jan 9, 2019
8c63107
Updated pubx
torch2424 Jan 9, 2019
d63132d
Made the bundle size smaller and fixed analytics
torch2424 Jan 9, 2019
42865ba
Fixed widgetManager restoring default on save failures
torch2424 Jan 9, 2019
36c4224
Finished debugger
torch2424 Jan 9, 2019
21131bf
Fixed broken styling from the benchmark
torch2424 Jan 10, 2019
c46b4a7
Updated README, and removed old debugger
torch2424 Jan 10, 2019
70fa95f
Fixing up header images
torch2424 Jan 10, 2019
79fed96
Updated debugger image
torch2424 Jan 10, 2019
2deae36
Still updating header images
torch2424 Jan 10, 2019
2ff0a1a
Trying to find image size
torch2424 Jan 10, 2019
027c5d6
Updated images onto same line
torch2424 Jan 10, 2019
0809c1f
Updated images size
torch2424 Jan 10, 2019
8d0c595
Images fix
torch2424 Jan 10, 2019
fab4418
Finished updating readme
torch2424 Jan 10, 2019
61052cf
Finished README Cleanup
torch2424 Jan 10, 2019
56e7986
Fixed up TOC and added benchmark image
torch2424 Jan 10, 2019
97d50aa
Removed old manifest mocing, since it is now done in rollup
torch2424 Jan 10, 2019
a9752d4
Added analytics events to the readme
torch2424 Jan 10, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 104 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,18 @@
![npm bundle size (minified)](https://img.shields.io/bundlephobia/min/wasmboy.svg)
![npm](https://img.shields.io/npm/dt/wasmboy.svg)
![GitHub](https://img.shields.io/github/license/torch2424/wasmboy.svg)
[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/torch2424)

<!--- Short Description-->

🎮👾🕹️ Gameboy Emulator Library written in Web Assembly using [AssemblyScript](https://github.com/AssemblyScript/assemblyscript), Debugger/Shell in Preact 🎮👾🕹️

**Project is still < 1.0.0. Most games are playable, but the emulator is still not very accurate. Expect bugs.**

[1.0 Roadmap Tracking Issue](https://github.com/torch2424/wasmBoy/issues/197)

[Debugger / Demo with support for mobile controls](https://torch2424.github.io/wasmBoy/)
[Core/Lib Documentation](https://github.com/torch2424/wasmBoy/wiki)

[Documentation](https://github.com/torch2424/wasmBoy/wiki)
<!-- Header Images -->

<!-- Header gif -->

![Pokemon Crystal Wasmboy Demo](./docs/images/wasmBoyPokemonCrystal.gif)
![Pokemon Crystal Wasmboy Debugger Demo](./docs/images/debuggerDesktopDemo.gif)

<!-- Generated with: https://github.com/ekalinin/github-markdown-toc -->

Expand All @@ -32,16 +27,22 @@
- [Features](#features)
- [Usage](#usage)
- [Supported Platforms](#supported-platforms)
- [Example Gifs &amp; Screenshots](#example-gifs--screenshots)
- [In-Game Screenshots](#in-game-screenshots)
- [Gameboy Support](#gameboy-support)
- [Gameboy Color Support](#gameboy-color-support)
- [Demo Applications](#demo-applications)
- [Debugger](#debugger)
- [Benchmark](#benchmark)
- [Tests](#tests)
- [Blarrg](#blarrg)
- [Mooneye](#mooneye)
- [Timing](#timing)
- [Halt](#halt)
- [Contributing](#contributing)
- [Installation](#installation)
- [CLI Commands / Npm Scripts](#cli-commands--npm-scripts)
- [Notable Projects](#notable-projects)
- [Special Thanks](#special-thanks)
- [Random Tips for new Gameboy EmuDevs](#random-tips-for-new-gameboy-emudevs)
- [Resources](#resources)

# Features
Expand Down Expand Up @@ -73,23 +74,77 @@ Documentation for the project can be found on the [WasmBoy Wiki](https://github.

Try to test and aim for support on all major browsers (Chrome, Firefox, and Safari). Also, Node support works with the [`headless` option in the WasmBoy config](https://github.com/torch2424/wasmBoy/wiki/Lib-API#wasmboyoptions), and using the [Worker Threads](https://nodejs.org/api/worker_threads.html) `--experimental-worker` flag.

# Example Gifs & Screenshots
# In-Game Screenshots

**Gameboy Support**
### Gameboy Support

![Is that a demo in your pocket](./docs/images/wasmBoyIsThatADemoInYourPocket.png) ![Megaman 2](./docs/images/wasmBoyMegaman2.png) ![Pokemon Blue](./docs/images/wasmBoyPokemonBlue.png) ![tetris](./docs/images/wasmBoyTetris.png) ![tobu tobu girl](./test/performance/testroms/tobutobugirl/tobutobugirl.gb.noPerformanceOptions.png)

**Gameboy Color Support**
### Gameboy Color Support

![Links Awakening](./docs/images/wasmBoyLinksAwakening.png) ![L s d j](./docs/images/wasmBoyLsdj.png) ![Megaman extreme 2](./docs/images/wasmBoyMegamanXtreme2.png) ![Pokemon Silver](./docs/images/wasmBoyPokemonSilver.png) ![Pokemon Yellow](./docs/images/wasmBoyPokemonYellow.png) ![back to color demo](./test/performance/testroms/back-to-color/back-to-color.gbc.noPerformanceOptions.png)

**Options & Save States**
# Demo Applications

### Debugger

[Application Link](https://wasmboy.app/)

A full debugger meant for analyzing the internals of the gameboy. Great for HomeBrew Gameboy Development, or using as a reference point for building your own GameBoy emulator. **See the gif at the top of the README for an example.**

**Features**

- Support of all Gameboy Components: CPU, PPU (Graphics), APU (Audio), Memory, Interrupts, and Timers. 🎮
- Per cycle state of each Game Boy components data, internal registers, and relevant memory addresses. 🌐
- Loaded ROM Information and parsing of the [Cartridge Header](http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header). 💾
- CPU Control options. Stepping per opcode, and breakpoints. 🧠
- Graphics Background Map, with border for current "camera" location with respect to scroll registers. 🖼️
- Graphics Tile Data, to display the loaded tiles currently loaded across all VRAM Banks. 🎨
- WasmBoy Control options. Play, Pause, Save State, and Load State. ⏯️ 📚
- Ability to log the entire WasmBoy Library Object and Memory to the DevTools Console. 🖥️
- Highly productive "Docker" layout, with snapping of widgets onto sections of the screen and tab support. ⚓
- Saved Layouts between sessions. 💠
- Help widget with tips on how to be effective in the debugger. 🙋

**Anaytics / Privacy**

[Analytics Wrapper Service](./demo/debugger/analytics.js)

Analytics is used on this application simply for performance monitoring, and tracking popularity of the applications. The following events are sent, with nothing more than the event name. The analytics provider used is [Google Analytics](https://analytics.google.com/analytics/web/).

- Whenever a new ROM is loaded, and played for the first time.
- Whether attempting to load a ROM was successful.
- Whenever a state is saved.
- Whenever a state is loaded.
- Whenever custom WasmBoy options are applied.
- Whenever the Google Drive option is selected.
- Whenever the mobile demo is manually reloaded.

**Mobile Demo**

For UI/UX reasons, on mobile the debugger is simply a web app for testing the lib. This is useful for testing a ROM on the go. For playing games, I would suggest [VaporBoy](https://vaporboy.net/). Below is an example of the mobile demo:

![Pokemon Crystal Wasmboy Mobile Demo](./docs/images/debuggerMobileDemo.gif)

### Benchmark

![Wasm boy options and save states gif](./docs/images/wasmBoySaveStateOptions.gif)
[Application Link](https://wasmboy.app/benchmark/)

**Debugger**
[Medium Article](https://medium.com/@torch2424/webassembly-is-fast-a-real-world-benchmark-of-webassembly-vs-es6-d85a23f8e193)

![was boy pokemon silver debugger demo](./docs/images/wasmBoyPokemonSilverDebugger.gif)
Since WasmBoy is built in AssemblyScript, it can also run it's core through the Typescript compiler if we mock out some of the WebAssembly interface. The benchmarking tool was built as a way to compare WebAssembly performance to Javascript / ES6 performance, after compiling the core to both WebAssembly and Javascript. It includes detailed stats, live running output, and multiple graphs. Also great for comparing the performance of devices that run WasmBoy.

**Anaytics / Privacy**

Analytics is used on this application simply for performance monitoring, and tracking popularity of the application. The following events are sent, with nothing more than the event name. The analytics provider used is [Google Analytics](https://analytics.google.com/analytics/web/).

- Whenever a new ROM is loaded from the particular source.
- Whenever the benchmark is ran.
- Whenever results are rendered for the benchmark.

**Example**

![WasmBoy Benchmark Runner Section on Safari](./docs/images/benchmarkSafariBackToColorRunner.png)

# Tests

Expand Down Expand Up @@ -139,7 +194,7 @@ halt_ime0_ei, halt_ime0_nointr_timing, halt_ime1_timing

# Contributing

Feel free to fork and submit PRs! Any help is much appreciated, and would be a ton of fun!
Feel free to fork and submit PRs! Opening an issue is reccomended before starting any development, as a discussion would be nice on the idea / feature before writing code. Any help is much appreciated, and would be a ton of fun!

### Installation

Expand All @@ -149,61 +204,68 @@ Just your standard node app. Install Node with [nvm](https://github.com/creation

The project contains three different elements.

- The `debugger` is the container for the wasmboy library, which is simply a [preact](https://github.com/developit/preact) application, generated with [preact-cli](https://github.com/developit/preact-cli).
- The `core` or `wasm` which is the web assembly module for wasmboy written in [AssemblyScript](https://github.com/AssemblyScript/assemblyscript).
- The `lib` which is the importable library of wasmboy that can be used in other projects, that adds a top level API to the `core`.
- The `demo`, which is a collection of different apps that are used for demoing purposes of the `lib` and `core`.

Each of these uses a different build process. The debugger uses [webpack](https://webpack.js.org/), the wasm uses the [AssemblyScript](https://github.com/AssemblyScript/assemblyscript) compiler CLI tool, and the lib uses [Rollup.js](https://rollupjs.org/guide/en).
Most of the build process in this project is done using [Rollup.js](https://rollupjs.org/guide/en). Each element / component of the project is configured in its own `rollup.*.js` file, and are then all used within the standard `rollup.config.js` file by the rollup CLI. Also, The `core` wasm uses the [AssemblyScript](https://github.com/AssemblyScript/assemblyscript) compiler CLI tool.

Commands for each part of the project will be prepended with their element name and a colon, e.g `debugger:[command here]`.

Common command parts are:

- `dev` / `watch` - How the project should be served and developed with tools like reloading.
- `build` - Make production builds of the component / element of the project.

Commands not prepended with a colon are meant for easily building on all of the different parts as a whole.

Not all commands are documented, only ones relevant to making changes to the library for contributions. `*` represents the category of commands, and is not an actual command.

```bash
# Command to serve the project, and watch the debugger, wasm, and lib for changes
# Uses concurrently: https://github.com/kimmobrunfeldt/concurrently
# Concurrently helps cleanup the output and organizes all three watchers/servers
npm start
# Concurrently helps cleanup the output and organizes watchers on commands that require concurrent tools

# Serve the general project for development (Watches the core, lib, and debugger)
npm run start

# Same as npm start
npm run dev

# Same as npm start
npm run watch

# Build the wasm module and the lib to be ready to be pushed to npm or released
# Build everything to be ready to be pushed to npm or released
npm run build

# Linting commands used during precommit an tests
npm run prettier:*

# Commands for building/serving the core, offers commands for building with the Assemblyscript Compiler (WASM) or Typescript (JS)
npm run core:*

# Commands for building/serving the JS lib
npm run lib:*

# Run tests in `test/accuracy/test.js`
npm run test

# Run tests in `test/performance/test.js`
npm run test:performance

# Watch the debugger (preact) project for changes and livereload
npm run debugger:watch
# All commands for testing, and are test related
npm run test:*

# Build the debugger (preact) project and serve it
npm run debugger:serve
# Commands for the building / serving the debugger
npm run debugger:*

# Build the debugger (preact) project
npm run debugger:build
# Commands for building / serving the benchmark tool
npm run benchmark:*

# Watch the wasm (AssemblyScript) *.ts files and build on changes
npm run core:watch

# Build the wasm (AssemblyScript) *.ts files, with the correct CLI flags
npm run core:build

# Watch the Wasmboy ES6 Module for changes, and build
npm run lib:watch

# Build the WasmBoy Es6 module
npm run lib:build
# Commands for building / serving all available apps in wasmboy
npm run demo:*
```

The debugger application/container for wasmboy utilizes the [preact-cli](https://github.com/developit/preact-cli/blob/master/README.md). Additional workflow commands and tips can be found there.

Using the [gh-pages](https://www.npmjs.com/package/gh-pages) for debugger/demo deployment onto gh-pages.

# Notable Projects
Expand Down
6 changes: 4 additions & 2 deletions core/debug/debug-graphics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function getLY(): i32 {
return Graphics.scanlineRegister;
}

export function drawBackgroundMapToWasmMemory(showColor: i32 = 0): void {
export function drawBackgroundMapToWasmMemory(showColor: i32): void {
// http://www.codeslinger.co.uk/pages/projects/gameboy/graphics.html
// Bit 7 - LCD Display Enable (0=Off, 1=On)
// Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
Expand Down Expand Up @@ -221,7 +221,9 @@ export function drawTileDataToWasmMemory(): void {
tileDataMapGridY * 8 + tileLineY,
0x1f * 8,
TILE_DATA_LOCATION,
true
true,
0,
-1
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions core/graphics/tiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export function drawPixelsFromLineOfTile(
outputLineY: i32,
outputWidth: i32,
wasmMemoryStart: i32,
shouldRepresentMonochromeColorByColorId: boolean = false,
paletteLocation: i32 = 0,
bgMapAttributes: i32 = -1
shouldRepresentMonochromeColorByColorId: boolean,
paletteLocation: i32,
bgMapAttributes: i32
): i32 {
// Get our number of pixels drawn
let pixelsDrawn: i32 = 0;
Expand Down
2 changes: 1 addition & 1 deletion demo/benchmark/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { h, render, Component } from 'preact';

import 'bulma/css/bulma.css';
import '../debugger/style.css';
import './style.css';
import './index.css';

import valoo from 'valoo';
Expand Down
7 changes: 4 additions & 3 deletions demo/benchmark/loadrom.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { h, Component } from 'preact';
import Portal from 'preact-portal';

import '../debugger/wasmboyFilePicker/wasmboyFilePicker.css';
import './wasmboyFilePicker.css';

// Import some functions from our lib
import { sendAnalyticsEvent } from './analytics';
import { fetchROMAsByteArray } from '../../lib/wasmboy/fetchrom.js';

// Import our open source roms from the debugger
import { openSourceROMs, getOpenSourceROMElements } from '../debugger/wasmboyFilePicker/openSourceROMs';
// Import our open source roms
import { openSourceROMS } from '../openSourceROMs';
import { getOpenSourceROMElements } from '../openSourceROMsPreact';

export default class LoadROMSelector extends Component {
constructor(props) {
Expand Down
File renamed without changes.
85 changes: 85 additions & 0 deletions demo/debugger/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import loadScript from 'load-script';

class DebuggerAnalyticsLib {
constructor() {
/*ROLLUP_REPLACE_DEBUGGER_DEV
this.readyPromise = Promise.resolve();
return;
ROLLUP_REPLACE_DEBUGGER_DEV*/

this.readyPromise = new Promise((resolve, reject) => {
if (typeof window !== 'undefined') {
loadScript('https://www.googletagmanager.com/gtag/js?id=UA-125276735-1', (err, script) => {
if (err) {
reject(err);
}

window.dataLayer = window.dataLayer || [];
function gtag() {
window.dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-125276735-1');

// Attach Analytics to this class
this.gtag = gtag;
resolve();
});
} else {
reject(new Error('Not in a browser Environment'));
}
});
}

_fireAnalyticsEvent(eventAction) {
const fireEventTask = async () => {
await this.readyPromise;

if (this.gtag) {
this.gtag('event', eventAction);
} else {
console.log('Analytics Event Action:', eventAction);
}
};

fireEventTask().catch(() => {
// Do Nothing
});
}

// Define our events
ROMLoadedAndStarted() {
this._fireAnalyticsEvent('rom_loaded_and_started');
}

loadROMSuccess() {
this._fireAnalyticsEvent('load_rom_success');
}

loadROMFail() {
this._fireAnalyticsEvent('load_rom_fail');
}

saveState() {
this._fireAnalyticsEvent('save_state');
}

loadState() {
this._fireAnalyticsEvent('load_state');
}

appliedOptions() {
this._fireAnalyticsEvent('applied_options');
}

googleDriveLoad() {
this._fireAnalyticsEvent('google_drive_load');
}

reload() {
this._fireAnalyticsEvent('reload');
}
}

const DebuggerAnalytics = new DebuggerAnalyticsLib();
export default DebuggerAnalytics;
Binary file added demo/debugger/assets/debuggerWalkthrough.mp4
Binary file not shown.
Binary file added demo/debugger/assets/helpOpenROM.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demo/debugger/assets/helpOpenWidget.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading