Implement Window special effect (win_demo.gba works, excpet the sprite)
Former-commit-id: 511d04045bbb678ceec39e34c483f04db154997b
This commit is contained in:
parent
1d2d950729
commit
8abebbe844
|
@ -6,10 +6,10 @@ use super::*;
|
||||||
use crate::bitfield::Bit;
|
use crate::bitfield::Bit;
|
||||||
use crate::num::FromPrimitive;
|
use crate::num::FromPrimitive;
|
||||||
|
|
||||||
mod blend;
|
|
||||||
mod mosaic;
|
mod mosaic;
|
||||||
|
mod sfx;
|
||||||
|
|
||||||
mod regs;
|
pub mod regs;
|
||||||
pub use regs::*;
|
pub use regs::*;
|
||||||
|
|
||||||
pub const VRAM_ADDR: Addr = 0x0600_0000;
|
pub const VRAM_ADDR: Addr = 0x0600_0000;
|
||||||
|
@ -164,6 +164,42 @@ pub struct Bg {
|
||||||
mosaic_first_row: Scanline,
|
mosaic_first_row: Scanline,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Window {
|
||||||
|
pub left: u8,
|
||||||
|
pub right: u8,
|
||||||
|
pub top: u8,
|
||||||
|
pub bottom: u8,
|
||||||
|
pub flags: WindowFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn inside(&self, x: usize, y: usize) -> bool {
|
||||||
|
let left = self.left as usize;
|
||||||
|
let mut right = self.right as usize;
|
||||||
|
let top = self.top as usize;
|
||||||
|
let mut bottom = self.bottom as usize;
|
||||||
|
|
||||||
|
if right > DISPLAY_WIDTH || right < left {
|
||||||
|
right = DISPLAY_WIDTH;
|
||||||
|
}
|
||||||
|
if bottom > DISPLAY_HEIGHT || bottom < top {
|
||||||
|
bottom = DISPLAY_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
(x >= left && x < right) && (y >= top && y < bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum WindowType {
|
||||||
|
Win0,
|
||||||
|
Win1,
|
||||||
|
WinObj,
|
||||||
|
WinOut,
|
||||||
|
WinNone,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct BgAffine {
|
pub struct BgAffine {
|
||||||
pub pa: i16, // dx
|
pub pa: i16, // dx
|
||||||
|
@ -176,29 +212,28 @@ pub struct BgAffine {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Gpu {
|
pub struct Gpu {
|
||||||
|
pub state: GpuState,
|
||||||
|
cycles: usize,
|
||||||
|
|
||||||
// registers
|
// registers
|
||||||
|
pub current_scanline: usize, // VCOUNT
|
||||||
pub dispcnt: DisplayControl,
|
pub dispcnt: DisplayControl,
|
||||||
pub dispstat: DisplayStatus,
|
pub dispstat: DisplayStatus,
|
||||||
|
|
||||||
pub bg: [Bg; 4],
|
pub bg: [Bg; 4],
|
||||||
pub bg_aff: [BgAffine; 2],
|
pub bg_aff: [BgAffine; 2],
|
||||||
|
|
||||||
pub win0h: u16,
|
pub win0: Window,
|
||||||
pub win1h: u16,
|
pub win1: Window,
|
||||||
pub win0v: u16,
|
pub winout_flags: WindowFlags,
|
||||||
pub win1v: u16,
|
pub winobj_flags: WindowFlags,
|
||||||
pub winin: u16,
|
|
||||||
pub winout: u16,
|
|
||||||
pub mosaic: RegMosaic,
|
pub mosaic: RegMosaic,
|
||||||
pub bldcnt: BlendControl,
|
pub bldcnt: BlendControl,
|
||||||
pub bldalpha: BlendAlpha,
|
pub bldalpha: BlendAlpha,
|
||||||
pub bldy: u16,
|
pub bldy: u16,
|
||||||
|
|
||||||
cycles: usize,
|
|
||||||
|
|
||||||
pub frame_buffer: FrameBuffer,
|
pub frame_buffer: FrameBuffer,
|
||||||
pub state: GpuState,
|
|
||||||
pub current_scanline: usize, // VCOUNT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
|
@ -208,12 +243,10 @@ impl Gpu {
|
||||||
dispstat: DisplayStatus(0),
|
dispstat: DisplayStatus(0),
|
||||||
bg: [Bg::default(); 4],
|
bg: [Bg::default(); 4],
|
||||||
bg_aff: [BgAffine::default(); 2],
|
bg_aff: [BgAffine::default(); 2],
|
||||||
win0h: 0,
|
win0: Window::default(),
|
||||||
win1h: 0,
|
win1: Window::default(),
|
||||||
win0v: 0,
|
winout_flags: WindowFlags::from(0),
|
||||||
win1v: 0,
|
winobj_flags: WindowFlags::from(0),
|
||||||
winin: 0,
|
|
||||||
winout: 0,
|
|
||||||
mosaic: RegMosaic(0),
|
mosaic: RegMosaic(0),
|
||||||
bldcnt: BlendControl(0),
|
bldcnt: BlendControl(0),
|
||||||
bldalpha: BlendAlpha(0),
|
bldalpha: BlendAlpha(0),
|
||||||
|
@ -405,10 +438,10 @@ impl Gpu {
|
||||||
_ => panic!("{:?} not supported", self.dispcnt.mode()),
|
_ => panic!("{:?} not supported", self.dispcnt.mode()),
|
||||||
}
|
}
|
||||||
self.mosaic_sfx();
|
self.mosaic_sfx();
|
||||||
let post_blend_line = self.blend_line(sb);
|
let post_sfx_line = self.composite_sfx(sb);
|
||||||
for x in 0..DISPLAY_WIDTH {
|
for x in 0..DISPLAY_WIDTH {
|
||||||
self.frame_buffer.0[x + self.current_scanline * DISPLAY_WIDTH] =
|
self.frame_buffer.0[x + self.current_scanline * DISPLAY_WIDTH] =
|
||||||
post_blend_line[x].to_rgb24();
|
post_sfx_line[x].to_rgb24();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::blend::BldMode;
|
use super::sfx::BldMode;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub const SCREEN_BLOCK_SIZE: u32 = 0x800;
|
pub const SCREEN_BLOCK_SIZE: u32 = 0x800;
|
||||||
|
@ -7,6 +7,9 @@ impl DisplayControl {
|
||||||
pub fn disp_bg(&self, bg: usize) -> bool {
|
pub fn disp_bg(&self, bg: usize) -> bool {
|
||||||
self.0.bit(8 + bg)
|
self.0.bit(8 + bg)
|
||||||
}
|
}
|
||||||
|
pub fn is_using_windows(&self) -> bool {
|
||||||
|
self.disp_window0() || self.disp_window1() || self.disp_obj_window()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BgControl {
|
impl BgControl {
|
||||||
|
@ -106,6 +109,7 @@ bitfield! {
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
#[derive(Default)]
|
||||||
pub struct BlendFlags: u32 {
|
pub struct BlendFlags: u32 {
|
||||||
const BG0 = 0b00000001;
|
const BG0 = 0b00000001;
|
||||||
const BG1 = 0b00000010;
|
const BG1 = 0b00000010;
|
||||||
|
@ -122,12 +126,18 @@ impl From<u16> for BlendFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const BG_LAYER_FLAG: [BlendFlags; 4] = [
|
impl BlendFlags {
|
||||||
BlendFlags::BG0,
|
const BG_LAYER_FLAG: [BlendFlags; 4] = [
|
||||||
BlendFlags::BG1,
|
BlendFlags::BG0,
|
||||||
BlendFlags::BG2,
|
BlendFlags::BG1,
|
||||||
BlendFlags::BG3,
|
BlendFlags::BG2,
|
||||||
];
|
BlendFlags::BG3,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn from_bg(bg: usize) -> BlendFlags {
|
||||||
|
Self::BG_LAYER_FLAG[bg]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitfield! {
|
bitfield! {
|
||||||
#[derive(Default, Copy, Clone)]
|
#[derive(Default, Copy, Clone)]
|
||||||
|
@ -146,3 +156,46 @@ bitfield! {
|
||||||
pub eva, _: 5, 0;
|
pub eva, _: 5, 0;
|
||||||
pub evb, _: 12, 8;
|
pub evb, _: 12, 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WindowFlags: u32 {
|
||||||
|
const BG0 = 0b00000001;
|
||||||
|
const BG1 = 0b00000010;
|
||||||
|
const BG2 = 0b00000100;
|
||||||
|
const BG3 = 0b00001000;
|
||||||
|
const OBJ = 0b00010000;
|
||||||
|
const SFX = 0b00100000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u16> for WindowFlags {
|
||||||
|
fn from(v: u16) -> WindowFlags {
|
||||||
|
WindowFlags::from_bits(v as u32).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowFlags {
|
||||||
|
pub fn sfx_enabled(&self) -> bool {
|
||||||
|
self.contains(WindowFlags::SFX)
|
||||||
|
}
|
||||||
|
pub fn bg_enabled(&self, bg: usize) -> bool {
|
||||||
|
self.contains(BG_WIN_FLAG[bg])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BG_WIN_FLAG: [WindowFlags; 4] = [
|
||||||
|
WindowFlags::BG0,
|
||||||
|
WindowFlags::BG1,
|
||||||
|
WindowFlags::BG2,
|
||||||
|
WindowFlags::BG3,
|
||||||
|
];
|
||||||
|
|
||||||
|
bitfield! {
|
||||||
|
#[derive(Default, Copy, Clone)]
|
||||||
|
pub struct WindowReg(u16);
|
||||||
|
impl Debug;
|
||||||
|
u16;
|
||||||
|
pub into WindowFlags, lower, _: 5, 0;
|
||||||
|
pub into WindowFlags, upper, _: 13, 8;
|
||||||
|
}
|
||||||
|
|
|
@ -27,91 +27,168 @@ impl Rgb15 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<WindowFlags> for BlendFlags {
|
||||||
|
fn from(wf: WindowFlags) -> BlendFlags {
|
||||||
|
BlendFlags::from_bits(wf.bits()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct Layer {
|
||||||
|
color: Rgb15,
|
||||||
|
blend_flag: BlendFlags,
|
||||||
|
}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
fn get_topmost_color(
|
fn get_top_layer(
|
||||||
&self,
|
&self,
|
||||||
sb: &SysBus,
|
sb: &SysBus,
|
||||||
screen_x: usize,
|
screen_x: usize,
|
||||||
layers: &BlendFlags,
|
bflags: BlendFlags,
|
||||||
) -> Option<Rgb15> {
|
wflags: WindowFlags,
|
||||||
|
) -> Option<Layer> {
|
||||||
// TODO - only BGs are supported, don't forget OBJs
|
// TODO - only BGs are supported, don't forget OBJs
|
||||||
|
|
||||||
let mut color: Option<Rgb15> = None;
|
|
||||||
|
|
||||||
// priorities are 0-4 when 0 is the highest
|
// priorities are 0-4 when 0 is the highest
|
||||||
'outer: for priority in 0..4 {
|
'outer: for priority in 0..4 {
|
||||||
for bg in 0..4 {
|
for bg in 0..4 {
|
||||||
let c = self.bg[bg].line[screen_x];
|
let c = self.bg[bg].line[screen_x];
|
||||||
|
let bflag = BlendFlags::from_bg(bg);
|
||||||
if self.dispcnt.disp_bg(bg)
|
if self.dispcnt.disp_bg(bg)
|
||||||
&& !c.is_transparent()
|
&& !c.is_transparent()
|
||||||
&& (layers.is_empty() || layers.contains(BG_LAYER_FLAG[bg]))
|
&& bflags.contains(bflag)
|
||||||
|
&& wflags.bg_enabled(bg)
|
||||||
&& self.bg[bg].bgcnt.priority() == priority
|
&& self.bg[bg].bgcnt.priority() == priority
|
||||||
{
|
{
|
||||||
color = Some(c);
|
return Some(Layer {
|
||||||
break 'outer;
|
color: c,
|
||||||
|
blend_flag: bflag,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if color.is_none() && layers.contains(BlendFlags::BACKDROP) {
|
if bflags.contains(BlendFlags::BACKDROP) {
|
||||||
color = Some(Rgb15(sb.palette_ram.read_16(0)))
|
return Some(Layer {
|
||||||
|
color: Rgb15(sb.palette_ram.read_16(0)),
|
||||||
|
blend_flag: BlendFlags::BACKDROP,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
color
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blend_line(&mut self, sb: &mut SysBus) -> Scanline {
|
fn get_active_window_type(&self, x: usize, y: usize) -> WindowType {
|
||||||
let mut bld_line = Scanline::default();
|
if !self.dispcnt.is_using_windows() {
|
||||||
let bldmode = self.bldcnt.mode();
|
WindowType::WinNone
|
||||||
match bldmode {
|
} else {
|
||||||
BldMode::BldAlpha => {
|
if self.dispcnt.disp_window0() && self.win0.inside(x, y) {
|
||||||
let top_layers = self.bldcnt.top();
|
return WindowType::Win0;
|
||||||
let bottom_layers = self.bldcnt.bottom();
|
}
|
||||||
|
if self.dispcnt.disp_window1() && self.win1.inside(x, y) {
|
||||||
|
return WindowType::Win1;
|
||||||
|
}
|
||||||
|
// TODO win_obj
|
||||||
|
return WindowType::WinOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for x in 0..DISPLAY_WIDTH {
|
fn get_window_flags(&self, wintyp: WindowType) -> WindowFlags {
|
||||||
if let Some(top_color) = self.get_topmost_color(sb, x, &top_layers) {
|
match wintyp {
|
||||||
if let Some(bot_color) = self.get_topmost_color(sb, x, &bottom_layers) {
|
WindowType::Win0 => self.win0.flags,
|
||||||
let eva = self.bldalpha.eva();
|
WindowType::Win1 => self.win1.flags,
|
||||||
let evb = self.bldalpha.evb();
|
WindowType::WinObj => self.winobj_flags,
|
||||||
bld_line[x] = top_color.blend_with(bot_color, eva, evb);
|
WindowType::WinOut => self.winout_flags,
|
||||||
} else {
|
WindowType::WinNone => WindowFlags::all(),
|
||||||
bld_line[x] = top_color;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sfx_blend_alpha(
|
||||||
|
&self,
|
||||||
|
sb: &SysBus,
|
||||||
|
x: usize,
|
||||||
|
_y: usize,
|
||||||
|
wflags: WindowFlags,
|
||||||
|
) -> Option<Rgb15> {
|
||||||
|
let top_layers = self.bldcnt.top();
|
||||||
|
let bottom_layers = self.bldcnt.bottom();
|
||||||
|
if let Some(top_layer) = self.get_top_layer(sb, x, top_layers, wflags) {
|
||||||
|
if let Some(bot_layer) = self.get_top_layer(sb, x, bottom_layers, wflags) {
|
||||||
|
let eva = self.bldalpha.eva();
|
||||||
|
let evb = self.bldalpha.evb();
|
||||||
|
return Some(top_layer.color.blend_with(bot_layer.color, eva, evb));
|
||||||
|
} else {
|
||||||
|
return Some(top_layer.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sfx_blend_bw(
|
||||||
|
&self,
|
||||||
|
sb: &SysBus,
|
||||||
|
fadeto: Rgb15,
|
||||||
|
x: usize,
|
||||||
|
_y: usize,
|
||||||
|
wflags: WindowFlags,
|
||||||
|
) -> Option<Rgb15> {
|
||||||
|
let top_layers = self.bldcnt.top();
|
||||||
|
let evy = self.bldy;
|
||||||
|
|
||||||
|
if let Some(layer) = self.get_top_layer(sb, x, top_layers, wflags) {
|
||||||
|
return Some(layer.color.blend_with(fadeto, 16 - evy, evy));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn composite_sfx(&self, sb: &SysBus) -> Scanline {
|
||||||
|
let mut line = Scanline::default();
|
||||||
|
let y = self.current_scanline;
|
||||||
|
for x in 0..DISPLAY_WIDTH {
|
||||||
|
let window = self.get_active_window_type(x, y);
|
||||||
|
let wflags = self.get_window_flags(window);
|
||||||
|
let toplayer = self
|
||||||
|
.get_top_layer(sb, x, BlendFlags::all(), wflags)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let bldmode = if wflags.sfx_enabled() {
|
||||||
|
self.bldcnt.mode()
|
||||||
|
} else {
|
||||||
|
BldMode::BldNone
|
||||||
|
};
|
||||||
|
|
||||||
|
match bldmode {
|
||||||
|
BldMode::BldAlpha => {
|
||||||
|
if self.bldcnt.top().contains(toplayer.blend_flag)
|
||||||
|
|| self.bldcnt.bottom().contains(toplayer.blend_flag)
|
||||||
|
{
|
||||||
|
line[x] = self
|
||||||
|
.sfx_blend_alpha(sb, x, y, wflags)
|
||||||
|
.unwrap_or(toplayer.color);
|
||||||
} else {
|
} else {
|
||||||
bld_line[x] = self.get_topmost_color(sb, x, &BlendFlags::all()).unwrap();
|
line[x] = toplayer.color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
BldMode::BldWhite => {
|
||||||
BldMode::BldWhite => {
|
let result = if self.bldcnt.top().contains(toplayer.blend_flag) {
|
||||||
let top_layers = self.bldcnt.top();
|
self.sfx_blend_bw(sb, Rgb15::WHITE, x, y, wflags)
|
||||||
let evy = self.bldy;
|
.unwrap_or(toplayer.color)
|
||||||
|
} else {
|
||||||
for x in 0..DISPLAY_WIDTH {
|
toplayer.color
|
||||||
bld_line[x] =
|
};
|
||||||
if let Some(top_color) = self.get_topmost_color(sb, x, &top_layers) {
|
line[x] = result;
|
||||||
top_color.blend_with(Rgb15::WHITE, 16 - evy, evy)
|
|
||||||
} else {
|
|
||||||
self.get_topmost_color(sb, x, &BlendFlags::all()).unwrap()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
BldMode::BldBlack => {
|
||||||
BldMode::BldBlack => {
|
let result = if self.bldcnt.top().contains(toplayer.blend_flag) {
|
||||||
let top_layers = self.bldcnt.top();
|
self.sfx_blend_bw(sb, Rgb15::BLACK, x, y, wflags)
|
||||||
let evy = self.bldy;
|
.unwrap_or(toplayer.color)
|
||||||
|
} else {
|
||||||
for x in 0..DISPLAY_WIDTH {
|
toplayer.color
|
||||||
bld_line[x] =
|
};
|
||||||
if let Some(top_color) = self.get_topmost_color(sb, x, &top_layers) {
|
line[x] = result;
|
||||||
top_color.blend_with(Rgb15::BLACK, 16 - evy, evy)
|
|
||||||
} else {
|
|
||||||
self.get_topmost_color(sb, x, &BlendFlags::all()).unwrap()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
BldMode::BldNone => {
|
||||||
BldMode::BldNone => {
|
line[x] = toplayer.color;
|
||||||
for x in 0..DISPLAY_WIDTH {
|
|
||||||
bld_line[x] = self.get_topmost_color(sb, x, &BlendFlags::all()).unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bld_line
|
line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use super::arm7tdmi::{Addr, Bus};
|
use super::arm7tdmi::{Addr, Bus};
|
||||||
use super::gba::IoDevices;
|
use super::gba::IoDevices;
|
||||||
|
use super::gpu::regs::WindowFlags;
|
||||||
use super::keypad;
|
use super::keypad;
|
||||||
use super::sysbus::BoxedMemory;
|
use super::sysbus::BoxedMemory;
|
||||||
|
|
||||||
|
@ -163,12 +164,16 @@ impl Bus for IoRegs {
|
||||||
REG_BG1CNT => io.gpu.bg[1].bgcnt.0,
|
REG_BG1CNT => io.gpu.bg[1].bgcnt.0,
|
||||||
REG_BG2CNT => io.gpu.bg[2].bgcnt.0,
|
REG_BG2CNT => io.gpu.bg[2].bgcnt.0,
|
||||||
REG_BG3CNT => io.gpu.bg[3].bgcnt.0,
|
REG_BG3CNT => io.gpu.bg[3].bgcnt.0,
|
||||||
REG_WIN0H => io.gpu.win0h,
|
REG_WIN0H => ((io.gpu.win0.left as u16) << 8 | (io.gpu.win0.right as u16)),
|
||||||
REG_WIN1H => io.gpu.win1h,
|
REG_WIN1H => ((io.gpu.win1.left as u16) << 8 | (io.gpu.win1.right as u16)),
|
||||||
REG_WIN0V => io.gpu.win0v,
|
REG_WIN0V => ((io.gpu.win0.top as u16) << 8 | (io.gpu.win0.bottom as u16)),
|
||||||
REG_WIN1V => io.gpu.win1v,
|
REG_WIN1V => ((io.gpu.win1.top as u16) << 8 | (io.gpu.win1.bottom as u16)),
|
||||||
REG_WININ => io.gpu.winin,
|
REG_WININ => {
|
||||||
REG_WINOUT => io.gpu.winout,
|
((io.gpu.win1.flags.bits() as u16) << 8) | (io.gpu.win0.flags.bits() as u16)
|
||||||
|
}
|
||||||
|
REG_WINOUT => {
|
||||||
|
((io.gpu.winobj_flags.bits() as u16) << 8) | (io.gpu.winout_flags.bits() as u16)
|
||||||
|
}
|
||||||
REG_BLDCNT => io.gpu.bldcnt.0,
|
REG_BLDCNT => io.gpu.bldcnt.0,
|
||||||
REG_BLDALPHA => io.gpu.bldalpha.0,
|
REG_BLDALPHA => io.gpu.bldalpha.0,
|
||||||
|
|
||||||
|
@ -236,12 +241,38 @@ impl Bus for IoRegs {
|
||||||
REG_BG3PB => io.gpu.bg_aff[1].pb = value as i16,
|
REG_BG3PB => io.gpu.bg_aff[1].pb = value as i16,
|
||||||
REG_BG3PC => io.gpu.bg_aff[1].pc = value as i16,
|
REG_BG3PC => io.gpu.bg_aff[1].pc = value as i16,
|
||||||
REG_BG3PD => io.gpu.bg_aff[1].pd = value as i16,
|
REG_BG3PD => io.gpu.bg_aff[1].pd = value as i16,
|
||||||
REG_WIN0H => io.gpu.win0h = value,
|
REG_WIN0H => {
|
||||||
REG_WIN1H => io.gpu.win1h = value,
|
let right = value & 0xff;
|
||||||
REG_WIN0V => io.gpu.win0v = value,
|
let left = value >> 8;
|
||||||
REG_WIN1V => io.gpu.win1v = value,
|
io.gpu.win0.right = right as u8;
|
||||||
REG_WININ => io.gpu.winin = value,
|
io.gpu.win0.left = left as u8;
|
||||||
REG_WINOUT => io.gpu.winout = value,
|
}
|
||||||
|
REG_WIN1H => {
|
||||||
|
let right = value & 0xff;
|
||||||
|
let left = value >> 8;
|
||||||
|
io.gpu.win1.right = right as u8;
|
||||||
|
io.gpu.win1.left = left as u8;
|
||||||
|
}
|
||||||
|
REG_WIN0V => {
|
||||||
|
let bottom = value & 0xff;
|
||||||
|
let top = value >> 8;
|
||||||
|
io.gpu.win0.bottom = bottom as u8;
|
||||||
|
io.gpu.win0.top = top as u8;
|
||||||
|
}
|
||||||
|
REG_WIN1V => {
|
||||||
|
let bottom = value & 0xff;
|
||||||
|
let top = value >> 8;
|
||||||
|
io.gpu.win1.bottom = bottom as u8;
|
||||||
|
io.gpu.win1.top = top as u8;
|
||||||
|
}
|
||||||
|
REG_WININ => {
|
||||||
|
io.gpu.win0.flags = WindowFlags::from(value & 0xff);
|
||||||
|
io.gpu.win1.flags = WindowFlags::from(value >> 8);
|
||||||
|
}
|
||||||
|
REG_WINOUT => {
|
||||||
|
io.gpu.winout_flags = WindowFlags::from(value & 0xff);
|
||||||
|
io.gpu.winobj_flags = WindowFlags::from(value >> 8);
|
||||||
|
}
|
||||||
REG_MOSAIC => io.gpu.mosaic.0 = value,
|
REG_MOSAIC => io.gpu.mosaic.0 = value,
|
||||||
REG_BLDCNT => io.gpu.bldcnt.0 = value,
|
REG_BLDCNT => io.gpu.bldcnt.0 = value,
|
||||||
REG_BLDALPHA => io.gpu.bldalpha.0 = value,
|
REG_BLDALPHA => io.gpu.bldalpha.0 = value,
|
||||||
|
|
Reference in a new issue