Improve Display
This commit is contained in:
parent
b71397d16a
commit
2499eedfd2
@ -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),
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user