euphrates/hardware/sms_vdp/
line.rs1use super::*;
2
3pub trait SmsVdpLineImpler: SmsVdpGraphics {
4 type Vdp: SmsVdpInternal;
5
6 fn vdp(&mut self) -> &mut Self::Vdp;
7}
8
9impl<'a, V: 'a, G: 'a> SmsVdpLineImpler for SmsVdpGraphicsImpler<'a, V, G>
10where
11 V: SmsVdpInternal,
12 Self: SmsVdpGraphics,
13{
14 type Vdp = V;
15
16 #[inline(always)]
17 fn vdp(&mut self) -> &mut Self::Vdp {
18 self.vdp
19 }
20}
21
22pub fn line<V>(x: &mut V) -> Result<(), SmsVdpGraphicsError>
23where
24 V: SmsVdpLineImpler,
25{
26 x.draw_line()?;
27
28 let vdp = x.vdp();
29
30 let v = vdp.v();
31
32 if v == vdp.active_lines() {
33 let flags = vdp.status_flags();
36 vdp.set_status_flags(flags | FRAME_INTERRUPT_FLAG);
37 vdp.set_new_irq(true);
38 }
39
40 let new_v = (v + 1) % vdp.total_lines();
41
42 vdp.set_v(new_v);
43
44 if new_v <= vdp.active_lines() {
45 let line_counter = vdp.line_counter();
47 vdp.set_line_counter(line_counter.wrapping_sub(1));
48 if vdp.line_counter() == 0xFF {
49 let reg_line_counter = vdp.reg_line_counter();
50 vdp.set_line_counter(reg_line_counter);
51 vdp.set_line_interrupt_pending(true);
52 vdp.set_new_irq(true);
53 }
54 } else {
55 let reg_line_counter = vdp.reg_line_counter();
56 vdp.set_line_counter(reg_line_counter);
57 }
58
59 if new_v == 0 {
60 let reg9 = unsafe { vdp.register_unchecked(9) };
61 vdp.set_y_scroll(reg9);
62 }
63
64 let cycles = vdp.cycles();
65 vdp.set_cycles(cycles + 342);
66
67 return Ok(());
68}