diff options
| author | Jens Arnold <amiconn@rockbox.org> | 2005-03-02 23:49:38 +0000 |
|---|---|---|
| committer | Jens Arnold <amiconn@rockbox.org> | 2005-03-02 23:49:38 +0000 |
| commit | 384de102469fee4e0792df8fe38586d3206774ed (patch) | |
| tree | ee5342103e17738acfb8421328ea7c57433f55e6 /apps/plugins/rockboy/lcdc.c | |
| parent | 48dad47df98bdec632e8930b6a97359dc2c428f5 (diff) | |
| download | rockbox-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.c | 180 |
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; + } + } +} + + + + + + + |