use super::{
base_system::{BaseSystem, MSX_H, MSX_W1, MSX_W2},
vdp::{SCREEN0, SCREEN1, SCREEN2},
};
use std::cell::RefCell;
use sdl3::{
pixels::{Color, PixelFormat},
render::{FRect, Texture},
surface::Surface,
sys::pixels::SDL_PixelFormat,
};
fn color_from_hex(pixel: u32) -> Color {
Color::from_u32(
unsafe { &PixelFormat::from_ll(SDL_PixelFormat::ARGB8888) },
pixel,
)
}
#[derive(Clone, Debug, Copy)]
enum ActiveTexture {
Tex256,
Tex320,
}
#[derive(PartialEq)]
pub enum GraphicsType {
None,
Normal,
}
impl GraphicsType {
pub fn create<'a>(self, quality: bool) -> GraphicsDriver<'a> {
match self {
GraphicsType::None => GraphicsDriver::None, GraphicsType::Normal => {
let surface256 = Surface::new(MSX_W2, MSX_H, unsafe {
PixelFormat::from_ll(SDL_PixelFormat::RGB24)
})
.unwrap();
let surface320 = Surface::new(MSX_W1, MSX_H, unsafe {
PixelFormat::from_ll(SDL_PixelFormat::RGB24)
})
.unwrap();
let colors = [
color_from_hex(0xff000000),
color_from_hex(0xff010101),
color_from_hex(0xff3eb849),
color_from_hex(0xff74d07d),
color_from_hex(0xff5955e0),
color_from_hex(0xff8076f1),
color_from_hex(0xffb95e51),
color_from_hex(0xff65dbef),
color_from_hex(0xffdb6559),
color_from_hex(0xffff897d),
color_from_hex(0xffccc35e),
color_from_hex(0xffded087),
color_from_hex(0xff3aa241),
color_from_hex(0xffb766b5),
color_from_hex(0xffcccccc),
color_from_hex(0xffffffff),
];
let param = GraphicsDriverNormalParam {
quality,
surface256,
surface320,
active_texture: ActiveTexture::Tex256,
x0: 0,
y0: 0,
};
GraphicsDriver::Normal(colors, RefCell::new(param))
}
}
}
}
pub struct GraphicsDriverNormalParam<'a> {
quality: bool,
surface256: Surface<'a>,
surface320: Surface<'a>,
active_texture: ActiveTexture,
x0: i16,
y0: i16,
}
pub enum GraphicsDriver<'a> {
None,
Normal([Color; 16], RefCell<GraphicsDriverNormalParam<'a>>),
}
impl GraphicsDriver<'_> {
pub fn render(&self, sys: &mut BaseSystem) {
match &self {
GraphicsDriver::None => {}
GraphicsDriver::Normal(_colors, param) => {
let active_texture = param.borrow().active_texture;
let x0 = param.borrow().x0 as f32;
let y0 = param.borrow().y0 as f32;
match active_texture {
ActiveTexture::Tex256 => {
let canvas = sys.get_canvas();
let texture_creator = canvas.texture_creator();
let texture =
Texture::from_surface(¶m.borrow().surface256, &texture_creator)
.unwrap();
canvas.clear();
canvas
.copy(
&texture,
None,
FRect {
x: x0,
y: y0,
w: x0 + MSX_W2 as f32,
h: y0 + MSX_H as f32,
},
)
.unwrap();
}
ActiveTexture::Tex320 => {
let canvas = sys.get_canvas();
let texture_creator = canvas.texture_creator();
let texture =
Texture::from_surface(¶m.borrow().surface256, &texture_creator)
.unwrap();
canvas.clear();
canvas
.copy(
&texture,
None,
FRect {
x: x0,
y: y0,
w: x0 + MSX_W1 as f32,
h: y0 + MSX_H as f32,
},
)
.unwrap();
}
}
}
}
}
pub fn set_logical_resolution(&mut self, scr_mode: u8) {
match &self {
GraphicsDriver::None => {}
GraphicsDriver::Normal(_colors, param) => match scr_mode {
SCREEN0 => param.borrow_mut().active_texture = ActiveTexture::Tex320,
SCREEN2 => param.borrow_mut().active_texture = ActiveTexture::Tex256,
SCREEN1 => param.borrow_mut().active_texture = ActiveTexture::Tex256,
_ => panic!("setLogicalResolution: mode not supported"),
},
}
}
pub fn draw_pixel(&mut self, x: u32, y: u32, color: usize) {
match &self {
GraphicsDriver::None => {}
GraphicsDriver::Normal(colors, param) => {
let active_texture = param.borrow().active_texture;
match active_texture {
ActiveTexture::Tex256 => {
param.borrow_mut().surface256.with_lock_mut(|buffer| {
let offset = y as usize * 3 * MSX_W2 as usize + x as usize * 3;
buffer[offset] = colors[color].r;
buffer[offset + 1] = colors[color].g;
buffer[offset + 2] = colors[color].b;
})
}
ActiveTexture::Tex320 => {
param.borrow_mut().surface320.with_lock_mut(|buffer| {
let offset = y as usize * 3 * MSX_W1 as usize + x as usize * 3;
buffer[offset] = colors[color].r;
buffer[offset + 1] = colors[color].g;
buffer[offset + 2] = colors[color].b;
})
}
}
}
}
}
}