1use super::{
2 base_system::{BaseSystem, MSX_H, MSX_W1, MSX_W2},
3 vdp::{SCREEN0, SCREEN1, SCREEN2},
4};
5
6use std::cell::RefCell;
7
8use sdl3::{
9 pixels::{Color, PixelFormat},
10 render::{FRect, Texture},
11 surface::Surface,
12 sys::pixels::SDL_PixelFormat,
13};
14
15fn color_from_hex(pixel: u32) -> Color {
17 Color::from_u32(
18 unsafe { &PixelFormat::from_ll(SDL_PixelFormat::ARGB8888) },
19 pixel,
20 )
21}
22
23#[derive(Clone, Debug, Copy)]
24enum ActiveTexture {
25 Tex256,
26 Tex320,
27}
28
29#[derive(PartialEq)]
30pub enum GraphicsType {
31 None,
32 Normal,
33}
34
35impl GraphicsType {
36 pub fn create<'a>(self, quality: bool) -> GraphicsDriver<'a> {
37 match self {
38 GraphicsType::None => GraphicsDriver::None, GraphicsType::Normal => {
40 let surface256 = Surface::new(MSX_W2, MSX_H, unsafe {
41 PixelFormat::from_ll(SDL_PixelFormat::RGB24)
42 })
43 .unwrap();
44 let surface320 = Surface::new(MSX_W1, MSX_H, unsafe {
45 PixelFormat::from_ll(SDL_PixelFormat::RGB24)
46 })
47 .unwrap();
48 let colors = [
49 color_from_hex(0xff000000),
50 color_from_hex(0xff010101),
51 color_from_hex(0xff3eb849),
52 color_from_hex(0xff74d07d),
53 color_from_hex(0xff5955e0),
54 color_from_hex(0xff8076f1),
55 color_from_hex(0xffb95e51),
56 color_from_hex(0xff65dbef),
57 color_from_hex(0xffdb6559),
58 color_from_hex(0xffff897d),
59 color_from_hex(0xffccc35e),
60 color_from_hex(0xffded087),
61 color_from_hex(0xff3aa241),
62 color_from_hex(0xffb766b5),
63 color_from_hex(0xffcccccc),
64 color_from_hex(0xffffffff),
65 ];
66 let param = GraphicsDriverNormalParam {
67 quality,
68 surface256,
69 surface320,
70 active_texture: ActiveTexture::Tex256,
71 x0: 0,
72 y0: 0,
73 };
74 GraphicsDriver::Normal(colors, RefCell::new(param))
75 }
76 }
77 }
78}
79
80pub struct GraphicsDriverNormalParam<'a> {
81 quality: bool,
82 surface256: Surface<'a>,
83 surface320: Surface<'a>,
84 active_texture: ActiveTexture,
85 x0: i16,
86 y0: i16,
87}
88
89pub enum GraphicsDriver<'a> {
90 None,
91 Normal([Color; 16], RefCell<GraphicsDriverNormalParam<'a>>),
92}
93
94impl GraphicsDriver<'_> {
95 pub fn render(&self, sys: &mut BaseSystem) {
96 match &self {
97 GraphicsDriver::None => {}
98 GraphicsDriver::Normal(_colors, param) => {
99 let active_texture = param.borrow().active_texture;
100 let x0 = param.borrow().x0 as f32;
101 let y0 = param.borrow().y0 as f32;
102 match active_texture {
103 ActiveTexture::Tex256 => {
104 let canvas = sys.get_canvas();
105 let texture_creator = canvas.texture_creator();
106 let mut texture =
107 Texture::from_surface(¶m.borrow().surface256, &texture_creator)
108 .unwrap();
109 texture.set_scale_mode(if param.borrow().quality {
110 sdl3::render::ScaleMode::Linear
111 } else {
112 sdl3::render::ScaleMode::Nearest
113 });
114 canvas.clear();
115 canvas
116 .copy(
117 &texture,
118 None,
119 FRect {
120 x: x0,
121 y: y0,
122 w: x0 + MSX_W2 as f32,
123 h: y0 + MSX_H as f32,
124 },
125 )
126 .unwrap();
127 }
128 ActiveTexture::Tex320 => {
129 let canvas = sys.get_canvas();
130 let texture_creator = canvas.texture_creator();
131 let mut texture =
132 Texture::from_surface(¶m.borrow().surface256, &texture_creator)
133 .unwrap();
134 texture.set_scale_mode(if param.borrow().quality {
135 sdl3::render::ScaleMode::Linear
136 } else {
137 sdl3::render::ScaleMode::Nearest
138 });
139 canvas.clear();
140 canvas
141 .copy(
142 &texture,
143 None,
144 FRect {
145 x: x0,
146 y: y0,
147 w: x0 + MSX_W1 as f32,
148 h: y0 + MSX_H as f32,
149 },
150 )
151 .unwrap();
152 }
153 }
154 }
155 }
156 }
157 pub fn set_logical_resolution(&mut self, scr_mode: u8) {
158 match &self {
159 GraphicsDriver::None => {}
160 GraphicsDriver::Normal(_colors, param) => match scr_mode {
161 SCREEN0 => param.borrow_mut().active_texture = ActiveTexture::Tex320,
162 SCREEN2 => param.borrow_mut().active_texture = ActiveTexture::Tex256,
163 SCREEN1 => param.borrow_mut().active_texture = ActiveTexture::Tex256,
164 _ => panic!("setLogicalResolution: mode not supported"),
165 },
166 }
167 }
168 pub fn draw_pixel(&mut self, x: u32, y: u32, color: usize) {
169 match &self {
170 GraphicsDriver::None => {}
171 GraphicsDriver::Normal(colors, param) => {
172 let active_texture = param.borrow().active_texture;
173 match active_texture {
174 ActiveTexture::Tex256 => {
175 param.borrow_mut().surface256.with_lock_mut(|buffer| {
176 let offset = y as usize * 3 * MSX_W2 as usize + x as usize * 3;
177 buffer[offset] = colors[color].r;
178 buffer[offset + 1] = colors[color].g;
179 buffer[offset + 2] = colors[color].b;
180 })
181 }
182 ActiveTexture::Tex320 => {
183 param.borrow_mut().surface320.with_lock_mut(|buffer| {
184 let offset = y as usize * 3 * MSX_W1 as usize + x as usize * 3;
185 buffer[offset] = colors[color].r;
186 buffer[offset + 1] = colors[color].g;
187 buffer[offset + 2] = colors[color].b;
188 })
189 }
190 }
191 }
192 }
193 }
194}