Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
boytacean
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
João Magalhães
boytacean
Commits
9d55eb6c
Verified
Commit
9d55eb6c
authored
1 year ago
by
João Magalhães
Browse files
Options
Downloads
Patches
Plain Diff
feat: initial support for config
parent
d07e7f09
No related branches found
No related tags found
1 merge request
!16
Support for Game Boy Color (CGB) 😎🖍️
Pipeline
#2557
failed
1 year ago
Stage: build
Stage: test
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/cpu.rs
+9
-1
9 additions, 1 deletion
src/cpu.rs
src/gb.rs
+138
-36
138 additions, 36 deletions
src/gb.rs
src/inst.rs
+25
-0
25 additions, 0 deletions
src/inst.rs
src/mmu.rs
+18
-3
18 additions, 3 deletions
src/mmu.rs
with
190 additions
and
40 deletions
src/cpu.rs
+
9
−
1
View file @
9d55eb6c
use
core
::
panic
;
use
core
::
panic
;
use
std
::{
cell
::
RefCell
,
rc
::
Rc
};
use
crate
::{
use
crate
::{
apu
::
Apu
,
apu
::
Apu
,
debugln
,
debugln
,
gb
::
GameBoyConfig
,
inst
::{
EXTENDED
,
INSTRUCTIONS
},
inst
::{
EXTENDED
,
INSTRUCTIONS
},
mmu
::
Mmu
,
mmu
::
Mmu
,
pad
::
Pad
,
pad
::
Pad
,
...
@@ -38,10 +40,15 @@ pub struct Cpu {
...
@@ -38,10 +40,15 @@ pub struct Cpu {
/// Temporary counter used to control the number of cycles
/// Temporary counter used to control the number of cycles
/// taken by the current or last CPU operation.
/// taken by the current or last CPU operation.
pub
cycles
:
u8
,
pub
cycles
:
u8
,
/// The pointer to the parent configuration of the running
/// Game Boy emulator, that can be used to control the behaviour
/// of Game Boy emulation.
gbc
:
Rc
<
RefCell
<
GameBoyConfig
>>
,
}
}
impl
Cpu
{
impl
Cpu
{
pub
fn
new
(
mmu
:
Mmu
)
->
Self
{
pub
fn
new
(
mmu
:
Mmu
,
gbc
:
Rc
<
RefCell
<
GameBoyConfig
>>
)
->
Self
{
Self
{
Self
{
pc
:
0x0
,
pc
:
0x0
,
sp
:
0x0
,
sp
:
0x0
,
...
@@ -60,6 +67,7 @@ impl Cpu {
...
@@ -60,6 +67,7 @@ impl Cpu {
halted
:
false
,
halted
:
false
,
mmu
,
mmu
,
cycles
:
0
,
cycles
:
0
,
gbc
:
gbc
,
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
src/gb.rs
+
138
−
36
View file @
9d55eb6c
...
@@ -13,7 +13,7 @@ use crate::{
...
@@ -13,7 +13,7 @@ use crate::{
util
::
read_file
,
util
::
read_file
,
};
};
use
std
::
collections
::
VecDeque
;
use
std
::
{
cell
::
RefCell
,
collections
::
VecDeque
,
rc
::
Rc
}
;
#[cfg(feature
=
"wasm"
)]
#[cfg(feature
=
"wasm"
)]
use
wasm_bindgen
::
prelude
::
*
;
use
wasm_bindgen
::
prelude
::
*
;
...
@@ -32,28 +32,22 @@ use std::{
...
@@ -32,28 +32,22 @@ use std::{
/// Enumeration that describes the multiple running
/// Enumeration that describes the multiple running
// modes of the Game Boy emulator.
// modes of the Game Boy emulator.
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
#[derive(Clone,
Copy,
PartialEq,
Eq)]
pub
enum
GBMode
{
pub
enum
GBMode
{
Dmg
=
1
,
Dmg
=
1
,
Cgb
=
2
,
Cgb
=
2
,
Sgb
=
3
,
Sgb
=
3
,
}
}
/// Top level structure that abstracts the usage of the
/// Game Boy system under the Boytacean emulator.
/// Should serve as the main entry-point API.
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
pub
struct
GameBoy
{
#[derive(Clone,
Copy,
PartialEq,
Eq)]
pub
struct
GameBoyConfig
{
/// The current running mode of the emulator, this
/// The current running mode of the emulator, this
/// may affect many aspects of the emulation, like
/// may affect many aspects of the emulation, like
/// CPU frequency, PPU frequency, Boot rome size, etc.
/// CPU frequency, PPU frequency, Boot rome size, etc.
mode
:
GBMode
,
mode
:
GBMode
,
/// Reference to the Game Boy CPU component to be
/// used as the main element of the system, when
/// clocked, the amount of ticks from it will be
/// used as reference or the rest of the components.
cpu
:
Cpu
,
/// If the PPU is enabled, it will be clocked.
/// If the PPU is enabled, it will be clocked.
ppu_enabled
:
bool
,
ppu_enabled
:
bool
,
...
@@ -75,6 +69,98 @@ pub struct GameBoy {
...
@@ -75,6 +69,98 @@ pub struct GameBoy {
clock_freq
:
u32
,
clock_freq
:
u32
,
}
}
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
impl
GameBoyConfig
{
#[inline(always)]
pub
fn
is_dmg
(
&
self
)
->
bool
{
self
.mode
==
GBMode
::
Dmg
}
#[inline(always)]
pub
fn
is_cgb
(
&
self
)
->
bool
{
self
.mode
==
GBMode
::
Cgb
}
#[inline(always)]
pub
fn
is_sgb
(
&
self
)
->
bool
{
self
.mode
==
GBMode
::
Sgb
}
#[inline(always)]
pub
fn
mode
(
&
self
)
->
GBMode
{
self
.mode
}
#[inline(always)]
pub
fn
set_mode
(
&
mut
self
,
value
:
GBMode
)
{
self
.mode
=
value
;
}
#[inline(always)]
pub
fn
ppu_enabled
(
&
self
)
->
bool
{
self
.ppu_enabled
}
#[inline(always)]
pub
fn
set_ppu_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.ppu_enabled
=
value
;
}
#[inline(always)]
pub
fn
apu_enabled
(
&
self
)
->
bool
{
self
.apu_enabled
}
#[inline(always)]
pub
fn
set_apu_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.apu_enabled
=
value
;
}
#[inline(always)]
pub
fn
timer_enabled
(
&
self
)
->
bool
{
self
.timer_enabled
}
#[inline(always)]
pub
fn
set_timer_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.timer_enabled
=
value
;
}
#[inline(always)]
pub
fn
serial_enabled
(
&
self
)
->
bool
{
self
.serial_enabled
}
#[inline(always)]
pub
fn
set_serial_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.serial_enabled
=
value
;
}
#[inline(always)]
pub
fn
clock_freq
(
&
self
)
->
u32
{
self
.clock_freq
}
#[inline(always)]
pub
fn
set_clock_freq
(
&
mut
self
,
value
:
u32
)
{
self
.clock_freq
=
value
;
}
}
/// Top level structure that abstracts the usage of the
/// Game Boy system under the Boytacean emulator.
/// Should serve as the main entry-point API.
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
pub
struct
GameBoy
{
/// Reference to the Game Boy CPU component to be
/// used as the main element of the system, when
/// clocked, the amount of ticks from it will be
/// used as reference or the rest of the components.
cpu
:
Cpu
,
gbc
:
Rc
<
RefCell
<
GameBoyConfig
>>
,
}
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen)]
pub
struct
Registers
{
pub
struct
Registers
{
pub
pc
:
u16
,
pub
pc
:
u16
,
...
@@ -104,22 +190,24 @@ pub trait AudioProvider {
...
@@ -104,22 +190,24 @@ pub trait AudioProvider {
impl
GameBoy
{
impl
GameBoy
{
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen(constructor))]
#[cfg_attr(feature
=
"wasm"
,
wasm_bindgen(constructor))]
pub
fn
new
(
mode
:
GBMode
)
->
Self
{
pub
fn
new
(
mode
:
GBMode
)
->
Self
{
let
ppu
=
Ppu
::
default
();
let
gbc
=
Rc
::
new
(
RefCell
::
new
(
GameBoyConfig
{
let
apu
=
Apu
::
default
();
let
pad
=
Pad
::
default
();
let
timer
=
Timer
::
default
();
let
serial
=
Serial
::
default
();
let
mmu
=
Mmu
::
new
(
ppu
,
apu
,
pad
,
timer
,
serial
);
let
cpu
=
Cpu
::
new
(
mmu
);
Self
{
mode
,
mode
,
cpu
,
ppu_enabled
:
true
,
ppu_enabled
:
true
,
apu_enabled
:
true
,
apu_enabled
:
true
,
timer_enabled
:
true
,
timer_enabled
:
true
,
serial_enabled
:
true
,
serial_enabled
:
true
,
clock_freq
:
GameBoy
::
CPU_FREQ
,
clock_freq
:
GameBoy
::
CPU_FREQ
,
}
}));
let
ppu
=
Ppu
::
default
();
let
apu
=
Apu
::
default
();
let
pad
=
Pad
::
default
();
let
timer
=
Timer
::
default
();
let
serial
=
Serial
::
default
();
let
mmu
=
Mmu
::
new
(
ppu
,
apu
,
pad
,
timer
,
serial
,
gbc
.clone
());
let
cpu
=
Cpu
::
new
(
mmu
,
gbc
.clone
());
Self
{
cpu
,
gbc
}
}
}
pub
fn
reset
(
&
mut
self
)
{
pub
fn
reset
(
&
mut
self
)
{
...
@@ -133,16 +221,16 @@ impl GameBoy {
...
@@ -133,16 +221,16 @@ impl GameBoy {
pub
fn
clock
(
&
mut
self
)
->
u8
{
pub
fn
clock
(
&
mut
self
)
->
u8
{
let
cycles
=
self
.cpu_clock
();
let
cycles
=
self
.cpu_clock
();
if
self
.ppu_enabled
{
if
self
.ppu_enabled
()
{
self
.ppu_clock
(
cycles
);
self
.ppu_clock
(
cycles
);
}
}
if
self
.apu_enabled
{
if
self
.apu_enabled
()
{
self
.apu_clock
(
cycles
);
self
.apu_clock
(
cycles
);
}
}
if
self
.timer_enabled
{
if
self
.timer_enabled
()
{
self
.timer_clock
(
cycles
);
self
.timer_clock
(
cycles
);
}
}
if
self
.serial_enabled
{
if
self
.serial_enabled
()
{
self
.serial_clock
(
cycles
);
self
.serial_clock
(
cycles
);
}
}
cycles
cycles
...
@@ -193,7 +281,7 @@ impl GameBoy {
...
@@ -193,7 +281,7 @@ impl GameBoy {
}
}
pub
fn
load
(
&
mut
self
,
boot
:
bool
)
{
pub
fn
load
(
&
mut
self
,
boot
:
bool
)
{
match
self
.mode
{
match
self
.mode
()
{
GBMode
::
Dmg
=>
self
.load_dmg
(
boot
),
GBMode
::
Dmg
=>
self
.load_dmg
(
boot
),
GBMode
::
Cgb
=>
self
.load_cgb
(
boot
),
GBMode
::
Cgb
=>
self
.load_cgb
(
boot
),
GBMode
::
Sgb
=>
todo!
(),
GBMode
::
Sgb
=>
todo!
(),
...
@@ -357,44 +445,58 @@ impl GameBoy {
...
@@ -357,44 +445,58 @@ impl GameBoy {
String
::
from
(
COMPILATION_TIME
)
String
::
from
(
COMPILATION_TIME
)
}
}
#[inline(always)]
pub
fn
mode
(
&
self
)
->
GBMode
{
(
*
self
.gbc
)
.borrow
()
.mode
()
}
pub
fn
set_mode
(
&
mut
self
,
value
:
GBMode
)
{
(
*
self
.gbc
)
.borrow_mut
()
.set_mode
(
value
);
}
#[inline(always)]
pub
fn
ppu_enabled
(
&
self
)
->
bool
{
pub
fn
ppu_enabled
(
&
self
)
->
bool
{
self
.ppu_enabled
(
*
self
.
gbc
)
.borrow
()
.
ppu_enabled
()
}
}
pub
fn
set_ppu_enabled
(
&
mut
self
,
value
:
bool
)
{
pub
fn
set_ppu_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.ppu_enabled
=
value
;
(
*
self
.
gbc
)
.borrow_mut
()
.set_
ppu_enabled
(
value
)
;
}
}
#[inline(always)]
pub
fn
apu_enabled
(
&
self
)
->
bool
{
pub
fn
apu_enabled
(
&
self
)
->
bool
{
self
.apu_enabled
(
*
self
.
gbc
)
.borrow
()
.
apu_enabled
}
}
pub
fn
set_apu_enabled
(
&
mut
self
,
value
:
bool
)
{
pub
fn
set_apu_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.apu_enabled
=
value
;
(
*
self
.
gbc
)
.borrow_mut
()
.set_
apu_enabled
(
value
)
;
}
}
#[inline(always)]
pub
fn
timer_enabled
(
&
self
)
->
bool
{
pub
fn
timer_enabled
(
&
self
)
->
bool
{
self
.timer_enabled
(
*
self
.
gbc
)
.borrow
()
.
timer_enabled
()
}
}
pub
fn
set_timer_enabled
(
&
mut
self
,
value
:
bool
)
{
pub
fn
set_timer_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.timer_enabled
=
value
;
(
*
self
.
gbc
)
.borrow_mut
()
.set_
timer_enabled
(
value
)
;
}
}
#[inline(always)]
pub
fn
serial_enabled
(
&
self
)
->
bool
{
pub
fn
serial_enabled
(
&
self
)
->
bool
{
self
.serial_enabled
(
*
self
.
gbc
)
.borrow
()
.
serial_enabled
()
}
}
pub
fn
set_serial_enabled
(
&
mut
self
,
value
:
bool
)
{
pub
fn
set_serial_enabled
(
&
mut
self
,
value
:
bool
)
{
self
.serial_enabled
=
value
;
(
*
self
.
gbc
)
.borrow_mut
()
.set_
serial_enabled
(
value
)
;
}
}
#[inline(always)]
pub
fn
clock_freq
(
&
self
)
->
u32
{
pub
fn
clock_freq
(
&
self
)
->
u32
{
self
.clock_freq
(
*
self
.
gbc
)
.borrow
()
.
clock_freq
()
}
}
pub
fn
set_clock_freq
(
&
mut
self
,
value
:
u32
)
{
pub
fn
set_clock_freq
(
&
mut
self
,
value
:
u32
)
{
self
.clock_freq
=
value
;
(
*
self
.
gbc
)
.borrow_mut
()
.set_
clock_freq
(
value
)
;
self
.apu
()
.set_clock_freq
(
value
);
self
.apu
()
.set_clock_freq
(
value
);
}
}
...
...
This diff is collapsed.
Click to expand it.
src/inst.rs
+
25
−
0
View file @
9d55eb6c
...
@@ -3119,11 +3119,13 @@ fn set_7_a(cpu: &mut Cpu) {
...
@@ -3119,11 +3119,13 @@ fn set_7_a(cpu: &mut Cpu) {
}
}
/// Helper function to set one bit in a u8.
/// Helper function to set one bit in a u8.
#[inline(always)]
fn
set
(
value
:
u8
,
bit
:
u8
)
->
u8
{
fn
set
(
value
:
u8
,
bit
:
u8
)
->
u8
{
value
|
(
1u8
<<
(
bit
as
usize
))
value
|
(
1u8
<<
(
bit
as
usize
))
}
}
/// Helper function to clear one bit in a u8.
/// Helper function to clear one bit in a u8.
#[inline(always)]
fn
res
(
value
:
u8
,
bit
:
u8
)
->
u8
{
fn
res
(
value
:
u8
,
bit
:
u8
)
->
u8
{
value
&
!
(
1u8
<<
(
bit
as
usize
))
value
&
!
(
1u8
<<
(
bit
as
usize
))
}
}
...
@@ -3131,6 +3133,7 @@ fn res(value: u8, bit: u8) -> u8 {
...
@@ -3131,6 +3133,7 @@ fn res(value: u8, bit: u8) -> u8 {
/// Helper function that rotates (shifts) left the given
/// Helper function that rotates (shifts) left the given
/// byte (probably from a register) and updates the
/// byte (probably from a register) and updates the
/// proper flag registers.
/// proper flag registers.
#[inline(always)]
fn
rl
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
rl
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
let
carry
=
cpu
.carry
();
let
carry
=
cpu
.carry
();
...
@@ -3145,6 +3148,7 @@ fn rl(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3145,6 +3148,7 @@ fn rl(cpu: &mut Cpu, value: u8) -> u8 {
result
result
}
}
#[inline(always)]
fn
rlc
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
rlc
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
cpu
.set_carry
((
value
&
0x80
)
==
0x80
);
cpu
.set_carry
((
value
&
0x80
)
==
0x80
);
...
@@ -3160,6 +3164,7 @@ fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3160,6 +3164,7 @@ fn rlc(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function that rotates (shifts) right the given
/// Helper function that rotates (shifts) right the given
/// byte (probably from a register) and updates the
/// byte (probably from a register) and updates the
/// proper flag registers.
/// proper flag registers.
#[inline(always)]
fn
rr
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
rr
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
let
carry
=
cpu
.carry
();
let
carry
=
cpu
.carry
();
...
@@ -3174,6 +3179,7 @@ fn rr(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3174,6 +3179,7 @@ fn rr(cpu: &mut Cpu, value: u8) -> u8 {
result
result
}
}
#[inline(always)]
fn
rrc
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
rrc
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
cpu
.set_carry
((
value
&
0x1
)
==
0x1
);
cpu
.set_carry
((
value
&
0x1
)
==
0x1
);
...
@@ -3188,52 +3194,61 @@ fn rrc(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3188,52 +3194,61 @@ fn rrc(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function to test one bit in a u8.
/// Helper function to test one bit in a u8.
/// Returns true if bit is 0.
/// Returns true if bit is 0.
#[inline(always)]
fn
bit_zero
(
val
:
u8
,
bit
:
u8
)
->
bool
{
fn
bit_zero
(
val
:
u8
,
bit
:
u8
)
->
bool
{
(
val
&
(
1u8
<<
(
bit
as
usize
)))
==
0
(
val
&
(
1u8
<<
(
bit
as
usize
)))
==
0
}
}
#[inline(always)]
fn
bit_a
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_a
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.a
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.a
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_b
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_b
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.b
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.b
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_c
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_c
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.c
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.c
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_d
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_d
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.d
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.d
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_e
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_e
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.e
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.e
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_h
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_h
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.h
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.h
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_l
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_l
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
bit_zero
(
cpu
.l
,
bit
));
cpu
.set_zero
(
bit_zero
(
cpu
.l
,
bit
));
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
bit_mhl
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
fn
bit_mhl
(
cpu
:
&
mut
Cpu
,
bit
:
u8
)
{
let
byte
=
cpu
.mmu
.read
(
cpu
.hl
());
let
byte
=
cpu
.mmu
.read
(
cpu
.hl
());
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
...
@@ -3241,6 +3256,7 @@ fn bit_mhl(cpu: &mut Cpu, bit: u8) {
...
@@ -3241,6 +3256,7 @@ fn bit_mhl(cpu: &mut Cpu, bit: u8) {
cpu
.set_half_carry
(
true
);
cpu
.set_half_carry
(
true
);
}
}
#[inline(always)]
fn
add_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
fn
add_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
let
first
=
first
as
u32
;
let
first
=
first
as
u32
;
let
second
=
second
as
u32
;
let
second
=
second
as
u32
;
...
@@ -3256,6 +3272,7 @@ fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
...
@@ -3256,6 +3272,7 @@ fn add_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b
result_b
}
}
#[inline(always)]
fn
add_carry_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
fn
add_carry_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
let
first
=
first
as
u32
;
let
first
=
first
as
u32
;
let
second
=
second
as
u32
;
let
second
=
second
as
u32
;
...
@@ -3272,6 +3289,7 @@ fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
...
@@ -3272,6 +3289,7 @@ fn add_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b
result_b
}
}
#[inline(always)]
fn
sub_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
fn
sub_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
let
first
=
first
as
u32
;
let
first
=
first
as
u32
;
let
second
=
second
as
u32
;
let
second
=
second
as
u32
;
...
@@ -3287,6 +3305,7 @@ fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
...
@@ -3287,6 +3305,7 @@ fn sub_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b
result_b
}
}
#[inline(always)]
fn
sub_carry_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
fn
sub_carry_set_flags
(
cpu
:
&
mut
Cpu
,
first
:
u8
,
second
:
u8
)
->
u8
{
let
first
=
first
as
u32
;
let
first
=
first
as
u32
;
let
second
=
second
as
u32
;
let
second
=
second
as
u32
;
...
@@ -3303,6 +3322,7 @@ fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
...
@@ -3303,6 +3322,7 @@ fn sub_carry_set_flags(cpu: &mut Cpu, first: u8, second: u8) -> u8 {
result_b
result_b
}
}
#[inline(always)]
fn
add_u16_u16
(
cpu
:
&
mut
Cpu
,
first
:
u16
,
second
:
u16
)
->
u16
{
fn
add_u16_u16
(
cpu
:
&
mut
Cpu
,
first
:
u16
,
second
:
u16
)
->
u16
{
let
first
=
first
as
u32
;
let
first
=
first
as
u32
;
let
second
=
second
as
u32
;
let
second
=
second
as
u32
;
...
@@ -3315,6 +3335,7 @@ fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
...
@@ -3315,6 +3335,7 @@ fn add_u16_u16(cpu: &mut Cpu, first: u16, second: u16) -> u16 {
result
as
u16
result
as
u16
}
}
#[inline(always)]
fn
swap
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
swap
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
cpu
.set_sub
(
false
);
cpu
.set_sub
(
false
);
cpu
.set_zero
(
value
==
0
);
cpu
.set_zero
(
value
==
0
);
...
@@ -3326,6 +3347,7 @@ fn swap(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3326,6 +3347,7 @@ fn swap(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function to shift an `u8` to the left and update CPU
/// Helper function to shift an `u8` to the left and update CPU
/// flags.
/// flags.
#[inline(always)]
fn
sla
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
sla
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
let
result
=
value
<<
1
;
let
result
=
value
<<
1
;
...
@@ -3337,6 +3359,7 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3337,6 +3359,7 @@ fn sla(cpu: &mut Cpu, value: u8) -> u8 {
result
result
}
}
#[inline(always)]
fn
sra
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
sra
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
let
result
=
(
value
>>
1
)
|
(
value
&
0x80
);
let
result
=
(
value
>>
1
)
|
(
value
&
0x80
);
...
@@ -3348,6 +3371,7 @@ fn sra(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3348,6 +3371,7 @@ fn sra(cpu: &mut Cpu, value: u8) -> u8 {
result
result
}
}
#[inline(always)]
fn
srl
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
fn
srl
(
cpu
:
&
mut
Cpu
,
value
:
u8
)
->
u8
{
let
result
=
value
>>
1
;
let
result
=
value
>>
1
;
...
@@ -3362,6 +3386,7 @@ fn srl(cpu: &mut Cpu, value: u8) -> u8 {
...
@@ -3362,6 +3386,7 @@ fn srl(cpu: &mut Cpu, value: u8) -> u8 {
/// Helper function for RST instructions, pushes the
/// Helper function for RST instructions, pushes the
/// current PC to the stack and jumps to the provided
/// current PC to the stack and jumps to the provided
/// address.
/// address.
#[inline(always)]
fn
rst
(
cpu
:
&
mut
Cpu
,
addr
:
u16
)
{
fn
rst
(
cpu
:
&
mut
Cpu
,
addr
:
u16
)
{
cpu
.push_word
(
cpu
.pc
);
cpu
.push_word
(
cpu
.pc
);
cpu
.pc
=
addr
;
cpu
.pc
=
addr
;
...
...
This diff is collapsed.
Click to expand it.
src/mmu.rs
+
18
−
3
View file @
9d55eb6c
use
crate
::{
apu
::
Apu
,
debugln
,
pad
::
Pad
,
ppu
::
Ppu
,
rom
::
Cartridge
,
serial
::
Serial
,
timer
::
Timer
};
use
std
::{
cell
::
RefCell
,
rc
::
Rc
};
use
crate
::{
apu
::
Apu
,
debugln
,
gb
::
GameBoyConfig
,
pad
::
Pad
,
ppu
::
Ppu
,
rom
::
Cartridge
,
serial
::
Serial
,
timer
::
Timer
,
};
pub
const
BOOT_SIZE_DMG
:
usize
=
256
;
pub
const
BOOT_SIZE_DMG
:
usize
=
256
;
pub
const
BOOT_SIZE_CGB
:
usize
=
2304
;
pub
const
BOOT_SIZE_CGB
:
usize
=
2304
;
...
@@ -55,14 +60,23 @@ pub struct Mmu {
...
@@ -55,14 +60,23 @@ pub struct Mmu {
ram
:
Vec
<
u8
>
,
ram
:
Vec
<
u8
>
,
/// The RAM bank to be used in the read and write operation of
/// The RAM bank to be used in the read and write operation of
/// the 0xD000-0xDFFF memory range
.
CGB Only
/// the 0xD000-0xDFFF memory range
(
CGB Only
).
ram_bank
:
u8
,
ram_bank
:
u8
,
ram_offset
:
u16
,
ram_offset
:
u16
,
gbc
:
Rc
<
RefCell
<
GameBoyConfig
>>
,
}
}
impl
Mmu
{
impl
Mmu
{
pub
fn
new
(
ppu
:
Ppu
,
apu
:
Apu
,
pad
:
Pad
,
timer
:
Timer
,
serial
:
Serial
)
->
Self
{
pub
fn
new
(
ppu
:
Ppu
,
apu
:
Apu
,
pad
:
Pad
,
timer
:
Timer
,
serial
:
Serial
,
gbc
:
Rc
<
RefCell
<
GameBoyConfig
>>
,
)
->
Self
{
Self
{
Self
{
ppu
,
ppu
,
apu
,
apu
,
...
@@ -76,6 +90,7 @@ impl Mmu {
...
@@ -76,6 +90,7 @@ impl Mmu {
ram_bank
:
0x1
,
ram_bank
:
0x1
,
ram_offset
:
0x1000
,
ram_offset
:
0x1000
,
ie
:
0x0
,
ie
:
0x0
,
gbc
:
gbc
,
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment