|
2 | 2 | #![no_main] |
3 | 3 |
|
4 | 4 | pub mod eadk; |
| 5 | +use eadk::*; |
| 6 | + |
| 7 | +use core::ops::Range; |
| 8 | + |
| 9 | +#[allow(non_upper_case_globals)] |
5 | 10 |
|
6 | 11 | #[used] |
7 | 12 | #[link_section = ".rodata.eadk_app_name"] |
8 | | -pub static EADK_APP_NAME: [u8; 10] = *b"HelloRust\0"; |
| 13 | +pub static EADK_APP_NAME: [u8; 11] = *b"Mandelrust\0"; |
9 | 14 |
|
10 | 15 | #[used] |
11 | 16 | #[link_section = ".rodata.eadk_api_level"] |
12 | 17 | pub static EADK_APP_API_LEVEL: u32 = 0; |
13 | 18 |
|
14 | 19 | #[used] |
15 | 20 | #[link_section = ".rodata.eadk_app_icon"] |
16 | | -pub static EADK_APP_ICON: [u8; 4250] = *include_bytes!("../target/icon.nwi"); |
| 21 | +pub static EADK_APP_ICON: [u8; 2648] = *include_bytes!("../target/icon.nwi"); |
| 22 | + |
| 23 | +const WIDTH: usize = 320; |
| 24 | +const HEIGHT: usize = 240; |
| 25 | + |
| 26 | +fn color_range(n : u8) -> Color { |
| 27 | + let n = n as u16; |
| 28 | + let r = (n/2)<<11; |
| 29 | + let g = (0xb7*n/0xff)<<5; |
| 30 | + let b = (0x34*n/0xff)>>1; |
| 31 | + Color { rgb565: r | g | b } |
| 32 | +} |
| 33 | + |
| 34 | +const BHEIGHT : usize = 256; |
17 | 35 |
|
18 | | -fn random_u16() -> u16 { |
19 | | - return eadk::random() as u16; |
| 36 | +struct Buffer { |
| 37 | + // 5 values of 6 bits per word |
| 38 | + buffer : [[u8; BHEIGHT]; WIDTH], |
| 39 | + dx : usize, |
| 40 | + dy : usize, |
20 | 41 | } |
21 | 42 |
|
22 | | -fn random_coordinate() -> u16 { |
23 | | - return (eadk::random() % 0xFF) as u16; |
| 43 | +impl Buffer { |
| 44 | + fn new() -> Buffer { |
| 45 | + Buffer { buffer: [[0; BHEIGHT]; WIDTH], dx: 0, dy: 0 } |
| 46 | + } |
| 47 | + |
| 48 | + fn pos(&self, x: usize, y: usize) -> (usize, usize) { |
| 49 | + ((x + self.dx)%WIDTH, (y + self.dy)%BHEIGHT) |
| 50 | + } |
| 51 | + |
| 52 | + fn set(&mut self, x: usize, y:usize, v:u8) { |
| 53 | + let (xa, ya) = self.pos(x,y); |
| 54 | + self.buffer[xa][ya] = v; |
| 55 | + } |
| 56 | + |
| 57 | + fn get(&self, x: usize, y: usize) -> u8 { |
| 58 | + let (xa, ya) = self.pos(x,y); |
| 59 | + self.buffer[xa][ya] |
| 60 | + } |
| 61 | + |
| 62 | + fn scroll_x(&mut self, delta_x: isize) { |
| 63 | + self.dx = (((self.dx as isize) + delta_x + WIDTH as isize) as usize) % WIDTH; |
| 64 | + } |
| 65 | + |
| 66 | + fn scroll_y(&mut self, delta_y: isize) { |
| 67 | + self.dy = (((self.dy as isize) + delta_y + BHEIGHT as isize) as usize) % BHEIGHT; |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +struct Zone { |
| 72 | + x_range: Range<usize>, |
| 73 | + y_range: Range<usize>, |
| 74 | +} |
| 75 | + |
| 76 | +impl Zone { |
| 77 | + fn screen() -> Zone { |
| 78 | + Zone { x_range: 0..WIDTH, y_range: 0..HEIGHT } |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +fn mandel(buf: &mut Buffer, zone: Zone, x_center: f32, y_center: f32, width:f32, n:u8, coarse: bool) { |
| 83 | + let scale : f32 = width / WIDTH as f32; |
| 84 | + |
| 85 | + for xi in zone.x_range { |
| 86 | + if coarse && xi%3 != 1 { continue } |
| 87 | + let cr : f32 = ((xi as i16 - (WIDTH/2) as i16) as f32)*scale+x_center; |
| 88 | + for yi in zone.y_range.clone() { |
| 89 | + if coarse && yi%3 != 1 { continue } |
| 90 | + let ci : f32 = ((yi as i16 - (HEIGHT/2) as i16) as f32)*scale+y_center; |
| 91 | + let mut zr : f32 = 0.; |
| 92 | + let mut zi : f32 = 0.; |
| 93 | + let mut v = 63; |
| 94 | + for n in 0..n { |
| 95 | + let ozr = zr; |
| 96 | + zr = zr*zr - zi*zi + cr; |
| 97 | + zi = 2.*ozr*zi + ci; |
| 98 | + if zr*zr + zi*zi > 4. { |
| 99 | + v = n; |
| 100 | + break; |
| 101 | + } |
| 102 | + } |
| 103 | + if coarse { |
| 104 | + for x in xi-1..=xi+1 { |
| 105 | + for y in yi-1..=yi+1 { |
| 106 | + buf.set(x, y, v); |
| 107 | + } |
| 108 | + } |
| 109 | + } else { |
| 110 | + buf.set(xi, yi, v); |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +fn blit(buf: &Buffer) { |
| 117 | + display::wait_for_vblank(); |
| 118 | + const SIDE: usize = 16; |
| 119 | + let mut array = [Color { rgb565: 0 }; SIDE*SIDE]; |
| 120 | + for x in 0..WIDTH/SIDE { |
| 121 | + for y in 0..HEIGHT/SIDE { |
| 122 | + for xi in 0..SIDE { |
| 123 | + for yi in 0..SIDE { |
| 124 | + array[yi*SIDE+xi] = color_range(buf.get(x*SIDE+xi,y*SIDE+yi)); |
| 125 | + } |
| 126 | + } |
| 127 | + let r = Rect { x: (SIDE*x) as u16, y: (SIDE*y) as u16, width: SIDE |
| 128 | + as u16, height: SIDE as u16}; |
| 129 | + display::push_rect(r, &array); |
| 130 | + } |
| 131 | + } |
24 | 132 | } |
25 | 133 |
|
26 | 134 | #[no_mangle] |
27 | | -pub fn main() { |
28 | | - for _ in 0..100 { |
29 | | - let c = eadk::Color { rgb565: random_u16() }; |
30 | | - let r = eadk::Rect { x: random_coordinate(), y: random_coordinate(), width: random_coordinate(), height: random_coordinate() }; |
31 | | - eadk::display::push_rect_uniform(r, c); |
| 135 | +fn main() { |
| 136 | + let mut buffer = Buffer::new(); |
| 137 | + let mut x : f32 = -0.5; |
| 138 | + let mut y : f32 = 0.0; |
| 139 | + let mut n : u8 = 64; |
| 140 | + let mut size : f32 = 3.5; |
| 141 | + let mut was_coarse : bool = false; |
| 142 | + let delta_pixel : isize = 2; |
| 143 | + mandel(&mut buffer, Zone::screen(), x, y, size, n, false); |
| 144 | + blit(&buffer); |
| 145 | + loop { |
| 146 | + let scan = keyboard::Scan::scan(); |
| 147 | + let mut zone = Zone::screen(); |
| 148 | + use keyboard::Key::*; |
| 149 | + let factor = if scan.is_key_down(Shift) { 5 } else { 1 }; |
| 150 | + let delta_pixel = factor * delta_pixel; |
| 151 | + let delta_size = delta_pixel as f32 * size / WIDTH as f32; |
| 152 | + let mut coarse = false; |
| 153 | + if scan.is_key_down(Plus) || scan.is_key_down(Ok) { |
| 154 | + size /= 1.5; |
| 155 | + coarse = true; |
| 156 | + was_coarse = true; |
| 157 | + } else if scan.is_key_down(Minus) || scan.is_key_down(Back) { |
| 158 | + size *= 1.5; |
| 159 | + coarse = true; |
| 160 | + was_coarse = true; |
| 161 | + } else if scan.is_key_down(Multiplication) { |
| 162 | + n = (n + 4).clamp(1,63); |
| 163 | + } else if scan.is_key_down(Division) { |
| 164 | + n = (n - 4).clamp(1,100); |
| 165 | + } else if scan.is_key_down(Left) { |
| 166 | + x -= delta_size; |
| 167 | + buffer.scroll_x(-delta_pixel); |
| 168 | + zone.x_range = 0..(delta_pixel as usize); |
| 169 | + } else if scan.is_key_down(Right) { |
| 170 | + x += delta_size; |
| 171 | + buffer.scroll_x(delta_pixel); |
| 172 | + zone.x_range= (WIDTH - delta_pixel as usize)..WIDTH; |
| 173 | + } else if scan.is_key_down(Up) { |
| 174 | + y -= delta_size; |
| 175 | + buffer.scroll_y(-delta_pixel); |
| 176 | + zone.y_range = 0..(delta_pixel as usize); |
| 177 | + } else if scan.is_key_down(Down) { |
| 178 | + y += delta_size; |
| 179 | + buffer.scroll_y(delta_pixel); |
| 180 | + zone.y_range = (HEIGHT - delta_pixel as usize)..HEIGHT; |
| 181 | + } else if scan.is_key_down(Zero) { |
| 182 | + x = -0.5; y = 0.0; size = 3.5; n = 40; |
| 183 | + } else if was_coarse { |
| 184 | + was_coarse = false; |
| 185 | + } else { |
| 186 | + continue; |
| 187 | + } |
| 188 | + size = size.min(3.5); |
| 189 | + mandel(&mut buffer,zone,x,y,size,n,coarse); |
| 190 | + blit(&buffer); |
32 | 191 | } |
33 | | - loop {} |
34 | 192 | } |
0 commit comments