Double-buffer video on DSi/XL/LL to produce smoother display output. Minor cleanup of keyboard handler.

This commit is contained in:
Dave Bernazzani 2025-04-16 06:43:18 -04:00
parent bca29e25b4
commit 84938112cd
5 changed files with 49 additions and 44 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -103,7 +103,7 @@ u8 bStartSoundEngine = 0; // Set to true to unmute sound after 1 frame of r
int bg0, bg1, bg0b, bg1b; // Some vars for NDS background screen handling
u16 vusCptVBL = 0; // We use this as a basic timer for the Mario sprite... could be removed if another timer can be utilized
u8 touch_debounce = 0; // A bit of touch-screen debounce
u8 key_debounce = 0; // A bit of key debounce
u8 key_debounce = 0; // A bit of key debounce to ensure the key is held pressed for a minimum amount of time
// The DS/DSi has 12 keys that can be mapped
u16 NDS_keyMap[12] __attribute__((section(".dtcm"))) = {KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_A, KEY_B, KEY_X, KEY_Y, KEY_R, KEY_L, KEY_START, KEY_SELECT};
@ -1115,7 +1115,6 @@ void SpeccySE_main(void)
{
u16 iTx, iTy;
u32 ucDEUX;
static u32 lastUN = 0;
static u8 dampenClick = 0;
u8 meta_key = 0;
@ -1318,12 +1317,6 @@ void SpeccySE_main(void)
meta_key = handle_spectrum_keyboard_press(iTx, iTy);
}
if (kbd_key != 0)
{
kbd_keys[kbd_keys_pressed++] = kbd_key;
key_debounce = 3;
}
// If the special menu key indicates we should show the choice menu, do so here...
if (meta_key == MENU_CHOICE_MENU)
{
@ -1337,18 +1330,23 @@ void SpeccySE_main(void)
if (++dampenClick > 0) // Make sure the key is pressed for an appreciable amount of time...
{
if ((kbd_key != 0) && (lastUN == 0))
if (kbd_key != 0)
{
mmEffect(SFX_KEYCLICK); // Play short key click for feedback...
kbd_keys[kbd_keys_pressed++] = kbd_key;
key_debounce = 5;
if (last_kbd_key == 0)
{
mmEffect(SFX_KEYCLICK); // Play short key click for feedback...
}
last_kbd_key = kbd_key;
}
lastUN = kbd_key;
}
}
} // SCR_TOUCH
else
{
touch_debounce = 0;
lastUN = 0; dampenClick = 0;
dampenClick = 0;
last_kbd_key = 0;
}
}
@ -1495,12 +1493,13 @@ void SpeccySE_main(void)
// ----------------------------------------------------------------------------------------
void useVRAM(void)
{
vramSetBankD(VRAM_D_LCD ); // Not using this for video but 128K of faster RAM always useful! Mapped at 0x06860000 - 256K Used for tape patch look-up
vramSetBankE(VRAM_E_LCD ); // Not using this for video but 64K of faster RAM always useful! Mapped at 0x06880000 - ..
vramSetBankF(VRAM_F_LCD ); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x06890000 - ..
vramSetBankG(VRAM_G_LCD ); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x06894000 - ..
vramSetBankH(VRAM_H_LCD ); // Not using this for video but 32K of faster RAM always useful! Mapped at 0x06898000 - ..
vramSetBankI(VRAM_I_LCD ); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x068A0000 - Unused - reserved for future use
vramSetBankB(VRAM_B_LCD); // 128K VRAM used for snapshot DCAP buffer - but could be repurposed during emulation ...
vramSetBankD(VRAM_D_LCD); // Not using this for video but 128K of faster RAM always useful! Mapped at 0x06860000 - 256K Used for tape patch look-up
vramSetBankE(VRAM_E_LCD); // Not using this for video but 64K of faster RAM always useful! Mapped at 0x06880000 - ..
vramSetBankF(VRAM_F_LCD); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x06890000 - ..
vramSetBankG(VRAM_G_LCD); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x06894000 - ..
vramSetBankH(VRAM_H_LCD); // Not using this for video but 32K of faster RAM always useful! Mapped at 0x06898000 - ..
vramSetBankI(VRAM_I_LCD); // Not using this for video but 16K of faster RAM always useful! Mapped at 0x068A0000 - Unused - reserved for future use
}
/*********************************************************************************
@ -1509,10 +1508,9 @@ void useVRAM(void)
void speccySEInit(void)
{
// Init graphic mode (bitmap mode)
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | DISPLAY_SPR_1D_LAYOUT | DISPLAY_SPR_ACTIVE);
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | DISPLAY_SPR_1D_LAYOUT | DISPLAY_SPR_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_MAIN_SPRITE); // Once emulation of game starts, we steal this back for an additional 128K of VRAM at 0x6820000 which we will use as a snapshot buffer for taking screen pics
vramSetBankC(VRAM_C_SUB_BG);
// Stop blending effect of intro
@ -1642,8 +1640,15 @@ void speccySEInitCPU(void)
// -------------------------------------------------------------
void irqVBlank(void)
{
// Manage time
extern u8 backgroundRenderScreen;
// Manage time
vusCptVBL++;
if (backgroundRenderScreen) // Only set for DSi mode... double buffer
{
dmaCopyWordsAsynch(3, (u16*)(backgroundRenderScreen & 1 ? 0x06820000:0x06830000), (u16*)0x06000000, 64*1024);
backgroundRenderScreen = 0;
}
}
// ----------------------------------------------------------------------

View File

@ -132,6 +132,7 @@ extern u16 nds_key;
extern u8 kbd_key;
extern u16 vusCptVBL;
extern u16 *pVidFlipBuf;
extern u16 *pVidDrawBuf;
extern u16 keyCoresp[MAX_KEY_OPTIONS];
extern u16 NDS_keyMap[];
extern u8 soundEmuPause;

View File

@ -229,26 +229,6 @@ u8 showMessage(char *szCh1, char *szCh2)
return uRet;
}
void SpeccySEModeNormal(void) {
REG_BG3CNT = BG_BMP8_256x256;
REG_BG3PA = (1<<8);
REG_BG3PB = 0;
REG_BG3PC = 0;
REG_BG3PD = (1<<8);
REG_BG3X = 0;
REG_BG3Y = 0;
}
//*****************************************************************************
// Put the top screen in refocused bitmap mode
//*****************************************************************************
void SpeccySEInitScreenUp(void) {
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
vramSetBankB(VRAM_B_MAIN_SPRITE);
SpeccySEModeNormal();
}
/*********************************************************************************
* Show The 14 games on the list to allow the user to choose a new game.
********************************************************************************/
@ -1401,9 +1381,8 @@ void speccySEChangeOptions(void)
u16 ucHaut=0x00, ucBas=0x00,ucA=0x00,ucY= 5, bOK=0;
// Upper Screen Background
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE | DISPLAY_SPR_1D_LAYOUT | DISPLAY_SPR_ACTIVE);
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankB(VRAM_B_MAIN_SPRITE_0x06400000);
bg0 = bgInit(0, BgType_Text8bpp, BgSize_T_256x512, 31,0);
bg1 = bgInit(1, BgType_Text8bpp, BgSize_T_256x512, 29,0);
bgSetPriority(bg0,1);bgSetPriority(bg1,0);
@ -1661,6 +1640,7 @@ u8 spectrumInit(char *szGame)
videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG_0x06000000); // This is our top emulation screen (where the game is played)
vramSetBankB(VRAM_B_LCD);
REG_BG3CNT = BG_BMP8_256x256;
REG_BG3PA = (1<<8);
REG_BG3PB = 0;

