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) {
|
fn write_byte_none(&mut self, addr: u16, val: u8) {
|
||||||
match addr {
|
match addr {
|
||||||
0xA000 ... 0xBFFF => {
|
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),
|
_ => 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_SPRITE_ENABLE: u8 = 1 << 1;
|
||||||
const CTRL_BG_DISPLAY: u8 = 1 << 0;
|
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)]
|
#[derive(Debug)]
|
||||||
enum DisplayMode {
|
enum DisplayMode {
|
||||||
Scanline,
|
ReadOAMMemory,
|
||||||
Readmode,
|
ReadFullMemory,
|
||||||
HBlank,
|
HBlank,
|
||||||
VBlank,
|
VBlank,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DisplayMode {
|
impl Default for DisplayMode {
|
||||||
fn default() -> DisplayMode {
|
fn default() -> DisplayMode {
|
||||||
DisplayMode::Scanline
|
DisplayMode::HBlank
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +73,6 @@ pub struct Display {
|
|||||||
pub event_pump: sdl2::EventPump,
|
pub event_pump: sdl2::EventPump,
|
||||||
|
|
||||||
vblank_fired: bool,
|
vblank_fired: bool,
|
||||||
stat_fired: bool,
|
|
||||||
vblank_interrupt: bool,
|
vblank_interrupt: bool,
|
||||||
stat_interrupt: bool,
|
stat_interrupt: bool,
|
||||||
}
|
}
|
||||||
@ -102,7 +107,6 @@ impl Display {
|
|||||||
event_pump: event_pump,
|
event_pump: event_pump,
|
||||||
|
|
||||||
vblank_fired: false,
|
vblank_fired: false,
|
||||||
stat_fired: false,
|
|
||||||
vblank_interrupt: false,
|
vblank_interrupt: false,
|
||||||
stat_interrupt: false,
|
stat_interrupt: false,
|
||||||
}
|
}
|
||||||
@ -179,52 +183,76 @@ impl Display {
|
|||||||
|
|
||||||
// Do we want to have a time delta here?
|
// Do we want to have a time delta here?
|
||||||
pub fn tick(&mut self, ticks: u16) {
|
pub fn tick(&mut self, ticks: u16) {
|
||||||
self.current_ticks += ticks;
|
|
||||||
self.status &= 0xFC;
|
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 {
|
match self.current_mode {
|
||||||
DisplayMode::Scanline => {
|
DisplayMode::ReadOAMMemory => { // Mode 2, Reading OAM memory, RAM may be accessed.
|
||||||
if self.current_ticks > TICKS_END_SCANLINE {
|
if self.current_ticks > TICKS_END_SCANLINE {
|
||||||
self.vblank_fired = false;
|
|
||||||
self.stat_fired = false;
|
|
||||||
self.current_ticks = 0;
|
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 {
|
if self.current_ticks > TICKS_END_READMODE {
|
||||||
self.current_ticks = 0;
|
self.current_ticks = 0;
|
||||||
self.current_mode = DisplayMode::HBlank;
|
self.current_mode = DisplayMode::HBlank;
|
||||||
self.renderscan();
|
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 {
|
if self.current_ticks > TICKS_END_HBLANK {
|
||||||
self.current_ticks = 0;
|
self.current_ticks = 0;
|
||||||
self.curline += 1;
|
self.curline += 1;
|
||||||
|
// render scan?
|
||||||
if self.curline == 143 {
|
if self.curline == 143 {
|
||||||
self.current_mode = DisplayMode::VBlank;
|
self.current_mode = DisplayMode::VBlank; // To Mode 1
|
||||||
self.vblank_interrupt = true;
|
if self.status & STAT_MODE_VBLANK_INT > 0 {
|
||||||
self.vblank_fired = true; // We don't need this, do we?
|
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 {
|
} 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 &= 0xFC;
|
||||||
self.status |= 0;
|
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 {
|
if self.current_ticks > TICKS_END_VBLANK {
|
||||||
self.current_ticks = 0;
|
self.current_ticks = 0;
|
||||||
self.curline += 1;
|
self.curline += 1;
|
||||||
|
if self.curline == 144 {
|
||||||
|
self.vblank_interrupt = true;
|
||||||
|
}
|
||||||
if self.curline > 153 {
|
if self.curline > 153 {
|
||||||
self.renderer.present();
|
self.current_mode = DisplayMode::ReadOAMMemory; // Mode 2, scanline.
|
||||||
self.renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 0, 0));
|
|
||||||
self.renderer.clear();
|
|
||||||
self.current_mode = DisplayMode::Scanline;
|
|
||||||
self.curline = 0;
|
self.curline = 0;
|
||||||
|
if self.status & STAT_MODE_OAM_INT > 0 {
|
||||||
|
self.stat_interrupt = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.status |= 1;
|
self.status |= 1;
|
||||||
@ -234,8 +262,9 @@ impl Display {
|
|||||||
// Update the status register
|
// Update the status register
|
||||||
if self.curline == self.lyc {
|
if self.curline == self.lyc {
|
||||||
self.status |= 1 << 2;
|
self.status |= 1 << 2;
|
||||||
self.stat_fired = true;
|
if self.status & STAT_LYC_LC_COINCIDENCE_INT > 0 {
|
||||||
self.stat_interrupt = true;
|
self.stat_interrupt = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.status &= !(1 << 2);
|
self.status &= !(1 << 2);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user