Improve Display

This commit is contained in:
Kevin Hamacher 2016-05-29 14:11:34 +02:00
parent b71397d16a
commit 2499eedfd2
2 changed files with 56 additions and 26 deletions

View File

@ -109,7 +109,8 @@ impl Cartridge {
fn write_byte_none(&mut self, addr: u16, val: u8) {
match addr {
0xA000 ... 0xBFFF => {
self.ram[addr as usize - 0xA000] = val;
// self.ram[addr as usize - 0xA000] = val;
println!("No MBC, ignoring RAM write {:02X} to {:04X}", val, addr);
}
_ => println!("No MBC, unable to write {:02X} to {:04X}", val, addr),
}

View File

@ -28,17 +28,23 @@ const CTRL_BG_SPRITE_SIZE: u8 = 1 << 2;
const CTRL_BG_SPRITE_ENABLE: u8 = 1 << 1;
const CTRL_BG_DISPLAY: u8 = 1 << 0;
// Status flags
const STAT_LYC_LC_COINCIDENCE_INT: u8 = 1 << 6;
const STAT_MODE_OAM_INT: u8 = 1 << 5;
const STAT_MODE_VBLANK_INT: u8 = 1 << 4;
const STAT_MODE_HBLANK_INT: u8 = 1 << 3;
#[derive(Debug)]
enum DisplayMode {
Scanline,
Readmode,
ReadOAMMemory,
ReadFullMemory,
HBlank,
VBlank,
}
impl Default for DisplayMode {
fn default() -> DisplayMode {
DisplayMode::Scanline
DisplayMode::HBlank
}
}
@ -67,7 +73,6 @@ pub struct Display {
pub event_pump: sdl2::EventPump,
vblank_fired: bool,
stat_fired: bool,
vblank_interrupt: bool,
stat_interrupt: bool,
}
@ -102,7 +107,6 @@ impl Display {
event_pump: event_pump,
vblank_fired: false,
stat_fired: false,
vblank_interrupt: false,
stat_interrupt: false,
}
@ -179,52 +183,76 @@ impl Display {
// Do we want to have a time delta here?
pub fn tick(&mut self, ticks: u16) {
self.current_ticks += ticks;
self.status &= 0xFC;
if self.control & CTRL_LCD_DISPLAY_ENABLE == 0 {
// Display is disabled
self.current_ticks = 0;
self.current_mode = DisplayMode::VBlank;
self.curline = 0;
return;
}
self.current_ticks += ticks;
match self.current_mode {
DisplayMode::Scanline => {
DisplayMode::ReadOAMMemory => { // Mode 2, Reading OAM memory, RAM may be accessed.
if self.current_ticks > TICKS_END_SCANLINE {
self.vblank_fired = false;
self.stat_fired = false;
self.current_ticks = 0;
self.current_mode = DisplayMode::Readmode;
self.current_mode = DisplayMode::ReadFullMemory;
}
self.status |= 3;
self.status |= 2;
},
DisplayMode::Readmode => {
DisplayMode::ReadFullMemory => { // Mode 3, reading OAM, VMEM and palette data.
// Nothing may be accessed.
if self.current_ticks > TICKS_END_READMODE {
self.current_ticks = 0;
self.current_mode = DisplayMode::HBlank;
self.renderscan();
if self.status & STAT_MODE_HBLANK_INT > 0 {
self.stat_interrupt = true;
}
}
self.status |= 2;
self.status |= 3;
},
DisplayMode::HBlank => {
DisplayMode::HBlank => { // Mode 0, H-Blank, Memory (RAM, OAM) may be accessed.
if self.current_ticks > TICKS_END_HBLANK {
self.current_ticks = 0;
self.curline += 1;
// render scan?
if self.curline == 143 {
self.current_mode = DisplayMode::VBlank;
self.vblank_interrupt = true;
self.vblank_fired = true; // We don't need this, do we?
self.current_mode = DisplayMode::VBlank; // To Mode 1
if self.status & STAT_MODE_VBLANK_INT > 0 {
self.stat_interrupt = true;
}
// render frame.
self.renderer.present();
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 0, 0));
self.renderer.clear();
} else {
self.current_mode = DisplayMode::Scanline;
self.current_mode = DisplayMode::ReadOAMMemory; // Mode 2 again
if self.status & STAT_MODE_OAM_INT > 0 {
self.stat_interrupt = true;
}
}
}
self.status &= 0xFC;
self.status |= 0;
},
DisplayMode::VBlank => {
DisplayMode::VBlank => { // Mode 1, V-Blank (or display disabled), Memory (RAM, OAM)
// may be accessed
if self.current_ticks > TICKS_END_VBLANK {
self.current_ticks = 0;
self.curline += 1;
if self.curline == 144 {
self.vblank_interrupt = true;
}
if self.curline > 153 {
self.renderer.present();
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 0, 0));
self.renderer.clear();
self.current_mode = DisplayMode::Scanline;
self.current_mode = DisplayMode::ReadOAMMemory; // Mode 2, scanline.
self.curline = 0;
if self.status & STAT_MODE_OAM_INT > 0 {
self.stat_interrupt = true;
}
}
}
self.status |= 1;
@ -234,8 +262,9 @@ impl Display {
// Update the status register
if self.curline == self.lyc {
self.status |= 1 << 2;
self.stat_fired = true;
self.stat_interrupt = true;
if self.status & STAT_LYC_LC_COINCIDENCE_INT > 0 {
self.stat_interrupt = true;
}
} else {
self.status &= !(1 << 2);
}