View File

@ -38,6 +38,7 @@ u8 zx_special_key __attribute__((section(".dtcm"))) = 0;
u32 last_file_size __attribute__((section(".dtcm"))) = 0;
u8 isCompressed __attribute__((section(".dtcm"))) = 1;
u8 tape_play_skip_frame __attribute__((section(".dtcm"))) = 0;
u8 backgroundRenderScreen = 0;
ITCM_CODE unsigned char cpu_readport_speccy(register unsigned short Port)
{
@ -331,17 +332,33 @@ u32 zx_colors_extend32[16] __attribute__((section(".dtcm"))) =
// and is heavily optimized to draw as fast as possible. Since the screen is
// often drawing background (paper vs ink), that's handled via look-up table.
// ----------------------------------------------------------------------------
u8 bRenderSkipOnce = 1;
ITCM_CODE void speccy_render_screen_line(u8 line)
{
u32 *vidBuf;
u8 *zx_ScreenPage = 0;
u32 *vidBuf = (u32*) (0x06000000 + (line << 8)); // Video buffer... write 32-bits at a time for maximum speed
if (line == 0) // At start of each new frame, handle the flashing 'timer'
{
if (isDSiMode() && !tape_is_playing()) // For the DSi we can double-buffer and draw the screen in the background
{
if (bRenderSkipOnce) bRenderSkipOnce=0;
else backgroundRenderScreen = 0x80 | (flash_timer & 1);
}
tape_play_skip_frame++;
if (++flash_timer & 0x10) {flash_timer=0; bFlash ^= 1;} // Same timing as real ULA - 16 frames on and 16 frames off
}
if (isDSiMode() && !tape_is_playing())
{
vidBuf = (u32*) ((flash_timer & 1 ? 0x06820000:0x06830000) + (line << 8)); // Video buffer... write 32-bits at a time for maximum speed
}
else // For the DS-Lite/Phat we direct render for speed - also when tape is loading...
{
vidBuf = (u32*)(0x06000000 + (line << 8)); // Video buffer... write 32-bits at a time for maximum speed
bRenderSkipOnce = 1; // When we stop the tape, we want to allow the first frame to re-draw before rendering
}
// -----------------------------------------------------------------------------
// Only draw one out of every 32 frames when we are loading tape. We want to
// give as much horsepower to the emulation CPU as possible here - this is
@ -584,6 +601,8 @@ void speccy_reset(void)
zx_128k_mode = 0; // Assume 48K until told otherwise
backgroundRenderScreen = 0;
// Set the 'average' contention delay...
static const u8 contend_delay[3] = {4,3,5};
zx_contend_delay = contend_delay[myConfig.contention];