Direct render the VIC to the DSi LCD buffer for 40% speedup.

For the DS-Lite/Phat, render instead to a DTCM fast memory buffer and 32-bit copy it to the LCD buffer for 10% speedup.
This commit is contained in:
Dave Bernazzani 2025-04-26 19:58:08 -04:00
parent cc7126bf38
commit fc89bff792
6 changed files with 174 additions and 147 deletions

View File

@ -613,7 +613,6 @@ bool C64::LoadSnapshot(char *filename)
while (c != 10) while (c != 10)
c = fgetc(f); // Shouldn't be necessary c = fgetc(f); // Shouldn't be necessary
if (fgetc(f) != SNAPSHOT_VERSION) { if (fgetc(f) != SNAPSHOT_VERSION) {
ShowRequester("Unknown snapshot format", "OK", NULL);
fclose(f); fclose(f);
return false; return false;
} }
@ -666,18 +665,15 @@ bool C64::LoadSnapshot(char *filename)
fclose(f); fclose(f);
if (error) { if (error) {
ShowRequester("Error reading snapshot file", "OK", NULL);
Reset(); Reset();
return false; return false;
} else } else
return true; return true;
} else { } else {
fclose(f); fclose(f);
ShowRequester("Not a Frodo snapshot file", "OK", NULL);
return false; return false;
} }
} else { } else {
ShowRequester("Can't open snapshot file", "OK", NULL);
return false; return false;
} }
} }
@ -853,14 +849,12 @@ ITCM_CODE void C64::VBlank(bool draw_frame)
if (draw_frame) if (draw_frame)
{ {
TheDisplay->Update();
frames++; frames++;
while (GetTicks() < (((unsigned int)TICKS_PER_SEC/(unsigned int)50) * (unsigned int)frames)) while (GetTicks() < (((unsigned int)TICKS_PER_SEC/(unsigned int)50) * (unsigned int)frames))
{ {
if (ThePrefs.TrueDrive && TheDisplay->led_state[0]) break; // If reading the drive in 'true drive' mode, just plow along... if (ThePrefs.TrueDrive && TheDisplay->led_state[0]) break; // If reading the drive in 'true drive' mode, just plow along...
asm("nop"); asm("nop");
//break; // Uncomment this for full speed... break; // Uncomment this for full speed...
} }
frames_per_sec++; frames_per_sec++;
@ -1144,7 +1138,7 @@ void C64::main_loop(void)
// The order of calls is important here // The order of calls is important here
int cycles = TheVIC->EmulateLine(); int cycles = TheVIC->EmulateLine();
TheSID->EmulateLine(); TheSID->EmulateLine(SID_CYCLES_PER_LINE);
#if !PRECISE_CIA_CYCLES #if !PRECISE_CIA_CYCLES
TheCIA1->EmulateLine(63); TheCIA1->EmulateLine(63);
TheCIA2->EmulateLine(63); TheCIA2->EmulateLine(63);
@ -1162,7 +1156,7 @@ void C64::main_loop(void)
// Note, we can't just use the Idle flag here as the drive periodically goes non-idle to // Note, we can't just use the Idle flag here as the drive periodically goes non-idle to
// check status - so we use the LED state which is a better indicator of drive activity... // check status - so we use the LED state which is a better indicator of drive activity...
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
if (TheDisplay->led_state[0]) ThePrefs.DrawEveryN = 10; if (TheDisplay->led_state[0]) ThePrefs.DrawEveryN = 5;
else ThePrefs.DrawEveryN = isDSiMode() ? 1:2; else ThePrefs.DrawEveryN = isDSiMode() ? 1:2;
// ----------------------------------------------------------- // -----------------------------------------------------------

View File

@ -380,9 +380,17 @@ void WaitForVblank()
/* /*
* Redraw bitmap * Redraw bitmap
*/ */
void C64Display::Update(void) ITCM_CODE void C64Display::Update(int raster, u8 *src)
{ {
dmaCopyWordsAsynch(3, bufmem+(512*14), frontBuffer+(512*14), BUFMEM_SIZE-(18*1024)); if ((raster < 32) || (raster > 272)) return;
// Output the raster line to the LCD...
u32 *dest = (uint32*)((u32)0x06000000 + (512*(raster-17)));
u32 *source = (u32*) src;
for (int i=0; i<(DISPLAY_X-0x10)/4; i++)
{
*dest++ = *source++;
}
} }
@ -453,7 +461,7 @@ int i = 0;
int debug[8]={0,0,0,0,0,0,0,0}; int debug[8]={0,0,0,0,0,0,0,0};
void C64Display::Speedometer(int speed) void C64Display::Speedometer(int speed)
{ {
#if 0 #if 1
char tmp[34]; char tmp[34];
sprintf(tmp, "%-8d", speed); sprintf(tmp, "%-8d", speed);
@ -474,7 +482,15 @@ void C64Display::Speedometer(int speed)
uint8 *C64Display::BitmapBase(void) uint8 *C64Display::BitmapBase(void)
{ {
return (uint8 *)bufmem; extern uint8 fast_line_buffer[];
// ---------------------------------------------------------------
// For the DSi we can write directly to the LCD screen as the DSi
// has the ability to read/write from individual bytes of the LCD
// unlike the older DS-Lite/Phat which requires 16-bit access...
// ---------------------------------------------------------------
if (isDSiMode()) return (uint8*)0x06000000;
else return (uint8 *)fast_line_buffer;
} }

View File

@ -38,7 +38,7 @@
#ifndef _DISPLAY_H #ifndef _DISPLAY_H
#define _DISPLAY_H #define _DISPLAY_H
const int DISPLAY_X = 0x170; const int DISPLAY_X = 0x180;
const int DISPLAY_Y = 0x11f; const int DISPLAY_Y = 0x11f;
class C64Window; class C64Window;
@ -51,7 +51,7 @@ class C64Display {
public: public:
C64Display(C64 *the_c64); C64Display(C64 *the_c64);
~C64Display(); ~C64Display();
void Update(void); void Update(int raster, u8 *src);
void UpdateLEDs(int l0, int l1); void UpdateLEDs(int l0, int l1);
void Speedometer(int speed); void Speedometer(int speed);
uint8 *BitmapBase(void); uint8 *BitmapBase(void);

View File

@ -829,11 +829,8 @@ void DigitalRenderer::calc_filter(void)
#ifdef USE_FIXPOINT_MATHS #ifdef USE_FIXPOINT_MATHS
// explanations see below. // explanations see below.
#ifdef __NDS__
arg = fr / (int)(SAMPLE_FREQ >> 1); arg = fr / (int)(SAMPLE_FREQ >> 1);
#else
arg = fr / (SAMPLE_FREQ >> 1);
#endif
if (arg > FixNo(0.99)) {arg = FixNo(0.99);} if (arg > FixNo(0.99)) {arg = FixNo(0.99);}
if (arg < FixNo(0.01)) {arg = FixNo(0.01);} if (arg < FixNo(0.01)) {arg = FixNo(0.01);}
@ -858,7 +855,11 @@ void DigitalRenderer::calc_filter(void)
d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break; d1 = FixNo(-2); d2 = FixNo(1); f_ampl = FixNo(0.25) * (1 - g1 + g2); break;
case FILT_BP: case FILT_BP:
d1 = 0; d2 = FixNo(-1); d1 = 0; d2 = FixNo(-1);
f_ampl = FixNo(0.25) * (1 + g1 + g2) * (1 + fixcos(arg)) / fixsin(arg); {
FixPoint c = fixsqrt(g2*g2 + FixNo(2.0)*g2 - g1*g1 + FixNo(1.0));
f_ampl = FixNo(0.25) * (FixNo(-2.0)*g2*g2 - (FixNo(4.0)+FixNo(2.0)*c)*g2 - FixNo(2.0)*c + (c+FixNo(2.0))*g1*g1 - FixNo(2.0)) / (-g2*g2 - (c+FixNo(2.0))*g2 - c + g1*g1 - FixNo(1.0));
}
break; break;
case FILT_NOTCH: case FILT_NOTCH:
d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1); d1 = FixNo(-2) * fixcos(arg); d2 = FixNo(1);
@ -1077,18 +1078,9 @@ ITCM_CODE int16 DigitalRenderer::calc_buffer(int16 *buf, long count)
buf--; return *buf; buf--; return *buf;
} }
/*
* SID_NDS.i
*
* RISC OS specific parts of the sound emulation
* Frodo (C) 1994-1997,2002 Christian Bauer
* Acorn port by Andreas Dehmel, 1997
*
*/
DigitalRenderer* p __attribute__((section(".dtcm"))); DigitalRenderer* p __attribute__((section(".dtcm")));
bool paused __attribute__((section(".dtcm"))) = false; bool paused __attribute__((section(".dtcm"))) = false;
int16 last_sample = 0x8000; int16 last_sample __attribute__((section(".dtcm"))) = 0x8000;
ITCM_CODE mm_word SoundMixCallback(mm_word len, mm_addr stream, mm_stream_formats format) ITCM_CODE mm_word SoundMixCallback(mm_word len, mm_addr stream, mm_stream_formats format)
{ {

View File

@ -67,7 +67,7 @@ public:
void ResumeSound(void); void ResumeSound(void);
void GetState(MOS6581State *ss); void GetState(MOS6581State *ss);
void SetState(MOS6581State *ss); void SetState(MOS6581State *ss);
void EmulateLine(void); void EmulateLine(int);
private: private:
void open_close_renderer(int old_type, int new_type); void open_close_renderer(int old_type, int new_type);
@ -149,7 +149,7 @@ struct MOS6581State {
* Fill buffer (for Unix sound routines), sample volume (for sampled voice) * Fill buffer (for Unix sound routines), sample volume (for sampled voice)
*/ */
inline void MOS6581::EmulateLine(void) inline void MOS6581::EmulateLine(int cycles)
{ {
// Simulate voice 3 phase accumulator // Simulate voice 3 phase accumulator
if (regs[0x12] & 0x08) // Voice 3 control register if (regs[0x12] & 0x08) // Voice 3 control register
@ -166,7 +166,7 @@ inline void MOS6581::EmulateLine(void)
switch (fake_v3_eg_state) switch (fake_v3_eg_state)
{ {
case EG_ATTACK: case EG_ATTACK:
fake_v3_eg_level += (SID_CYCLES_PER_LINE << 16) / EGDivTable[regs[0x13] >> 4]; fake_v3_eg_level += (cycles << 16) / EGDivTable[regs[0x13] >> 4];
if (fake_v3_eg_level > 0xffffff) if (fake_v3_eg_level > 0xffffff)
{ {
fake_v3_eg_level = 0xffffff; fake_v3_eg_level = 0xffffff;
@ -176,7 +176,7 @@ inline void MOS6581::EmulateLine(void)
case EG_DECAY_SUSTAIN: case EG_DECAY_SUSTAIN:
{ {
int32_t s_level = (regs[0x14] >> 4) * 0x111111; int32_t s_level = (regs[0x14] >> 4) * 0x111111;
fake_v3_eg_level -= ((SID_CYCLES_PER_LINE << 16) / EGDivTable[regs[0x13] & 0x0f]) >> EGDRShift[fake_v3_eg_level >> 16]; fake_v3_eg_level -= ((cycles << 16) / EGDivTable[regs[0x13] & 0x0f]) >> EGDRShift[fake_v3_eg_level >> 16];
if (fake_v3_eg_level < s_level) if (fake_v3_eg_level < s_level)
{ {
fake_v3_eg_level = s_level; fake_v3_eg_level = s_level;
@ -186,7 +186,7 @@ inline void MOS6581::EmulateLine(void)
case EG_RELEASE: case EG_RELEASE:
if (fake_v3_eg_level != 0) if (fake_v3_eg_level != 0)
{ {
fake_v3_eg_level -= ((SID_CYCLES_PER_LINE << 16) / EGDivTable[regs[0x14] & 0x0f]) >> EGDRShift[fake_v3_eg_level >> 16]; fake_v3_eg_level -= ((cycles << 16) / EGDivTable[regs[0x14] & 0x0f]) >> EGDRShift[fake_v3_eg_level >> 16];
if (fake_v3_eg_level < 0) if (fake_v3_eg_level < 0)
{ {
fake_v3_eg_level = 0; fake_v3_eg_level = 0;

View File

@ -101,6 +101,7 @@ const int COL38_XSTART = 0x27;
const int COL38_XSTOP = 0x157; const int COL38_XSTOP = 0x157;
uint8 fast_line_buffer[512] __attribute__((section(".dtcm")));
// Tables for sprite X expansion // Tables for sprite X expansion
uint16 ExpTable[256] __attribute__((section(".dtcm"))) = { uint16 ExpTable[256] __attribute__((section(".dtcm"))) = {
@ -1073,48 +1074,43 @@ inline void MOS6569::el_mc_idle(uint8 *p, uint8 *r)
} }
#ifdef GLOBAL_VARS
ITCM_CODE void el_sprites(uint8 *chunky_ptr) ITCM_CODE void el_sprites(uint8 *chunky_ptr)
#else
inline void MOS6569::el_sprites(uint8 *chunky_ptr)
#endif
{ {
int i; unsigned spr_coll=0, gfx_coll=0;
int snum, sbit; // Sprite number/bit mask
int spr_coll=0, gfx_coll=0;
// Draw each active sprite // Draw each active sprite
for (snum=0, sbit=1; snum<8; snum++, sbit<<=1) for (unsigned snum = 0; snum < 8; ++snum) {
if ((sprite_on & sbit) && mx[snum] < DISPLAY_X-32) uint8_t sbit = 1 << snum;
{
int spr_mask_pos; // Sprite bit position in fore_mask_buf
uint32 sdata, fore_mask;
uint8 *p = chunky_ptr + mx[snum] + 8; // Is sprite visible?
uint8 *q = spr_coll_buf + mx[snum] + 8; if ((sprite_on & sbit) && mx[snum] < DISPLAY_X-32) {
uint8_t *p = chunky_ptr + mx[snum] + 8;
uint8_t *q = spr_coll_buf + mx[snum] + 8;
uint8 *sdatap = get_physical(matrix_base[0x3f8 + snum] << 6 | (mc[snum] * 3)); // Fetch sprite data and mask
sdata = (*sdatap << 24) | (*(sdatap+1) << 16) | (*(sdatap+2) << 8); uint8_t *sdatap = get_physical(matrix_base[0x3f8 + snum] << 6 | (mc[snum]*3));
uint32_t sdata = (*sdatap << 24) | (*(sdatap+1) << 16) | (*(sdatap+2) << 8);
uint8 color = spr_color[snum]; uint8_t color = spr_color[snum];
spr_mask_pos = mx[snum] + 8 - x_scroll; unsigned spr_mask_pos = mx[snum] + 8 - x_scroll; // Sprite bit position in fore_mask_buf
unsigned sshift = spr_mask_pos & 7;
uint8 *fmbp = fore_mask_buf + (spr_mask_pos / 8); uint8_t *fmbp = fore_mask_buf + (spr_mask_pos / 8);
int sshift = spr_mask_pos & 7; uint32_t fore_mask = (fmbp[0] << 24) | (fmbp[1] << 16) | (fmbp[2] << 8) | (fmbp[3] << 0);
fore_mask = (((*(fmbp+0) << 24) | (*(fmbp+1) << 16) | (*(fmbp+2) << 8) fore_mask = (fore_mask << sshift) | (fmbp[4] >> (8-sshift));
| (*(fmbp+3))) << sshift) | (*(fmbp+4) >> (8-sshift));
if (mxe & sbit) { // X-expanded if (mxe & sbit) { // X-expanded
if (mx[snum] >= DISPLAY_X-56) if (mx[snum] >= DISPLAY_X-56)
continue; continue;
uint32 sdata_l = 0, sdata_r = 0, fore_mask_r; // Fetch extra sprite mask
fore_mask_r = (((*(fmbp+4) << 24) | (*(fmbp+5) << 16) | (*(fmbp+6) << 8) uint32_t sdata_l = 0, sdata_r = 0;
| (*(fmbp+7))) << sshift) | (*(fmbp+8) >> (8-sshift)); uint32_t fore_mask_r = (fmbp[4] << 24) | (fmbp[5] << 16) | (fmbp[6] << 8);
fore_mask_r <<= sshift;
if (mmc & sbit) { // Multicolor mode if (mmc & sbit) { // X-expanded multicolor mode
uint32 plane0_l, plane0_r, plane1_l, plane1_r; uint32_t plane0_l, plane0_r, plane1_l, plane1_r;
// Expand sprite data // Expand sprite data
sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff]; sdata_l = MultiExpTable[sdata >> 24 & 0xff] << 16 | MultiExpTable[sdata >> 16 & 0xff];
@ -1129,59 +1125,61 @@ inline void MOS6569::el_sprites(uint8 *chunky_ptr)
// Collision with graphics? // Collision with graphics?
if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) { if ((fore_mask & (plane0_l | plane1_l)) || (fore_mask_r & (plane0_r | plane1_r))) {
gfx_coll |= sbit; gfx_coll |= sbit;
if (mdp & sbit) { }
plane0_l &= ~fore_mask; // Mask sprite if in background
plane1_l &= ~fore_mask; // Mask sprite if in background
plane0_r &= ~fore_mask_r; if ((mdp & sbit) == 0) {
plane1_r &= ~fore_mask_r; fore_mask = 0;
} fore_mask_r = 0;
} }
// Paint sprite // Paint sprite
for (i=0; i<32; i++, plane0_l<<=1, plane1_l<<=1) { for (unsigned i = 0; i < 32; ++i, plane0_l <<= 1, plane1_l <<= 1, fore_mask <<= 1) {
uint8 col; uint8_t col;
if (plane1_l & 0x80000000) { if (plane1_l & 0x80000000) {
if (plane0_l & 0x80000000) if (plane0_l & 0x80000000) {
col = mm1_color; col = mm1_color;
else } else {
col = color; col = color;
}
} else { } else {
if (plane0_l & 0x80000000) if (plane0_l & 0x80000000) {
col = mm0_color; col = mm0_color;
else } else {
continue; continue;
}
} }
// Check for collisions if (q[i]) { // Obscured by higher-priority data?
if (q[i])
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
else { } else if ((fore_mask & 0x80000000) == 0) {
p[i] = col; p[i] = col;
q[i] = sbit;
} }
q[i] |= sbit;
} }
for (; i<48; i++, plane0_r<<=1, plane1_r<<=1) { for (unsigned i = 32; i < 48; ++i, plane0_r <<= 1, plane1_r <<= 1, fore_mask_r <<= 1) {
uint8 col; uint8_t col;
if (plane1_r & 0x80000000) { if (plane1_r & 0x80000000) {
if (plane0_r & 0x80000000) if (plane0_r & 0x80000000) {
col = mm1_color; col = mm1_color;
else } else {
col = color; col = color;
}
} else { } else {
if (plane0_r & 0x80000000) if (plane0_r & 0x80000000) {
col = mm0_color; col = mm0_color;
else } else {
continue; continue;
}
} }
// Check for collisions if (q[i]) { // Obscured by higher-priority data?
if (q[i])
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
else { } else if ((fore_mask_r & 0x80000000) == 0) {
p[i] = col; p[i] = col;
q[i] = sbit;
} }
q[i] |= sbit;
} }
} else { // Standard mode } else { // X-expanded standard mode
// Expand sprite data // Expand sprite data
sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff]; sdata_l = ExpTable[sdata >> 24 & 0xff] << 16 | ExpTable[sdata >> 16 & 0xff];
@ -1190,37 +1188,41 @@ inline void MOS6569::el_sprites(uint8 *chunky_ptr)
// Collision with graphics? // Collision with graphics?
if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) { if ((fore_mask & sdata_l) || (fore_mask_r & sdata_r)) {
gfx_coll |= sbit; gfx_coll |= sbit;
if (mdp & sbit) { }
sdata_l &= ~fore_mask; // Mask sprite if in background
sdata_r &= ~fore_mask_r; // Mask sprite if in background
} if ((mdp & sbit) == 0) {
fore_mask = 0;
fore_mask_r = 0;
} }
// Paint sprite // Paint sprite
for (i=0; i<32; i++, sdata_l<<=1) for (unsigned i = 0; i < 32; ++i, sdata_l <<= 1, fore_mask <<= 1) {
if (sdata_l & 0x80000000) { if (sdata_l & 0x80000000) {
if (q[i]) // Collision with sprite? if (q[i]) { // Obscured by higher-priority data?
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
else { // Draw pixel if no collision } else if ((fore_mask & 0x80000000) == 0) {
p[i] = color; p[i] = color;
q[i] = sbit;
} }
q[i] |= sbit;
} }
for (; i<48; i++, sdata_r<<=1) }
for (unsigned i = 32; i < 48; ++i, sdata_r <<= 1, fore_mask_r <<= 1) {
if (sdata_r & 0x80000000) { if (sdata_r & 0x80000000) {
if (q[i]) // Collision with sprite? if (q[i]) { // Obscured by higher-priority data?
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
else { // Draw pixel if no collision } else if ((fore_mask_r & 0x80000000) == 0) {
p[i] = color; p[i] = color;
q[i] = sbit;
} }
q[i] |= sbit;
} }
}
} }
} else // Unexpanded } else { // Unexpanded
if (mmc & sbit) { // Multicolor mode if (mmc & sbit) { // Unexpanded multicolor mode
uint32 plane0, plane1; uint32_t plane0, plane1;
// Convert sprite chunky pixels to bitplanes // Convert sprite chunky pixels to bitplanes
plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1; plane0 = (sdata & 0x55555555) | (sdata & 0x55555555) << 1;
@ -1229,78 +1231,89 @@ inline void MOS6569::el_sprites(uint8 *chunky_ptr)
// Collision with graphics? // Collision with graphics?
if (fore_mask & (plane0 | plane1)) { if (fore_mask & (plane0 | plane1)) {
gfx_coll |= sbit; gfx_coll |= sbit;
if (mdp & sbit) { }
plane0 &= ~fore_mask; // Mask sprite if in background
plane1 &= ~fore_mask; // Mask sprite if in background
} if ((mdp & sbit) == 0) {
fore_mask = 0;
} }
// Paint sprite // Paint sprite
for (i=0; i<24; i++, plane0<<=1, plane1<<=1) { for (unsigned i = 0; i < 24; ++i, plane0 <<= 1, plane1 <<= 1, fore_mask <<= 1) {
uint8 col; uint8_t col;
if (plane1 & 0x80000000) { if (plane1 & 0x80000000) {
if (plane0 & 0x80000000) if (plane0 & 0x80000000) {
col = mm1_color; col = mm1_color;
else } else {
col = color; col = color;
}
} else { } else {
if (plane0 & 0x80000000) if (plane0 & 0x80000000) {
col = mm0_color; col = mm0_color;
else } else {
continue; continue;
}
} }
if (q[i]) if (q[i]) { // Obscured by higher-priority data?
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
else { } else if ((fore_mask & 0x80000000) == 0) {
p[i] = col; p[i] = col;
q[i] = sbit;
} }
q[i] |= sbit;
} }
} else { // Standard mode } else { // Unexpanded standard mode
// Collision with graphics? // Collision with graphics?
if (fore_mask & sdata) { if (fore_mask & sdata) {
gfx_coll |= sbit; gfx_coll |= sbit;
if (mdp & sbit) }
sdata &= ~fore_mask; // Mask sprite if in background
// Mask sprite if in background
if ((mdp & sbit) == 0) {
fore_mask = 0;
} }
// Paint sprite // Paint sprite
for (i=0; i<24; i++, sdata<<=1) for (unsigned i = 0; i < 24; ++i, sdata <<= 1, fore_mask <<= 1) {
if (sdata & 0x80000000) { if (sdata & 0x80000000) {
if (q[i]) { // Collision with sprite? if (q[i]) { // Obscured by higher-priority data?
spr_coll |= q[i] | sbit; spr_coll |= q[i] | sbit;
} else { // Draw pixel if no collision } else if ((fore_mask & 0x80000000) == 0) {
p[i] = color; p[i] = color;
q[i] = sbit;
} }
q[i] |= sbit;
} }
}
} }
} }
// Check sprite-sprite collisions
if (clx_spr)
clx_spr |= spr_coll;
else {
clx_spr |= spr_coll;
irq_flag |= 0x04;
if (irq_mask & 0x04) {
irq_flag |= 0x80;
the_cpu->TriggerVICIRQ();
} }
} }
// Check sprite-background collisions if (1) {
if (clx_bgr)
clx_bgr |= gfx_coll; // Check sprite-sprite collisions
else { if (clx_spr) {
clx_bgr |= gfx_coll; clx_spr |= spr_coll;
irq_flag |= 0x02; } else {
if (irq_mask & 0x02) { clx_spr |= spr_coll;
irq_flag |= 0x80; irq_flag |= 0x04;
the_cpu->TriggerVICIRQ(); if (irq_mask & 0x04) {
irq_flag |= 0x80;
the_cpu->TriggerVICIRQ();
}
}
// Check sprite-background collisions
if (clx_bgr) {
clx_bgr |= gfx_coll;
} else {
clx_bgr |= gfx_coll;
irq_flag |= 0x02;
if (irq_mask & 0x02) {
irq_flag |= 0x80;
the_cpu->TriggerVICIRQ();
}
} }
} }
} }
@ -1374,8 +1387,20 @@ int MOS6569::EmulateLine(void)
// End of screen reached? // End of screen reached?
if (raster != TOTAL_RASTERS) if (raster != TOTAL_RASTERS)
{
// Not end of screen... output the next scanline as it will be 'stale' and not cached...
if (!isDSiMode())
{
// For the DS-Lite/Phat, we copy out one pixel line buffer to the LCD
if (!frame_skipped)
{
the_display->Update(raster, (u8*)(chunky_line_start));
}
}
raster_y = raster; raster_y = raster;
else { }
else // Yes, enter vblank - new frame coming up
{
dampen_memcpy++; dampen_memcpy++;
vblank(); vblank();
raster = 0; raster = 0;
@ -1651,7 +1676,7 @@ int MOS6569::EmulateLine(void)
} }
// Increment pointer in chunky buffer // Increment pointer in chunky buffer
chunky_line_start += xmod; if (isDSiMode()) chunky_line_start += xmod;
// Increment row counter, go to idle state on overflow // Increment row counter, go to idle state on overflow
if (rc == 7) { if (rc == 7) {