fix crash when specifying --source on command line
[rofl0r-gnuboy.git] / hw.c
blob3c6caf095a51d9797360b6b3ebdfee2704281fa4
1 #include <string.h>
4 #include "defs.h"
5 #include "cpu.h"
6 #include "hw.h"
7 #include "regs.h"
8 #include "lcd.h"
9 #include "mem.h"
10 #include "fastmem.h"
13 struct hw hw;
18 * hw_interrupt changes the virtual interrupt lines included in the
19 * specified mask to the values the corresponding bits in i take, and
20 * in doing so, raises the appropriate bit of R_IF for any interrupt
21 * lines that transition from low to high.
24 void hw_interrupt(byte i, byte mask)
26 byte oldif = R_IF;
27 i &= 0x1F & mask;
28 R_IF |= i & (hw.ilines ^ i);
30 /* FIXME - is this correct? not sure the docs understand... */
31 if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu.ime) cpu.halt = 0;
32 /* if ((i & (hw.ilines ^ i) & R_IE) && cpu.ime) cpu.halt = 0; */
33 /* if ((i & R_IE) && cpu.ime) cpu.halt = 0; */
35 hw.ilines &= ~mask;
36 hw.ilines |= i;
41 * hw_dma performs plain old memory-to-oam dma, the original dmg
42 * dma. Although on the hardware it takes a good deal of time, the cpu
43 * continues running during this mode of dma, so no special tricks to
44 * stall the cpu are necessary.
47 void hw_dma(byte b)
49 int i;
50 addr a;
52 a = ((addr)b) << 8;
53 for (i = 0; i < 160; i++, a++)
54 lcd.oam.mem[i] = readb(a);
59 void hw_hdma_cmd(byte c)
61 int cnt;
62 addr sa;
63 int da;
65 /* Begin or cancel HDMA */
66 if ((hw.hdma|c) & 0x80)
68 hw.hdma = c;
69 R_HDMA5 = c & 0x7f;
70 return;
73 /* Perform GDMA */
74 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
75 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
76 cnt = ((int)c)+1;
77 /* FIXME - this should use cpu time! */
78 /*cpu_timers(102 * cnt);*/
79 cnt <<= 4;
80 while (cnt--)
81 writeb(da++, readb(sa++));
82 R_HDMA1 = sa >> 8;
83 R_HDMA2 = sa & 0xF0;
84 R_HDMA3 = 0x1F & (da >> 8);
85 R_HDMA4 = da & 0xF0;
86 R_HDMA5 = 0xFF;
90 void hw_hdma()
92 int cnt;
93 addr sa;
94 int da;
96 sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
97 da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
98 cnt = 16;
99 while (cnt--)
100 writeb(da++, readb(sa++));
101 R_HDMA1 = sa >> 8;
102 R_HDMA2 = sa & 0xF0;
103 R_HDMA3 = 0x1F & (da >> 8);
104 R_HDMA4 = da & 0xF0;
105 R_HDMA5--;
106 hw.hdma--;
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()
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 void pad_press(byte k)
142 if (hw.pad & k)
143 return;
144 hw.pad |= k;
145 pad_refresh();
148 void pad_release(byte k)
150 if (!(hw.pad & k))
151 return;
152 hw.pad &= ~k;
153 pad_refresh();
156 void pad_set(byte k, int st)
158 st ? pad_press(k) : pad_release(k);
161 void hw_reset()
163 hw.ilines = hw.pad = 0;
165 memset(ram.hi, 0, sizeof ram.hi);
167 R_P1 = 0xFF;
168 R_LCDC = 0x91;
169 R_BGP = 0xFC;
170 R_OBP0 = 0xFF;
171 R_OBP1 = 0xFF;
172 R_SVBK = 0x01;
173 R_HDMA5 = 0xFF;
174 R_VBK = 0xFE;