forked from len0rd/rockbox
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
This commit is contained in:
parent
48dad47df9
commit
384de10246
56 changed files with 9225 additions and 1 deletions
180
apps/plugins/rockboy/lcdc.c
Normal file
180
apps/plugins/rockboy/lcdc.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue