refresh.h: fix compilation with non-GNU compatible compiler
[rofl0r-gnuboy.git] / lcdc.c
blobe247f92cfe9184928257d67153d80f7f37770e62
3 #include <stdlib.h>
5 #include "defs.h"
6 #include "hw.h"
7 #include "cpu.h"
8 #include "regs.h"
9 #include "lcd.h"
11 #define C (cpu.lcdc)
15 * stat_trigger updates the STAT interrupt line to reflect whether any
16 * of the conditions set to be tested (by bits 3-6 of R_STAT) are met.
17 * This function should be called whenever any of the following occur:
18 * 1) LY or LYC changes.
19 * 2) A state transition affects the low 2 bits of R_STAT (see below).
20 * 3) The program writes to the upper bits of R_STAT.
21 * stat_trigger also updates bit 2 of R_STAT to reflect whether LY=LYC.
24 void stat_trigger()
26 static const int condbits[4] = { 0x08, 0x10, 0x20, 0x00 };
27 int flag = 0;
29 if (R_LY == R_LYC)
31 R_STAT |= 0x04;
32 if (R_STAT & 0x40) flag = IF_STAT;
34 else R_STAT &= ~0x04;
36 if (R_STAT & condbits[R_STAT&3]) flag = IF_STAT;
38 if (!(R_LCDC & 0x80)) flag = 0;
40 hw_interrupt(flag, IF_STAT);
43 void stat_write(byte b)
45 R_STAT = (R_STAT & 0x07) | (b & 0x78);
46 if (!hw.cgb && !(R_STAT & 2)) /* DMG STAT write bug => interrupt */
47 hw_interrupt(IF_STAT, IF_STAT);
48 stat_trigger();
53 * stat_change is called when a transition results in a change to the
54 * LCD STAT condition (the low 2 bits of R_STAT). It raises or lowers
55 * the VBLANK interrupt line appropriately and calls stat_trigger to
56 * update the STAT interrupt line.
59 static void stat_change(int stat)
61 stat &= 3;
62 R_STAT = (R_STAT & 0x7C) | stat;
64 if (stat != 1) hw_interrupt(0, IF_VBLANK);
65 /* hw_interrupt((stat == 1) ? IF_VBLANK : 0, IF_VBLANK); */
66 stat_trigger();
70 void lcdc_change(byte b)
72 byte old = R_LCDC;
73 R_LCDC = b;
74 if ((R_LCDC ^ old) & 0x80) /* lcd on/off change */
76 R_LY = 0;
77 stat_change(2);
78 C = 40;
79 lcd_begin();
84 void lcdc_trans()
86 if (!(R_LCDC & 0x80))
88 while (C <= 0)
90 switch ((byte)(R_STAT & 3))
92 case 0:
93 case 1:
94 stat_change(2);
95 C += 40;
96 break;
97 case 2:
98 stat_change(3);
99 C += 86;
100 break;
101 case 3:
102 stat_change(0);
103 if (hw.hdma & 0x80)
104 hw_hdma();
105 else
106 C += 102;
107 break;
109 return;
112 while (C <= 0)
114 switch ((byte)(R_STAT & 3))
116 case 1:
117 if (!(hw.ilines & IF_VBLANK))
119 C += 218;
120 hw_interrupt(IF_VBLANK, IF_VBLANK);
121 break;
123 if (R_LY == 0)
125 lcd_begin();
126 stat_change(2);
127 C += 40;
128 break;
130 else if (R_LY < 152)
131 C += 228;
132 else if (R_LY == 152)
133 C += 28;
134 else
136 R_LY = -1;
137 C += 200;
139 R_LY++;
140 stat_trigger();
141 break;
142 case 2:
143 lcd_refreshline();
144 stat_change(3);
145 C += 86;
146 break;
147 case 3:
148 stat_change(0);
149 if (hw.hdma & 0x80)
150 hw_hdma();
151 /* FIXME -- how much of the hblank does hdma use?? */
152 /* else */
153 C += 102;
154 break;
155 case 0:
156 if (++R_LY >= 144)
158 if (cpu.halt)
160 hw_interrupt(IF_VBLANK, IF_VBLANK);
161 C += 228;
163 else C += 10;
164 stat_change(1);
165 break;
167 stat_change(2);
168 C += 40;
169 break;