summaryrefslogtreecommitdiff
path: root/apps/plugins/rockboy/lcdc.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
committerJens Arnold <amiconn@rockbox.org>2005-03-02 23:49:38 +0000
commit384de102469fee4e0792df8fe38586d3206774ed (patch)
treeee5342103e17738acfb8421328ea7c57433f55e6 /apps/plugins/rockboy/lcdc.c
parent48dad47df98bdec632e8930b6a97359dc2c428f5 (diff)
downloadrockbox-384de102469fee4e0792df8fe38586d3206774ed.zip
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.gz
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.bz2
rockbox-384de102469fee4e0792df8fe38586d3206774ed.tar.xz
Rockboy - gameboy emulation for rockbox, based on gnuboy. Still a bit early, but already playable on iRiver H1xx and the simulators. The archos recorder version is currently rather slow...
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6104 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/rockboy/lcdc.c')
-rw-r--r--apps/plugins/rockboy/lcdc.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/apps/plugins/rockboy/lcdc.c b/apps/plugins/rockboy/lcdc.c
new file mode 100644
index 0000000..c82b828
--- /dev/null
+++ b/apps/plugins/rockboy/lcdc.c
@@ -0,0 +1,180 @@
+
+
+#include "rockmacros.h"
+
+#include "defs.h"
+#include "hw.h"
+#include "cpu.h"
+#include "regs.h"
+#include "lcd.h"
+
+
+#define C (cpu.lcdc)
+
+
+/*
+ * stat_trigger updates the STAT interrupt line to reflect whether any
+ * of the conditions set to be tested (by bits 3-6 of R_STAT) are met.
+ * This function should be called whenever any of the following occur:
+ * 1) LY or LYC changes.
+ * 2) A state transition affects the low 2 bits of R_STAT (see below).
+ * 3) The program writes to the upper bits of R_STAT.
+ * stat_trigger also updates bit 2 of R_STAT to reflect whether LY=LYC.
+ */
+
+void stat_trigger(void)
+{
+ static const int condbits[4] = { 0x08, 0x30, 0x20, 0x00 };
+ int flag = 0;
+
+ if ((R_LY < 0x91) && (R_LY == R_LYC))
+ {
+ R_STAT |= 0x04;
+ if (R_STAT & 0x40) flag = IF_STAT;
+ }
+ else R_STAT &= ~0x04;
+
+ if (R_STAT & condbits[R_STAT&3]) flag = IF_STAT;
+
+ if (!(R_LCDC & 0x80)) flag = 0;
+
+ hw_interrupt(flag, IF_STAT);
+}
+
+void stat_write(byte b)
+{
+ R_STAT = (R_STAT & 0x07) | (b & 0x78);
+ if (!hw.cgb &&!(R_STAT & 2)) /* DMG STAT write bug => interrupt */
+ hw_interrupt(IF_STAT, IF_STAT);
+ stat_trigger();
+}
+
+
+/*
+ * stat_change is called when a transition results in a change to the
+ * LCD STAT condition (the low 2 bits of R_STAT). It raises or lowers
+ * the VBLANK interrupt line appropriately and calls stat_trigger to
+ * update the STAT interrupt line.
+ */
+
+static void stat_change(int stat)
+{
+ stat &= 3;
+ R_STAT = (R_STAT & 0x7C) | stat;
+
+ if (stat != 1) hw_interrupt(0, IF_VBLANK);
+ /* hw_interrupt((stat == 1) ? IF_VBLANK : 0, IF_VBLANK); */
+ stat_trigger();
+}
+
+
+void lcdc_change(byte b)
+{
+ byte old = R_LCDC;
+ R_LCDC = b;
+ if ((R_LCDC ^ old) & 0x80) /* lcd on/off change */
+ {
+ R_LY = 0;
+ stat_change(2);
+ C = 40;
+ lcd_begin();
+ }
+}
+
+
+void lcdc_trans(void)
+{
+ if (!(R_LCDC & 0x80))
+ {
+ while (C <= 0)
+ {
+ switch ((byte)(R_STAT & 3))
+ {
+ case 0:
+ case 1:
+ stat_change(2);
+ C += 40;
+ break;
+ case 2:
+ stat_change(3);
+ C += 86;
+ break;
+ case 3:
+ stat_change(0);
+ if (hw.hdma & 0x80)
+ hw_hdma();
+ else
+ C += 102;
+ break;
+ }
+ return;
+ }
+ }
+ while (C <= 0)
+ {
+ switch ((byte)(R_STAT & 3))
+ {
+ case 1:
+ if (!(hw.ilines & IF_VBLANK))
+ {
+ C += 218;
+ hw_interrupt(IF_VBLANK, IF_VBLANK);
+ break;
+ }
+ if (R_LY == 0)
+ {
+ lcd_begin();
+ stat_change(2);
+ C += 40;
+ break;
+ }
+ else if (R_LY < 152)
+ C += 228;
+ else if (R_LY == 152)
+ C += 28;
+ else
+ {
+ R_LY = -1;
+ C += 200;
+ }
+ R_LY++;
+ stat_trigger();
+ break;
+ case 2:
+ lcd_refreshline();
+ stat_change(3);
+ C += 86;
+ break;
+ case 3:
+ stat_change(0);
+ if (hw.hdma & 0x80)
+ hw_hdma();
+ /* FIXME -- how much of the hblank does hdma use?? */
+ /* else */
+ C += 102;
+ break;
+ case 0:
+ if (++R_LY >= 144)
+ {
+ if (cpu.halt)
+ {
+ hw_interrupt(IF_VBLANK, IF_VBLANK);
+ C += 228;
+ }
+ else C += 10;
+ stat_change(1);
+ break;
+ }
+ stat_change(2);
+ C += 40;
+ break;
+ }
+ }
+}
+
+
+
+
+
+
+