mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 20:55:17 -05:00
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
183
apps/plugins/rockboy/hw.c
Normal file
183
apps/plugins/rockboy/hw.c
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
|
||||
|
||||
|
||||
#include "rockmacros.h"
|
||||
#include "defs.h"
|
||||
#include "cpu.h"
|
||||
#include "hw.h"
|
||||
#include "regs.h"
|
||||
#include "lcd.h"
|
||||
#include "mem.h"
|
||||
#include "fastmem.h"
|
||||
|
||||
|
||||
struct hw hw;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* hw_interrupt changes the virtual interrupt lines included in the
|
||||
* specified mask to the values the corresponding bits in i take, and
|
||||
* in doing so, raises the appropriate bit of R_IF for any interrupt
|
||||
* lines that transition from low to high.
|
||||
*/
|
||||
|
||||
void hw_interrupt(byte i, byte mask)
|
||||
{
|
||||
byte oldif = R_IF;
|
||||
i &= 0x1F & mask;
|
||||
R_IF |= i & (hw.ilines ^ i);
|
||||
|
||||
/* FIXME - is this correct? not sure the docs understand... */
|
||||
if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu.ime) cpu.halt = 0;
|
||||
/* if ((i & (hw.ilines ^ i) & R_IE) && cpu.ime) cpu.halt = 0; */
|
||||
/* if ((i & R_IE) && cpu.ime) cpu.halt = 0; */
|
||||
|
||||
hw.ilines &= ~mask;
|
||||
hw.ilines |= i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hw_dma performs plain old memory-to-oam dma, the original dmg
|
||||
* dma. Although on the hardware it takes a good deal of time, the cpu
|
||||
* continues running during this mode of dma, so no special tricks to
|
||||
* stall the cpu are necessary.
|
||||
*/
|
||||
|
||||
void hw_dma(byte b)
|
||||
{
|
||||
int i;
|
||||
addr a;
|
||||
|
||||
a = ((addr)b) << 8;
|
||||
for (i = 0; i < 160; i++, a++)
|
||||
lcd.oam.mem[i] = readb(a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void hw_hdma_cmd(byte c)
|
||||
{
|
||||
int cnt;
|
||||
addr sa;
|
||||
int da;
|
||||
|
||||
/* Begin or cancel HDMA */
|
||||
if ((hw.hdma|c) & 0x80)
|
||||
{
|
||||
hw.hdma = c;
|
||||
R_HDMA5 = c & 0x7f;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform GDMA */
|
||||
sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
|
||||
da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
|
||||
cnt = ((int)c)+1;
|
||||
/* FIXME - this should use cpu time! */
|
||||
/*cpu_timers(102 * cnt);*/
|
||||
cnt <<= 4;
|
||||
while (cnt--)
|
||||
writeb(da++, readb(sa++));
|
||||
R_HDMA1 = sa >> 8;
|
||||
R_HDMA2 = sa & 0xF0;
|
||||
R_HDMA3 = 0x1F & (da >> 8);
|
||||
R_HDMA4 = da & 0xF0;
|
||||
R_HDMA5 = 0xFF;
|
||||
}
|
||||
|
||||
|
||||
void hw_hdma(void)
|
||||
{
|
||||
int cnt;
|
||||
addr sa;
|
||||
int da;
|
||||
|
||||
sa = ((addr)R_HDMA1 << 8) | (R_HDMA2&0xf0);
|
||||
da = 0x8000 | ((int)(R_HDMA3&0x1f) << 8) | (R_HDMA4&0xf0);
|
||||
cnt = 16;
|
||||
while (cnt--)
|
||||
writeb(da++, readb(sa++));
|
||||
R_HDMA1 = sa >> 8;
|
||||
R_HDMA2 = sa & 0xF0;
|
||||
R_HDMA3 = 0x1F & (da >> 8);
|
||||
R_HDMA4 = da & 0xF0;
|
||||
R_HDMA5--;
|
||||
hw.hdma--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pad_refresh updates the P1 register from the pad states, generating
|
||||
* the appropriate interrupts (by quickly raising and lowering the
|
||||
* interrupt line) if a transition has been made.
|
||||
*/
|
||||
|
||||
void pad_refresh()
|
||||
{
|
||||
byte oldp1;
|
||||
oldp1 = R_P1;
|
||||
R_P1 &= 0x30;
|
||||
R_P1 |= 0xc0;
|
||||
if (!(R_P1 & 0x10))
|
||||
R_P1 |= (hw.pad & 0x0F);
|
||||
if (!(R_P1 & 0x20))
|
||||
R_P1 |= (hw.pad >> 4);
|
||||
R_P1 ^= 0x0F;
|
||||
if (oldp1 & ~R_P1 & 0x0F)
|
||||
{
|
||||
hw_interrupt(IF_PAD, IF_PAD);
|
||||
hw_interrupt(0, IF_PAD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* These simple functions just update the state of a button on the
|
||||
* pad.
|
||||
*/
|
||||
|
||||
void pad_press(byte k)
|
||||
{
|
||||
if (hw.pad & k)
|
||||
return;
|
||||
hw.pad |= k;
|
||||
pad_refresh();
|
||||
}
|
||||
|
||||
void pad_release(byte k)
|
||||
{
|
||||
if (!(hw.pad & k))
|
||||
return;
|
||||
hw.pad &= ~k;
|
||||
pad_refresh();
|
||||
}
|
||||
|
||||
void pad_set(byte k, int st)
|
||||
{
|
||||
st ? pad_press(k) : pad_release(k);
|
||||
}
|
||||
|
||||
void hw_reset()
|
||||
{
|
||||
hw.ilines = hw.pad = 0;
|
||||
|
||||
memset(ram.hi, 0, sizeof ram.hi);
|
||||
|
||||
R_P1 = 0xFF;
|
||||
R_LCDC = 0x91;
|
||||
R_BGP = 0xFC;
|
||||
R_OBP0 = 0xFF;
|
||||
R_OBP1 = 0xFF;
|
||||
R_SVBK = 0x01;
|
||||
R_HDMA5 = 0xFF;
|
||||
R_VBK = 0xFE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue