-
Notifications
You must be signed in to change notification settings - Fork 8
/
lib.rs
147 lines (121 loc) · 3.69 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#![cfg_attr(target_os = "none", no_std)]
use core::borrow::Borrow;
use m4vga::rast::direct;
use m4vga::util::race_buf::{RaceBuffer, RaceReader, RaceWriter};
use m4vga_fx_common::{Demo, Raster, Render};
use math::{Augment, Mat3f, Matrix, Project, Vec2};
#[cfg(target_os = "none")]
use libm::F32Ext;
pub const NATIVE_WIDTH: usize = 800;
pub const NATIVE_HEIGHT: usize = 600;
const X_SCALE: usize = 2;
const Y_SCALE: usize = 2;
const WIDTH: usize = 800 / X_SCALE;
const HEIGHT: usize = 600 / Y_SCALE;
pub const HALF_HEIGHT: usize = HEIGHT / 2;
const COLS: f32 = WIDTH as f32;
const ROWS: f32 = HEIGHT as f32;
pub const BUFFER_STRIDE: usize = WIDTH / 4;
const ROT: f32 = 0.005;
pub type Row = [u32; BUFFER_STRIDE];
pub struct State<S> {
pub race_buf: RaceBuffer<S, Row>,
pub m: Mat3f,
pub rot: Mat3f,
}
impl<S> State<S> {
pub fn new(segments: [S; 2]) -> Self {
State {
race_buf: RaceBuffer::new(segments),
m: Mat3f::identity(),
rot: Mat3f::rotate(ROT),
}
}
}
pub struct RasterState<'a, S> {
reader: RaceReader<'a, S, Row>,
}
pub struct RenderState<'a, S> {
writer: RaceWriter<'a, S, Row>,
m: &'a mut Mat3f,
rot: &'a Mat3f,
}
impl<'a, S: 'a> Demo<'a> for State<S>
where
S: Borrow<[Row]> + AsMut<[Row]>,
{
type Raster = RasterState<'a, S>;
type Render = RenderState<'a, S>;
fn split(&'a mut self) -> (Self::Raster, Self::Render) {
let (reader, writer) = self.race_buf.split();
(
RasterState { reader },
RenderState {
writer,
m: &mut self.m,
rot: &self.rot,
},
)
}
}
impl<'a, S> Raster for RasterState<'a, S>
where
S: Borrow<[Row]>,
{
fn raster_callback(
&mut self,
ln: usize,
target: &mut m4vga::rast::TargetBuffer,
ctx: &mut m4vga::rast::RasterCtx,
p: m4vga::priority::I0,
) {
let buf = self.reader.take_line(ln / Y_SCALE, &p);
ctx.cycles_per_pixel *= X_SCALE;
ctx.repeat_lines = Y_SCALE - 1;
direct::direct_color(0, target, ctx, buf, BUFFER_STRIDE);
}
}
impl<'a, S> Render for RenderState<'a, S>
where
S: Borrow<[Row]> + AsMut<[Row]>,
{
fn render_frame(&mut self, frame: usize, thread: m4vga::priority::Thread) {
self.writer.reset(&thread);
m4vga::util::measurement::sig_d_set();
let s = (frame as f32 / 50.).sin() * 0.7 + 1.;
let tx = (frame as f32 / 100.).cos() * 100.;
let ty = 0.;
let m_ = *self.m * Mat3f::translate(tx, ty) * Mat3f::scale(s, s);
let top_left = (m_ * Vec2(-COLS / 2., -ROWS / 2.).augment()).project();
let top_right = (m_ * Vec2(COLS / 2., -ROWS / 2.).augment()).project();
let bot_left = (m_ * Vec2(-COLS / 2., ROWS / 2.).augment()).project();
let xi = (top_right - top_left) * (1. / COLS);
let yi = (bot_left - top_left) * (1. / ROWS);
let mut ybase = top_left;
for _ in 0..HEIGHT {
let mut buf = self.writer.generate_line(&thread);
let buf = u32_as_u8_mut(&mut *buf);
{
let mut pos = ybase;
for x in 0..WIDTH {
buf[x] = tex_fetch(pos.0, pos.1) as u8;
pos = pos + xi;
}
}
ybase = ybase + yi;
}
*self.m = *self.m * *self.rot;
m4vga::util::measurement::sig_d_clear();
}
}
fn u32_as_u8_mut(slice: &mut [u32]) -> &mut [u8] {
unsafe {
core::slice::from_raw_parts_mut(
slice.as_mut_ptr() as *mut u8,
slice.len() * 4,
)
}
}
fn tex_fetch(u: f32, v: f32) -> u32 {
u as i32 as u32 ^ v as i32 as u32
}