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 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"
|
||||
|
||||
|
@ -36,7 +36,7 @@ extern void mmInstall( int fifo_channel );
|
||||
//---------------------------------------------------------------------------------
|
||||
void VblankHandler(void) {
|
||||
//---------------------------------------------------------------------------------
|
||||
Wifi_Update();
|
||||
//Wifi_Update();
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ int main() {
|
||||
|
||||
SetYtrigger(80);
|
||||
|
||||
installWifiFIFO();
|
||||
//installWifiFIFO();
|
||||
installSoundFIFO();
|
||||
|
||||
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]
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// For disk and data pack games which may write back data, we don't want to base the CRC on the actual contents of
|
||||
// the media... so instead we'll just hash the filename as a CRC which is good enough to identify it in the future.
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// --------------------------------------------------
|
||||
// Compute the CRC of a memory buffer of any size...
|
||||
// --------------------------------------------------
|
||||
u32 getCRC32(u8 *buf, u32 size)
|
||||
{
|
||||
u32 crc = 0xFFFFFFFF;
|
||||
|
@ -35,6 +35,12 @@
|
||||
|
||||
#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 DX = 0;
|
||||
u32 DY = 0;
|
||||
@ -51,12 +57,19 @@ u8 SpectrumBios128[0x8000] = {0}; // We keep the 32k ZX Spectrum 128K
|
||||
|
||||
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];
|
||||
char initial_file[MAX_FILENAME_LEN] = "";
|
||||
char initial_path[MAX_FILENAME_LEN] = "";
|
||||
char last_path[MAX_FILENAME_LEN] = "";
|
||||
char last_file[MAX_FILENAME_LEN] = "";
|
||||
|
||||
// --------------------------------------------------
|
||||
// A few housekeeping vars to help with emulation...
|
||||
// --------------------------------------------------
|
||||
u8 last_speccy_mode = 99;
|
||||
u8 bFirstTime = 3;
|
||||
u8 bottom_screen = 0;
|
||||
@ -95,9 +108,11 @@ u8 key_debounce = 0; // A bit of key debounce
|
||||
// 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};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------
|
||||
// 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"))) = {
|
||||
JST_UP, //0
|
||||
JST_DOWN,
|
||||
@ -489,6 +504,11 @@ void CassetteInsert(char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// 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_EXIT 0 // Exit the menu
|
||||
#define MENU_ACTION_PLAY 1 // Play Cassette
|
||||
@ -521,7 +541,7 @@ CassetteDiskMenu_t generic_cassette_menu =
|
||||
{" STOP CASSETTE ", MENU_ACTION_STOP},
|
||||
{" SWAP CASSETTE ", MENU_ACTION_SWAP},
|
||||
{" REWIND CASSETTE ", MENU_ACTION_REWIND},
|
||||
{" POSITION CASSETTE", MENU_ACTION_POSITION},
|
||||
{" POSITION CASSETTE ", MENU_ACTION_POSITION},
|
||||
{" EXIT MENU ", MENU_ACTION_EXIT},
|
||||
{" NULL ", MENU_ACTION_END},
|
||||
},
|
||||
@ -552,7 +572,7 @@ void CassetteMenuShow(bool bClearScreen, u8 sel)
|
||||
menu = &generic_cassette_menu;
|
||||
|
||||
// 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
|
||||
while (menu->menulist[cassette_menu_items].menu_action != MENU_ACTION_END)
|
||||
@ -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;
|
||||
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_dampen = 0;
|
||||
u8 last_kbd_key = 0;
|
||||
@ -834,6 +862,9 @@ u8 handle_spectrum_keyboard_press(u16 iTx, u16 iTy) // ZX Spectrum keyboard
|
||||
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)
|
||||
{
|
||||
if ((iTy >= 165) && (iTy < 192)) // Bottom row is where the debugger keys are...
|
||||
@ -1545,7 +1576,7 @@ void BottomScreenCassette(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_Memory128, 0x00, sizeof(RAM_Memory128));
|
||||
@ -1617,9 +1648,9 @@ void LoadBIOSFiles(void)
|
||||
if (size) bSpeccyBiosFound = true; else memset(SpectrumBios128, 0xFF, 0x8000);
|
||||
}
|
||||
|
||||
/*********************************************************************************
|
||||
/************************************************************************************
|
||||
* Program entry point - check if an argument has been passed in probably from TWL++
|
||||
********************************************************************************/
|
||||
***********************************************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Init sound
|
||||
@ -1648,7 +1679,7 @@ int main(int argc, char **argv)
|
||||
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();
|
||||
LoadBIOSFiles();
|
||||
@ -1662,7 +1693,7 @@ int main(int argc, char **argv)
|
||||
// Handle command line argument... mostly for TWL++
|
||||
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)
|
||||
{
|
||||
static char path[128];
|
||||
|
@ -27,7 +27,7 @@ extern u32 DX, DY;
|
||||
#define MENU_CHOICE_DEFINE_KEYS 0x06
|
||||
#define MENU_CHOICE_POKE_MEMORY 0x07
|
||||
#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.
|
||||
@ -129,8 +129,8 @@ extern char initial_file[];
|
||||
extern char initial_path[];
|
||||
extern u16 nds_key;
|
||||
extern u8 kbd_key;
|
||||
extern u16 vusCptVBL; // Video Management
|
||||
extern u16 *pVidFlipBuf; // Video flipping buffer
|
||||
extern u16 vusCptVBL;
|
||||
extern u16 *pVidFlipBuf;
|
||||
extern u16 keyCoresp[MAX_KEY_OPTIONS];
|
||||
extern u16 NDS_keyMap[];
|
||||
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.
|
||||
// -------------------------------------------------------------------------
|
||||
int Filescmp (const void *c1, const void *c2)
|
||||
|
@ -591,20 +591,8 @@ void ExecOneInstruction(void)
|
||||
{
|
||||
register byte I;
|
||||
register pair J;
|
||||
u8 render = zx_ScreenRendering;
|
||||
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++);
|
||||
CPU.TStates += Cycles_NoM1Wait[I];
|
||||
|
||||
@ -646,7 +634,8 @@ ITCM_CODE void ExecZ80_Speccy(u32 RunToCycles)
|
||||
{
|
||||
register byte I;
|
||||
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)
|
||||
{
|
||||
@ -658,7 +647,18 @@ ITCM_CODE void ExecZ80_Speccy(u32 RunToCycles)
|
||||
// ----------------------------------------------------------------------------------------
|
||||
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++);
|
||||
|
@ -103,7 +103,6 @@ u32 highscore_checksum(void)
|
||||
// ------------------------------------------------------------------------------
|
||||
void highscore_init(void)
|
||||
{
|
||||
u8 upgrade_database = 0;
|
||||
u8 create_defaults = 0;
|
||||
|
||||
strcpy(highscores.last_initials, " ");
|
||||
@ -128,26 +127,7 @@ void highscore_init(void)
|
||||
create_defaults = 1;
|
||||
}
|
||||
|
||||
if (upgrade_database)
|
||||
{
|
||||
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...
|
||||
if (create_defaults) // Doesn't exist yet or is invalid... create defaults and save it...
|
||||
{
|
||||
strcpy(highscores.last_initials, " ");
|
||||
|
||||
|
@ -245,7 +245,7 @@ void pok_select(void)
|
||||
DSPrint(0,4+i,0," ");
|
||||
}
|
||||
}
|
||||
WAITVBL;WAITVBL;WAITVBL;WAITVBL;
|
||||
WAITVBL;WAITVBL;WAITVBL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +266,7 @@ void pok_select(void)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
if (i < screen_max)
|
||||
@ -281,7 +281,7 @@ void pok_select(void)
|
||||
DSPrint(0,4+i,0," ");
|
||||
}
|
||||
}
|
||||
WAITVBL;WAITVBL;WAITVBL;WAITVBL;
|
||||
WAITVBL;WAITVBL;WAITVBL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 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()
|
||||
{
|
||||
u32 spare = 0;
|
||||
|
@ -54,13 +54,11 @@ bool screenshotbmp(const char* filename) {
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// The screenshot requires a bit less than 100K of memory...
|
||||
// We steal this from the back end of the big read-only
|
||||
// memory block. If we have a tape that is huge, we would
|
||||
// run into problems but it would be astronomically rare
|
||||
// and it's better than wasting another 100K bytes that is
|
||||
// mostly underutilized.
|
||||
// We steal this from the compression buffer which is not
|
||||
// otherwise used except when save/loading save states.
|
||||
// ---------------------------------------------------------
|
||||
u8 *temp = (u8*)ROM_Memory + (sizeof(ROM_Memory) - (100*1024));
|
||||
extern u8 CompressBuffer[];
|
||||
u8 *temp = (u8*)CompressBuffer;
|
||||
|
||||
HEADER *header= (HEADER*)temp;
|
||||
INFOHEADER *infoheader = (INFOHEADER*)(temp + sizeof(HEADER));
|
||||
|
@ -45,6 +45,18 @@ ITCM_CODE unsigned char cpu_readport_speccy(register unsigned short Port)
|
||||
|
||||
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
|
||||
// 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;
|
||||
|
||||
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];
|
||||
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)
|
||||
{
|
||||
@ -338,16 +352,18 @@ ITCM_CODE void speccy_render_screen_line(u8 line)
|
||||
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;
|
||||
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
|
||||
// ----------------------------------------------------------------
|
||||
@ -377,12 +393,17 @@ ITCM_CODE void speccy_render_screen_line(u8 line)
|
||||
u8 ink = (attr & 0x07); // Ink Color is the foreground
|
||||
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 & 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...
|
||||
{
|
||||
// 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];
|
||||
}
|
||||
@ -567,9 +588,11 @@ void speccy_reset(void)
|
||||
static const u8 contend_delay[3] = {4,3,5};
|
||||
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.
|
||||
// ----------------------------------------------
|
||||
if (speccy_mode < MODE_SNA)
|
||||
{
|
||||
tape_parse_blocks(last_file_size);
|
||||
@ -580,7 +603,10 @@ void speccy_reset(void)
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -760,8 +786,8 @@ ITCM_CODE u32 speccy_run(void)
|
||||
// ----------------------------------------------
|
||||
// Execute 1 scanline worth of CPU instructions.
|
||||
//
|
||||
// We break this up into four pieces in order
|
||||
// to get more chances to render the audio beeper
|
||||
// We break this up into pieces in order to
|
||||
// get more chances to render the audio beeper
|
||||
// which requires a fairly high sample rate...
|
||||
// -----------------------------------------------
|
||||
if (tape_state)
|
||||
@ -817,8 +843,8 @@ ITCM_CODE u32 speccy_run(void)
|
||||
zx_current_line = 0;
|
||||
zx_ScreenRendering = 0;
|
||||
CPU.IRequest = INT_RST38;
|
||||
IntZ80(&CPU, CPU.IRequest);
|
||||
CPU.TStates_IRequest = CPU.TStates;
|
||||
IntZ80(&CPU, CPU.IRequest);
|
||||
return 0; // End of frame
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,13 @@
|
||||
#include "SpeccyUtils.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 BLOCK_ID_STANDARD 0x10
|
||||
@ -52,9 +59,11 @@
|
||||
// Yes, this is special. It happens frequently enough we trap on the high bit here...
|
||||
#define SEND_DATA_BITS 0x80
|
||||
|
||||
|
||||
// Some defaults mostly for the .TAP files as the .TZX
|
||||
// will override some/many of these...
|
||||
// ---------------------------------------------------------
|
||||
// Some defaults mostly for the .TAP files and
|
||||
// standard load blocks for the .TZX format.
|
||||
// Custom/turbo blocks will override some/many of these...
|
||||
// ---------------------------------------------------------
|
||||
#define DEFAULT_PILOT_LENGTH 2168
|
||||
#define DEFAULT_DATA_ZERO_PULSE_WIDTH 855
|
||||
#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];
|
||||
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)
|
||||
{
|
||||
memset(TapePositionTable, 0x00, sizeof(TapePositionTable));
|
||||
@ -132,7 +145,7 @@ u8 tape_find_positions(void)
|
||||
{
|
||||
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].description);
|
||||
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)
|
||||
{
|
||||
@ -145,14 +158,17 @@ u8 tape_find_positions(void)
|
||||
{
|
||||
strcpy(TapePositionTable[pos_idx].description, TapeBlocks[i].block_filename);
|
||||
TapePositionTable[pos_idx].block_id = i;
|
||||
pos_idx++;
|
||||
if (++pos_idx == 255) break; // That's all we can handle
|
||||
}
|
||||
}
|
||||
}
|
||||
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 B = (CPU.BC.B.h-1) & 0xFF;
|
||||
@ -442,15 +458,20 @@ void tape_parse_blocks(int tapeSize)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Some utility functions to know when the tape is playing
|
||||
// and also to reset or play the current tape.
|
||||
// --------------------------------------------------------
|
||||
|
||||
u8 tape_is_playing(void)
|
||||
{
|
||||
return (tape_state != TAPE_STOP);
|
||||
@ -485,7 +506,12 @@ void tape_position(u8 newPos)
|
||||
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;
|
||||
void tape_frame(void)
|
||||
{
|
||||
@ -493,6 +519,10 @@ void tape_frame(void)
|
||||
|
||||
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 (bottom_screen == 2)
|
||||
|
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,
|
||||
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