core/gpu: Impl bitmap mode 5 and properly handle wraparound for bitmap modes.
resolves #90 Former-commit-id: 633580870e2d44d95a8b53b6311232f0fad48bd9 Former-commit-id: aa2ba32116900f635f12f9dcc9d29344367711eb
This commit is contained in:
parent
90e492d81a
commit
1b1b855702
|
@ -384,6 +384,10 @@ impl Gpu {
|
||||||
self.render_mode4(2);
|
self.render_mode4(2);
|
||||||
self.finalize_scanline(2, 2);
|
self.finalize_scanline(2, 2);
|
||||||
}
|
}
|
||||||
|
5 => {
|
||||||
|
self.render_mode5(2);
|
||||||
|
self.finalize_scanline(2, 2);
|
||||||
|
}
|
||||||
_ => panic!("{:?} not supported", self.dispcnt.mode()),
|
_ => panic!("{:?} not supported", self.dispcnt.mode()),
|
||||||
}
|
}
|
||||||
// self.mosaic_sfx();
|
// self.mosaic_sfx();
|
||||||
|
|
|
@ -36,6 +36,11 @@ pub(super) static SCREEN_VIEWPORT: ViewPort = ViewPort {
|
||||||
w: DISPLAY_WIDTH as i32,
|
w: DISPLAY_WIDTH as i32,
|
||||||
h: DISPLAY_HEIGHT as i32,
|
h: DISPLAY_HEIGHT as i32,
|
||||||
};
|
};
|
||||||
|
pub(super) static MODE5_VIEWPORT: ViewPort = ViewPort {
|
||||||
|
origin: (0, 0),
|
||||||
|
w: 160,
|
||||||
|
h: 128,
|
||||||
|
};
|
||||||
|
|
||||||
pub(super) mod utils {
|
pub(super) mod utils {
|
||||||
use super::Point;
|
use super::Point;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use super::super::consts::*;
|
||||||
use super::super::Gpu;
|
use super::super::Gpu;
|
||||||
use super::super::Rgb15;
|
use super::super::Rgb15;
|
||||||
|
|
||||||
use super::{utils, SCREEN_VIEWPORT};
|
use super::{utils, MODE5_VIEWPORT, SCREEN_VIEWPORT};
|
||||||
|
|
||||||
use crate::Bus;
|
use crate::Bus;
|
||||||
|
|
||||||
|
@ -16,13 +16,19 @@ impl Gpu {
|
||||||
let pc = self.bg_aff[bg - 2].pc as i32;
|
let pc = self.bg_aff[bg - 2].pc as i32;
|
||||||
let ref_point = self.get_ref_point(bg);
|
let ref_point = self.get_ref_point(bg);
|
||||||
|
|
||||||
|
let wraparound = self.backgrounds[bg].bgcnt.affine_wraparound();
|
||||||
|
|
||||||
for x in 0..DISPLAY_WIDTH {
|
for x in 0..DISPLAY_WIDTH {
|
||||||
let t = utils::transform_bg_point(ref_point, x as i32, pa, pc);
|
let mut t = utils::transform_bg_point(ref_point, x as i32, pa, pc);
|
||||||
if !SCREEN_VIEWPORT.contains_point(t) {
|
if !SCREEN_VIEWPORT.contains_point(t) {
|
||||||
|
if wraparound {
|
||||||
|
t.0 = t.0.rem_euclid(SCREEN_VIEWPORT.w);
|
||||||
|
t.1 = t.1.rem_euclid(SCREEN_VIEWPORT.h);
|
||||||
|
} else {
|
||||||
self.backgrounds[bg].line[x] = Rgb15::TRANSPARENT;
|
self.backgrounds[bg].line[x] = Rgb15::TRANSPARENT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let pixel_index = index2d!(u32, t.0, t.1, DISPLAY_WIDTH);
|
let pixel_index = index2d!(u32, t.0, t.1, DISPLAY_WIDTH);
|
||||||
let pixel_ofs = 2 * pixel_index;
|
let pixel_ofs = 2 * pixel_index;
|
||||||
let color = Rgb15(self.vram.read_16(pixel_ofs));
|
let color = Rgb15(self.vram.read_16(pixel_ofs));
|
||||||
|
@ -43,12 +49,19 @@ impl Gpu {
|
||||||
let pc = self.bg_aff[bg - 2].pc as i32;
|
let pc = self.bg_aff[bg - 2].pc as i32;
|
||||||
let ref_point = self.get_ref_point(bg);
|
let ref_point = self.get_ref_point(bg);
|
||||||
|
|
||||||
|
let wraparound = self.backgrounds[bg].bgcnt.affine_wraparound();
|
||||||
|
|
||||||
for x in 0..DISPLAY_WIDTH {
|
for x in 0..DISPLAY_WIDTH {
|
||||||
let t = utils::transform_bg_point(ref_point, x as i32, pa, pc);
|
let mut t = utils::transform_bg_point(ref_point, x as i32, pa, pc);
|
||||||
if !SCREEN_VIEWPORT.contains_point(t) {
|
if !SCREEN_VIEWPORT.contains_point(t) {
|
||||||
|
if wraparound {
|
||||||
|
t.0 = t.0.rem_euclid(SCREEN_VIEWPORT.w);
|
||||||
|
t.1 = t.1.rem_euclid(SCREEN_VIEWPORT.h);
|
||||||
|
} else {
|
||||||
self.backgrounds[bg].line[x] = Rgb15::TRANSPARENT;
|
self.backgrounds[bg].line[x] = Rgb15::TRANSPARENT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let bitmap_index = index2d!(u32, t.0, t.1, DISPLAY_WIDTH);
|
let bitmap_index = index2d!(u32, t.0, t.1, DISPLAY_WIDTH);
|
||||||
let bitmap_ofs = page_ofs + (bitmap_index as u32);
|
let bitmap_ofs = page_ofs + (bitmap_index as u32);
|
||||||
let index = self.vram.read_8(bitmap_ofs) as u32;
|
let index = self.vram.read_8(bitmap_ofs) as u32;
|
||||||
|
@ -56,4 +69,36 @@ impl Gpu {
|
||||||
self.backgrounds[bg].line[x] = color;
|
self.backgrounds[bg].line[x] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(in super::super) fn render_mode5(&mut self, bg: usize) {
|
||||||
|
let page_ofs: u32 = match self.dispcnt.display_frame() {
|
||||||
|
0 => 0x0600_0000 - VRAM_ADDR,
|
||||||
|
1 => 0x0600_a000 - VRAM_ADDR,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _y = self.vcount;
|
||||||
|
|
||||||
|
let pa = self.bg_aff[bg - 2].pa as i32;
|
||||||
|
let pc = self.bg_aff[bg - 2].pc as i32;
|
||||||
|
let ref_point = self.get_ref_point(bg);
|
||||||
|
|
||||||
|
let wraparound = self.backgrounds[bg].bgcnt.affine_wraparound();
|
||||||
|
|
||||||
|
for x in 0..DISPLAY_WIDTH {
|
||||||
|
let mut t = utils::transform_bg_point(ref_point, x as i32, pa, pc);
|
||||||
|
if !MODE5_VIEWPORT.contains_point(t) {
|
||||||
|
if wraparound {
|
||||||
|
t.0 = t.0.rem_euclid(MODE5_VIEWPORT.w);
|
||||||
|
t.1 = t.1.rem_euclid(MODE5_VIEWPORT.h);
|
||||||
|
} else {
|
||||||
|
self.backgrounds[bg].line[x] = Rgb15::TRANSPARENT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let pixel_ofs = page_ofs + 2 * index2d!(u32, t.0, t.1, MODE5_VIEWPORT.w);
|
||||||
|
let color = Rgb15(self.vram.read_16(pixel_ofs));
|
||||||
|
self.backgrounds[bg].line[x] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue