From e13fbac96b9bc97d54dbaa63a1e14d850ba495dd Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Sun, 20 Feb 2022 21:28:18 -0600 Subject: [PATCH] High res text, paletted and direct --- src/display.rs | 105 +++++++++++++++++++++++++++++++++++++++++++------ src/font.rom | Bin 0 -> 2048 bytes src/main.rs | 15 ++++--- 3 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 src/font.rom diff --git a/src/display.rs b/src/display.rs index 1e6a0f0..1c4b642 100644 --- a/src/display.rs +++ b/src/display.rs @@ -13,16 +13,10 @@ struct DisplayRegisters { col_offset: u32 } -struct VideoMode { - gfx: bool, - highres: bool, - -} - impl Default for DisplayRegisters { fn default() -> Self { Self { - mode: 7, + mode: 6, screen: 0x10000, palette: 0x20000 - 0x100, font: 0x20000 - 0x100 - 0x2000, @@ -59,19 +53,43 @@ fn init_display_registers(machine: &mut P, start: Word) { machine.poke24(start + 19, dr.col_offset.into()); } +fn init_font(machine: &mut P) { + let bytes = include_bytes!("font.rom"); + let font_addr = DisplayRegisters::default().font; + + for (offset, byte) in bytes.into_iter().enumerate() { + machine.poke(Word::from(font_addr + offset as u32), *byte) + } +} + pub fn draw(machine: &P, frame: &mut[u8]) { let reg = read_display_registers(machine, 16.into()); let (gfx, highres, paletted) = (reg.mode & 1 > 0, reg.mode & 2 > 0, reg.mode & 4 > 0); - match (gfx, highres, paletted) { - (true, true, true) => draw_gfx_high_paletted(machine, reg, frame), - (true, true, false) => draw_gfx_high_direct(machine, reg, frame), - (_, _, _) => {} + match (paletted, highres, gfx) { + (true, true, true) => draw_paletted_high_gfx(machine, reg, frame), + (false, true, true) => draw_direct_high_gfx(machine, reg, frame), + (true, true, false) => draw_paletted_high_text(machine, reg, frame), + (false, true, false) => draw_direct_high_text(machine, reg, frame), + (_, _, _) => {panic!("Unimplemented mode {}", reg.mode)} } } pub fn reset(machine: &mut P) { init_display_registers(machine, 16.into()); + init_font(machine); + init_palette(machine); +} + +fn init_palette(machine: &mut P) { + let palette_addr = read_display_registers(machine, Word::from(16)).palette; + let default_palette = [ + 0x00, 0x05, 0x65, 0x11, 0xa8, 0x49, 0xeb, 0xff, + 0xe1, 0xf4, 0xfc, 0x1c, 0x37, 0x8e, 0xee, 0xfa + ]; + for (i, b) in default_palette.into_iter().enumerate() { + machine.poke(Word::from(palette_addr + i as u32), b); + } } fn to_byte_address((x, y): (u32, u32), reg: DisplayRegisters) -> u32 { @@ -79,7 +97,7 @@ fn to_byte_address((x, y): (u32, u32), reg: DisplayRegisters) -> u32 { ((x + reg.col_offset) % reg.width) + row_start } -fn draw_gfx_high_direct(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { +fn draw_direct_high_gfx(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); let (vulcan_row, vulcan_col) = ((display_row >> 2) as u32, (display_col >> 2) as u32); @@ -94,7 +112,7 @@ fn draw_gfx_high_direct(machine: &P, reg: DisplayRegisters, frame: } } -fn draw_gfx_high_paletted(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { +fn draw_paletted_high_gfx(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { let (display_row, display_col) = (i / 640, i % 640); let (vulcan_row, vulcan_col) = ((display_row >> 2) as u32, (display_col >> 2) as u32); @@ -109,4 +127,65 @@ fn draw_gfx_high_paletted(machine: &P, reg: DisplayRegisters, frame pixel[2] = blue << 5; pixel[3] = 0xff; } +} + +fn draw_paletted_high_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { + for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { + let (display_row, display_col) = (i / 640, i % 640); + let (vulcan_row, vulcan_col) = ((display_row >> 3) as u32, (display_col >> 3) as u32); + + let addr = to_byte_address((vulcan_col, vulcan_row), reg); + let char_idx= machine.peek(Word::from(addr)); + let (char_row, char_col) = (display_row % 8, display_col % 8); + let char_byte = machine.peek(Word::from(reg.font + ((char_idx as u32) << 3) + char_row as u32)); + + let color_addr = addr + (reg.width * reg.height); + let color_byte = machine.peek(Word::from(color_addr)); + let (fg_color_idx, bg_color_idx) = (color_byte & 0xf, color_byte >> 4); + + let fg_color = machine.peek(Word::from(reg.palette + fg_color_idx as u32)); + let bg_color = machine.peek(Word::from(reg.palette + bg_color_idx as u32)); + + let (fg_red, fg_green, fg_blue) = (fg_color >> 5, (fg_color >> 3) & 7, (fg_color & 3) << 1); + let (bg_red, bg_green, bg_blue) = (bg_color >> 5, (bg_color >> 3) & 7, (bg_color & 3) << 1); + + if char_byte & (1 << (7 - char_col)) != 0 { + pixel[0] = fg_red << 5; + pixel[1] = fg_green << 5; + pixel[2] = fg_blue << 5; + } else { + pixel[0] = bg_red << 5; + pixel[1] = bg_green << 5; + pixel[2] = bg_blue << 5; + } + pixel[3] = 0xff; + } +} + +fn draw_direct_high_text(machine: &P, reg: DisplayRegisters, frame: &mut [u8]) { + for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { + let (display_row, display_col) = (i / 640, i % 640); + let (vulcan_row, vulcan_col) = ((display_row >> 3) as u32, (display_col >> 3) as u32); + + let addr = to_byte_address((vulcan_col, vulcan_row), reg); + let char_idx= machine.peek(Word::from(addr)); + let (char_row, char_col) = (display_row % 8, display_col % 8); + let char_byte = machine.peek(Word::from(reg.font + ((char_idx as u32) << 3) + char_row as u32)); + + let color_addr = addr + (reg.width * reg.height); + let color = machine.peek(Word::from(color_addr)); + + let (red, green, blue) = (color >> 5, (color >> 3) & 7, (color & 3) << 1); + + if char_byte & (1 << (7 - char_col)) != 0 { + pixel[0] = red << 5; + pixel[1] = green << 5; + pixel[2] = blue << 5; + } else { + pixel[0] = 0; + pixel[1] = 0; + pixel[2] = 0; + } + pixel[3] = 0xff; + } } \ No newline at end of file diff --git a/src/font.rom b/src/font.rom new file mode 100644 index 0000000000000000000000000000000000000000..3945e5102eb546e5a6c86eb54d388ffa8c3aaa0f GIT binary patch literal 2048 zcmYLKy^1485H2oIG{_q^UZDkZ4=~YOg9q(XIB_&ArlZCv(h1y*ZxiE3@H%(mM=&-F zC+KKUC_ zH`)#S=5V;t0x?){QDt2!k<07qarJt+KsE*n$WKpDOvlq=*|y7iwW?LE)b#7AQuAXq zn-#^$Ota_GyqfY^J~hYlvH2wLM$_4J^p0*79UGDu`T6;$Z*OmJr8L@F-7cAJ2;n-f z=6sOw6%$gEFhO3D&%-?D?51e~*n4v^@4-=!qZ}N|`$DQL=|!xyQD<$yWkuDE8})GL zGnH3fwAG8YT_9d`E>Kogt^^NMmB;~j9pD1#z+t3eE~6&WT1Iq-x}9I|PJ1V687qK{ z0TaMS<;Xk9CZ!EoCZXv^l$~#S4<0-`Ab^8F8Lyh-GMS`@!4a5Ya+M)2!sDjEJmEiM zy|CMDn;La_AH0{|7-vimyn&l30W`}q_nt1_wpfd8V zn~QI|W7m2)0-ow2u%9*?`1kw$X}9)_3vw}D@&|DPsJ-uL2mg-s)ZZt+ae9j9Efx-w zH{k$(R%_(WenASQgkMk|;vq?plZFMOuUtlQSbj|YpDsDpF3~b`Z7nYq%18ae3=nSu zZ3{i+&_FKoKF^ns7i%Ey()>M;)Uo~y7FpIVUn*ml7Wzn76R`vUd<*|3`eXf3b^uh+ zRxX=TCLV|f0G#9uSI{15pzqL#v3~MRV6Q@qC3(MIz(D%n@*jE`W49?aX8ib2fJzoy zn2>G&n+;rN0Ec}ADB(cHL!HhiJiH9J3|#9Z$NZGl4(&%=xMJil12+R6&TFJlLZ7%t zvg|W#0T_713ur7frr6)>?nkM+E_B@vgSd&$mD4d~=wqI6m^ftCO}{`QmJ#g~Jk?kg zTOG~G%F5uNz`4@)8^)=pOg}~O7WIslXaQq2y{s&*-*avcT z*S0v<;*ZHS*sfbd(Gt*iRtKJ+f&CZT&>mz~Y2)MXs(yY(!;Bn{`9^ewcCXm{kq{?d zsFS~oTH^5xj#CV$Huw}_uC(MohqJIO*vQ<=X_G)rs3PMG5n^!G3T>8tX!9-~;BlZ~ GBG`X*C$>xg literal 0 HcmV?d00001 diff --git a/src/main.rs b/src/main.rs index 5d557cf..f323be5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,6 @@ use winit::{ }; use pixels::{Pixels, SurfaceTexture}; -use rand::RngCore; use std::time::Instant; use winit::window::Window; use crate::cpu::CPU; @@ -33,20 +32,20 @@ fn main() { .unwrap() }; - let mut pixels = { + let pixels = { let surface_texture = SurfaceTexture::new(640, 480, &window); Pixels::new(640, 480, surface_texture).unwrap() }; - let mut rng = rand::thread_rng(); + let rng = rand::thread_rng(); let memory = Memory::from(rng); let mut cpu = CPU::new(memory); display::reset(&mut cpu); - for n in 0..256 { - let color = ((n / 32) << 3) as u8; - cpu.poke(Word::from(0x20000 - 0x100 + n as u32), color); - } + // for n in 0..256 { + // let color = ((n / 32) << 3) as u8; + // cpu.poke(Word::from(0x20000 - 0x100 + n as u32), color); + // } window_loop(event_loop, window, pixels, cpu) } @@ -67,7 +66,7 @@ fn window_loop(event_loop: EventLoop<()>, window: Window, mut pixels: Pixels, mu let draw_time = Instant::now() - start; pixels.render().expect("Problem displaying framebuffer"); let total_time = Instant::now() - start; - //println!("Tick took {} total, {} to draw", total_time.as_micros(), draw_time.as_micros()); + println!("Tick took {} total, {} to draw", total_time.as_micros(), draw_time.as_micros()); } _ => {} }