diff --git a/README.md b/README.md index 6db941ea..bac04eb2 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ Compatible with C64 and C128 machines/variants, NTSC and PAL supported. * **[Ethernet Usage](docs/Ethernet_Usage.md)** * **[NFC Loading System](docs/NFC_Loader.md)** * **[TeensyROM Web Browser](docs/Browser_Usage.md)** + * **[GEOS 64](docs/GEOS64_Usage.md)** * **[Custom BASIC Commands](docs/Custom_BASIC_Commands.md)** * **[TR Host Extensions (TR+ only)](docs/TR_Host_Extensions.md)** * **[USB/Ethernet Remote Command Protocol](docs/ControlComms.md)** diff --git a/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c index 2fa7bb93..5b1e57e1 100644 --- a/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c +++ b/Source/Teensy/MinimalBoot/Common/IO_Handlers/IOH_GeoRAM.c @@ -80,7 +80,7 @@ FLASHMEM void InitHndlr_GeoRAM() NumGeoRAM_Banks = NumBanks; fSpecialBtnChange = &SpecialBtn_GeoRAM; Serial.printf("GeoRAM Size: %dK bytes\n", NumBanks * RAM_Bank_Size / 1024); - LoadRAMBanks(GeoRAM_Bank, NumBanks, GeoRAM_Filename); + LoadRAMBanksReplaced(GeoRAM_Bank, NumBanks, GeoRAM_Filename); } FLASHMEM void PollingHndlr_GeoRAM() diff --git a/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c b/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c index 0d4a19f3..2b0abd83 100644 --- a/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c +++ b/Source/Teensy/MinimalBoot/Common/IO_Handlers/RAMBanks.c @@ -96,20 +96,8 @@ FLASHMEM static FS *RAMBanksFS(char *Path, char **ptrFileName) return FSfromSourceID(MenuSourceID); } -FLASHMEM void LoadRAMBanks(uint8_t *Bank[], uint8_t NumBanks, const char *SourcePath) +FLASHMEM static void ReadRAMBanksFile(File &LoadFile, uint8_t *Bank[], uint8_t NumBanks) { - 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); @@ -124,6 +112,22 @@ FLASHMEM void LoadRAMBanks(uint8_t *Bank[], uint8_t NumBanks, const char *Source LoadFile.close(); } +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; + } + ReadRAMBanksFile(LoadFile, Bank, NumBanks); +} + FLASHMEM static bool WriteRAMBanksFile(FS *sourceFS, const char *FileName, uint8_t *Bank[], uint8_t NumBanks) { Serial.printf("Saving: %s\n", FileName); @@ -210,6 +214,8 @@ FLASHMEM static void WithExtension(char *Dest, const char *FileName, const char strlcat(Dest, Extension, MaxPathLength); } +static const char TempExtension[] = ".tmp", BackupExtension[] = ".bak"; + // 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) { @@ -221,8 +227,8 @@ FLASHMEM void SaveRAMBanksReplacing(uint8_t *Bank[], uint8_t NumBanks, const cha FS *sourceFS = RAMBanksFS(Filename, &ptrFileName); char TempFilename[MaxPathLength], BackupFilename[MaxPathLength]; - WithExtension(TempFilename, ptrFileName, ".tmp"); - WithExtension(BackupFilename, ptrFileName, ".bak"); + WithExtension(TempFilename, ptrFileName, TempExtension); + WithExtension(BackupFilename, ptrFileName, BackupExtension); if (!WriteRAMBanksFile(sourceFS, TempFilename, Bank, NumBanks)) return; bool HadSave = sourceFS->exists(ptrFileName); @@ -239,3 +245,38 @@ FLASHMEM void SaveRAMBanksReplacing(uint8_t *Bank[], uint8_t NumBanks, const cha } FlashSavedLED(); } + +// Loads a file saved by SaveRAMBanksReplacing. Power lost between its two renames leaves no file, +// only a complete .tmp (the newer save) and the .bak; a .tmp of any other size is a torn write. +FLASHMEM void LoadRAMBanksReplaced(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) + { + char Fallback[MaxPathLength]; + WithExtension(Fallback, ptrFileName, TempExtension); + LoadFile = sourceFS->open(Fallback, FILE_READ); + if (LoadFile && LoadFile.size() != (uint32_t)NumBanks * RAM_Bank_Size) + { + Serial.printf("Skipping %s: %lu Bytes\n", Fallback, (uint32_t)LoadFile.size()); + LoadFile.close(); + } + if (!LoadFile) + { + WithExtension(Fallback, ptrFileName, BackupExtension); + LoadFile = sourceFS->open(Fallback, FILE_READ); + } + if (!LoadFile) + { + Serial.println("Not found!"); + return; + } + Serial.printf("Not found, loading: %s\n", Fallback); + } + ReadRAMBanksFile(LoadFile, Bank, NumBanks); +} diff --git a/docs/GEOS64_Usage.md b/docs/GEOS64_Usage.md new file mode 100644 index 00000000..166d1342 --- /dev/null +++ b/docs/GEOS64_Usage.md @@ -0,0 +1,58 @@ +# GEOS 64 on the TeensyROM + +## What it is +* Starts GEOS 64 from your own boot disk image on the SD card, with a USB mouse, and no disk drive. + * GEOS itself is not included: you supply the disk image. +* Runs on the TR and the TR+. +* Plug a USB mouse into the TeensyROM's USB host port. + * It is not a 1351 mouse: only GEOS, with the TR mouse driver the TeensyROM adds, sees it. +* Find it in the main menu: `F1` (Teensy Memory), then **Utilities**, then **GEOS 64**. + +## SD card setup +* Make a folder named `/GEOS64` on the SD card. +* Copy your GEOS 64 boot disk image into it, under any file name ending in `.D81` (for example `GEOS64.D81`). + * The TeensyROM finds the boot disk by what is on it, not by its name: the image must hold `DESK TOP` and the boot file `GEOBOOT`. + * D81 images only: the image with the deskTop and the applications on one disk. + * Don't end the name in `-TR` (`GEOS-TR.D81`): that name is kept for the copy described below, and is skipped. + * Versions that name their deskTop differently (Gateway, Wheels) are not found. +* If the folder holds more than one boot disk, the first one found is used. Only the first 8 `.D81` files in the folder are checked. + +## The -TR copy +* GEOS saves to the disk it starts from, so the TeensyROM never starts from your original image. +* The first time you select GEOS 64, it makes a copy next to the original with `-TR` added to the name (`GEOS64.D81` becomes `GEOS64-TR.D81`) and adds the TR USB mouse driver to the copy. Your original is not changed. +* Later launches reuse the `-TR` copy, so your saved work is still there. +* To start over from your original, delete the `-TR` copy. The next launch makes a new one. + +## GeoRAM +* GEOS 64 runs with GeoRAM (128K to 512K, as much as fits) as its Special IO, selected automatically. +* At launch, the TeensyROM loads `SD:/georam.ram` into GeoRAM. +* **(TR+ only)** To save GeoRAM, press and release the Alt button (to the left of the menu button). + * The contents are written to `georam.ram` on the SD card, and the LED flashes for about 1.5 seconds once the save is done. + * The previous `georam.ram` is kept as `georam.bak`. + * If the power goes off during a save, the next launch loads the newest complete save: the one just made if it was fully written, otherwise the previous one. +* GEOS's `CONFIGURE` does not run at start-up, since it looks for a disk drive, so GEOS does not set GeoRAM up as a RAM disk. + +## Date and time +* GEOS starts with the date and time of the TeensyROM's real-time clock, adjusted by the Time Zone setting. + * Set the clock and time zone in the Settings menu (`F8`, page 6). See [General Usage](General_Usage.md#the-settings-menu). + * Without Ethernet, the clock can also be set over USB with the `SetRTCToken` command. See [Remote Command Protocol](ControlComms.md). + +## Messages +If GEOS 64 can't start, the TeensyROM stays at the menu and shows one of these: + +| Message | Meaning | +|--|--| +| GEOS 64 starts from your boot disk image on the SD card. Insert the card. | No SD card was found. | +| Copy your GEOS 64 boot disk image (.D81) to /GEOS64 on the SD card, then select this again. | There is no `/GEOS64` folder, or no D81 in it holds `DESK TOP`. | +| ``: not a D64, D71 or D81 without error bytes | The file's size is not that of a disk image (a D81 is 819,200 bytes). | +| ``: (other reason) | The image could not be read, or its directory is damaged. | +| Could not add the mouse driver to a copy of ``: the disk is full | No room for the driver. Free some space on your original image, or use another one. "the directory is full" is the same for directory entries. | +| Could not add the mouse driver to a copy of ``: the SD card could not be written | The copy could not be written to the SD card. | +| `-TR.D81` has no desktop; remove it to start over | The `-TR` copy has lost `DESK TOP`. Delete it. | +| `-TR.D81` was set aside and could not be put back | Power was lost while the copy was being updated, and the TeensyROM could not restore it. Look for `-TR.D81.BAK` in `/GEOS64`. | +| `-TR.D81`: the boot file is not on the disk | The image has no `GEOBOOT`. | +| `-TR.D81`: the boot file's disk driver is not one the TR can replace | This `GEOBOOT` is not a version the TeensyROM can start. | + +
+ +[Back to main ReadMe](/README.md)