1use crate::ga::{Ink, Palette};
2use crate::image::Mode;
3
4pub fn compress<D: as_slice::AsSlice<Element = u8>>(data: D) -> Vec<u8> {
7 eprintln!("[WARNING] OCP compression has never been tested");
8
9 let data = data.as_slice();
10 const MARKER: u8 = 1;
11
12 let mut res = Vec::new();
13
14 res.push(b'M');
15 res.push(b'J');
16 res.push(b'H');
17
18 let length = data.len();
19 let high = (length >> 8) as u8;
20 let low = (length % 256) as u8;
21
22 res.push(low);
23 res.push(high);
24
25 let mut previous = 0;
26 let mut count = 0;
27
28 for current in &data[1..] {
29 let current = *current;
30
31 if current == MARKER {
32 if count != 0 {
33 res.push(MARKER);
34 res.push(count);
35 res.push(previous);
36 }
37
38 res.push(MARKER);
39 res.push(1);
40 res.push(MARKER);
41 }
42 else if previous == current {
43 if count == 255 {
44 res.push(MARKER);
45 res.push(0);
46 res.push(current);
47 count = 0;
48 }
49 else {
50 count += 1;
51 }
52 }
53 else {
54 if count == 1 {
55 debug_assert!(MARKER != current);
56 res.push(current);
57 }
58 else {
59 res.push(MARKER);
60 res.push(count);
61 res.push(current);
62 }
63 count = 0;
64 }
65
66 previous = current;
67 }
68
69 if count == 1 {
70 res.push(previous);
71 }
72 else if count > 1 {
73 res.push(MARKER);
74 res.push(count);
75 res.push(previous);
76 }
77
78 res
79}
80
81const NB_PAL: usize = 12;
82
83pub struct OcpPal {
84 screen_mode: Mode,
85 cycling: bool,
86 cycling_delay: u8,
87 palettes: [Palette; NB_PAL],
88
89 excluded: [u8; 16],
90 projected: [u8; 16]
91}
92
93impl OcpPal {
94 pub fn palette(&self, nb: usize) -> &Palette {
96 assert!(nb < 12);
97 &self.palettes[nb]
98 }
99
100 pub fn from_buffer(data: &[u8]) -> Self {
101 let mut data = data.iter().cloned();
102
103 let screen_mode: Mode = (data.next().unwrap()).into();
104 let cycling = data.next().unwrap() == 0xFF;
105 let cycling_delay = data.next().unwrap();
106
107 let mut palettes: [Palette; NB_PAL] = Default::default(); for pen in 0..=16i32 {
109 for idx in 0..NB_PAL {
110 let ga_ink = data.next().unwrap();
111 let ink = Ink::from_gate_array_color_number(ga_ink);
112 dbg!(pen, idx, ink);
113 palettes[idx].set(pen, ink);
114 }
115 }
116
117 let excluded = data.next_chunk().unwrap();
118 let projected = data.next_chunk().unwrap();
119
120 assert!(data.next().is_none());
121
122 Self {
123 screen_mode,
124 cycling,
125 cycling_delay,
126 palettes,
127 excluded,
128 projected
129 }
130 }
131}