diff --git a/Source/Teensy/MinimalBoot/Common/IOHandlers.h b/Source/Teensy/MinimalBoot/Common/IOHandlers.h index 88bc75b7..722267c2 100644 --- a/Source/Teensy/MinimalBoot/Common/IOHandlers.h +++ b/Source/Teensy/MinimalBoot/Common/IOHandlers.h @@ -109,6 +109,8 @@ struct stcIOHandlers #ifndef MinimumBuild #include "IO_Handlers/IOH_MIDI.c" #include "IO_Handlers/IOH_Debug.c" + #include "IO_Handlers/RAMBanks.c" + #include "IO_Handlers/IOH_GeoRAM.c" #ifdef Fab04_REU #include "IO_Handlers/IOH_REU.c" #endif @@ -158,6 +160,7 @@ stcIOHandlers* IOHandler[] = //Synch order/qty with enum enumIOHandlers &IOHndlr_KernalReplace, //IOH_KernalReplace, #endif &IOHndlr_Debug, //IOH_Debug, + &IOHndlr_GeoRAM, //IOH_GeoRAM, //*not* manually selectable, see LastSelectableIOH diff --git a/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c new file mode 100644 index 00000000..49997e10 --- /dev/null +++ b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT + +// Berkeley Softworks geoRAM: a 256-byte window at $DE00 onto the page selected by two +// write-only registers, $DFFE (page 0-63 within a 16K block) and $DFFF (16K block). +// No DMA, so it runs on every TR, in C64 and C128 mode. +// ref: VICE src/c64/cart/georam.c + +void IO1Hndlr_GeoRAM(uint8_t Address, bool R_Wn); +void IO2Hndlr_GeoRAM(uint8_t Address, bool R_Wn); +void InitHndlr_GeoRAM(); +extern void (*fSpecialBtnChange)(bool Up_nDn); + +stcIOHandlers IOHndlr_GeoRAM = +{ + "GeoRAM", //Name of handler + &InitHndlr_GeoRAM, //Called once at handler startup + &IO1Hndlr_GeoRAM, //IO1 R/W handler + &IO2Hndlr_GeoRAM, //IO2 R/W handler + NULL, //ROML Read handler, in addition to any ROM data sent + NULL, //ROMH Read handler, in addition to any ROM data sent + NULL, //Polled in main routine + NULL, //called at the end of EVERY c64 cycle +}; + +#define GeoRAM_Filename "SD:/georam.ram" +#define MAX_GEORAM_BANKS 64 // 512K, the original geoRAM +#define MIN_GEORAM_BANKS 16 // 128K +#define GeoRAM_PagesPerBlock 64 +#define GeoRAM_BanksPerBlock (16384 / RAM_Bank_Size) + +// VICE decodes the registers across $DF80-$DFFF (A0 picks which); $DF00-$DF7F is left free. +#define GeoRAM_RegsBase 0x80 +#define GeoRAM_RegBlockBit 0x01 + +// volatile: the IO ISRs read the page only while there are banks, so the two stores +// must reach memory in the order written +static volatile uint8_t NumGeoRAM_Banks = 0; +static uint8_t *GeoRAM_Bank[MAX_GEORAM_BANKS]; +static uint8_t GeoRAM_Block, GeoRAM_PageNum; +static uint8_t * volatile GeoRAM_Page; + +static void GeoRAM_SelectPage() +{ + if (NumGeoRAM_Banks == 0) return; + // the unused high register bits wrap, as on real hardware + uint32_t Offset = ((GeoRAM_Block & (NumGeoRAM_Banks / GeoRAM_BanksPerBlock - 1)) * GeoRAM_PagesPerBlock + + (GeoRAM_PageNum & (GeoRAM_PagesPerBlock - 1))) * 256; + GeoRAM_Page = GeoRAM_Bank[Offset / RAM_Bank_Size] + (Offset % RAM_Bank_Size); +} + +FLASHMEM void FreeGeoRAM() +{ + // the handler is still installed and the C64 may be running: the IO ISRs must stop + // touching the banks before the first one is freed + uint8_t NumBanks = NumGeoRAM_Banks; + NumGeoRAM_Banks = 0; + FreeRAMBanks(GeoRAM_Bank, &NumBanks); +} + +FLASHMEM void SpecialBtn_GeoRAM(bool Up_nDn) +{ + // on button release save GeoRAM contents + if(Up_nDn) SaveRAMBanksReplacing(GeoRAM_Bank, NumGeoRAM_Banks, GeoRAM_Filename); +} + +FLASHMEM void InitHndlr_GeoRAM() +{ + FreeGeoRAM(); + GeoRAM_Block = GeoRAM_PageNum = 0; + uint8_t NumBanks = AllocRAMBanks(GeoRAM_Bank, MAX_GEORAM_BANKS, MIN_GEORAM_BANKS); + if (NumBanks == 0) + { + Serial.printf("GeoRAM is disabled\n"); + return; + } + GeoRAM_Page = GeoRAM_Bank[0]; + NumGeoRAM_Banks = NumBanks; + fSpecialBtnChange = &SpecialBtn_GeoRAM; + Serial.printf("GeoRAM Size: %dK bytes\n", NumBanks * RAM_Bank_Size / 1024); + LoadRAMBanks(GeoRAM_Bank, NumBanks, GeoRAM_Filename); +} + +void IO1Hndlr_GeoRAM(uint8_t Address, bool R_Wn) +{ + if (NumGeoRAM_Banks == 0) return; // disabled: $DE00 stays open bus, so software sees no geoRAM + if (R_Wn) DataPortWriteWaitLog(GeoRAM_Page[Address]); + else + { + uint8_t Data = DataPortWaitRead(); + GeoRAM_Page[Address] = Data; + TraceLogAddValidData(Data); + } +} + +void IO2Hndlr_GeoRAM(uint8_t Address, bool R_Wn) +{ + if (R_Wn || Address < GeoRAM_RegsBase) return; // write-only registers + uint8_t Data = DataPortWaitRead(); + if (Address & GeoRAM_RegBlockBit) GeoRAM_Block = Data; + else GeoRAM_PageNum = Data; + GeoRAM_SelectPage(); + TraceLogAddValidData(Data); +} diff --git a/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_REU.c b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_REU.c index 269499dc..36e46597 100644 --- a/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_REU.c +++ b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_REU.c @@ -29,8 +29,7 @@ #ifdef USE_RAM12 - #define REU_RAM_Bank_Size 0x2000 - #define REU_Size (NumREU_Banks * REU_RAM_Bank_Size) //Dynamically allocated based on NumREU_Banks, each bank is 8k (0x2000) + #define REU_Size (NumREU_Banks * RAM_Bank_Size) //Dynamically allocated based on NumREU_Banks, each bank is 8k (0x2000) #define REU_RAM_READ(a,d) d=REU_Bank[a>>13][a&0x1fff] #define REU_RAM_WRITE(a,d) REU_Bank[a>>13][a&0x1fff]=d #define MIN_REU_BANKS 16 // 128K, smallest real REU (1700) @@ -76,11 +75,6 @@ stcIOHandlers IOHndlr_REU = extern bool PerformDMA(DMA_Trans_RnW RnW, uint16_t StartAddr, uint8_t *Buffer, uint32_t Length, DMA_Addr_Mode FixC64Addr); extern bool CloseDMA(); extern void (*fSpecialBtnChange)(bool Up_nDn); //Pointer to function called when Special Button Changes -extern void EEPreadStr(uint16_t addr, char* buf); -extern RegMenuTypes RegMenuTypeFromFileName(char** ptrptrFileName); -extern bool SDFullInit(); -extern bool USBFileSystemWait(); -extern FS *FSfromSourceID(RegMenuTypes SourceID); //ref: https://codebase64.net/doku.php?id=base:reu_registers //tests: @@ -145,17 +139,11 @@ extern bool DMA_RnW, DMA_FixC64Addr; extern uint32_t DMA_Length, DMA_Count, DMA_StartAddr; extern bool DMAByte(uint8_t *Data); -extern void FreeDriveDirMenu(); -extern uint8_t RAM_Image[]; -// CrtChips.h declares the main image's static table and count. extern StructMenuItem *DriveDirMenu; -extern uint8_t *ptrRAM_ImageEnd; // points to end of CRT-used RAM1 buffer void FreeREU() -{ //free banks allocated in RAM2 and reset NumREUBanks - for(uint16_t cnt=0; cnt < NumREU_Banks; cnt++) - if((uint32_t)REU_Bank[cnt] >= 0x20200000) free(REU_Bank[cnt]); - NumREU_Banks = 0; +{ + FreeRAMBanks(REU_Bank, &NumREU_Banks); } void DMAByte_BASkip(uint8_t *Data1) @@ -455,83 +443,12 @@ FLASHMEM void ReadWriteREU(bool RnW, uint32_t REUAddr, uint8_t *REUBuf, uint16_t FLASHMEM void Save_REU() { - if (NumREU_Banks == 0) return; // nothing to save: probably due to failure to allocate 128K - - //Create filename based on current. reu000.reu becomes reu001.reu, etc +#ifndef USE_RAM12 + #error Save_REU saves RAM1/2 banks only +#endif char Filename[MaxPathLength]; EEPreadStr(eepAdREUFilename, Filename); - char *ptrFileName = Filename; //pointer to move past SD/USB/TR: - RegMenuTypes MenuSourceID = RegMenuTypeFromFileName(&ptrFileName); - - if (MenuSourceID == rmtSD) SDFullInit(); // SD.begin(BUILTIN_SDCARD); with retry if presence detected - if (MenuSourceID == rmtUSBDrive) USBFileSystemWait(); //wait up to 1.5 sec in case USB drive just changed or powered up - //rmtTeensy not allowed, no reu files in Teensy Mem - - FS *sourceFS = FSfromSourceID(MenuSourceID); - - char Extension[20]; - char *pDot = strrchr(ptrFileName, '.'); //find last dot - if (pDot == NULL) pDot = ptrFileName + strlen(ptrFileName); //if no extension, set to end of filename - strcpy(Extension, pDot); //copy extension - *pDot = 0; //terminate at dot/extension - - bool IsNum = true; //are last 3digits of filename all numbers? - if (strlen(ptrFileName)>=3) - { - for(char *charloc=pDot-3; charloc'9') IsNum = false; - //Serial.printf("%08x: %c %02x\n", (uint32_t)charloc, *charloc, *charloc); - } - } - else IsNum = false; - - - uint16_t NewNum = 0; - if (IsNum) - { //find current number and then terminate it - NewNum = atoi(pDot-3); - *(pDot-3) = 0; //terminate number - } - - //now see if the file exists, or itterate until it doesn't - char NewFilename[MaxPathLength]; - - do sprintf(NewFilename, "%s%03d%s", ptrFileName, NewNum++, Extension); - while (sourceFS->exists(NewFilename)); - - Serial.printf("Saving REU: %s\n", NewFilename); - File SaveFile = sourceFS->open(NewFilename, FILE_WRITE); - if (!SaveFile) - { - Serial.println("Unable to open!"); - return; - } - - //uint32_t StartmS = millis(); - uint8_t NextByte; - - for (uint32_t CharNum=0; CharNum= 0x20200000) - free(REU_Bank[unused_bank]); - NumREU_Banks = NewNumREU_Banks; - } - - Printf_dbg_reu("After resizing to power of 2, %luK bytes allocated\n", (uint32_t)NumREU_Banks * REU_RAM_Bank_Size / 1024); - - if (NumREU_Banks < MIN_REU_BANKS) // If REU is not 128k or larger + NumREU_Banks = AllocRAMBanks(REU_Bank, MAX_REU_BANKS, MIN_REU_BANKS); + if (NumREU_Banks == 0) { - Serial.printf("Unable to allocate minimum REU size of 128K\n" - "REU is disabled\n"); - FreeREU(); + Serial.printf("REU is disabled\n"); return; } @@ -622,37 +490,9 @@ uint8_t *pRAM_Image = ptrRAM_ImageEnd; //start at end of any CRT-used RAM1 fSpecialBtnChange = &SpecialBtn_REU; //REU RAM is ready; enable button now so a failed/missing preload below doesn't skip it Serial.printf("REU Size: %luK bytes\n", (uint32_t)REU_Size / 1024); - //pre-load REU into RAM here: char Filename[MaxPathLength]; EEPreadStr(eepAdREUFilename, Filename); - char *ptrFileName = Filename; //pointer to move past SD/USB/TR: - Serial.printf("Loading REU: %s\n", Filename); - RegMenuTypes MenuSourceID = RegMenuTypeFromFileName(&ptrFileName); - - if (MenuSourceID == rmtSD) SDFullInit(); // SD.begin(BUILTIN_SDCARD); with retry if presence detected - if (MenuSourceID == rmtUSBDrive) USBFileSystemWait(); //wait up to 1.5 sec in case USB drive just changed or powered up - //rmtTeensy not allowed, no reu files in Teensy Mem - - FS *sourceFS = FSfromSourceID(MenuSourceID); - File LoadFile = sourceFS->open(ptrFileName, FILE_READ); - if (!LoadFile) - { - Serial.println("Not found!"); - return; - } - - if (LoadFile.size() > REU_Size) - Serial.printf("Too Large! Loading first %luK\n", (uint32_t)REU_Size/1024); - - //uint32_t StartmS = millis(); - uint32_t CharNum = 0; - for (uint8_t Bank = 0; Bank < NumREU_Banks && LoadFile.available(); Bank++) - CharNum += LoadFile.read(REU_Bank[Bank], REU_RAM_Bank_Size); - //Serial.printf("Read %lu Bytes in %lumS\n", CharNum, millis()-StartmS); - Serial.printf("Read %lu Bytes into REU\n", CharNum); - LoadFile.close(); - //delay(250); - + LoadRAMBanks(REU_Bank, NumREU_Banks, Filename); #elif defined(USE_PSRAM) //higher clock speed and shorter CS setup/hold do help, but still not enough for NUVIEs w/ sound diff --git a/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c b/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c new file mode 100644 index 00000000..684290d0 --- /dev/null +++ b/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c @@ -0,0 +1,237 @@ +// MIT License +// +// Copyright (c) 2026 Travis Smith +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +// and associated documentation files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom +// the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +// RAM expansion memory (REU, GeoRAM): 8k banks taken from the free end of RAM1's RAM_Image, +// then from RAM2, preloaded from and saved to an image file. + +#define RAM_Bank_Size 0x2000 + +extern void EEPreadStr(uint16_t addr, char* buf); +extern RegMenuTypes RegMenuTypeFromFileName(char** ptrptrFileName); +extern bool SDFullInit(); +extern bool USBFileSystemWait(); +extern FS *FSfromSourceID(RegMenuTypes SourceID); +extern void FreeDriveDirMenu(); +extern uint8_t RAM_Image[]; +extern uint8_t *ptrRAM_ImageEnd; // points to end of CRT-used RAM1 buffer + +FLASHMEM void FreeRAMBanks(uint8_t *Bank[], uint8_t *NumBanks) +{ + for(uint16_t cnt=0; cnt < *NumBanks; cnt++) + if((uint32_t)Bank[cnt] >= 0x20200000) free(Bank[cnt]); + *NumBanks = 0; +} + +// Returns the number of banks allocated: a power of 2 up to MaxBanks, or 0 if fewer than MinBanks fit. +FLASHMEM uint8_t AllocRAMBanks(uint8_t *Bank[], uint8_t MaxBanks, uint8_t MinBanks) +{ + uint8_t NumBanks = 0; + FreeDriveDirMenu(); + + if (NumCrtChips == 0) ptrRAM_ImageEnd = RAM_Image; //If no CRT loaded, RAM1 is entirely free + uint8_t *pRAM_Image = ptrRAM_ImageEnd; //start at end of any CRT-used RAM1 + + while (((uint32_t)pRAM_Image - (uint32_t)RAM_Image + RAM_Bank_Size <= RAM_ImageSize) + && (NumBanks < MaxBanks)) + { + Bank[NumBanks] = pRAM_Image; + pRAM_Image += RAM_Bank_Size; + NumBanks++; + } + + while(NumBanks < MaxBanks && (NULL != (Bank[NumBanks] = (uint8_t*)malloc(RAM_Bank_Size)))) + NumBanks++; + + if (NumBanks & (NumBanks-1)) //not a power of 2 + { + // largest power less than or equal to NumBanks + uint8_t NewNumBanks = 1 << (7 - (__builtin_clz(NumBanks) - 24)); + Serial.printf("Resizing from %d banks to %d banks\n", NumBanks, NewNumBanks); + + for (uint8_t unused_bank = NewNumBanks; unused_bank < NumBanks; unused_bank++) + if((uint32_t)Bank[unused_bank] >= 0x20200000) + free(Bank[unused_bank]); + NumBanks = NewNumBanks; + } + + if (NumBanks < MinBanks) + { + Serial.printf("Unable to allocate minimum size of %dK\n", MinBanks * RAM_Bank_Size / 1024); + FreeRAMBanks(Bank, &NumBanks); + } + return NumBanks; +} + +// Path is source-prefixed ("SD:/reu.reu") +FLASHMEM static FS *RAMBanksFS(char *Path, char **ptrFileName) +{ + *ptrFileName = Path; + RegMenuTypes MenuSourceID = RegMenuTypeFromFileName(ptrFileName); + + if (MenuSourceID == rmtSD) SDFullInit(); // SD.begin(BUILTIN_SDCARD); with retry if presence detected + if (MenuSourceID == rmtUSBDrive) USBFileSystemWait(); //wait up to 1.5 sec in case USB drive just changed or powered up + //rmtTeensy not allowed, no RAM image files in Teensy Mem + + return FSfromSourceID(MenuSourceID); +} + +FLASHMEM void LoadRAMBanks(uint8_t *Bank[], uint8_t NumBanks, const char *SourcePath) +{ + char Filename[MaxPathLength]; + strlcpy(Filename, SourcePath, MaxPathLength); + Serial.printf("Loading: %s\n", Filename); + char *ptrFileName; + FS *sourceFS = RAMBanksFS(Filename, &ptrFileName); + File LoadFile = sourceFS->open(ptrFileName, FILE_READ); + if (!LoadFile) + { + Serial.println("Not found!"); + return; + } + + if (LoadFile.size() > (uint32_t)NumBanks * RAM_Bank_Size) + Serial.printf("Too Large! Loading first %luK\n", (uint32_t)NumBanks * RAM_Bank_Size / 1024); + + uint32_t CharNum = 0; + for (uint8_t BankNum = 0; BankNum < NumBanks && LoadFile.available(); BankNum++) + { + int BytesRead = LoadFile.read(Bank[BankNum], RAM_Bank_Size); + if (BytesRead <= 0) break; + CharNum += BytesRead; + } + Serial.printf("Read %lu Bytes\n", CharNum); + LoadFile.close(); +} + +FLASHMEM static bool WriteRAMBanksFile(FS *sourceFS, const char *FileName, uint8_t *Bank[], uint8_t NumBanks) +{ + Serial.printf("Saving: %s\n", FileName); + sourceFS->remove(FileName); // FILE_WRITE appends to an existing file + File SaveFile = sourceFS->open(FileName, FILE_WRITE); + if (!SaveFile) + { + Serial.println("Unable to open!"); + return false; + } + + for (uint8_t BankNum = 0; BankNum < NumBanks; BankNum++) + { + if (SaveFile.write(Bank[BankNum], RAM_Bank_Size) != RAM_Bank_Size) + { + Serial.printf("Write failed after %dKBytes!\n", BankNum * RAM_Bank_Size / 1024); + SaveFile.close(); + return false; + } + } + Serial.printf("Saved %dKBytes\n", NumBanks * RAM_Bank_Size / 1024); + SaveFile.close(); + return true; +} + +FLASHMEM static void FlashSavedLED() +{ + uint32_t LastmS = millis(); + bool LEDState = true; + + for (uint32_t FlashCount=0; FlashCount<20; FlashCount++) + { + while(millis()-LastmS < 75); + LastmS = millis(); + if ((LEDState = !LEDState)) SetLEDOn; + else SetLEDOff; + } +} + +// Saves to the first free numbered name: reu.reu becomes reu000.reu, reu000.reu becomes reu001.reu, etc +FLASHMEM void SaveRAMBanks(uint8_t *Bank[], uint8_t NumBanks, const char *SourcePath) +{ + if (NumBanks == 0) return; // nothing to save: probably due to failure to allocate + + char Filename[MaxPathLength]; + strlcpy(Filename, SourcePath, MaxPathLength); + char *ptrFileName; + FS *sourceFS = RAMBanksFS(Filename, &ptrFileName); + + char Extension[20]; + char *pDot = strrchr(ptrFileName, '.'); + if (pDot == NULL) pDot = ptrFileName + strlen(ptrFileName); //if no extension, set to end of filename + strlcpy(Extension, pDot, sizeof(Extension)); + *pDot = 0; + + bool IsNum = true; //are last 3digits of filename all numbers? + if (strlen(ptrFileName)>=3) + { + for(char *charloc=pDot-3; charloc'9') IsNum = false; + } + else IsNum = false; + + uint16_t NewNum = 0; + if (IsNum) + { //find current number and then terminate it + NewNum = atoi(pDot-3); + *(pDot-3) = 0; //terminate number + } + + char NewFilename[MaxPathLength]; + + do sprintf(NewFilename, "%s%03d%s", ptrFileName, NewNum++, Extension); + while (sourceFS->exists(NewFilename)); + + if (WriteRAMBanksFile(sourceFS, NewFilename, Bank, NumBanks)) FlashSavedLED(); +} + +FLASHMEM static void WithExtension(char *Dest, const char *FileName, const char *Extension) +{ + strlcpy(Dest, FileName, MaxPathLength); + char *pDot = strrchr(Dest, '.'); + if (pDot != NULL) *pDot = 0; + strlcat(Dest, Extension, MaxPathLength); +} + +// Overwrites the file, keeping the one it replaces as .bak: georam.ram becomes georam.bak +FLASHMEM void SaveRAMBanksReplacing(uint8_t *Bank[], uint8_t NumBanks, const char *SourcePath) +{ + if (NumBanks == 0) return; // nothing to save: probably due to failure to allocate + + char Filename[MaxPathLength]; + strlcpy(Filename, SourcePath, MaxPathLength); + char *ptrFileName; + FS *sourceFS = RAMBanksFS(Filename, &ptrFileName); + + char TempFilename[MaxPathLength], BackupFilename[MaxPathLength]; + WithExtension(TempFilename, ptrFileName, ".tmp"); + WithExtension(BackupFilename, ptrFileName, ".bak"); + + if (!WriteRAMBanksFile(sourceFS, TempFilename, Bank, NumBanks)) return; + bool HadSave = sourceFS->exists(ptrFileName); + if (HadSave) + { // rename refuses an existing target + sourceFS->remove(BackupFilename); + sourceFS->rename(ptrFileName, BackupFilename); + } + if (!sourceFS->rename(TempFilename, ptrFileName)) + { + Serial.printf("Unable to rename %s to %s!\n", TempFilename, ptrFileName); + if (HadSave) sourceFS->rename(BackupFilename, ptrFileName); + return; + } + FlashSavedLED(); +} diff --git a/Source/Teensy/MinimalBoot/Common/Menu_Regs.h b/Source/Teensy/MinimalBoot/Common/Menu_Regs.h index 166ecfe0..a3c616da 100644 --- a/Source/Teensy/MinimalBoot/Common/Menu_Regs.h +++ b/Source/Teensy/MinimalBoot/Common/Menu_Regs.h @@ -437,7 +437,8 @@ enum enumIOHandlers //Synch order/qty with IOHandler[] (IOHandlers.h) #ifdef Fab04_KernalReplace IOH_KernalReplace, #endif - IOH_Debug, //last manually selectable, see LastSelectableIOH + IOH_Debug, + IOH_GeoRAM, //last manually selectable, see LastSelectableIOH //*not* manually selectable, see LastSelectableIOH @@ -471,4 +472,4 @@ enum enumIOHandlers //Synch order/qty with IOHandler[] (IOHandlers.h) IOH_Num_Handlers //always last }; -#define LastSelectableIOH IOH_Debug //127 max. Used in IOH_TeensyROM.c for Special IO display/select +#define LastSelectableIOH IOH_GeoRAM //127 max. Used in IOH_TeensyROM.c for Special IO display/select diff --git a/Source/Teensy/RemoteControl.ino b/Source/Teensy/RemoteControl.ino index cfa10e5e..351577da 100644 --- a/Source/Teensy/RemoteControl.ino +++ b/Source/Teensy/RemoteControl.ino @@ -273,6 +273,7 @@ void RemoteLaunch(RegMenuTypes MenuSourceID, const char *FileNamePath, bool DoCa #ifdef Fab04_REU FreeREU(); #endif + FreeGeoRAM(); FreeSwiftlinkBuffs(); if (MenuSourceID == rmtTeensy) diff --git a/Source/Teensy/Teensy.ino b/Source/Teensy/Teensy.ino index ff171ca6..569254f0 100644 --- a/Source/Teensy/Teensy.ino +++ b/Source/Teensy/Teensy.ino @@ -420,7 +420,8 @@ FLASHMEM void SetUpMainMenuROM() FreeCrtChips(); #ifdef Fab04_REU FreeREU(); -#endif +#endif + FreeGeoRAM(); FreeSwiftlinkBuffs(); RedirectEmptyDriveDirMenu(); free((void*)MIDIRxBuf); MIDIRxBuf=NULL;