Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Gekkio committed Dec 18, 2014
0 parents commit 7e3a322
Show file tree
Hide file tree
Showing 79 changed files with 8,247 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*~
*.swp
*.gb
*.o
/roms
/target
/Cargo.lock
/*.dll
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]

name = "mooneye-gb"
version = "0.0.0"
authors = ["Joonas Javanainen <[email protected]>"]

[dependencies.sdl2]
git = "https://github.com/AngryLawyer/rust-sdl2.git"

[dependencies.snooze-rs]
git = "https://github.com/Gekkio/snooze-rs.git"

[dependencies.time]
git = "https://github.com/rust-lang/time.git"
15 changes: 15 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
This software is licensed under the Apache 2 license, quoted below.

Copyright 2014 Joonas Javanainen <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.
8 changes: 8 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Mooneye GB

Another Gameboy emulator written in Rust.

**Warning**:

* Project is WIP
* Doesn't work properly without a boot ROM
30 changes: 30 additions & 0 deletions docs/accuracy/bootrom.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Boot rom emulation accuracy

## Open questions

## Answered questions

### Is it possible to restore the bootrom by writing some value to $FF50?

*Answer*: No

This was tested on a GBP (MGB-001) with the following test ROM, which attempts to write all possible values to $FF50:

ld hl, $0000
ld b, $00 ; value to be written to $FF50

- ld a, b
ld ($FF00+$50), a
ld a, (HL)
cp $31 ; DMG bootrom should have $31 at $0000
jr z, +
inc b ; attempt next value
jr nz, - ; retry until overflow

+ nop

; if A is $FF and B is $00, test failed
; A should be $31
; B should contain the written value
jp finish
38 changes: 38 additions & 0 deletions docs/accuracy/cpu.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# CPU emulation accuracy

## Open questions

### What is the exact behaviour of DI and EI?

These instructions don't change interrupts immediately, but with a delay. What happens if you do another DI/EI while a delayed operation is ongoing?

### Some instructions take more cycles than just the memory accesses. At which point in the instruction execution do these extra cycles occur?

These instructions cost more than the memory accesses:

* LD SP, HL
* LD HL, (SP+e)
* ADD HL, rr
* ADD SP, e
* JP cc, nn
* JP nn
* JR cc, n
* JR n
* INC rr
* DEC rr
* PUSH rr
* RST
* RET cc
* RET
* RETI

Most of these instructions involve writing a 16-bit register, which could explain the timing.

## Answered questions

### Does BIT b, (HL) take 12 or 16 cycles?

*Answer:* 12 cycles

Blargg's instruction timing ROM confirms that BIT takes 12, and RES/SET take 16 cycles, which makes perfect sense.
Some opcode listings in the internet (e.g. GBCPUman.pdf) are wrong.
20 changes: 20 additions & 0 deletions docs/accuracy/joypad.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Joypad emulation accuracy

## Open questions

### Do joypad interrupts depend on the select bits P14-P15, or do we get an interrupt whenever any key is pressed regardless of select bit state?

## Answered questions

### The joypad register (P1) has only 4 inputs (P10-P13). What happens if you enable both key select bits P14-P15 and press overlapping keys?

Both sets of keys are "merged" in the input bits P10-P13. So, if you have both key select bits enabled and press any combination of A and Right, you will see P10 go down (= "set"). Also, if you press A and Right, and then stop pressing Right, P10 should still be down because A is still being pressed.

### What is the initial state of the joypad register (P1)? Does the boot rom write to it?

The DMG/GBP boot rom doesn't write to the joypad register, and the initial value is 0xCF.
This means that key select bits P14-P15 (bits 4-5) are low (= "set").

If GBC is used with old Gameboy games, the boot rom writes and reads from P1, because old games support
palette switches with certain key combinations during boot. After booting, the value is 0xFF.
This means all bits are high (= "unset").
15 changes: 15 additions & 0 deletions docs/accuracy/timer.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Timer emulation accuracy

## Open questions

## Answered questions

### Does writing to DIV ($FF04) reset both the internal and the visible register?

*Answer:* Yes

DIV is incremented every 64 t-cycles, so there is an internal counter that counts to 64. If we write any value to the DIV register, it is reset to 0, but we don't know if the internal counter is also reset.

Consider the case where at time t=0 we reset the counter, and at time t=1 the DIV register would have incremented if we didn't do the reset. Do we see the DIV increment at time t=1 or t=64?

A test ROM confirmed that increment happens at t=64, so the internal counter is also reset. See tests/div_timing.
Empty file added roms/.gitkeep
Empty file.
49 changes: 49 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::comm;
use std::error::Error;
use std::sync::Arc;
use machine::MachineMessage;

pub mod sdl;

pub trait Backend<C: BackendSharedMemory> {
fn main_loop(&mut self, SyncSender<BackendMessage>, Receiver<MachineMessage>);
fn shared_memory(&self) -> Arc<C>;
}

pub trait BackendSharedMemory {
fn draw_scanline(&self, &[GbColor, ..160], y: u8);
}

pub enum BackendMessage {
KeyDown(GbKey), KeyUp(GbKey), Break, Step, Run, Turbo(bool)
}

#[deriving(Show)]
pub enum GbKey {
Right, Left, Up, Down, A, B, Select, Start
}

#[deriving(PartialEq, FromPrimitive, Copy)]
pub enum GbColor {
Off = 0,
Light = 1,
Dark = 2,
On = 3
}

impl GbColor {
pub fn from_u8(value: u8) -> GbColor {
FromPrimitive::from_u8(value).unwrap_or(GbColor::Off)
}
}

pub fn init() -> Result<sdl::SdlBackend, Box<Error>> {
match sdl::SdlBackend::init() {
Ok(backend) => Ok(backend),
Err(error) => Err(box error as Box<Error>)
}
}

pub fn new_channel() -> (SyncSender<BackendMessage>, Receiver<BackendMessage>) {
comm::sync_channel(128)
}
Binary file added src/backend/sdl/font/inconsolata_20/glyph.rgba
Binary file not shown.
Loading

0 comments on commit 7e3a322

Please sign in to comment.