fix FS#8187 - charging breaks sleep timer. Now if the timer goes off and the player...
[Rockbox.git] / apps / plugins / rockboy / hw.c
blob10193c0d1dc86a5a63ec572275d534e51011ccd7
4 #include "rockmacros.h"
5 #include "defs.h"
6 #include "cpu-gb.h"
7 #include "hw.h"
8 #include "regs.h"
9 #include "lcd-gb.h"
10 #include "mem.h"
11 #include "fastmem.h"
14 struct hw hw IBSS_ATTR;
19 * hw_interrupt changes the virtual interrupt lines included in the
20 * specified mask to the values the corresponding bits in i take, and
21 * in doing so, raises the appropriate bit of R_IF for any interrupt
22 * lines that transition from low to high.
25 void hw_interrupt(byte i, byte mask)
27 byte oldif = R_IF;
28 i &= 0x1F & mask;
29 R_IF |= i & (hw.ilines ^ i);
31 /* FIXME - is this correct? not sure the docs understand... */
32 if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu.ime) cpu.halt = 0;
33 /* if ((i & (hw.ilines ^ i) & R_IE) && cpu.ime) cpu.halt = 0; */
34 /* if ((i & R_IE) && cpu.ime) cpu.halt = 0; */
36 hw.ilines &= ~mask;
37 hw.ilines |= i;
42 * hw_dma performs plain old memory-to-oam dma, the original dmg
43 * dma. Although on the hardware it takes a good deal of time, the cpu
44 * continues running during this mode of dma, so no special tricks to
45 * stall the cpu are necessary.
48 void hw_dma(byte b)
50 int i;
51 addr a;
53 a = ((addr)b) << 8;
54 for (i = 0; i < 160; i++, a++)
55 lcd.oam.mem[i] = readb(a);
58 void hw_hdma(void)
60 int cnt;
61 addr sa;
62 int da;
64 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
65 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
66 for (cnt=16; cnt>0; cnt--)
67 writeb(da++, readb(sa++));
68 cpu_timers(16);
69 R_HDMA1 = sa >> 8;
70 R_HDMA2 = sa & 0xF0;
71 R_HDMA3 = 0x1F & (da >> 8);
72 R_HDMA4 = da & 0xF0;
73 R_HDMA5--;
74 hw.hdma--;
77 void hw_hdma_cmd(byte c)
79 int cnt;
80 addr sa;
81 int da;
83 /* Begin or cancel HDMA */
84 if ((hw.hdma|c) & 0x80)
86 hw.hdma = c;
87 R_HDMA5 = c & 0x7f;
88 if ((R_STAT&0x03) == 0x00) hw_hdma();
89 return;
92 /* Perform GDMA */
93 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
94 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
95 cnt = (((int)c)+1) << 4;
96 /* FIXME - this should use cpu time! */
97 /*cpu_timers(102 * cnt);*/
98 cpu_timers((460>>cpu.speed)+cnt); /*dalias*/
99 /*cpu_timers(228 + (16*cnt));*/ /* this should be right according to no$ */
100 while (cnt--)
101 writeb(da++, readb(sa++));
102 R_HDMA1 = sa >> 8;
103 R_HDMA2 = sa & 0xF0;
104 R_HDMA3 = 0x1F & (da >> 8);
105 R_HDMA4 = da & 0xF0;
106 R_HDMA5 = 0xFF;
111 * pad_refresh updates the P1 register from the pad states, generating
112 * the appropriate interrupts (by quickly raising and lowering the
113 * interrupt line) if a transition has been made.
116 void pad_refresh(void)
118 byte oldp1;
119 oldp1 = R_P1;
120 R_P1 &= 0x30;
121 R_P1 |= 0xc0;
122 if (!(R_P1 & 0x10))
123 R_P1 |= (hw.pad & 0x0F);
124 if (!(R_P1 & 0x20))
125 R_P1 |= (hw.pad >> 4);
126 R_P1 ^= 0x0F;
127 if (oldp1 & ~R_P1 & 0x0F)
129 hw_interrupt(IF_PAD, IF_PAD);
130 hw_interrupt(0, IF_PAD);
136 * These simple functions just update the state of a button on the
137 * pad.
140 static void pad_press(byte k) ICODE_ATTR;
141 static void pad_press(byte k)
143 if (hw.pad & k)
144 return;
145 hw.pad |= k;
146 pad_refresh();
149 static void pad_release(byte k) ICODE_ATTR;
150 static void pad_release(byte k)
152 if (!(hw.pad & k))
153 return;
154 hw.pad &= ~k;
155 pad_refresh();
158 void pad_set(byte k, int st)
160 st ? pad_press(k) : pad_release(k);
163 void hw_reset(void)
165 hw.ilines = hw.pad = 0;
167 memset(ram.hi, 0, sizeof ram.hi);
169 R_P1 = 0xFF;
170 R_LCDC = 0x91;
171 R_BGP = 0xFC;
172 R_OBP0 = 0xFF;
173 R_OBP1 = 0xFF;
174 R_SVBK = 0x01;
175 R_HDMA5 = 0xFF;
176 R_VBK = 0xFE;