summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/rockboy/hw.c')
-rw-r--r--apps/plugins/rockboy/hw.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/hw.c b/apps/plugins/rockboy/hw.c
new file mode 100644
index 0000000000..c287e24f8a
--- /dev/null
+++ b/apps/plugins/rockboy/hw.c
@@ -0,0 +1,183 @@
1
2
3
4#include "rockmacros.h"
5#include "defs.h"
6#include "cpu.h"
7#include "hw.h"
8#include "regs.h"
9#include "lcd.h"
10#include "mem.h"
11#include "fastmem.h"
12
13
14struct hw hw;
15
16
17
18/*
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.
23 */
24
25void hw_interrupt(byte i, byte mask)
26{
27 byte oldif = R_IF;
28 i &= 0x1F & mask;
29 R_IF |= i & (hw.ilines ^ i);
30
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; */
35
36 hw.ilines &= ~mask;
37 hw.ilines |= i;
38}
39
40
41/*
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.
46 */
47
48void hw_dma(byte b)
49{
50 int i;
51 addr a;
52
53 a = ((addr)b) << 8;
54 for (i = 0; i < 160; i++, a++)
55 lcd.oam.mem[i] = readb(a);
56}
57
58
59
60void hw_hdma_cmd(byte c)
61{
62 int cnt;
63 addr sa;
64 int da;
65
66 /* Begin or cancel HDMA */
67 if ((hw.hdma|c) & 0x80)
68 {
69 hw.hdma = c;
70 R_HDMA5 = c & 0x7f;
71 return;
72 }
73
74 /* Perform GDMA */
75 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
76 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
77 cnt = ((int)c)+1;
78 /* FIXME - this should use cpu time! */
79 /*cpu_timers(102 * cnt);*/
80 cnt <<= 4;
81 while (cnt--)
82 writeb(da++, readb(sa++));
83 R_HDMA1 = sa >> 8;
84 R_HDMA2 = sa & 0xF0;
85 R_HDMA3 = 0x1F & (da >> 8);
86 R_HDMA4 = da & 0xF0;
87 R_HDMA5 = 0xFF;
88}
89
90
91void hw_hdma(void)
92{
93 int cnt;
94 addr sa;
95 int da;
96
97 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
98 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
99 cnt = 16;
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--;
107 hw.hdma--;
108}
109
110
111/*
112 * pad_refresh updates the P1 register from the pad states, generating
113 * the appropriate interrupts (by quickly raising and lowering the
114 * interrupt line) if a transition has been made.
115 */
116
117void pad_refresh()
118{
119 byte oldp1;
120 oldp1 = R_P1;
121 R_P1 &= 0x30;
122 R_P1 |= 0xc0;
123 if (!(R_P1 & 0x10))
124 R_P1 |= (hw.pad & 0x0F);
125 if (!(R_P1 & 0x20))
126 R_P1 |= (hw.pad >> 4);
127 R_P1 ^= 0x0F;
128 if (oldp1 & ~R_P1 & 0x0F)
129 {
130 hw_interrupt(IF_PAD, IF_PAD);
131 hw_interrupt(0, IF_PAD);
132 }
133}
134
135
136/*
137 * These simple functions just update the state of a button on the
138 * pad.
139 */
140
141void pad_press(byte k)
142{
143 if (hw.pad & k)
144 return;
145 hw.pad |= k;
146 pad_refresh();
147}
148
149void pad_release(byte k)
150{
151 if (!(hw.pad & k))
152 return;
153 hw.pad &= ~k;
154 pad_refresh();
155}
156
157void pad_set(byte k, int st)
158{
159 st ? pad_press(k) : pad_release(k);
160}
161
162void hw_reset()
163{
164 hw.ilines = hw.pad = 0;
165
166 memset(ram.hi, 0, sizeof ram.hi);
167
168 R_P1 = 0xFF;
169 R_LCDC = 0x91;
170 R_BGP = 0xFC;
171 R_OBP0 = 0xFF;
172 R_OBP1 = 0xFF;
173 R_SVBK = 0x01;
174 R_HDMA5 = 0xFF;
175 R_VBK = 0xFE;
176}
177
178
179
180
181
182
183