mirror of
https://github.com/wavemotion-dave/SpeccySE.git
synced 2025-06-18 13:55:33 -04:00
Cleanup for the 1.0 release.
This commit is contained in:
parent
a0aaae083c
commit
bdde6bed8c
2
Makefile
2
Makefile
@ -15,7 +15,7 @@ include $(DEVKITARM)/ds_rules
|
|||||||
|
|
||||||
export TARGET := SpeccySE
|
export TARGET := SpeccySE
|
||||||
export TOPDIR := $(CURDIR)
|
export TOPDIR := $(CURDIR)
|
||||||
export VERSION := 0.9a
|
export VERSION := 1.0
|
||||||
|
|
||||||
ICON := -b $(CURDIR)/logo.bmp "SpeccySE $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/SpeccySE"
|
ICON := -b $(CURDIR)/logo.bmp "SpeccySE $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/SpeccySE"
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ extern void mmInstall( int fifo_channel );
|
|||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
void VblankHandler(void) {
|
void VblankHandler(void) {
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
Wifi_Update();
|
//Wifi_Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ int main() {
|
|||||||
|
|
||||||
SetYtrigger(80);
|
SetYtrigger(80);
|
||||||
|
|
||||||
installWifiFIFO();
|
//installWifiFIFO();
|
||||||
installSoundFIFO();
|
installSoundFIFO();
|
||||||
|
|
||||||
installSystemFIFO();
|
installSystemFIFO();
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@ -52,10 +52,9 @@ const u32 crc32_table[256] = {
|
|||||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, // 248 [0xF8 .. 0xFF]
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, // 248 [0xF8 .. 0xFF]
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// --------------------------------------------------
|
||||||
// For disk and data pack games which may write back data, we don't want to base the CRC on the actual contents of
|
// Compute the CRC of a memory buffer of any size...
|
||||||
// the media... so instead we'll just hash the filename as a CRC which is good enough to identify it in the future.
|
// --------------------------------------------------
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
|
||||||
u32 getCRC32(u8 *buf, u32 size)
|
u32 getCRC32(u8 *buf, u32 size)
|
||||||
{
|
{
|
||||||
u32 crc = 0xFFFFFFFF;
|
u32 crc = 0xFFFFFFFF;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// Copying and distribution of this emulator, its source code and associated
|
// Copying and distribution of this emulator, its source code and associated
|
||||||
// readme files, with or without modification, are permitted in any medium without
|
// readme files, with or without modification, are permitted in any medium without
|
||||||
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
||||||
// Fayzullin (Z80 core) are thanked profusely.
|
// Fayzullin (Z80 core) are thanked profusely.
|
||||||
//
|
//
|
||||||
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
||||||
@ -35,6 +35,12 @@
|
|||||||
|
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Most handy for development of the emulator is a set of 16 R/W
|
||||||
|
// registers and a couple of index vars... we show this when
|
||||||
|
// global settings is set to show the 'Debugger'. It's amazing
|
||||||
|
// how handy these general registers are for emulation development.
|
||||||
|
// -----------------------------------------------------------------
|
||||||
u32 debug[0x10]={0};
|
u32 debug[0x10]={0};
|
||||||
u32 DX = 0;
|
u32 DX = 0;
|
||||||
u32 DY = 0;
|
u32 DY = 0;
|
||||||
@ -44,19 +50,26 @@ u32 DY = 0;
|
|||||||
// 0x0000-0x3FFF Spectrum BIOS. Either 48.rom or 128.rom (bank 0 or 1)
|
// 0x0000-0x3FFF Spectrum BIOS. Either 48.rom or 128.rom (bank 0 or 1)
|
||||||
// 0x4000-0xFFFF Spectrum 48K of RAM / Memory
|
// 0x4000-0xFFFF Spectrum 48K of RAM / Memory
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
u8 RAM_Memory[0x10000] ALIGN(32) = {0}; // The Z80 Memory is 64K
|
u8 RAM_Memory[0x10000] ALIGN(32) = {0}; // The Z80 Memory is 64K
|
||||||
u8 RAM_Memory128[0x20000] ALIGN(32) = {0}; // The Z80 Memory is 64K but we expand this for a 128K model
|
u8 RAM_Memory128[0x20000] ALIGN(32) = {0}; // The Z80 Memory is 64K but we expand this for a 128K model
|
||||||
u8 SpectrumBios[0x4000] = {0}; // We keep the 16k ZX Spectrum 48K BIOS around
|
u8 SpectrumBios[0x4000] = {0}; // We keep the 16k ZX Spectrum 48K BIOS around
|
||||||
u8 SpectrumBios128[0x8000] = {0}; // We keep the 32k ZX Spectrum 128K BIOS around
|
u8 SpectrumBios128[0x8000] = {0}; // We keep the 32k ZX Spectrum 128K BIOS around
|
||||||
|
|
||||||
u8 ROM_Memory[MAX_TAPE_SIZE]; // This is where we keep the raw untouched file as read from the SD card (.TAP, .TZX, .Z80, etc)
|
u8 ROM_Memory[MAX_TAPE_SIZE]; // This is where we keep the raw untouched file as read from the SD card (.TAP, .TZX, .Z80, etc)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// We track the most recent directory and file loaded... both the initial one
|
||||||
|
// (for the CRC32) and subsequent additional tape loads (Side 2, Side B, etc)
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
static char cmd_line_file[256];
|
static char cmd_line_file[256];
|
||||||
char initial_file[MAX_FILENAME_LEN] = "";
|
char initial_file[MAX_FILENAME_LEN] = "";
|
||||||
char initial_path[MAX_FILENAME_LEN] = "";
|
char initial_path[MAX_FILENAME_LEN] = "";
|
||||||
char last_path[MAX_FILENAME_LEN] = "";
|
char last_path[MAX_FILENAME_LEN] = "";
|
||||||
char last_file[MAX_FILENAME_LEN] = "";
|
char last_file[MAX_FILENAME_LEN] = "";
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// A few housekeeping vars to help with emulation...
|
||||||
|
// --------------------------------------------------
|
||||||
u8 last_speccy_mode = 99;
|
u8 last_speccy_mode = 99;
|
||||||
u8 bFirstTime = 3;
|
u8 bFirstTime = 3;
|
||||||
u8 bottom_screen = 0;
|
u8 bottom_screen = 0;
|
||||||
@ -77,9 +90,9 @@ u8 bSpeccyBiosFound = false;
|
|||||||
u8 soundEmuPause __attribute__((section(".dtcm"))) = 1; // Set to 1 to pause (mute) sound, 0 is sound unmuted (sound channels active)
|
u8 soundEmuPause __attribute__((section(".dtcm"))) = 1; // Set to 1 to pause (mute) sound, 0 is sound unmuted (sound channels active)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------
|
||||||
// This set of critical vars is what determines the machine type -
|
// This set of critical vars is what determines the machine type -
|
||||||
// -----------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------
|
||||||
u8 speccy_mode __attribute__((section(".dtcm"))) = 0; // See defines for the various modes...
|
u8 speccy_mode __attribute__((section(".dtcm"))) = 0; // See defines for the various modes...
|
||||||
u8 kbd_key __attribute__((section(".dtcm"))) = 0; // 0 if no key pressed, othewise the ASCII key (e.g. 'A', 'B', '3', etc)
|
u8 kbd_key __attribute__((section(".dtcm"))) = 0; // 0 if no key pressed, othewise the ASCII key (e.g. 'A', 'B', '3', etc)
|
||||||
u16 nds_key __attribute__((section(".dtcm"))) = 0; // 0 if no key pressed, othewise the NDS keys from keysCurrent() or similar
|
u16 nds_key __attribute__((section(".dtcm"))) = 0; // 0 if no key pressed, othewise the NDS keys from keysCurrent() or similar
|
||||||
u8 last_mapped_key __attribute__((section(".dtcm"))) = 0; // The last mapped key which has been pressed - used for key click feedback
|
u8 last_mapped_key __attribute__((section(".dtcm"))) = 0; // The last mapped key which has been pressed - used for key click feedback
|
||||||
@ -95,16 +108,18 @@ u8 key_debounce = 0; // A bit of key debounce
|
|||||||
// The DS/DSi has 12 keys that can be mapped
|
// 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};
|
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};
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// The key map for the ZX Spectrum... mapped into the NDS controller
|
// The key map for the ZX Spectrum... mapped into the NDS controller
|
||||||
// --------------------------------------------------------------------
|
// We allow mapping of the 5 joystick 'presses' (up, down, left, right
|
||||||
|
// and fire) along with all 40 of the possible ZX Spectrum keyboard keys.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
u16 keyCoresp[MAX_KEY_OPTIONS] __attribute__((section(".dtcm"))) = {
|
u16 keyCoresp[MAX_KEY_OPTIONS] __attribute__((section(".dtcm"))) = {
|
||||||
JST_UP, //0
|
JST_UP, //0
|
||||||
JST_DOWN,
|
JST_DOWN,
|
||||||
JST_LEFT,
|
JST_LEFT,
|
||||||
JST_RIGHT,
|
JST_RIGHT,
|
||||||
JST_FIRE,
|
JST_FIRE,
|
||||||
|
|
||||||
META_KBD_A, //5
|
META_KBD_A, //5
|
||||||
META_KBD_B,
|
META_KBD_B,
|
||||||
META_KBD_C,
|
META_KBD_C,
|
||||||
@ -117,7 +132,7 @@ u16 keyCoresp[MAX_KEY_OPTIONS] __attribute__((section(".dtcm"))) = {
|
|||||||
META_KBD_J,
|
META_KBD_J,
|
||||||
META_KBD_K, //15
|
META_KBD_K, //15
|
||||||
META_KBD_L,
|
META_KBD_L,
|
||||||
META_KBD_M,
|
META_KBD_M,
|
||||||
META_KBD_N,
|
META_KBD_N,
|
||||||
META_KBD_O,
|
META_KBD_O,
|
||||||
META_KBD_P, //20
|
META_KBD_P, //20
|
||||||
@ -142,7 +157,7 @@ u16 keyCoresp[MAX_KEY_OPTIONS] __attribute__((section(".dtcm"))) = {
|
|||||||
META_KBD_8,
|
META_KBD_8,
|
||||||
META_KBD_9,
|
META_KBD_9,
|
||||||
META_KBD_0, //40
|
META_KBD_0, //40
|
||||||
|
|
||||||
META_KBD_SHIFT,
|
META_KBD_SHIFT,
|
||||||
META_KBD_SYMBOL,
|
META_KBD_SYMBOL,
|
||||||
META_KBD_SPACE,
|
META_KBD_SPACE,
|
||||||
@ -217,7 +232,7 @@ ITCM_CODE mm_word OurSoundMixer(mm_word len, mm_addr dest, mm_stream_formats for
|
|||||||
}
|
}
|
||||||
if (breather) {breather -= (len*2); if (breather < 0) breather = 0;}
|
if (breather) {breather -= (len*2); if (breather < 0) breather = 0;}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,20 +247,20 @@ s16 beeper_vol[4] __attribute__((section(".dtcm"))) = { 0x000, 0x200, 0x600, 0xA
|
|||||||
u32 vol __attribute__((section(".dtcm"))) = 0;
|
u32 vol __attribute__((section(".dtcm"))) = 0;
|
||||||
ITCM_CODE void processDirectAudio(void)
|
ITCM_CODE void processDirectAudio(void)
|
||||||
{
|
{
|
||||||
if (zx_AY_enabled)
|
if (zx_AY_enabled)
|
||||||
{
|
{
|
||||||
ay38910Mixer(2, mixbufAY, &myAY);
|
ay38910Mixer(2, mixbufAY, &myAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u8 i=0; i<2; i++)
|
for (u8 i=0; i<2; i++)
|
||||||
{
|
{
|
||||||
// Smooth edges of beeper slightly...
|
// Smooth edges of beeper slightly...
|
||||||
if (portFE & 0x10) {if (vol < 3) vol++;}
|
if (portFE & 0x10) {if (vol < 3) vol++;}
|
||||||
else {if (vol) vol--;}
|
else {if (vol) vol--;}
|
||||||
|
|
||||||
if (breather) {return;}
|
if (breather) {return;}
|
||||||
s16 sample = mixbufAY[i];
|
s16 sample = mixbufAY[i];
|
||||||
if (beeper_vol[vol])
|
if (beeper_vol[vol])
|
||||||
{
|
{
|
||||||
sample += beeper_vol[vol] + (8 - (int)(rand() & 0xF)); // Sample plus a bit of white noise to break up aliasing
|
sample += beeper_vol[vol] + (8 - (int)(rand() & 0xF)); // Sample plus a bit of white noise to break up aliasing
|
||||||
}
|
}
|
||||||
@ -269,7 +284,7 @@ void setupStream(void)
|
|||||||
mmLoadEffect(SFX_CLICKNOQUIT);
|
mmLoadEffect(SFX_CLICKNOQUIT);
|
||||||
mmLoadEffect(SFX_KEYCLICK);
|
mmLoadEffect(SFX_KEYCLICK);
|
||||||
mmLoadEffect(SFX_MUS_INTRO);
|
mmLoadEffect(SFX_MUS_INTRO);
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// open stream
|
// open stream
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -300,7 +315,7 @@ void sound_chip_reset()
|
|||||||
memset(mixer, 0x00, sizeof(mixer));
|
memset(mixer, 0x00, sizeof(mixer));
|
||||||
mixer_read=0;
|
mixer_read=0;
|
||||||
mixer_write=0;
|
mixer_write=0;
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// The AY sound chip is for the ZX Spectrum 128K
|
// The AY sound chip is for the ZX Spectrum 128K
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@ -308,7 +323,7 @@ void sound_chip_reset()
|
|||||||
ay38910IndexW(0x07, &myAY); // Register 7 is ENABLE
|
ay38910IndexW(0x07, &myAY); // Register 7 is ENABLE
|
||||||
ay38910DataW(0x3F, &myAY); // All OFF (negative logic)
|
ay38910DataW(0x3F, &myAY); // All OFF (negative logic)
|
||||||
ay38910Mixer(4, mixbufAY, &myAY);// Do an initial mix conversion to clear the output
|
ay38910Mixer(4, mixbufAY, &myAY);// Do an initial mix conversion to clear the output
|
||||||
|
|
||||||
memset(mixbufAY, 0x00, sizeof(mixbufAY));
|
memset(mixbufAY, 0x00, sizeof(mixbufAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,8 +332,8 @@ void sound_chip_reset()
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
void dsInstallSoundEmuFIFO(void)
|
void dsInstallSoundEmuFIFO(void)
|
||||||
{
|
{
|
||||||
SoundPause(); // Pause any sound output
|
SoundPause(); // Pause any sound output
|
||||||
sound_chip_reset(); // Reset the SN, AY and SCC chips
|
sound_chip_reset(); // Reset the SN, AY and SCC chips
|
||||||
setupStream(); // Setup maxmod stream...
|
setupStream(); // Setup maxmod stream...
|
||||||
bStartSoundEngine = 5; // Volume will 'unpause' after 5 frames in the main loop.
|
bStartSoundEngine = 5; // Volume will 'unpause' after 5 frames in the main loop.
|
||||||
}
|
}
|
||||||
@ -332,7 +347,7 @@ void dsInstallSoundEmuFIFO(void)
|
|||||||
// the RESET button on the touch-screen...
|
// the RESET button on the touch-screen...
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
void ResetSpectrum(void)
|
void ResetSpectrum(void)
|
||||||
{
|
{
|
||||||
JoyState = 0x00000000; // Nothing pressed to start
|
JoyState = 0x00000000; // Nothing pressed to start
|
||||||
|
|
||||||
sound_chip_reset(); // Reset the AY chip
|
sound_chip_reset(); // Reset the AY chip
|
||||||
@ -354,7 +369,7 @@ void ResetSpectrum(void)
|
|||||||
TIMER2_CR=TIMER_ENABLE | TIMER_DIV_1024;
|
TIMER2_CR=TIMER_ENABLE | TIMER_DIV_1024;
|
||||||
timingFrames = 0;
|
timingFrames = 0;
|
||||||
emuFps=0;
|
emuFps=0;
|
||||||
|
|
||||||
bFirstTime = 2;
|
bFirstTime = 2;
|
||||||
bStartIn = 0;
|
bStartIn = 0;
|
||||||
bottom_screen = 0;
|
bottom_screen = 0;
|
||||||
@ -385,7 +400,7 @@ int getMemFree() { // returns the amount of free memory in bytes
|
|||||||
void ShowDebugZ80(void)
|
void ShowDebugZ80(void)
|
||||||
{
|
{
|
||||||
u8 idx=2;
|
u8 idx=2;
|
||||||
|
|
||||||
if (myGlobalConfig.debugger == 3)
|
if (myGlobalConfig.debugger == 3)
|
||||||
{
|
{
|
||||||
sprintf(tmp, "PC %04X SP %04X", CPU.PC.W, CPU.SP.W);
|
sprintf(tmp, "PC %04X SP %04X", CPU.PC.W, CPU.SP.W);
|
||||||
@ -408,7 +423,7 @@ void ShowDebugZ80(void)
|
|||||||
DSPrint(0,idx++,7, tmp);
|
DSPrint(0,idx++,7, tmp);
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[0], myAY.ayRegs[1], myAY.ayRegs[2], myAY.ayRegs[3]);
|
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[0], myAY.ayRegs[1], myAY.ayRegs[2], myAY.ayRegs[3]);
|
||||||
DSPrint(0,idx++,7, tmp);
|
DSPrint(0,idx++,7, tmp);
|
||||||
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[4], myAY.ayRegs[5], myAY.ayRegs[6], myAY.ayRegs[7]);
|
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[4], myAY.ayRegs[5], myAY.ayRegs[6], myAY.ayRegs[7]);
|
||||||
@ -417,13 +432,13 @@ void ShowDebugZ80(void)
|
|||||||
DSPrint(0,idx++,7, tmp);
|
DSPrint(0,idx++,7, tmp);
|
||||||
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[12], myAY.ayRegs[13], myAY.ayRegs[14], myAY.ayRegs[15]);
|
sprintf(tmp, "AY %02X %02X %02X %02X", myAY.ayRegs[12], myAY.ayRegs[13], myAY.ayRegs[14], myAY.ayRegs[15]);
|
||||||
DSPrint(0,idx++,7, tmp);
|
DSPrint(0,idx++,7, tmp);
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
sprintf(tmp, "LOAD: %-9s", loader_type); DSPrint(0,idx++, 7, tmp);
|
sprintf(tmp, "LOAD: %-9s", loader_type); DSPrint(0,idx++, 7, tmp);
|
||||||
sprintf(tmp, "MEM Used %dK", getMemUsed()/1024); DSPrint(0,idx++,7, tmp);
|
sprintf(tmp, "MEM Used %dK", getMemUsed()/1024); DSPrint(0,idx++,7, tmp);
|
||||||
sprintf(tmp, "MEM Free %dK", getMemFree()/1024); DSPrint(0,idx++,7, tmp);
|
sprintf(tmp, "MEM Free %dK", getMemFree()/1024); DSPrint(0,idx++,7, tmp);
|
||||||
|
|
||||||
// CPU Disassembly!
|
// CPU Disassembly!
|
||||||
|
|
||||||
// Put out the debug registers...
|
// Put out the debug registers...
|
||||||
@ -440,7 +455,7 @@ void ShowDebugZ80(void)
|
|||||||
idx = 1;
|
idx = 1;
|
||||||
for (u8 i=0; i<4; i++)
|
for (u8 i=0; i<4; i++)
|
||||||
{
|
{
|
||||||
sprintf(tmp, "D%d %-7ld %04lX D%d %-7ld %04lX", i, (s32)debug[i], (debug[i] < 0xFFFF ? debug[i]:0xFFFF), 4+i, (s32)debug[4+i], (debug[4+i] < 0xFFFF ? debug[4+i]:0xFFFF));
|
sprintf(tmp, "D%d %-7ld %04lX D%d %-7ld %04lX", i, (s32)debug[i], (debug[i] < 0xFFFF ? debug[i]:0xFFFF), 4+i, (s32)debug[4+i], (debug[4+i] < 0xFFFF ? debug[4+i]:0xFFFF));
|
||||||
DSPrint(0,idx++,0, tmp);
|
DSPrint(0,idx++,0, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,12 +498,17 @@ void CassetteInsert(char *filename)
|
|||||||
fclose(inFile);
|
fclose(inFile);
|
||||||
tape_parse_blocks(last_file_size);
|
tape_parse_blocks(last_file_size);
|
||||||
tape_reset();
|
tape_reset();
|
||||||
|
|
||||||
strcpy(last_file, filename);
|
strcpy(last_file, filename);
|
||||||
getcwd(last_path, MAX_FILENAME_LEN);
|
getcwd(last_path, MAX_FILENAME_LEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The Cassette Menu can be called up directly from the keyboard graphic
|
||||||
|
// and allows the user to rewind the tape, swap in a new tape, etc.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
#define MENU_ACTION_END 255 // Always the last sentinal value
|
#define MENU_ACTION_END 255 // Always the last sentinal value
|
||||||
#define MENU_ACTION_EXIT 0 // Exit the menu
|
#define MENU_ACTION_EXIT 0 // Exit the menu
|
||||||
#define MENU_ACTION_PLAY 1 // Play Cassette
|
#define MENU_ACTION_PLAY 1 // Play Cassette
|
||||||
@ -500,13 +520,13 @@ void CassetteInsert(char *filename)
|
|||||||
#define MENU_ACTION_RESET 98 // Reset the machine
|
#define MENU_ACTION_RESET 98 // Reset the machine
|
||||||
#define MENU_ACTION_SKIP 99 // Skip this MENU choice
|
#define MENU_ACTION_SKIP 99 // Skip this MENU choice
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *menu_string;
|
char *menu_string;
|
||||||
u8 menu_action;
|
u8 menu_action;
|
||||||
} MenuItem_t;
|
} MenuItem_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char *title;
|
char *title;
|
||||||
u8 start_row;
|
u8 start_row;
|
||||||
@ -517,13 +537,13 @@ CassetteDiskMenu_t generic_cassette_menu =
|
|||||||
{
|
{
|
||||||
"CASSETTE MENU", 3,
|
"CASSETTE MENU", 3,
|
||||||
{
|
{
|
||||||
{" PLAY CASSETTE ", MENU_ACTION_PLAY},
|
{" PLAY CASSETTE ", MENU_ACTION_PLAY},
|
||||||
{" STOP CASSETTE ", MENU_ACTION_STOP},
|
{" STOP CASSETTE ", MENU_ACTION_STOP},
|
||||||
{" SWAP CASSETTE ", MENU_ACTION_SWAP},
|
{" SWAP CASSETTE ", MENU_ACTION_SWAP},
|
||||||
{" REWIND CASSETTE ", MENU_ACTION_REWIND},
|
{" REWIND CASSETTE ", MENU_ACTION_REWIND},
|
||||||
{" POSITION CASSETTE", MENU_ACTION_POSITION},
|
{" POSITION CASSETTE ", MENU_ACTION_POSITION},
|
||||||
{" EXIT MENU ", MENU_ACTION_EXIT},
|
{" EXIT MENU ", MENU_ACTION_EXIT},
|
||||||
{" NULL ", MENU_ACTION_END},
|
{" NULL ", MENU_ACTION_END},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -537,30 +557,30 @@ u8 cassette_menu_items = 0;
|
|||||||
void CassetteMenuShow(bool bClearScreen, u8 sel)
|
void CassetteMenuShow(bool bClearScreen, u8 sel)
|
||||||
{
|
{
|
||||||
cassette_menu_items = 0;
|
cassette_menu_items = 0;
|
||||||
|
|
||||||
if (bClearScreen)
|
if (bClearScreen)
|
||||||
{
|
{
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Put up the Cassette menu background
|
// Put up the Cassette menu background
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
BottomScreenCassette();
|
BottomScreenCassette();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
// Pick the right context menu based on the machine
|
// Pick the right context menu based on the machine
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
menu = &generic_cassette_menu;
|
menu = &generic_cassette_menu;
|
||||||
|
|
||||||
// Display the menu title
|
// Display the menu title
|
||||||
DSPrint(16-(strlen(menu->title)/2), menu->start_row, 6, menu->title);
|
DSPrint(15-(strlen(menu->title)/2), menu->start_row, 6, menu->title);
|
||||||
|
|
||||||
// And display all of the menu items
|
// And display all of the menu items
|
||||||
while (menu->menulist[cassette_menu_items].menu_action != MENU_ACTION_END)
|
while (menu->menulist[cassette_menu_items].menu_action != MENU_ACTION_END)
|
||||||
{
|
{
|
||||||
DSPrint(16-(strlen(menu->menulist[cassette_menu_items].menu_string)/2), menu->start_row+2+cassette_menu_items, (cassette_menu_items == sel) ? 7:6, menu->menulist[cassette_menu_items].menu_string);
|
DSPrint(16-(strlen(menu->menulist[cassette_menu_items].menu_string)/2), menu->start_row+2+cassette_menu_items, (cassette_menu_items == sel) ? 7:6, menu->menulist[cassette_menu_items].menu_string);
|
||||||
cassette_menu_items++;
|
cassette_menu_items++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
// And near the bottom, display the file/rom/disk/cassette that is currently loaded into memory.
|
// And near the bottom, display the file/rom/disk/cassette that is currently loaded into memory.
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
@ -613,12 +633,12 @@ void CassetteMenu(void)
|
|||||||
case MENU_ACTION_EXIT:
|
case MENU_ACTION_EXIT:
|
||||||
bExitMenu = true;
|
bExitMenu = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_ACTION_PLAY:
|
case MENU_ACTION_PLAY:
|
||||||
tape_play();
|
tape_play();
|
||||||
bExitMenu = true;
|
bExitMenu = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_ACTION_STOP:
|
case MENU_ACTION_STOP:
|
||||||
tape_stop();
|
tape_stop();
|
||||||
bExitMenu = true;
|
bExitMenu = true;
|
||||||
@ -673,7 +693,9 @@ void CassetteMenu(void)
|
|||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Show the Mini Menu - highlight the selected row.
|
// Show the Mini Menu - highlight the selected row. This can be called
|
||||||
|
// up directly from the ZX Keyboard Graphic - allows the user to quit
|
||||||
|
// the current game, set high scores, save/load game state, etc.
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
u8 mini_menu_items = 0;
|
u8 mini_menu_items = 0;
|
||||||
void MiniMenuShow(bool bClearScreen, u8 sel)
|
void MiniMenuShow(bool bClearScreen, u8 sel)
|
||||||
@ -764,6 +786,12 @@ u8 MiniMenu(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Keyboard handler - mapping DS touch screen virtual keys to keyboard keys
|
||||||
|
// that we can feed into the key processing handler in spectrum.c when the
|
||||||
|
// IO port is read.
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
u8 last_special_key = 0;
|
u8 last_special_key = 0;
|
||||||
u8 last_special_key_dampen = 0;
|
u8 last_special_key_dampen = 0;
|
||||||
u8 last_kbd_key = 0;
|
u8 last_kbd_key = 0;
|
||||||
@ -828,12 +856,15 @@ u8 handle_spectrum_keyboard_press(u16 iTx, u16 iTy) // ZX Spectrum keyboard
|
|||||||
else if ((iTx >= 54) && (iTx < 202)) kbd_key = ' ';
|
else if ((iTx >= 54) && (iTx < 202)) kbd_key = ' ';
|
||||||
else if ((iTx >= 202) && (iTx < 255)) return MENU_CHOICE_MENU;
|
else if ((iTx >= 202) && (iTx < 255)) return MENU_CHOICE_MENU;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayStatusLine(false);
|
DisplayStatusLine(false);
|
||||||
|
|
||||||
return MENU_CHOICE_NONE;
|
return MENU_CHOICE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
|
// Special version of the debugger overlay... handling just a small subset of keys...
|
||||||
|
// -----------------------------------------------------------------------------------
|
||||||
u8 handle_debugger_overlay(u16 iTx, u16 iTy)
|
u8 handle_debugger_overlay(u16 iTx, u16 iTy)
|
||||||
{
|
{
|
||||||
if ((iTy >= 165) && (iTy < 192)) // Bottom row is where the debugger keys are...
|
if ((iTy >= 165) && (iTy < 192)) // Bottom row is where the debugger keys are...
|
||||||
@ -848,7 +879,7 @@ u8 handle_debugger_overlay(u16 iTx, u16 iTy)
|
|||||||
if ((iTx >= 156) && (iTx < 187)) kbd_key = KBD_KEY_RET;
|
if ((iTx >= 156) && (iTx < 187)) kbd_key = KBD_KEY_RET;
|
||||||
if ((iTx >= 187) && (iTx < 222)) return MENU_CHOICE_MENU;
|
if ((iTx >= 187) && (iTx < 222)) return MENU_CHOICE_MENU;
|
||||||
else if ((iTx >= 222) && (iTx < 255)) return MENU_CHOICE_CASSETTE;
|
else if ((iTx >= 222) && (iTx < 255)) return MENU_CHOICE_CASSETTE;
|
||||||
|
|
||||||
DisplayStatusLine(false);
|
DisplayStatusLine(false);
|
||||||
}
|
}
|
||||||
else {kbd_key = 0; last_kbd_key = 0;}
|
else {kbd_key = 0; last_kbd_key = 0;}
|
||||||
@ -865,7 +896,7 @@ u8 __attribute__((noinline)) handle_meta_key(u8 meta_key)
|
|||||||
// Ask for verification
|
// Ask for verification
|
||||||
if (showMessage("DO YOU REALLY WANT TO", "RESET THE CURRENT GAME ?") == ID_SHM_YES)
|
if (showMessage("DO YOU REALLY WANT TO", "RESET THE CURRENT GAME ?") == ID_SHM_YES)
|
||||||
{
|
{
|
||||||
ResetSpectrum();
|
ResetSpectrum();
|
||||||
}
|
}
|
||||||
BottomScreenKeyboard();
|
BottomScreenKeyboard();
|
||||||
SoundUnPause();
|
SoundUnPause();
|
||||||
@ -910,14 +941,14 @@ u8 __attribute__((noinline)) handle_meta_key(u8 meta_key)
|
|||||||
BottomScreenKeyboard();
|
BottomScreenKeyboard();
|
||||||
SoundUnPause();
|
SoundUnPause();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_CHOICE_DEFINE_KEYS:
|
case MENU_CHOICE_DEFINE_KEYS:
|
||||||
SoundPause();
|
SoundPause();
|
||||||
SpeccySEChangeKeymap();
|
SpeccySEChangeKeymap();
|
||||||
BottomScreenKeyboard();
|
BottomScreenKeyboard();
|
||||||
SoundUnPause();
|
SoundUnPause();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_CHOICE_POKE_MEMORY:
|
case MENU_CHOICE_POKE_MEMORY:
|
||||||
SoundPause();
|
SoundPause();
|
||||||
pok_select();
|
pok_select();
|
||||||
@ -936,7 +967,7 @@ u8 __attribute__((noinline)) handle_meta_key(u8 meta_key)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show tape blocks with filenames/descriptions...
|
// Show tape blocks with filenames/descriptions...
|
||||||
u8 speccyTapePosition(void)
|
u8 speccyTapePosition(void)
|
||||||
{
|
{
|
||||||
u8 sel = 0;
|
u8 sel = 0;
|
||||||
@ -947,7 +978,7 @@ u8 speccyTapePosition(void)
|
|||||||
DisplayFileNameCassette();
|
DisplayFileNameCassette();
|
||||||
|
|
||||||
DSPrint(1,1,0," TAPE POSITIONS ");
|
DSPrint(1,1,0," TAPE POSITIONS ");
|
||||||
|
|
||||||
u8 max = tape_find_positions();
|
u8 max = tape_find_positions();
|
||||||
u8 screen_max = (max < 10 ? max:10);
|
u8 screen_max = (max < 10 ? max:10);
|
||||||
u8 offset = 0;
|
u8 offset = 0;
|
||||||
@ -956,7 +987,7 @@ u8 speccyTapePosition(void)
|
|||||||
sprintf(tmp, "%03d %-26s", TapePositionTable[offset+i].block_id, TapePositionTable[offset+i].description);
|
sprintf(tmp, "%03d %-26s", TapePositionTable[offset+i].block_id, TapePositionTable[offset+i].description);
|
||||||
DSPrint(1,3+i,(i==sel) ? 2:0,tmp);
|
DSPrint(1,3+i,(i==sel) ? 2:0,tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
u16 keys = keysCurrent();
|
u16 keys = keysCurrent();
|
||||||
@ -975,7 +1006,7 @@ u8 speccyTapePosition(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((offset + screen_max) < max)
|
if ((offset + screen_max) < max)
|
||||||
{
|
{
|
||||||
offset += 10;
|
offset += 10;
|
||||||
screen_max = ((max-offset) < 10 ? (max-offset):10);
|
screen_max = ((max-offset) < 10 ? (max-offset):10);
|
||||||
@ -1031,16 +1062,16 @@ u8 speccyTapePosition(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0);
|
while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0);
|
||||||
WAITVBL;WAITVBL;
|
WAITVBL;WAITVBL;
|
||||||
|
|
||||||
return sel+offset;
|
return sel+offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Chuckie-Style d-pad keeps moving in the last known direction for a few more
|
// Chuckie-Style d-pad keeps moving in the last known direction for a few more
|
||||||
// frames to help make those hairpin turns up and off ladders much easier...
|
// frames to help make those hairpin turns up and off ladders much easier...
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
u8 chuckie_key_up = 0;
|
u8 chuckie_key_up = 0;
|
||||||
u8 chuckie_key_down = 0;
|
u8 chuckie_key_down = 0;
|
||||||
@ -1060,13 +1091,13 @@ void SpeccySE_main(void)
|
|||||||
|
|
||||||
// Setup the debug buffer for DSi use
|
// Setup the debug buffer for DSi use
|
||||||
debug_init();
|
debug_init();
|
||||||
|
|
||||||
// Get the ZX Spectrum Emulator ready
|
// Get the ZX Spectrum Emulator ready
|
||||||
spectrumInit(gpFic[ucGameAct].szName);
|
spectrumInit(gpFic[ucGameAct].szName);
|
||||||
|
|
||||||
spectrumSetPalette();
|
spectrumSetPalette();
|
||||||
spectrumRun();
|
spectrumRun();
|
||||||
|
|
||||||
// Frame-to-frame timing...
|
// Frame-to-frame timing...
|
||||||
TIMER1_CR = 0;
|
TIMER1_CR = 0;
|
||||||
TIMER1_DATA=0;
|
TIMER1_DATA=0;
|
||||||
@ -1081,9 +1112,9 @@ void SpeccySE_main(void)
|
|||||||
|
|
||||||
// Force the sound engine to turn on when we start emulation
|
// Force the sound engine to turn on when we start emulation
|
||||||
bStartSoundEngine = 10;
|
bStartSoundEngine = 10;
|
||||||
|
|
||||||
bFirstTime = 2;
|
bFirstTime = 2;
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Stay in this loop running the Spectrum game until the user exits...
|
// Stay in this loop running the Spectrum game until the user exits...
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
@ -1124,7 +1155,7 @@ void SpeccySE_main(void)
|
|||||||
}
|
}
|
||||||
DisplayStatusLine(false);
|
DisplayStatusLine(false);
|
||||||
emuActFrames = 0;
|
emuActFrames = 0;
|
||||||
|
|
||||||
if (bStartIn)
|
if (bStartIn)
|
||||||
{
|
{
|
||||||
if (--bStartIn == 0)
|
if (--bStartIn == 0)
|
||||||
@ -1132,12 +1163,12 @@ void SpeccySE_main(void)
|
|||||||
tape_play();
|
tape_play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bFirstTime)
|
if (bFirstTime)
|
||||||
{
|
{
|
||||||
if (--bFirstTime == 0)
|
if (--bFirstTime == 0)
|
||||||
{
|
{
|
||||||
// Tape Loader - Put the LOAD "" into the keyboard buffer
|
// Tape Loader - Put the LOAD "" into the keyboard buffer
|
||||||
if (speccy_mode < MODE_SNA)
|
if (speccy_mode < MODE_SNA)
|
||||||
{
|
{
|
||||||
if (myConfig.autoLoad)
|
if (myConfig.autoLoad)
|
||||||
@ -1178,7 +1209,7 @@ void SpeccySE_main(void)
|
|||||||
while (TIMER2_DATA < 655*(timingFrames+1))
|
while (TIMER2_DATA < 655*(timingFrames+1))
|
||||||
{
|
{
|
||||||
if (myGlobalConfig.showFPS == 2) break; // If Full Speed, break out...
|
if (myGlobalConfig.showFPS == 2) break; // If Full Speed, break out...
|
||||||
if (tape_is_playing())
|
if (tape_is_playing())
|
||||||
{
|
{
|
||||||
mixer_read = mixer_write = 0;
|
mixer_read = mixer_write = 0;
|
||||||
bStartSoundEngine = 5; // Unpause sound after 5 frames
|
bStartSoundEngine = 5; // Unpause sound after 5 frames
|
||||||
@ -1197,7 +1228,7 @@ void SpeccySE_main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
// Hold the key press for a brief instant... To allow the
|
// Hold the key press for a brief instant... To allow the
|
||||||
// emulated ZX Spectrum to 'see' the key briefly... Good enough.
|
// emulated ZX Spectrum to 'see' the key briefly... Good enough.
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
if (key_debounce > 0) key_debounce--;
|
if (key_debounce > 0) key_debounce--;
|
||||||
@ -1230,12 +1261,12 @@ void SpeccySE_main(void)
|
|||||||
meta_key = handle_debugger_overlay(iTx, iTy);
|
meta_key = handle_debugger_overlay(iTx, iTy);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// Test the touchscreen for various full keyboard handlers...
|
// Test the touchscreen for various full keyboard handlers...
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
meta_key = handle_spectrum_keyboard_press(iTx, iTy);
|
meta_key = handle_spectrum_keyboard_press(iTx, iTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kbd_key != 0)
|
if (kbd_key != 0)
|
||||||
{
|
{
|
||||||
@ -1277,9 +1308,9 @@ void SpeccySE_main(void)
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
ucDEUX = 0;
|
ucDEUX = 0;
|
||||||
nds_key = keysCurrent(); // Get any current keys pressed on the NDS
|
nds_key = keysCurrent(); // Get any current keys pressed on the NDS
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Check various key combinations first...
|
// Check various key combinations first...
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
if ((nds_key & KEY_L) && (nds_key & KEY_R) && (nds_key & KEY_X))
|
if ((nds_key & KEY_L) && (nds_key & KEY_R) && (nds_key & KEY_X))
|
||||||
{
|
{
|
||||||
@ -1307,29 +1338,29 @@ void SpeccySE_main(void)
|
|||||||
{
|
{
|
||||||
chuckie_key_up = 12;
|
chuckie_key_up = 12;
|
||||||
chuckie_key_down = 0;
|
chuckie_key_down = 0;
|
||||||
}
|
}
|
||||||
if (nds_key & KEY_DOWN)
|
if (nds_key & KEY_DOWN)
|
||||||
{
|
{
|
||||||
chuckie_key_down = 12;
|
chuckie_key_down = 12;
|
||||||
chuckie_key_up = 0;
|
chuckie_key_up = 0;
|
||||||
}
|
}
|
||||||
if (nds_key & KEY_LEFT)
|
if (nds_key & KEY_LEFT)
|
||||||
{
|
{
|
||||||
chuckie_key_left = 12;
|
chuckie_key_left = 12;
|
||||||
chuckie_key_right = 0;
|
chuckie_key_right = 0;
|
||||||
}
|
}
|
||||||
if (nds_key & KEY_RIGHT)
|
if (nds_key & KEY_RIGHT)
|
||||||
{
|
{
|
||||||
chuckie_key_right = 12;
|
chuckie_key_right = 12;
|
||||||
chuckie_key_left = 0;
|
chuckie_key_left = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chuckie_key_up)
|
if (chuckie_key_up)
|
||||||
{
|
{
|
||||||
chuckie_key_up--;
|
chuckie_key_up--;
|
||||||
nds_key |= KEY_UP;
|
nds_key |= KEY_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chuckie_key_down)
|
if (chuckie_key_down)
|
||||||
{
|
{
|
||||||
chuckie_key_down--;
|
chuckie_key_down--;
|
||||||
@ -1348,7 +1379,7 @@ void SpeccySE_main(void)
|
|||||||
nds_key |= KEY_RIGHT;
|
nds_key |= KEY_RIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
// There are 12 NDS buttons (D-Pad, XYAB, L/R and Start+Select) - we allow mapping of any of these.
|
// There are 12 NDS buttons (D-Pad, XYAB, L/R and Start+Select) - we allow mapping of any of these.
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
@ -1385,7 +1416,7 @@ void SpeccySE_main(void)
|
|||||||
if (chuckie_key_right) chuckie_key_right--;
|
if (chuckie_key_right) chuckie_key_right--;
|
||||||
last_mapped_key = 0;
|
last_mapped_key = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
// Finally, check if there are any buffered keys that need to go into the keyboard handling.
|
// Finally, check if there are any buffered keys that need to go into the keyboard handling.
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
@ -1395,7 +1426,7 @@ void SpeccySE_main(void)
|
|||||||
// Accumulate all bits above into the Joystick State var...
|
// Accumulate all bits above into the Joystick State var...
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
JoyState = ucDEUX;
|
JoyState = ucDEUX;
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// Handle Auto-Fire if enabled in configuration...
|
// Handle Auto-Fire if enabled in configuration...
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
@ -1447,7 +1478,7 @@ void speccySEInit(void)
|
|||||||
unsigned short dmaVal =*(bgGetMapPtr(bg0)+51*32);
|
unsigned short dmaVal =*(bgGetMapPtr(bg0)+51*32);
|
||||||
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1),32*24*2);
|
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1),32*24*2);
|
||||||
|
|
||||||
// Put up the options screen
|
// Put up the options screen
|
||||||
BottomScreenOptions();
|
BottomScreenOptions();
|
||||||
|
|
||||||
// Find the files
|
// Find the files
|
||||||
@ -1457,7 +1488,7 @@ void speccySEInit(void)
|
|||||||
void BottomScreenOptions(void)
|
void BottomScreenOptions(void)
|
||||||
{
|
{
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
|
|
||||||
if (bottom_screen != 1)
|
if (bottom_screen != 1)
|
||||||
{
|
{
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
@ -1466,11 +1497,11 @@ void BottomScreenOptions(void)
|
|||||||
bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
|
bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
|
||||||
bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 29,0);
|
bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 29,0);
|
||||||
bgSetPriority(bg0b,1);bgSetPriority(bg1b,0);
|
bgSetPriority(bg0b,1);bgSetPriority(bg1b,0);
|
||||||
|
|
||||||
decompress(mainmenuTiles, bgGetGfxPtr(bg0b), LZ77Vram);
|
decompress(mainmenuTiles, bgGetGfxPtr(bg0b), LZ77Vram);
|
||||||
decompress(mainmenuMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
|
decompress(mainmenuMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
|
||||||
dmaCopy((void*) mainmenuPal,(void*) BG_PALETTE_SUB,256*2);
|
dmaCopy((void*) mainmenuPal,(void*) BG_PALETTE_SUB,256*2);
|
||||||
|
|
||||||
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
||||||
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
||||||
}
|
}
|
||||||
@ -1478,7 +1509,7 @@ void BottomScreenOptions(void)
|
|||||||
{
|
{
|
||||||
for (u8 i=0; i<23; i++) DSPrint(0,i,0," ");
|
for (u8 i=0; i<23; i++) DSPrint(0,i,0," ");
|
||||||
}
|
}
|
||||||
|
|
||||||
bottom_screen = 1;
|
bottom_screen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1488,7 +1519,7 @@ void BottomScreenOptions(void)
|
|||||||
void BottomScreenKeyboard(void)
|
void BottomScreenKeyboard(void)
|
||||||
{
|
{
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
|
|
||||||
if (myGlobalConfig.debugger == 3) // Full Z80 Debug overrides things... put up the debugger overlay
|
if (myGlobalConfig.debugger == 3) // Full Z80 Debug overrides things... put up the debugger overlay
|
||||||
{
|
{
|
||||||
// Init bottom screen
|
// Init bottom screen
|
||||||
@ -1505,10 +1536,10 @@ void BottomScreenKeyboard(void)
|
|||||||
dmaCopy((void*) bgGetMapPtr(bg0b)+32*30*2,(void*) bgGetMapPtr(bg1b),32*24*2);
|
dmaCopy((void*) bgGetMapPtr(bg0b)+32*30*2,(void*) bgGetMapPtr(bg1b),32*24*2);
|
||||||
dmaCopy((void*) speccy_kbdPal,(void*) BG_PALETTE_SUB,256*2);
|
dmaCopy((void*) speccy_kbdPal,(void*) BG_PALETTE_SUB,256*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
||||||
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
||||||
|
|
||||||
bottom_screen = 2;
|
bottom_screen = 2;
|
||||||
|
|
||||||
show_tape_counter = 0;
|
show_tape_counter = 0;
|
||||||
@ -1520,21 +1551,21 @@ void BottomScreenKeyboard(void)
|
|||||||
void BottomScreenCassette(void)
|
void BottomScreenCassette(void)
|
||||||
{
|
{
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
// Put up the cassette screen background...
|
// Put up the cassette screen background...
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
|
bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
|
||||||
bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 29,0);
|
bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 29,0);
|
||||||
bgSetPriority(bg0b,1);bgSetPriority(bg1b,0);
|
bgSetPriority(bg0b,1);bgSetPriority(bg1b,0);
|
||||||
|
|
||||||
decompress(cassetteTiles, bgGetGfxPtr(bg0b), LZ77Vram);
|
decompress(cassetteTiles, bgGetGfxPtr(bg0b), LZ77Vram);
|
||||||
decompress(cassetteMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
|
decompress(cassetteMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
|
||||||
dmaCopy((void*) cassettePal,(void*) BG_PALETTE_SUB,256*2);
|
dmaCopy((void*) cassettePal,(void*) BG_PALETTE_SUB,256*2);
|
||||||
|
|
||||||
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
unsigned short dmaVal = *(bgGetMapPtr(bg1b)+24*32);
|
||||||
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
|
||||||
|
|
||||||
bottom_screen = 3;
|
bottom_screen = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1544,16 +1575,16 @@ void BottomScreenCassette(void)
|
|||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
void speccySEInitCPU(void)
|
void speccySEInitCPU(void)
|
||||||
{
|
{
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Init Main Memory and VDP Video Memory
|
// Init Main Memory for the Spectrum
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
memset(RAM_Memory, 0x00, sizeof(RAM_Memory));
|
memset(RAM_Memory, 0x00, sizeof(RAM_Memory));
|
||||||
memset(RAM_Memory128, 0x00, sizeof(RAM_Memory128));
|
memset(RAM_Memory128, 0x00, sizeof(RAM_Memory128));
|
||||||
|
|
||||||
// -----------------------------------------------
|
// -----------------------------------------------
|
||||||
// Init bottom screen do display the ZX Keyboard
|
// Init bottom screen do display the ZX Keyboard
|
||||||
// -----------------------------------------------
|
// -----------------------------------------------
|
||||||
BottomScreenKeyboard();
|
BottomScreenKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
@ -1561,8 +1592,8 @@ void speccySEInitCPU(void)
|
|||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
void irqVBlank(void)
|
void irqVBlank(void)
|
||||||
{
|
{
|
||||||
// Manage time
|
// Manage time
|
||||||
vusCptVBL++;
|
vusCptVBL++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@ -1583,7 +1614,7 @@ void LoadBIOSFiles(void)
|
|||||||
size = ReadFileCarefully("48.rom", SpectrumBios, 0x4000, 0);
|
size = ReadFileCarefully("48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/48.rom", SpectrumBios, 0x4000, 0);
|
||||||
|
|
||||||
if (!size) size = ReadFileCarefully("48k.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("48k.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/48k.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/48k.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/48k.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/48k.rom", SpectrumBios, 0x4000, 0);
|
||||||
@ -1591,35 +1622,35 @@ void LoadBIOSFiles(void)
|
|||||||
if (!size) size = ReadFileCarefully("speccy.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("speccy.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/speccy.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/speccy.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/speccy.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/speccy.rom", SpectrumBios, 0x4000, 0);
|
||||||
|
|
||||||
if (!size) size = ReadFileCarefully("zxs48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("zxs48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/zxs48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/zxs48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/zxs48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/zxs48.rom", SpectrumBios, 0x4000, 0);
|
||||||
|
|
||||||
if (!size) size = ReadFileCarefully("spec48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("spec48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/spec48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/spec48.rom", SpectrumBios, 0x4000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/spec48.rom", SpectrumBios, 0x4000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/spec48.rom", SpectrumBios, 0x4000, 0);
|
||||||
|
|
||||||
if (size) bSpeccyBiosFound = true; else memset(SpectrumBios, 0xFF, 0x4000);
|
if (size) bSpeccyBiosFound = true; else memset(SpectrumBios, 0xFF, 0x4000);
|
||||||
|
|
||||||
size = ReadFileCarefully("128.rom", SpectrumBios128, 0x8000, 0);
|
size = ReadFileCarefully("128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/128.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/128.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
|
|
||||||
if (!size) size = ReadFileCarefully("128k.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("128k.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/128k.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/128k.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/128k.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/128k.rom", SpectrumBios128, 0x8000, 0);
|
||||||
|
|
||||||
if (!size) size = ReadFileCarefully("zxs128.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("zxs128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/roms/bios/zxs128.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/roms/bios/zxs128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
if (!size) size = ReadFileCarefully("/data/bios/zxs128.rom", SpectrumBios128, 0x8000, 0);
|
if (!size) size = ReadFileCarefully("/data/bios/zxs128.rom", SpectrumBios128, 0x8000, 0);
|
||||||
|
|
||||||
if (size) bSpeccyBiosFound = true; else memset(SpectrumBios128, 0xFF, 0x8000);
|
if (size) bSpeccyBiosFound = true; else memset(SpectrumBios128, 0xFF, 0x8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************
|
/************************************************************************************
|
||||||
* Program entry point - check if an argument has been passed in probably from TWL++
|
* Program entry point - check if an argument has been passed in probably from TWL++
|
||||||
********************************************************************************/
|
***********************************************************************************/
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Init sound
|
// Init sound
|
||||||
@ -1648,11 +1679,11 @@ int main(int argc, char **argv)
|
|||||||
irqEnable(IRQ_VBLANK);
|
irqEnable(IRQ_VBLANK);
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// Grab the BIOS before we try to switch any DIRECTORYories around...
|
// Grab the BIOS before we try to switch any directories around...
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
useVRAM();
|
useVRAM();
|
||||||
LoadBIOSFiles();
|
LoadBIOSFiles();
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
// And do an initial load of configuration... We'll match it up
|
// And do an initial load of configuration... We'll match it up
|
||||||
// with the game that was selected later...
|
// with the game that was selected later...
|
||||||
@ -1662,7 +1693,7 @@ int main(int argc, char **argv)
|
|||||||
// Handle command line argument... mostly for TWL++
|
// Handle command line argument... mostly for TWL++
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
// We want to start in the DIRECTORYory where the file is being launched...
|
// We want to start in the directory where the file is being launched...
|
||||||
if (strchr(argv[1], '/') != NULL)
|
if (strchr(argv[1], '/') != NULL)
|
||||||
{
|
{
|
||||||
static char path[128];
|
static char path[128];
|
||||||
@ -1682,7 +1713,7 @@ int main(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cmd_line_file[0]=0; // No file passed on command line...
|
cmd_line_file[0]=0; // No file passed on command line...
|
||||||
|
|
||||||
if (myGlobalConfig.lastDir && (strlen(myGlobalConfig.szLastPath) > 2))
|
if (myGlobalConfig.lastDir && (strlen(myGlobalConfig.szLastPath) > 2))
|
||||||
{
|
{
|
||||||
chdir(myGlobalConfig.szLastPath); // Try to start back where we last were...
|
chdir(myGlobalConfig.szLastPath); // Try to start back where we last were...
|
||||||
@ -1699,7 +1730,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SoundPause();
|
SoundPause();
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
@ -1749,7 +1780,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// The code below is a handy set of debug tools that allows us to
|
// The code below is a handy set of debug tools that allows us to
|
||||||
// write printf() like strings out to a file. Basically we accumulate
|
// write printf() like strings out to a file. Basically we accumulate
|
||||||
// the strings into a large RAM buffer and then when the L+R shoulder
|
// the strings into a large RAM buffer and then when the L+R shoulder
|
||||||
// buttons are pressed and held, we will snapshot out the debug.log file.
|
// buttons are pressed and held, we will snapshot out the debug.log file.
|
||||||
@ -1767,7 +1798,7 @@ void debug_init()
|
|||||||
{
|
{
|
||||||
if (!debug_buffer)
|
if (!debug_buffer)
|
||||||
{
|
{
|
||||||
if (isDSiMode())
|
if (isDSiMode())
|
||||||
{
|
{
|
||||||
MAX_DEBUG_BUF_SIZE = (1024*1024*2); // 2MB!!
|
MAX_DEBUG_BUF_SIZE = (1024*1024*2); // 2MB!!
|
||||||
debug_buffer = malloc(MAX_DEBUG_BUF_SIZE);
|
debug_buffer = malloc(MAX_DEBUG_BUF_SIZE);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// Copying and distribution of this emulator, its source code and associated
|
// Copying and distribution of this emulator, its source code and associated
|
||||||
// readme files, with or without modification, are permitted in any medium without
|
// readme files, with or without modification, are permitted in any medium without
|
||||||
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
||||||
// Fayzullin (ColEM core) are thanked profusely.
|
// Fayzullin (ColEM core) are thanked profusely.
|
||||||
//
|
//
|
||||||
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
||||||
@ -27,7 +27,7 @@ extern u32 DX, DY;
|
|||||||
#define MENU_CHOICE_DEFINE_KEYS 0x06
|
#define MENU_CHOICE_DEFINE_KEYS 0x06
|
||||||
#define MENU_CHOICE_POKE_MEMORY 0x07
|
#define MENU_CHOICE_POKE_MEMORY 0x07
|
||||||
#define MENU_CHOICE_CASSETTE 0x08
|
#define MENU_CHOICE_CASSETTE 0x08
|
||||||
#define MENU_CHOICE_MENU 0xFF // Special brings up a menu of choices
|
#define MENU_CHOICE_MENU 0xFF // Special brings up a mini-menu of choices
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
// Joystick UP, RIGHT, LEFT, DOWN and the FIRE button for the Kempston Joystick.
|
// Joystick UP, RIGHT, LEFT, DOWN and the FIRE button for the Kempston Joystick.
|
||||||
@ -110,7 +110,7 @@ extern u32 DX, DY;
|
|||||||
#define WAITVBL swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank();
|
#define WAITVBL swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank();
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// This massive patch table consumes 256K (64 x 4 byte function pointers)
|
// This massive patch table consumes 256K (64 x 4 byte function pointers)
|
||||||
// to allow us faster access to patch routines for tape edge detection.
|
// to allow us faster access to patch routines for tape edge detection.
|
||||||
// We put it in LCD VRAM as this is slightly faster access on the DS/DSi.
|
// We put it in LCD VRAM as this is slightly faster access on the DS/DSi.
|
||||||
// 99% of this massive array will be zeroes but we don't have another use
|
// 99% of this massive array will be zeroes but we don't have another use
|
||||||
@ -129,8 +129,8 @@ extern char initial_file[];
|
|||||||
extern char initial_path[];
|
extern char initial_path[];
|
||||||
extern u16 nds_key;
|
extern u16 nds_key;
|
||||||
extern u8 kbd_key;
|
extern u8 kbd_key;
|
||||||
extern u16 vusCptVBL; // Video Management
|
extern u16 vusCptVBL;
|
||||||
extern u16 *pVidFlipBuf; // Video flipping buffer
|
extern u16 *pVidFlipBuf;
|
||||||
extern u16 keyCoresp[MAX_KEY_OPTIONS];
|
extern u16 keyCoresp[MAX_KEY_OPTIONS];
|
||||||
extern u16 NDS_keyMap[];
|
extern u16 NDS_keyMap[];
|
||||||
extern u8 soundEmuPause;
|
extern u8 soundEmuPause;
|
||||||
|
@ -291,7 +291,7 @@ void dsDisplayFiles(u16 NoDebGame, u8 ucSel)
|
|||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Standard qsort routine for the games - we sort all DIRECTORYory
|
// Standard qsort routine for the games - we sort all directory
|
||||||
// listings first and then a case-insenstive sort of all games.
|
// listings first and then a case-insenstive sort of all games.
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
int Filescmp (const void *c1, const void *c2)
|
int Filescmp (const void *c1, const void *c2)
|
||||||
@ -1652,7 +1652,7 @@ void spectrumRun(void)
|
|||||||
BottomScreenKeyboard(); // Show the game-related screen with keypad / keyboard
|
BottomScreenKeyboard(); // Show the game-related screen with keypad / keyboard
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 ZX_Spectrum_palette[16*3] = {
|
u8 ZX_Spectrum_palette[16*3] = {
|
||||||
0x00,0x00,0x00, // Black
|
0x00,0x00,0x00, // Black
|
||||||
0x00,0x00,0xD8, // Blue
|
0x00,0x00,0xD8, // Blue
|
||||||
0xD8,0x00,0x00, // Red
|
0xD8,0x00,0x00, // Red
|
||||||
@ -1718,9 +1718,9 @@ u8 loadgame(const char *filename)
|
|||||||
// Save the initial filename and file - we need it for save/restore of state
|
// Save the initial filename and file - we need it for save/restore of state
|
||||||
strcpy(initial_file, filename);
|
strcpy(initial_file, filename);
|
||||||
getcwd(initial_path, MAX_FILENAME_LEN);
|
getcwd(initial_path, MAX_FILENAME_LEN);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// See if we are loading a file from a directory different than our
|
// See if we are loading a file from a directory different than our
|
||||||
// last saved directory... if so, we save this new directory as default.
|
// last saved directory... if so, we save this new directory as default.
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
if (myGlobalConfig.lastDir)
|
if (myGlobalConfig.lastDir)
|
||||||
@ -1730,7 +1730,7 @@ u8 loadgame(const char *filename)
|
|||||||
SaveConfig(FALSE);
|
SaveConfig(FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get file size the 'fast' way - use fstat() instead of fseek() or ftell()
|
// Get file size the 'fast' way - use fstat() instead of fseek() or ftell()
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
(void)fstat(fileno(handle), &stbuf);
|
(void)fstat(fileno(handle), &stbuf);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
// Copying and distribution of this emulator, its source code and associated
|
// Copying and distribution of this emulator, its source code and associated
|
||||||
// readme files, with or without modification, are permitted in any medium without
|
// readme files, with or without modification, are permitted in any medium without
|
||||||
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
// royalty provided this copyright notice is used and wavemotion-dave and Marat
|
||||||
// Fayzullin (ColEM core) are thanked profusely.
|
// Fayzullin (ColEM core) are thanked profusely.
|
||||||
//
|
//
|
||||||
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
// The SpeccySE emulator is offered as-is, without any warranty. Please see readme.md
|
||||||
@ -17,18 +17,18 @@
|
|||||||
|
|
||||||
#define MAX_FILES 2048
|
#define MAX_FILES 2048
|
||||||
#define MAX_FILENAME_LEN 160
|
#define MAX_FILENAME_LEN 160
|
||||||
#define MAX_TAPE_SIZE (640*1024) // 640K is big enough for any .TAP/.TZX or Snapshot
|
#define MAX_TAPE_SIZE (640*1024) // 640K is big enough for any .TAP/.TZX or Snapshot
|
||||||
|
|
||||||
#define MAX_CONFIGS 1000
|
#define MAX_CONFIGS 1000
|
||||||
#define CONFIG_VERSION 0x0004
|
#define CONFIG_VERSION 0x0004
|
||||||
|
|
||||||
#define SPECCY_FILE 0x01
|
#define SPECCY_FILE 0x01
|
||||||
#define DIRECTORY 0x02
|
#define DIRECTORY 0x02
|
||||||
|
|
||||||
#define ID_SHM_CANCEL 0x00
|
#define ID_SHM_CANCEL 0x00
|
||||||
#define ID_SHM_YES 0x01
|
#define ID_SHM_YES 0x01
|
||||||
#define ID_SHM_NO 0x02
|
#define ID_SHM_NO 0x02
|
||||||
|
|
||||||
#define DPAD_NORMAL 0
|
#define DPAD_NORMAL 0
|
||||||
#define DPAD_DIAGONALS 1
|
#define DPAD_DIAGONALS 1
|
||||||
#define DPAD_CHUCKIE 2
|
#define DPAD_CHUCKIE 2
|
||||||
@ -137,7 +137,7 @@ extern u8 RAM_Memory128[0x20000];
|
|||||||
extern u8 *MemoryMap[4];
|
extern u8 *MemoryMap[4];
|
||||||
extern AY38910 myAY;
|
extern AY38910 myAY;
|
||||||
|
|
||||||
extern FISpeccy gpFic[MAX_FILES];
|
extern FISpeccy gpFic[MAX_FILES];
|
||||||
extern int uNbRoms;
|
extern int uNbRoms;
|
||||||
extern int ucGameAct;
|
extern int ucGameAct;
|
||||||
extern int ucGameChoice;
|
extern int ucGameChoice;
|
||||||
|
@ -591,20 +591,8 @@ void ExecOneInstruction(void)
|
|||||||
{
|
{
|
||||||
register byte I;
|
register byte I;
|
||||||
register pair J;
|
register pair J;
|
||||||
u8 render = zx_ScreenRendering;
|
|
||||||
u32 RunToCycles = CPU.TStates+1;
|
u32 RunToCycles = CPU.TStates+1;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
// If we are in contended memory - add penalty. This is not cycle accurate but we want to
|
|
||||||
// at least make an attempt to get closer on the cycle timing. So we simply use an 'average'
|
|
||||||
// penalty of 4 cycles if we are in contended memory while the screen is rendering. It's
|
|
||||||
// rough but gets us close enough to play games. We can improve this later...
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
if (render)
|
|
||||||
{
|
|
||||||
if ((CPU.PC.W & 0xC000) == 0x4000) CPU.TStates += zx_contend_delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
I=OpZ80(CPU.PC.W++);
|
I=OpZ80(CPU.PC.W++);
|
||||||
CPU.TStates += Cycles_NoM1Wait[I];
|
CPU.TStates += Cycles_NoM1Wait[I];
|
||||||
|
|
||||||
@ -646,7 +634,8 @@ ITCM_CODE void ExecZ80_Speccy(u32 RunToCycles)
|
|||||||
{
|
{
|
||||||
register byte I;
|
register byte I;
|
||||||
register pair J;
|
register pair J;
|
||||||
u8 render = zx_ScreenRendering;
|
u8 render = zx_ScreenRendering; // Slightly faster access from stack
|
||||||
|
u8 delay = zx_contend_delay; // Slightly faster access from stack
|
||||||
|
|
||||||
while (CPU.TStates < RunToCycles)
|
while (CPU.TStates < RunToCycles)
|
||||||
{
|
{
|
||||||
@ -658,7 +647,18 @@ ITCM_CODE void ExecZ80_Speccy(u32 RunToCycles)
|
|||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
if (render)
|
if (render)
|
||||||
{
|
{
|
||||||
if ((CPU.PC.W & 0xC000) == 0x4000) CPU.TStates += zx_contend_delay;
|
if (CPU.PC.W & 0x4000) // Either 0x4000 or 0xC000
|
||||||
|
{
|
||||||
|
if (CPU.PC.W & 0x8000) // Must be 0xC000
|
||||||
|
{
|
||||||
|
// For the ZX 128K bank, we contend if the bank is odd (1,3,5,7)
|
||||||
|
if (zx_128k_mode && (portFD & 1)) CPU.TStates += delay;
|
||||||
|
}
|
||||||
|
else // Must be 0x4000 - we contend on any video access (both 48K and 128K)
|
||||||
|
{
|
||||||
|
CPU.TStates += delay;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
I=OpZ80(CPU.PC.W++);
|
I=OpZ80(CPU.PC.W++);
|
||||||
|
@ -38,10 +38,10 @@ void highscore_save(void);
|
|||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// Each score has this stuff... Initials, score and date.
|
// Each score has this stuff... Initials, score and date.
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
struct score_t
|
struct score_t
|
||||||
{
|
{
|
||||||
char initials[4]; // With NULL this is only 3 ascii characters
|
char initials[4]; // With NULL this is only 3 ascii characters
|
||||||
char score[7]; // Six digits of score
|
char score[7]; // Six digits of score
|
||||||
char reserved; // For the future...
|
char reserved; // For the future...
|
||||||
u16 year; // Date score was achieved. We'll auto-fill this from DS time
|
u16 year; // Date score was achieved. We'll auto-fill this from DS time
|
||||||
u8 month;
|
u8 month;
|
||||||
@ -60,8 +60,8 @@ struct highscore_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// We save up to 550 games worth of scores. We also have a spot for default initials
|
// We save up to 550 games worth of scores. We also have a spot for default initials
|
||||||
// so we can re-use the last initials for the last high-score entered. Saves time
|
// so we can re-use the last initials for the last high-score entered. Saves time
|
||||||
// for most people who are always the ones using their DS system.
|
// for most people who are always the ones using their DS system.
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
struct highscore_full_t
|
struct highscore_full_t
|
||||||
@ -88,10 +88,10 @@ u32 highscore_checksum(void)
|
|||||||
{
|
{
|
||||||
char *ptr = (char *)&highscores;
|
char *ptr = (char *)&highscores;
|
||||||
u32 sum = 0;
|
u32 sum = 0;
|
||||||
|
|
||||||
for (int i=0; i<(int)sizeof(highscores) - 4; i++)
|
for (int i=0; i<(int)sizeof(highscores) - 4; i++)
|
||||||
{
|
{
|
||||||
sum = *ptr++;
|
sum = *ptr++;
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
@ -101,23 +101,22 @@ u32 highscore_checksum(void)
|
|||||||
// Read the high score file, if it exists. If it doesn't exist or if the file
|
// Read the high score file, if it exists. If it doesn't exist or if the file
|
||||||
// is not the right version and/or is corrupt (crc check), reset to defaults.
|
// is not the right version and/or is corrupt (crc check), reset to defaults.
|
||||||
// ------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------
|
||||||
void highscore_init(void)
|
void highscore_init(void)
|
||||||
{
|
{
|
||||||
u8 upgrade_database = 0;
|
|
||||||
u8 create_defaults = 0;
|
u8 create_defaults = 0;
|
||||||
|
|
||||||
strcpy(highscores.last_initials, " ");
|
strcpy(highscores.last_initials, " ");
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// See if the high score file exists... if so, read it!
|
// See if the high score file exists... if so, read it!
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
if (ReadFileCarefully("/data/SpeccySE.hi", (u8*)&highscores, sizeof(highscores), 0))
|
if (ReadFileCarefully("/data/SpeccySE.hi", (u8*)&highscores, sizeof(highscores), 0))
|
||||||
{
|
{
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// If the high score version is wrong or if
|
// If the high score version is wrong or if
|
||||||
// the checksum is wrong, reset to defaults
|
// the checksum is wrong, reset to defaults
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
if (highscores.version != HS_VERSION)
|
if (highscores.version != HS_VERSION)
|
||||||
{
|
{
|
||||||
create_defaults = 1;
|
create_defaults = 1;
|
||||||
}
|
}
|
||||||
@ -127,30 +126,11 @@ void highscore_init(void)
|
|||||||
{
|
{
|
||||||
create_defaults = 1;
|
create_defaults = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upgrade_database)
|
if (create_defaults) // Doesn't exist yet or is invalid... create defaults and save it...
|
||||||
{
|
|
||||||
for (int i=400; i<MAX_HS_GAMES; i++)
|
|
||||||
{
|
|
||||||
highscores.highscore_table[i].crc = 0x00000000;
|
|
||||||
strcpy(highscores.highscore_table[i].notes, " ");
|
|
||||||
highscores.highscore_table[i].options = 0x0000;
|
|
||||||
for (int j=0; j<10; j++)
|
|
||||||
{
|
|
||||||
strcpy(highscores.highscore_table[i].scores[j].score, "000000");
|
|
||||||
strcpy(highscores.highscore_table[i].scores[j].initials, " ");
|
|
||||||
highscores.highscore_table[i].scores[j].reserved = 0;
|
|
||||||
highscores.highscore_table[i].scores[j].year = 0;
|
|
||||||
highscores.highscore_table[i].scores[j].month = 0;
|
|
||||||
highscores.highscore_table[i].scores[j].day = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
highscore_save();
|
|
||||||
}
|
|
||||||
else if (create_defaults) // Doesn't exist yet or is invalid... create defaults and save it...
|
|
||||||
{
|
{
|
||||||
strcpy(highscores.last_initials, " ");
|
strcpy(highscores.last_initials, " ");
|
||||||
|
|
||||||
for (int i=0; i<MAX_HS_GAMES; i++)
|
for (int i=0; i<MAX_HS_GAMES; i++)
|
||||||
{
|
{
|
||||||
highscores.highscore_table[i].crc = 0x00000000;
|
highscores.highscore_table[i].crc = 0x00000000;
|
||||||
@ -175,7 +155,7 @@ void highscore_init(void)
|
|||||||
// Save the high score file to disc. This gets saved in the /data directory and this
|
// Save the high score file to disc. This gets saved in the /data directory and this
|
||||||
// directory is created if it doesn't exist (mostly likely does if using TWL++)
|
// directory is created if it doesn't exist (mostly likely does if using TWL++)
|
||||||
// ------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------
|
||||||
void highscore_save(void)
|
void highscore_save(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
@ -188,7 +168,7 @@ void highscore_save(void)
|
|||||||
{
|
{
|
||||||
mkdir("/data", 0777); // Otherwise create the directory...
|
mkdir("/data", 0777); // Otherwise create the directory...
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Set our current highscore file version and checksum...
|
// Set our current highscore file version and checksum...
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
@ -229,13 +209,13 @@ void highscore_showoptions(u16 options)
|
|||||||
DSPrint(22,5,0, (char*)"[ALPHA]");
|
DSPrint(22,5,0, (char*)"[ALPHA]");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DSPrint(22,5,0, (char*)" ");
|
DSPrint(22,5,0, (char*)" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
// Show the 10 scores for this game...
|
// Show the 10 scores for this game...
|
||||||
// -----------------------------------------------------
|
// -----------------------------------------------------
|
||||||
void show_scores(short foundIdx, bool bShowLegend)
|
void show_scores(short foundIdx, bool bShowLegend)
|
||||||
{
|
{
|
||||||
@ -244,19 +224,19 @@ void show_scores(short foundIdx, bool bShowLegend)
|
|||||||
{
|
{
|
||||||
if ((highscores.highscore_table[foundIdx].options & HS_OPT_SORTMASK) == HS_OPT_SORTTIME)
|
if ((highscores.highscore_table[foundIdx].options & HS_OPT_SORTMASK) == HS_OPT_SORTTIME)
|
||||||
{
|
{
|
||||||
sprintf(hs_line, "%04d-%02d-%02d %-3s %c%c:%c%c.%c%c", highscores.highscore_table[foundIdx].scores[i].year, highscores.highscore_table[foundIdx].scores[i].month,highscores.highscore_table[foundIdx].scores[i].day,
|
sprintf(hs_line, "%04d-%02d-%02d %-3s %c%c:%c%c.%c%c", highscores.highscore_table[foundIdx].scores[i].year, highscores.highscore_table[foundIdx].scores[i].month,highscores.highscore_table[foundIdx].scores[i].day,
|
||||||
highscores.highscore_table[foundIdx].scores[i].initials, highscores.highscore_table[foundIdx].scores[i].score[0], highscores.highscore_table[foundIdx].scores[i].score[1],
|
highscores.highscore_table[foundIdx].scores[i].initials, highscores.highscore_table[foundIdx].scores[i].score[0], highscores.highscore_table[foundIdx].scores[i].score[1],
|
||||||
highscores.highscore_table[foundIdx].scores[i].score[2], highscores.highscore_table[foundIdx].scores[i].score[3], highscores.highscore_table[foundIdx].scores[i].score[4],
|
highscores.highscore_table[foundIdx].scores[i].score[2], highscores.highscore_table[foundIdx].scores[i].score[3], highscores.highscore_table[foundIdx].scores[i].score[4],
|
||||||
highscores.highscore_table[foundIdx].scores[i].score[5]);
|
highscores.highscore_table[foundIdx].scores[i].score[5]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(hs_line, "%04d-%02d-%02d %-3s %-6s ", highscores.highscore_table[foundIdx].scores[i].year, highscores.highscore_table[foundIdx].scores[i].month,highscores.highscore_table[foundIdx].scores[i].day,
|
sprintf(hs_line, "%04d-%02d-%02d %-3s %-6s ", highscores.highscore_table[foundIdx].scores[i].year, highscores.highscore_table[foundIdx].scores[i].month,highscores.highscore_table[foundIdx].scores[i].day,
|
||||||
highscores.highscore_table[foundIdx].scores[i].initials, highscores.highscore_table[foundIdx].scores[i].score);
|
highscores.highscore_table[foundIdx].scores[i].initials, highscores.highscore_table[foundIdx].scores[i].score);
|
||||||
}
|
}
|
||||||
DSPrint(3,6+i, 0, hs_line);
|
DSPrint(3,6+i, 0, hs_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bShowLegend)
|
if (bShowLegend)
|
||||||
{
|
{
|
||||||
DSPrint(1,16,0, (char*)" ");
|
DSPrint(1,16,0, (char*)" ");
|
||||||
@ -286,11 +266,11 @@ void highscore_sort(short foundIdx)
|
|||||||
{
|
{
|
||||||
if (strcmp(highscores.highscore_table[foundIdx].scores[j+1].score, "000000") == 0)
|
if (strcmp(highscores.highscore_table[foundIdx].scores[j+1].score, "000000") == 0)
|
||||||
strcpy(cmp1, "999999");
|
strcpy(cmp1, "999999");
|
||||||
else
|
else
|
||||||
strcpy(cmp1, highscores.highscore_table[foundIdx].scores[j+1].score);
|
strcpy(cmp1, highscores.highscore_table[foundIdx].scores[j+1].score);
|
||||||
if (strcmp(highscores.highscore_table[foundIdx].scores[j].score, "000000") == 0)
|
if (strcmp(highscores.highscore_table[foundIdx].scores[j].score, "000000") == 0)
|
||||||
strcpy(cmp2, "999999");
|
strcpy(cmp2, "999999");
|
||||||
else
|
else
|
||||||
strcpy(cmp2, highscores.highscore_table[foundIdx].scores[j].score);
|
strcpy(cmp2, highscores.highscore_table[foundIdx].scores[j].score);
|
||||||
if (strcmp(cmp1, cmp2) < 0)
|
if (strcmp(cmp1, cmp2) < 0)
|
||||||
{
|
{
|
||||||
@ -304,13 +284,13 @@ void highscore_sort(short foundIdx)
|
|||||||
{
|
{
|
||||||
if (strcmp(highscores.highscore_table[foundIdx].scores[j+1].score, "000000") == 0)
|
if (strcmp(highscores.highscore_table[foundIdx].scores[j+1].score, "000000") == 0)
|
||||||
strcpy(cmp1, "------");
|
strcpy(cmp1, "------");
|
||||||
else
|
else
|
||||||
strcpy(cmp1, highscores.highscore_table[foundIdx].scores[j+1].score);
|
strcpy(cmp1, highscores.highscore_table[foundIdx].scores[j+1].score);
|
||||||
if (strcmp(highscores.highscore_table[foundIdx].scores[j].score, "000000") == 0)
|
if (strcmp(highscores.highscore_table[foundIdx].scores[j].score, "000000") == 0)
|
||||||
strcpy(cmp2, "------");
|
strcpy(cmp2, "------");
|
||||||
else
|
else
|
||||||
strcpy(cmp2, highscores.highscore_table[foundIdx].scores[j].score);
|
strcpy(cmp2, highscores.highscore_table[foundIdx].scores[j].score);
|
||||||
|
|
||||||
if (strcmp(cmp1, cmp2) > 0)
|
if (strcmp(cmp1, cmp2) > 0)
|
||||||
{
|
{
|
||||||
// Swap...
|
// Swap...
|
||||||
@ -330,7 +310,7 @@ void highscore_sort(short foundIdx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -347,7 +327,7 @@ void highscore_entry(short foundIdx, u32 crc)
|
|||||||
char dampen=0;
|
char dampen=0;
|
||||||
time_t unixTime = time(NULL);
|
time_t unixTime = time(NULL);
|
||||||
struct tm* timeStruct = gmtime((const time_t *)&unixTime);
|
struct tm* timeStruct = gmtime((const time_t *)&unixTime);
|
||||||
|
|
||||||
DSPrint(2,19,0, (char*)"UP/DN/LEFT/RIGHT ENTER SCORE");
|
DSPrint(2,19,0, (char*)"UP/DN/LEFT/RIGHT ENTER SCORE");
|
||||||
DSPrint(2,20,0, (char*)"PRESS START TO SAVE SCORE ");
|
DSPrint(2,20,0, (char*)"PRESS START TO SAVE SCORE ");
|
||||||
DSPrint(2,21,0, (char*)"PRESS SELECT TO CANCEL ");
|
DSPrint(2,21,0, (char*)"PRESS SELECT TO CANCEL ");
|
||||||
@ -363,7 +343,7 @@ void highscore_entry(short foundIdx, u32 crc)
|
|||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
if (keysCurrent() & KEY_SELECT) {bEntryDone=1;}
|
if (keysCurrent() & KEY_SELECT) {bEntryDone=1;}
|
||||||
|
|
||||||
if (keysCurrent() & KEY_START)
|
if (keysCurrent() & KEY_START)
|
||||||
{
|
{
|
||||||
strcpy(highscores.last_initials, score_entry.initials);
|
strcpy(highscores.last_initials, score_entry.initials);
|
||||||
memcpy(&highscores.highscore_table[foundIdx].scores[9], &score_entry, sizeof(score_entry));
|
memcpy(&highscores.highscore_table[foundIdx].scores[9], &score_entry, sizeof(score_entry));
|
||||||
@ -377,14 +357,14 @@ void highscore_entry(short foundIdx, u32 crc)
|
|||||||
{
|
{
|
||||||
if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A))
|
if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A))
|
||||||
{
|
{
|
||||||
if (entry_idx < 8) entry_idx++;
|
if (entry_idx < 8) entry_idx++;
|
||||||
blink=25;
|
blink=25;
|
||||||
dampen=15;
|
dampen=15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keysCurrent() & KEY_LEFT)
|
if (keysCurrent() & KEY_LEFT)
|
||||||
{
|
{
|
||||||
if (entry_idx > 0) entry_idx--;
|
if (entry_idx > 0) entry_idx--;
|
||||||
blink=25;
|
blink=25;
|
||||||
dampen=15;
|
dampen=15;
|
||||||
}
|
}
|
||||||
@ -468,7 +448,7 @@ void highscore_entry(short foundIdx, u32 crc)
|
|||||||
}
|
}
|
||||||
DSPrint(3,16, 0, (char*)hs_line);
|
DSPrint(3,16, 0, (char*)hs_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
show_scores(foundIdx, true);
|
show_scores(foundIdx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +463,7 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
char blink=0;
|
char blink=0;
|
||||||
unsigned short entry_idx=0;
|
unsigned short entry_idx=0;
|
||||||
char dampen=0;
|
char dampen=0;
|
||||||
|
|
||||||
DSPrint(2,16,0, (char*)" NOTE: ");
|
DSPrint(2,16,0, (char*)" NOTE: ");
|
||||||
DSPrint(2,19,0, (char*)" UP/DN/LEFT/RIGHT ENTER NOTES");
|
DSPrint(2,19,0, (char*)" UP/DN/LEFT/RIGHT ENTER NOTES");
|
||||||
DSPrint(2,20,0, (char*)" X=TOGGLE SORT, L+R=CLR SCORE");
|
DSPrint(2,20,0, (char*)" X=TOGGLE SORT, L+R=CLR SCORE");
|
||||||
@ -492,13 +472,13 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
|
|
||||||
strcpy(notes, highscores.highscore_table[foundIdx].notes);
|
strcpy(notes, highscores.highscore_table[foundIdx].notes);
|
||||||
options = highscores.highscore_table[foundIdx].options;
|
options = highscores.highscore_table[foundIdx].options;
|
||||||
|
|
||||||
while (!bEntryDone)
|
while (!bEntryDone)
|
||||||
{
|
{
|
||||||
swiWaitForVBlank();
|
swiWaitForVBlank();
|
||||||
if (keysCurrent() & KEY_SELECT) {bEntryDone=1;}
|
if (keysCurrent() & KEY_SELECT) {bEntryDone=1;}
|
||||||
|
|
||||||
if (keysCurrent() & KEY_START)
|
if (keysCurrent() & KEY_START)
|
||||||
{
|
{
|
||||||
strcpy(highscores.highscore_table[foundIdx].notes, notes);
|
strcpy(highscores.highscore_table[foundIdx].notes, notes);
|
||||||
highscores.highscore_table[foundIdx].options = options;
|
highscores.highscore_table[foundIdx].options = options;
|
||||||
@ -512,14 +492,14 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
{
|
{
|
||||||
if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A))
|
if ((keysCurrent() & KEY_RIGHT) || (keysCurrent() & KEY_A))
|
||||||
{
|
{
|
||||||
if (entry_idx < 9) entry_idx++;
|
if (entry_idx < 9) entry_idx++;
|
||||||
blink=25;
|
blink=25;
|
||||||
dampen=15;
|
dampen=15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keysCurrent() & KEY_LEFT)
|
if (keysCurrent() & KEY_LEFT)
|
||||||
{
|
{
|
||||||
if (entry_idx > 0) entry_idx--;
|
if (entry_idx > 0) entry_idx--;
|
||||||
blink=25;
|
blink=25;
|
||||||
dampen=15;
|
dampen=15;
|
||||||
}
|
}
|
||||||
@ -550,7 +530,7 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
dampen=10;
|
dampen=10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keysCurrent() & KEY_X)
|
if (keysCurrent() & KEY_X)
|
||||||
{
|
{
|
||||||
if ((options & HS_OPT_SORTMASK) == HS_OPT_SORTLOW)
|
if ((options & HS_OPT_SORTMASK) == HS_OPT_SORTLOW)
|
||||||
{
|
{
|
||||||
@ -573,14 +553,14 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
highscore_showoptions(options);
|
highscore_showoptions(options);
|
||||||
dampen=15;
|
dampen=15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the entire game of scores...
|
// Clear the entire game of scores...
|
||||||
if ((keysCurrent() & KEY_L) && (keysCurrent() & KEY_R))
|
if ((keysCurrent() & KEY_L) && (keysCurrent() & KEY_R))
|
||||||
{
|
{
|
||||||
highscores.highscore_table[foundIdx].crc = 0x00000000;
|
highscores.highscore_table[foundIdx].crc = 0x00000000;
|
||||||
highscores.highscore_table[foundIdx].options = 0x0000;
|
highscores.highscore_table[foundIdx].options = 0x0000;
|
||||||
strcpy(highscores.highscore_table[foundIdx].notes, " ");
|
strcpy(highscores.highscore_table[foundIdx].notes, " ");
|
||||||
strcpy(notes, " ");
|
strcpy(notes, " ");
|
||||||
for (int j=0; j<10; j++)
|
for (int j=0; j<10; j++)
|
||||||
{
|
{
|
||||||
strcpy(highscores.highscore_table[foundIdx].scores[j].score, "000000");
|
strcpy(highscores.highscore_table[foundIdx].scores[j].score, "000000");
|
||||||
@ -591,8 +571,8 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
highscores.highscore_table[foundIdx].scores[j].day = 0;
|
highscores.highscore_table[foundIdx].scores[j].day = 0;
|
||||||
}
|
}
|
||||||
show_scores(foundIdx, false);
|
show_scores(foundIdx, false);
|
||||||
highscore_save();
|
highscore_save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -606,17 +586,17 @@ void highscore_options(short foundIdx, u32 crc)
|
|||||||
}
|
}
|
||||||
DSPrint(9,16, 0, (char*)hs_line);
|
DSPrint(9,16, 0, (char*)hs_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
show_scores(foundIdx, true);
|
show_scores(foundIdx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Entry point for the high score table. We are passed in the crc of the
|
// Entry point for the high score table. We are passed in the crc of the
|
||||||
// current game. We use the crc to check the high score database and see
|
// current game. We use the crc to check the high score database and see
|
||||||
// if there is already saved highscore data for this game. At the point
|
// if there is already saved highscore data for this game. At the point
|
||||||
// where this is called, the high score init has already been called.
|
// where this is called, the high score init has already been called.
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void highscore_display(u32 crc)
|
void highscore_display(u32 crc)
|
||||||
{
|
{
|
||||||
short foundIdx = -1;
|
short foundIdx = -1;
|
||||||
short firstBlank = -1;
|
short firstBlank = -1;
|
||||||
@ -646,12 +626,12 @@ void highscore_display(u32 crc)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundIdx == -1)
|
if (foundIdx == -1)
|
||||||
{
|
{
|
||||||
foundIdx = firstBlank;
|
foundIdx = firstBlank;
|
||||||
}
|
}
|
||||||
|
|
||||||
show_scores(foundIdx, true);
|
show_scores(foundIdx, true);
|
||||||
|
|
||||||
while (!bDone)
|
while (!bDone)
|
||||||
@ -661,7 +641,7 @@ void highscore_display(u32 crc)
|
|||||||
if (keysCurrent() & KEY_X) highscore_entry(foundIdx, crc);
|
if (keysCurrent() & KEY_X) highscore_entry(foundIdx, crc);
|
||||||
if (keysCurrent() & KEY_Y) highscore_options(foundIdx, crc);
|
if (keysCurrent() & KEY_Y) highscore_options(foundIdx, crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
BottomScreenKeyboard();
|
BottomScreenKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@
|
|||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
// I've seen a few rare POKEs that are massive - e.g. Jet Set Willy has a near
|
// I've seen a few rare POKEs that are massive - e.g. Jet Set Willy has a near
|
||||||
// re-write of a routine to change the jumping ... We don't support those large
|
// re-write of a routine to change the jumping ... We don't support those large
|
||||||
// POKEs here. Too much wasted memory and for now, we're keeping this very simple.
|
// POKEs here. Too much wasted memory and for now, we're keeping this very simple.
|
||||||
// This should handle about 99% of all POKEs out there. Most games use it to
|
// This should handle about 99% of all POKEs out there. Most games use it to
|
||||||
// produce extra lives, invulnerability or weapon upgrades.
|
// produce extra lives, invulnerability or weapon upgrades.
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
@ -66,7 +66,7 @@ void pok_apply(u8 sel)
|
|||||||
{
|
{
|
||||||
u8 bank = Pokes[sel].pok_bank[j];
|
u8 bank = Pokes[sel].pok_bank[j];
|
||||||
u16 value = Pokes[sel].pok_val[j];
|
u16 value = Pokes[sel].pok_val[j];
|
||||||
|
|
||||||
if (value == 256) // Must ask user for value...
|
if (value == 256) // Must ask user for value...
|
||||||
{
|
{
|
||||||
value = 0;
|
value = 0;
|
||||||
@ -81,7 +81,7 @@ void pok_apply(u8 sel)
|
|||||||
DSPrint(28,22,2,tmp);
|
DSPrint(28,22,2,tmp);
|
||||||
WAITVBL;
|
WAITVBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); // Wait for release
|
while ((keysCurrent() & (KEY_UP | KEY_DOWN | KEY_A ))!=0); // Wait for release
|
||||||
DSPrint(0,22,0," ");
|
DSPrint(0,22,0," ");
|
||||||
}
|
}
|
||||||
@ -102,13 +102,13 @@ u8 num_pokes = 0;
|
|||||||
u8 pok_readfile(void)
|
u8 pok_readfile(void)
|
||||||
{
|
{
|
||||||
if (last_file_crc_poke_read == file_crc) return num_pokes;
|
if (last_file_crc_poke_read == file_crc) return num_pokes;
|
||||||
|
|
||||||
last_file_crc_poke_read = file_crc;
|
last_file_crc_poke_read = file_crc;
|
||||||
|
|
||||||
// Zero out all pokes before reading file
|
// Zero out all pokes before reading file
|
||||||
memset(Pokes, 0x00, sizeof(Pokes));
|
memset(Pokes, 0x00, sizeof(Pokes));
|
||||||
num_pokes = 0;
|
num_pokes = 0;
|
||||||
|
|
||||||
// POK files must be in a ./pok subdirectory
|
// POK files must be in a ./pok subdirectory
|
||||||
sprintf(szLoadFile,"pok/%s", initial_file);
|
sprintf(szLoadFile,"pok/%s", initial_file);
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ u8 pok_readfile(void)
|
|||||||
fgets(szLine, 255, infile);
|
fgets(szLine, 255, infile);
|
||||||
|
|
||||||
char *ptr = szLine;
|
char *ptr = szLine;
|
||||||
|
|
||||||
if (szLine[0] == 'N')
|
if (szLine[0] == 'N')
|
||||||
{
|
{
|
||||||
memcpy(Pokes[num_pokes].pok_name, szLine+1, 30);
|
memcpy(Pokes[num_pokes].pok_name, szLine+1, 30);
|
||||||
@ -142,28 +142,28 @@ u8 pok_readfile(void)
|
|||||||
while (*ptr != ' ') ptr++; while (*ptr == ' ') ptr++; // Skip to next field
|
while (*ptr != ' ') ptr++; while (*ptr == ' ') ptr++; // Skip to next field
|
||||||
Pokes[num_pokes].pok_mem[mem_idx] = atoi(ptr);
|
Pokes[num_pokes].pok_mem[mem_idx] = atoi(ptr);
|
||||||
while (*ptr != ' ') ptr++; while (*ptr == ' ') ptr++; // Skip to next field
|
while (*ptr != ' ') ptr++; while (*ptr == ' ') ptr++; // Skip to next field
|
||||||
Pokes[num_pokes].pok_val[mem_idx] = atoi(ptr);
|
Pokes[num_pokes].pok_val[mem_idx] = atoi(ptr);
|
||||||
if (mem_idx < (MAX_POK_MEM-1)) mem_idx++;
|
if (mem_idx < (MAX_POK_MEM-1)) mem_idx++;
|
||||||
if (szLine[0] == 'Z')
|
if (szLine[0] == 'Z')
|
||||||
{
|
{
|
||||||
if (mem_idx < MAX_POK_MEM) num_pokes++;
|
if (mem_idx < MAX_POK_MEM) num_pokes++;
|
||||||
else memset(Pokes[num_pokes].pok_mem, 0x00, sizeof(Pokes[num_pokes].pok_mem));
|
else memset(Pokes[num_pokes].pok_mem, 0x00, sizeof(Pokes[num_pokes].pok_mem));
|
||||||
if (num_pokes >= MAX_POKES) break;
|
if (num_pokes >= MAX_POKES) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (szLine[0] == 'Y') break;
|
if (szLine[0] == 'Y') break;
|
||||||
} while (!feof(infile));
|
} while (!feof(infile));
|
||||||
|
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_pokes;
|
return num_pokes;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define POKES_PER_SCREEN 16
|
#define POKES_PER_SCREEN 16
|
||||||
|
|
||||||
// Show tape blocks with filenames/descriptions...
|
// Show tape blocks with filenames/descriptions...
|
||||||
void pok_select(void)
|
void pok_select(void)
|
||||||
{
|
{
|
||||||
char tmp[33];
|
char tmp[33];
|
||||||
@ -174,7 +174,7 @@ void pok_select(void)
|
|||||||
BottomScreenOptions();
|
BottomScreenOptions();
|
||||||
|
|
||||||
u8 max = pok_readfile();
|
u8 max = pok_readfile();
|
||||||
|
|
||||||
if (max == 0) // No POKEs found...
|
if (max == 0) // No POKEs found...
|
||||||
{
|
{
|
||||||
DSPrint(0,8,0, " NO .POK FILE WAS FOUND ");
|
DSPrint(0,8,0, " NO .POK FILE WAS FOUND ");
|
||||||
@ -188,7 +188,7 @@ void pok_select(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
DSPrint(0,23,0,"PRESS A TO APPLY POKE, B TO EXIT");
|
DSPrint(0,23,0,"PRESS A TO APPLY POKE, B TO EXIT");
|
||||||
|
|
||||||
u8 screen_max = (max < POKES_PER_SCREEN ? max:POKES_PER_SCREEN);
|
u8 screen_max = (max < POKES_PER_SCREEN ? max:POKES_PER_SCREEN);
|
||||||
u8 offset = 0;
|
u8 offset = 0;
|
||||||
for (u8 i=0; i < screen_max; i++)
|
for (u8 i=0; i < screen_max; i++)
|
||||||
@ -197,7 +197,7 @@ void pok_select(void)
|
|||||||
DSPrint(1,4+i,(i==sel) ? 2:0,tmp);
|
DSPrint(1,4+i,(i==sel) ? 2:0,tmp);
|
||||||
if (Pokes[offset+i].pok_applied) DSPrint(0,4+i,2,"@"); else DSPrint(0,4+i,0," ");
|
if (Pokes[offset+i].pok_applied) DSPrint(0,4+i,2,"@"); else DSPrint(0,4+i,0," ");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
u16 keys = keysCurrent();
|
u16 keys = keysCurrent();
|
||||||
@ -212,7 +212,7 @@ void pok_select(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (keys & KEY_B) {break;}
|
if (keys & KEY_B) {break;}
|
||||||
|
|
||||||
if (keys & KEY_DOWN)
|
if (keys & KEY_DOWN)
|
||||||
{
|
{
|
||||||
if (sel < (screen_max-1))
|
if (sel < (screen_max-1))
|
||||||
@ -226,7 +226,7 @@ void pok_select(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((offset + screen_max) < max)
|
if ((offset + screen_max) < max)
|
||||||
{
|
{
|
||||||
offset += POKES_PER_SCREEN;
|
offset += POKES_PER_SCREEN;
|
||||||
screen_max = ((max-offset) < POKES_PER_SCREEN ? (max-offset):POKES_PER_SCREEN);
|
screen_max = ((max-offset) < POKES_PER_SCREEN ? (max-offset):POKES_PER_SCREEN);
|
||||||
@ -245,7 +245,7 @@ void pok_select(void)
|
|||||||
DSPrint(0,4+i,0," ");
|
DSPrint(0,4+i,0," ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WAITVBL;WAITVBL;WAITVBL;WAITVBL;
|
WAITVBL;WAITVBL;WAITVBL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ void pok_select(void)
|
|||||||
{
|
{
|
||||||
offset -= POKES_PER_SCREEN;
|
offset -= POKES_PER_SCREEN;
|
||||||
screen_max = ((max-offset) < POKES_PER_SCREEN ? (max-offset):POKES_PER_SCREEN);
|
screen_max = ((max-offset) < POKES_PER_SCREEN ? (max-offset):POKES_PER_SCREEN);
|
||||||
sel = 0;
|
sel = POKES_PER_SCREEN-1;
|
||||||
for (u8 i=0; i < POKES_PER_SCREEN; i++)
|
for (u8 i=0; i < POKES_PER_SCREEN; i++)
|
||||||
{
|
{
|
||||||
if (i < screen_max)
|
if (i < screen_max)
|
||||||
@ -281,17 +281,17 @@ void pok_select(void)
|
|||||||
DSPrint(0,4+i,0," ");
|
DSPrint(0,4+i,0," ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WAITVBL;WAITVBL;WAITVBL;WAITVBL;
|
WAITVBL;WAITVBL;WAITVBL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (keysCurrent())
|
while (keysCurrent())
|
||||||
{
|
{
|
||||||
WAITVBL;WAITVBL;
|
WAITVBL;WAITVBL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,8 @@ u8 spare[512] = {0x00}; // We keep some spare bytes so we can use th
|
|||||||
static char szLoadFile[256]; // We build the filename out of the base filename and tack on .sav, .ee, etc.
|
static char szLoadFile[256]; // We build the filename out of the base filename and tack on .sav, .ee, etc.
|
||||||
static char tmpStr[32];
|
static char tmpStr[32];
|
||||||
|
|
||||||
static u8 CompressBuffer[150*1024];
|
u8 CompressBuffer[150*1024]; // Big enough to handle compression of even full 128K games - we also steal this memory for screen snapshot use
|
||||||
|
|
||||||
void spectrumSaveState()
|
void spectrumSaveState()
|
||||||
{
|
{
|
||||||
u32 spare = 0;
|
u32 spare = 0;
|
||||||
@ -167,7 +168,7 @@ void spectrumSaveState()
|
|||||||
ptr = RAM_Memory128;
|
ptr = RAM_Memory128;
|
||||||
mem_size = 0x20000;
|
mem_size = 0x20000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Compress the RAM data using 'high' compression ratio... it's
|
// Compress the RAM data using 'high' compression ratio... it's
|
||||||
// still quite fast for such small memory buffers and often shrinks
|
// still quite fast for such small memory buffers and often shrinks
|
||||||
@ -226,7 +227,7 @@ void spectrumLoadState()
|
|||||||
// Read Last Directory Path / Tape File
|
// Read Last Directory Path / Tape File
|
||||||
if (retVal) retVal = fread(&last_path, sizeof(last_path), 1, handle);
|
if (retVal) retVal = fread(&last_path, sizeof(last_path), 1, handle);
|
||||||
if (retVal) retVal = fread(&last_file, sizeof(last_file), 1, handle);
|
if (retVal) retVal = fread(&last_file, sizeof(last_file), 1, handle);
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// If the last known file was a tap file (.tap or .tzx) we want to
|
// If the last known file was a tap file (.tap or .tzx) we want to
|
||||||
// reload that as the user might have swapped tapes to side 2, etc.
|
// reload that as the user might have swapped tapes to side 2, etc.
|
||||||
@ -236,7 +237,7 @@ void spectrumLoadState()
|
|||||||
chdir(last_path);
|
chdir(last_path);
|
||||||
CassetteInsert(last_file);
|
CassetteInsert(last_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load CZ80 CPU
|
// Load CZ80 CPU
|
||||||
if (retVal) retVal = fread(&CPU, sizeof(CPU), 1, handle);
|
if (retVal) retVal = fread(&CPU, sizeof(CPU), 1, handle);
|
||||||
|
|
||||||
@ -320,7 +321,7 @@ void spectrumLoadState()
|
|||||||
// Decompress the previously compressed RAM and put it back into the
|
// Decompress the previously compressed RAM and put it back into the
|
||||||
// right memory location... this is quite fast all things considered.
|
// right memory location... this is quite fast all things considered.
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
(void)lzav_decompress( CompressBuffer, dest_memory, comp_len, mem_size );
|
(void)lzav_decompress( CompressBuffer, dest_memory, comp_len, mem_size );
|
||||||
|
|
||||||
strcpy(tmpStr, (retVal ? "OK ":"ERR"));
|
strcpy(tmpStr, (retVal ? "OK ":"ERR"));
|
||||||
DSPrint(13,0,0,tmpStr);
|
DSPrint(13,0,0,tmpStr);
|
||||||
|
@ -54,13 +54,11 @@ bool screenshotbmp(const char* filename) {
|
|||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// The screenshot requires a bit less than 100K of memory...
|
// The screenshot requires a bit less than 100K of memory...
|
||||||
// We steal this from the back end of the big read-only
|
// We steal this from the compression buffer which is not
|
||||||
// memory block. If we have a tape that is huge, we would
|
// otherwise used except when save/loading save states.
|
||||||
// run into problems but it would be astronomically rare
|
|
||||||
// and it's better than wasting another 100K bytes that is
|
|
||||||
// mostly underutilized.
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
u8 *temp = (u8*)ROM_Memory + (sizeof(ROM_Memory) - (100*1024));
|
extern u8 CompressBuffer[];
|
||||||
|
u8 *temp = (u8*)CompressBuffer;
|
||||||
|
|
||||||
HEADER *header= (HEADER*)temp;
|
HEADER *header= (HEADER*)temp;
|
||||||
INFOHEADER *infoheader = (INFOHEADER*)(temp + sizeof(HEADER));
|
INFOHEADER *infoheader = (INFOHEADER*)(temp + sizeof(HEADER));
|
||||||
|
@ -44,7 +44,19 @@ ITCM_CODE unsigned char cpu_readport_speccy(register unsigned short Port)
|
|||||||
static u8 bNonSpecialKeyWasPressed = 0;
|
static u8 bNonSpecialKeyWasPressed = 0;
|
||||||
|
|
||||||
if ((Port & 1) == 0) // Any Even Address will cause the ULA to respond
|
if ((Port & 1) == 0) // Any Even Address will cause the ULA to respond
|
||||||
{
|
{
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// If we are rendering the screen, a read from the ULA supplied port will produce
|
||||||
|
// a cycle penalty. This is not cycle accurate but we simply use an 'average'
|
||||||
|
// penalty of 4 cycles if we are in contended memory while the screen is rendering. It's
|
||||||
|
// rough but gets us close enough to play games. We can improve this later...
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
if (zx_ScreenRendering)
|
||||||
|
{
|
||||||
|
CPU.TStates += zx_contend_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// If we are not playing the tape but we got a hit on the
|
// If we are not playing the tape but we got a hit on the
|
||||||
// loader we can start the tape in motion - auto play...
|
// loader we can start the tape in motion - auto play...
|
||||||
@ -78,7 +90,7 @@ ITCM_CODE unsigned char cpu_readport_speccy(register unsigned short Port)
|
|||||||
// -----------------------------
|
// -----------------------------
|
||||||
u8 key = (portFE & 0x18) ? 0x00 : 0x40;
|
u8 key = (portFE & 0x18) ? 0x00 : 0x40;
|
||||||
|
|
||||||
for (u8 i=0; i< (kbd_keys_pressed ? kbd_keys_pressed:1); i++) // Always one pass at least for joysticks...
|
for (u8 i=0; i< kbd_keys_pressed; i++) // We may have more than one key pressed...
|
||||||
{
|
{
|
||||||
kbd_key = kbd_keys[i];
|
kbd_key = kbd_keys[i];
|
||||||
word inv = ~Port;
|
word inv = ~Port;
|
||||||
@ -315,7 +327,9 @@ u32 zx_colors_extend32[16] __attribute__((section(".dtcm"))) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Render one screen line of pixels. This is called on every visible scanline.
|
// Render one screen line of pixels. This is called on every visible scanline
|
||||||
|
// 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.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
ITCM_CODE void speccy_render_screen_line(u8 line)
|
ITCM_CODE void speccy_render_screen_line(u8 line)
|
||||||
{
|
{
|
||||||
@ -338,16 +352,18 @@ ITCM_CODE void speccy_render_screen_line(u8 line)
|
|||||||
if (tape_play_skip_frame & 0x1F) return;
|
if (tape_play_skip_frame & 0x1F) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isDSiMode() && (flash_timer & 1)) return; // For DS-Lite/Phat, we draw every other frame...
|
// -----------------------------------------------------------
|
||||||
|
// For DS-Lite/Phat, we draw every other frame to gain speed.
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
if (!isDSiMode() && (flash_timer & 1)) return;
|
||||||
|
|
||||||
// For the ZX 128K, we might be using page 7 for video display... it's rare, but possible...
|
// -----------------------------------------------------------------------
|
||||||
|
// Render the current line into our NDS video memory. For the ZX 128K, we
|
||||||
|
// might be using page 7 for video display... it's rare, but possible...
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
if (zx_128k_mode) zx_ScreenPage = RAM_Memory128 + ((portFD & 0x08) ? 7:5) * 0x4000;
|
if (zx_128k_mode) zx_ScreenPage = RAM_Memory128 + ((portFD & 0x08) ? 7:5) * 0x4000;
|
||||||
else zx_ScreenPage = RAM_Memory + 0x4000;
|
else zx_ScreenPage = RAM_Memory + 0x4000;
|
||||||
|
|
||||||
// --------------------------------------------------
|
|
||||||
// Render the current line into our NDS video memory
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// The color attribute is stored independently from the pixel data
|
// The color attribute is stored independently from the pixel data
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
@ -377,12 +393,17 @@ ITCM_CODE void speccy_render_screen_line(u8 line)
|
|||||||
u8 ink = (attr & 0x07); // Ink Color is the foreground
|
u8 ink = (attr & 0x07); // Ink Color is the foreground
|
||||||
if (attr & 0x40) ink |= 0x08; // Brightness
|
if (attr & 0x40) ink |= 0x08; // Brightness
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// I've tried look-up tables here, but nothing was as fast as checking the bit and shifting ink/paper to the right spot...
|
||||||
|
// ------------------------------------------------------------------------------------------------------------------------
|
||||||
*vidBuf++ = (((pixel & 0x80) ? ink:paper)) | (((pixel & 0x40) ? ink:paper) << 8) | (((pixel & 0x20) ? ink:paper) << 16) | (((pixel & 0x10) ? ink:paper) << 24);
|
*vidBuf++ = (((pixel & 0x80) ? ink:paper)) | (((pixel & 0x40) ? ink:paper) << 8) | (((pixel & 0x20) ? ink:paper) << 16) | (((pixel & 0x10) ? ink:paper) << 24);
|
||||||
*vidBuf++ = (((pixel & 0x08) ? ink:paper)) | (((pixel & 0x04) ? ink:paper) << 8) | (((pixel & 0x02) ? ink:paper) << 16) | (((pixel & 0x01) ? ink:paper) << 24);
|
*vidBuf++ = (((pixel & 0x08) ? ink:paper)) | (((pixel & 0x04) ? ink:paper) << 8) | (((pixel & 0x02) ? ink:paper) << 16) | (((pixel & 0x01) ? ink:paper) << 24);
|
||||||
}
|
}
|
||||||
else // Just drawing all background which is common...
|
else // Just drawing all background which is common...
|
||||||
{
|
{
|
||||||
// Draw background directly to the screen
|
// ------------------------------------------------------------------
|
||||||
|
// Draw background directly to the screen via extended look-up table
|
||||||
|
// ------------------------------------------------------------------
|
||||||
*vidBuf++ = zx_colors_extend32[paper];
|
*vidBuf++ = zx_colors_extend32[paper];
|
||||||
*vidBuf++ = zx_colors_extend32[paper];
|
*vidBuf++ = zx_colors_extend32[paper];
|
||||||
}
|
}
|
||||||
@ -567,9 +588,11 @@ void speccy_reset(void)
|
|||||||
static const u8 contend_delay[3] = {4,3,5};
|
static const u8 contend_delay[3] = {4,3,5};
|
||||||
zx_contend_delay = contend_delay[myConfig.contention];
|
zx_contend_delay = contend_delay[myConfig.contention];
|
||||||
|
|
||||||
// A bit wasteful to decompress again... but
|
// ----------------------------------------------
|
||||||
// we want to ensure that the memory is exactly
|
// Decompress the Z80/SNA snapshot here...
|
||||||
|
// We want to ensure that the memory is exactly
|
||||||
// as it should be when we reset the system.
|
// as it should be when we reset the system.
|
||||||
|
// ----------------------------------------------
|
||||||
if (speccy_mode < MODE_SNA)
|
if (speccy_mode < MODE_SNA)
|
||||||
{
|
{
|
||||||
tape_parse_blocks(last_file_size);
|
tape_parse_blocks(last_file_size);
|
||||||
@ -580,7 +603,10 @@ void speccy_reset(void)
|
|||||||
{
|
{
|
||||||
speccy_decompress_z80(last_file_size);
|
speccy_decompress_z80(last_file_size);
|
||||||
}
|
}
|
||||||
// else must be a diagnostic/ROM cart of some kind...
|
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
// Handle the various snapshot formats... Z80 and SNA supported
|
||||||
|
// -------------------------------------------------------------
|
||||||
|
|
||||||
if (speccy_mode == MODE_SNA) // SNA snapshot
|
if (speccy_mode == MODE_SNA) // SNA snapshot
|
||||||
{
|
{
|
||||||
@ -756,12 +782,12 @@ void speccy_reset(void)
|
|||||||
ITCM_CODE u32 speccy_run(void)
|
ITCM_CODE u32 speccy_run(void)
|
||||||
{
|
{
|
||||||
++zx_current_line; // This is the pixel line we're working on...
|
++zx_current_line; // This is the pixel line we're working on...
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
// Execute 1 scanline worth of CPU instructions.
|
// Execute 1 scanline worth of CPU instructions.
|
||||||
//
|
//
|
||||||
// We break this up into four pieces in order
|
// We break this up into pieces in order to
|
||||||
// to get more chances to render the audio beeper
|
// get more chances to render the audio beeper
|
||||||
// which requires a fairly high sample rate...
|
// which requires a fairly high sample rate...
|
||||||
// -----------------------------------------------
|
// -----------------------------------------------
|
||||||
if (tape_state)
|
if (tape_state)
|
||||||
@ -817,8 +843,8 @@ ITCM_CODE u32 speccy_run(void)
|
|||||||
zx_current_line = 0;
|
zx_current_line = 0;
|
||||||
zx_ScreenRendering = 0;
|
zx_ScreenRendering = 0;
|
||||||
CPU.IRequest = INT_RST38;
|
CPU.IRequest = INT_RST38;
|
||||||
IntZ80(&CPU, CPU.IRequest);
|
|
||||||
CPU.TStates_IRequest = CPU.TStates;
|
CPU.TStates_IRequest = CPU.TStates;
|
||||||
|
IntZ80(&CPU, CPU.IRequest);
|
||||||
return 0; // End of frame
|
return 0; // End of frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,13 @@
|
|||||||
#include "SpeccyUtils.h"
|
#include "SpeccyUtils.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// From a look around a massive number of .TZX files, I haven't seen
|
||||||
|
// any that had more than about 1400 blocks which is pretty huge...
|
||||||
|
// So as to not soak up too much NDS memory, we're capping the number
|
||||||
|
// of blocks defined in a TZX file at 2048 which should handle just
|
||||||
|
// about anything...
|
||||||
|
// -------------------------------------------------------------------
|
||||||
#define MAX_TAPE_BLOCKS 2048
|
#define MAX_TAPE_BLOCKS 2048
|
||||||
|
|
||||||
#define BLOCK_ID_STANDARD 0x10
|
#define BLOCK_ID_STANDARD 0x10
|
||||||
@ -52,9 +59,11 @@
|
|||||||
// Yes, this is special. It happens frequently enough we trap on the high bit here...
|
// Yes, this is special. It happens frequently enough we trap on the high bit here...
|
||||||
#define SEND_DATA_BITS 0x80
|
#define SEND_DATA_BITS 0x80
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
// Some defaults mostly for the .TAP files as the .TZX
|
// Some defaults mostly for the .TAP files and
|
||||||
// will override some/many of these...
|
// standard load blocks for the .TZX format.
|
||||||
|
// Custom/turbo blocks will override some/many of these...
|
||||||
|
// ---------------------------------------------------------
|
||||||
#define DEFAULT_PILOT_LENGTH 2168
|
#define DEFAULT_PILOT_LENGTH 2168
|
||||||
#define DEFAULT_DATA_ZERO_PULSE_WIDTH 855
|
#define DEFAULT_DATA_ZERO_PULSE_WIDTH 855
|
||||||
#define DEFAULT_DATA_ONE_PULSE_WIDTH 1710
|
#define DEFAULT_DATA_ONE_PULSE_WIDTH 1710
|
||||||
@ -115,6 +124,10 @@ inline byte OpZ80(word A) {return *(MemoryMap[(A)>>14] + ((A)&0x3FFF));}
|
|||||||
TapePositionTable_t TapePositionTable[255];
|
TapePositionTable_t TapePositionTable[255];
|
||||||
extern char strcasestr (const char *big, const char *little);
|
extern char strcasestr (const char *big, const char *little);
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Look for headers and blocks with descriptions and use
|
||||||
|
// those as index position for our cassette manager.
|
||||||
|
// --------------------------------------------------------
|
||||||
u8 tape_find_positions(void)
|
u8 tape_find_positions(void)
|
||||||
{
|
{
|
||||||
memset(TapePositionTable, 0x00, sizeof(TapePositionTable));
|
memset(TapePositionTable, 0x00, sizeof(TapePositionTable));
|
||||||
@ -132,7 +145,7 @@ u8 tape_find_positions(void)
|
|||||||
{
|
{
|
||||||
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].description);
|
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].description);
|
||||||
TapePositionTable[pos_idx].block_id = i;
|
TapePositionTable[pos_idx].block_id = i;
|
||||||
pos_idx++;
|
if (++pos_idx == 255) break; // That's all we can handle
|
||||||
}
|
}
|
||||||
else if (strlen(TapeBlocks[i].block_filename) > 2)
|
else if (strlen(TapeBlocks[i].block_filename) > 2)
|
||||||
{
|
{
|
||||||
@ -145,14 +158,17 @@ u8 tape_find_positions(void)
|
|||||||
{
|
{
|
||||||
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].block_filename);
|
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].block_filename);
|
||||||
TapePositionTable[pos_idx].block_id = i;
|
TapePositionTable[pos_idx].block_id = i;
|
||||||
pos_idx++;
|
if (++pos_idx == 255) break; // That's all we can handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pos_idx;
|
return pos_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used in the pre-loader in the standard ROM... speeds up a ~1 second loop
|
// --------------------------------------------------------
|
||||||
|
// Used in the pre-loader in the standard ROM... speeds up
|
||||||
|
// a roughly ~1 second loop and every little bit helps.
|
||||||
|
// --------------------------------------------------------
|
||||||
u8 tape_preloader_delay(void)
|
u8 tape_preloader_delay(void)
|
||||||
{
|
{
|
||||||
u8 B = (CPU.BC.B.h-1) & 0xFF;
|
u8 B = (CPU.BC.B.h-1) & 0xFF;
|
||||||
@ -442,15 +458,20 @@ void tape_parse_blocks(int tapeSize)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------
|
|
||||||
// Sometimes the final block will have a long gap - but it's not needed as the tape is done
|
|
||||||
// playing at that point... so we cut this short which helps the emulator stop the tape.
|
|
||||||
// -----------------------------------------------------------------------------------------
|
|
||||||
TapeBlocks[num_blocks_available-1].gap_delay_after = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// Sometimes the final block will have a long gap - but it's not needed as the tape is done
|
||||||
|
// playing at that point... so we cut this short which helps the emulator stop the tape.
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
TapeBlocks[num_blocks_available-1].gap_delay_after = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// Some utility functions to know when the tape is playing
|
||||||
|
// and also to reset or play the current tape.
|
||||||
|
// --------------------------------------------------------
|
||||||
|
|
||||||
u8 tape_is_playing(void)
|
u8 tape_is_playing(void)
|
||||||
{
|
{
|
||||||
return (tape_state != TAPE_STOP);
|
return (tape_state != TAPE_STOP);
|
||||||
@ -485,14 +506,23 @@ void tape_position(u8 newPos)
|
|||||||
current_block = TapePositionTable[newPos].block_id;
|
current_block = TapePositionTable[newPos].block_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame
|
// --------------------------------------------------------
|
||||||
|
// Called every frame - we use this to display a rough
|
||||||
|
// tape counter that is really just the number of 1K
|
||||||
|
// chunks that have been moved from the virtual tape into
|
||||||
|
// the Spectrum memory.
|
||||||
|
// --------------------------------------------------------
|
||||||
u8 show_tape_counter = 0;
|
u8 show_tape_counter = 0;
|
||||||
void tape_frame(void)
|
void tape_frame(void)
|
||||||
{
|
{
|
||||||
char tmp[5];
|
char tmp[5];
|
||||||
|
|
||||||
if (show_tape_counter) show_tape_counter--;
|
if (show_tape_counter) show_tape_counter--;
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
// If the tape is playing, show the counter and
|
||||||
|
// show the cassette icon in a green color.
|
||||||
|
// ----------------------------------------------
|
||||||
if (tape_state)
|
if (tape_state)
|
||||||
{
|
{
|
||||||
if (bottom_screen == 2)
|
if (bottom_screen == 2)
|
||||||
@ -500,7 +530,7 @@ void tape_frame(void)
|
|||||||
sprintf(tmp, "%03d", (tape_bytes_processed/1000) % 1000);
|
sprintf(tmp, "%03d", (tape_bytes_processed/1000) % 1000);
|
||||||
DSPrint(2, 20, 0, tmp);
|
DSPrint(2, 20, 0, tmp);
|
||||||
show_tape_counter = 30; // Keep showing the counter for a half second
|
show_tape_counter = 30; // Keep showing the counter for a half second
|
||||||
|
|
||||||
// Show the tape icon lit in green
|
// Show the tape icon lit in green
|
||||||
if (myGlobalConfig.debugger <= 2)
|
if (myGlobalConfig.debugger <= 2)
|
||||||
{
|
{
|
||||||
@ -509,9 +539,9 @@ void tape_frame(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// If we are done showing the counter, show
|
// If we are done showing the counter, show
|
||||||
// the stock cassette icon and no counter.
|
// the stock cassette icon and no counter.
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
if (show_tape_counter == 0)
|
if (show_tape_counter == 0)
|
||||||
@ -523,8 +553,8 @@ void tape_frame(void)
|
|||||||
{
|
{
|
||||||
DSPrint(2, 21, 2, "!\"#");
|
DSPrint(2, 21, 2, "!\"#");
|
||||||
DSPrint(2, 22, 2, "ABC");
|
DSPrint(2, 22, 2, "ABC");
|
||||||
}
|
}
|
||||||
|
|
||||||
show_tape_counter = 30;
|
show_tape_counter = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -984,7 +1014,7 @@ ld_sample:
|
|||||||
B-=3; // Reduce counter by 3
|
B-=3; // Reduce counter by 3
|
||||||
goto ld_sample; // Take another sample.
|
goto ld_sample; // Take another sample.
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU.TStates += 54; // It takes 54 total cycles when we take another pass around the loop
|
CPU.TStates += 54; // It takes 54 total cycles when we take another pass around the loop
|
||||||
if (--B) goto ld_sample; // If no time-out... take another sample.
|
if (--B) goto ld_sample; // If no time-out... take another sample.
|
||||||
|
|
||||||
|
BIN
png/cassette.bmp
BIN
png/cassette.bmp
Binary file not shown.
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 144 KiB |
@ -227,3 +227,8 @@ the benefit of running directly from SD card via TWL++ or Unlaunch or similar. B
|
|||||||
really if you're looking for world-class ZX emulation for your DS/DSi handheld,
|
really if you're looking for world-class ZX emulation for your DS/DSi handheld,
|
||||||
you're likely going to want ZXDS.
|
you're likely going to want ZXDS.
|
||||||
|
|
||||||
|
Version History :
|
||||||
|
-----------------------
|
||||||
|
Version 1.0 - 14-Apr-2025 by wavemotion-dave
|
||||||
|
* First official release of Speccy-SE!
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user