1use crate::api::VideoFrame;
2
3const NES_RGB_PALETTE: [[u8; 3]; 64] = [
4 [84, 84, 84],
5 [0, 30, 116],
6 [8, 16, 144],
7 [48, 0, 136],
8 [68, 0, 100],
9 [92, 0, 48],
10 [84, 4, 0],
11 [60, 24, 0],
12 [32, 42, 0],
13 [8, 58, 0],
14 [0, 64, 0],
15 [0, 60, 0],
16 [0, 50, 60],
17 [0, 0, 0],
18 [0, 0, 0],
19 [0, 0, 0],
20 [152, 150, 152],
21 [8, 76, 196],
22 [48, 50, 236],
23 [92, 30, 228],
24 [136, 20, 176],
25 [160, 20, 100],
26 [152, 34, 32],
27 [120, 60, 0],
28 [84, 90, 0],
29 [40, 114, 0],
30 [8, 124, 0],
31 [0, 118, 40],
32 [0, 102, 120],
33 [0, 0, 0],
34 [0, 0, 0],
35 [0, 0, 0],
36 [236, 238, 236],
37 [76, 154, 236],
38 [120, 124, 236],
39 [176, 98, 236],
40 [228, 84, 236],
41 [236, 88, 180],
42 [236, 106, 100],
43 [212, 136, 32],
44 [160, 170, 0],
45 [116, 196, 0],
46 [76, 208, 32],
47 [56, 204, 108],
48 [56, 180, 204],
49 [60, 60, 60],
50 [0, 0, 0],
51 [0, 0, 0],
52 [236, 238, 236],
53 [168, 204, 236],
54 [188, 188, 236],
55 [212, 178, 236],
56 [236, 174, 236],
57 [236, 174, 212],
58 [236, 180, 176],
59 [228, 196, 144],
60 [204, 210, 120],
61 [180, 222, 120],
62 [168, 226, 144],
63 [152, 226, 180],
64 [160, 214, 228],
65 [160, 162, 160],
66 [0, 0, 0],
67 [0, 0, 0],
68];
69
70pub fn palette_index_to_rgb(index: u8) -> [u8; 3] {
71 NES_RGB_PALETTE[(index & 0x3F) as usize]
72}
73
74pub fn frame_to_rgb(frame: VideoFrame<'_>) -> Vec<u8> {
75 let mut rgb = Vec::with_capacity(frame.pixels.len() * 3);
76 for &pixel in frame.pixels {
77 rgb.extend_from_slice(&palette_index_to_rgb(pixel));
78 }
79 rgb
80}
81
82pub fn frame_to_argb32(frame: VideoFrame<'_>) -> Vec<u32> {
83 let mut argb = Vec::with_capacity(frame.pixels.len());
84 for &pixel in frame.pixels {
85 let [r, g, b] = palette_index_to_rgb(pixel);
86 argb.push((0xFF_u32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b));
87 }
88 argb
89}
90
91pub struct VideoBuffer {
93 buffer: Vec<u32>,
94}
95
96impl VideoBuffer {
97 pub fn new(capacity: usize) -> Self {
98 Self {
99 buffer: vec![0; capacity],
100 }
101 }
102
103 pub fn as_mut_slice(&mut self) -> &mut [u32] {
104 &mut self.buffer
105 }
106
107 pub fn as_slice(&self) -> &[u32] {
108 &self.buffer
109 }
110}
111
112pub fn frame_to_argb32_into(frame: VideoFrame<'_>, output: &mut [u32]) {
114 for (dst, &pixel) in output.iter_mut().zip(frame.pixels) {
115 let [r, g, b] = palette_index_to_rgb(pixel);
116 *dst = (0xFF_u32 << 24) | (u32::from(r) << 16) | (u32::from(g) << 8) | u32::from(b);
117 }
118}