Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
2db2ca5
firmware: share the REU's RAM bank allocation, preload and save
kfox Oct 15, 2026
2759010
firmware: GeoRAM IO handler
kfox Oct 15, 2026
3bfb688
firmware: RAM bank save reports a failed write instead of acking it
kfox Oct 15, 2026
6ecc7db
firmware: drop RAMBanks.c comments that restate the code
kfox Oct 15, 2026
89c578c
firmware: a disabled GeoRAM leaves $DE00 open instead of answering fr…
kfox Oct 15, 2026
8686274
firmware: FreeGeoRAM stops the IO handlers using the banks before fre…
kfox Oct 15, 2026
1c8cf32
firmware: GeoRAM state is file-local
kfox Oct 15, 2026
b27c082
firmware: drop trailing spaces after the FreeGeoRAM calls
kfox Oct 15, 2026
9b91191
firmware: GeoRAM is the last selectable handler, after Debug
kfox Oct 15, 2026
1330587
firmware: a USB mouse read through registers beside GeoRAM and the REU
kfox Oct 16, 2026
d631ef3
tools: a GEOS 128 input driver for the TR's USB mouse
kfox Oct 16, 2026
78cbc05
firmware: the USB mouse poll keeps reports the USB ISR lands mid-read…
kfox Oct 16, 2026
d3990d3
tools: the GEOS 128 mouse driver ignores a page without the TR's ID, …
kfox Oct 16, 2026
50a74e6
tools: trmouse.py puts the class version at +12, and stops on a loope…
kfox Oct 16, 2026
2564b78
firmware: the USB mouse poll fences the IRQ disable, and clears a rep…
kfox Oct 16, 2026
b89f417
tools: the mouse driver's off-pointer comment drops a 1351 comparison…
kfox Oct 16, 2026
20aa955
tools: trmouse.py stops on a directory chain into the header or BAM, …
kfox Oct 16, 2026
caedc75
firmware: the USB mouse poll fences the IRQ re-enable against the com…
kfox Oct 16, 2026
04de5c8
tools: trmouse.py stops on a directory chain that leaves track 40
kfox Oct 16, 2026
f18ee29
tools: trmouse.py takes D64 and D71 boot disks too, follows the heade…
kfox Oct 16, 2026
b17b18b
tools: trmouse.py refuses a BAM that frees a live directory sector or…
kfox Oct 16, 2026
ea12ae5
tools: trmouse.py refuses any undercounted track and any live directo…
kfox Oct 16, 2026
be36f99
tools: trmouse.py writes the driver file as a C header for the firmware
kfox Oct 16, 2026
29dc444
tools: trmouse.py writes the driver header with LF endings and keeps …
kfox Oct 16, 2026
d73741c
firmware: a GEOS 128 boot-disk patch that adds the TR USB mouse drive…
kfox Oct 16, 2026
4be1f11
gitattributes: pin LF only on the generated GEOS mouse driver header,…
kfox Oct 16, 2026
5825d16
firmware: the GEOS disk patch refuses a full disk or directory before…
kfox Oct 16, 2026
a3e2cf0
firmware: the GEOS directory grow refuses a sector outside the direct…
kfox Oct 16, 2026
f35c3be
firmware: the GEOS directory grow checks for room before taking a sec…
kfox Oct 16, 2026
5ef62c9
firmware: the GEOS disk patch takes its DeskTop and driver from a tar…
kfox Oct 16, 2026
2bdf7fa
firmware: the GEOS disk patch refuses a target whose names or driver …
kfox Oct 16, 2026
95ca21e
firmware: a GEOS 128 menu item that finds the user's boot disk image …
kfox Oct 16, 2026
52799a5
firmware: the GEOS launcher stamps the driver with the RTC's local da…
kfox Oct 16, 2026
4268042
firmware: the GEOS launcher names the disk that will boot, the -TR co…
kfox Oct 16, 2026
03a6388
firmware: the GEOS launcher names the image a failed patch was for, a…
kfox Oct 17, 2026
b7d1933
firmware: GEOS 128 boot disk setup moves from the root menu to Teensy…
kfox Oct 20, 2026
ae2841f
firmware: the TR block device contract, register core and disk image …
kfox Oct 20, 2026
e09f7e1
firmware: TRBlock bounds the window access itself and tolerates an un…
kfox Oct 20, 2026
c86f8ce
tests: cover the unknown-size image, and state which failed writes ca…
kfox Oct 20, 2026
08d99d5
firmware: serve the block device beside the USB mouse registers, and …
kfox Oct 20, 2026
ae93ace
tools: a GEOS disk driver transport served by the TR block device
kfox Oct 21, 2026
f46a67d
tools: build the TR USB mouse driver for GEOS 64
kfox Oct 21, 2026
f881e79
firmware: build a PRG that starts GEOS from a boot disk image
kfox Oct 21, 2026
b7e7691
firmware: launch GEOS 64 from the TeensyROM Specific menu
kfox Oct 21, 2026
0facad9
tools: write the generated driver header with LF endings on every host
kfox Oct 21, 2026
4aafa1e
tools: GEOS 64 mouse skips the 80-column scaling and stops at its vec…
kfox Oct 21, 2026
c8b0563
firmware: keep the GEOS boot PRG inside 64K and refuse a target with …
kfox Oct 21, 2026
3611895
firmware: refuse a stock driver with other entries in the code the TR…
kfox Oct 21, 2026
ee97b3f
firmware: drop two comments that restate the GEOS launch functions
kfox Oct 21, 2026
9354832
tests: geos boot harness builds the boot PRG before retyping CONFIGUR…
kfox Oct 21, 2026
1823fb8
tools: the GEOS disk driver masks interrupts around IO as the stock d…
kfox Oct 21, 2026
ba2e6b1
firmware: start GEOS 64 with the TeensyROM's date and time
kfox Oct 21, 2026
3a2d2d3
tests: geos boot harness header states the build-then-retype order
kfox Oct 21, 2026
9f09609
firmware: a flush with no usable image reports no image
kfox Oct 21, 2026
9f5eeee
Merge branch 'geos-mailbox' into geos-launch
kfox Oct 21, 2026
3febf0d
firmware: add the mouse driver to an existing GEOS copy in place
kfox Oct 21, 2026
26d9329
firmware: report why GeosPatchFile could not open the image
kfox Oct 21, 2026
c86eabc
firmware: patch an existing GEOS copy through a temporary file, never…
kfox Oct 21, 2026
c5d21eb
firmware: GeosPatchCopy names the failure for a plain copy correctly
kfox Oct 21, 2026
ed1cd28
firmware: keep the replaced GEOS copy until its successor is in place
kfox Oct 21, 2026
b14faef
firmware: put back a GEOS copy that power loss left renamed aside
kfox Oct 21, 2026
7266e13
firmware: stop a launch that could not put a set-aside GEOS copy back
kfox Oct 21, 2026
8d129a2
firmware: say where the GEOS disk is when a failed copy cannot be rol…
kfox Oct 21, 2026
dc8b09e
firmware: drop the stale GEOS backup when the copy it preceded is in …
kfox Oct 21, 2026
04011cb
firmware: size the copy error buffer to hold a full backup path
kfox Oct 21, 2026
6e890a2
firmware: bound SendMsgPrintfln to its buffer
kfox Oct 21, 2026
3c93ff4
Merge main into geos-launcher, rebuilding the C64 menu header
kfox Oct 21, 2026
30331ad
Merge geos-launcher into geos-mailbox, bringing in main
kfox Oct 21, 2026
c131e54
Merge geos-mailbox into geos-launch, bringing in main
kfox Oct 21, 2026
ef59e5e
firmware: compare the transport span as unsigned so gcc's -Werror acc…
kfox Oct 21, 2026
2aa0d57
firmware: drop the GEOS 128 boot disk setup item until GEOS 128 launches
kfox Oct 21, 2026
cb01154
firmware: answer the TR block window first so its bytes reach the bus…
kfox Oct 21, 2026
8aa8939
tools: the GEOS disk driver reads each TR byte until two reads agree
kfox Oct 21, 2026
f206a5f
Merge geos-mailbox into geos-launch: answer the TR block window first
kfox Oct 21, 2026
0300249
firmware: list GEOS 64 last in TeensyROM Specific
kfox Oct 21, 2026
ce6ffef
firmware: the USB mouse registers live only beside GeoRAM, and plain …
kfox Oct 23, 2026
54a7f9a
firmware: GeoRAM polls the USB mouse from its handler instead of ever…
kfox Oct 23, 2026
bb4e2e1
firmware: the USB mouse's X and Y reads drive a byte kept ready, and …
kfox Oct 23, 2026
12d176d
firmware: GeoRAM drops its 256-byte no-RAM page
kfox Oct 23, 2026
ce7cf6c
firmware: keep the GEOS disk patcher out of ITCM
kfox Oct 23, 2026
e984c6d
firmware: start GEOS 64 at the right hour at noon and midnight
kfox Oct 23, 2026
9d1c7b9
firmware: GeoRAM saves back to georam.ram, keeping the last one as ge…
kfox Oct 23, 2026
2c86436
firmware: keep the GEOS patcher's messages in flash
kfox Oct 23, 2026
dbc1ba8
firmware: the USB mouse register map says the ID marks the registers,…
kfox Oct 23, 2026
167e779
Merge branch 'georam' into usb-mouse
kfox Oct 23, 2026
75795ff
Merge branch 'usb-mouse' into geos-launcher
kfox Oct 23, 2026
706af22
Merge branch 'geos-launcher' into geos-mailbox
kfox Oct 23, 2026
be1e07c
Merge branch 'geos-launcher' into geos-mailbox
kfox Oct 23, 2026
e7f06e2
firmware: regenerate the GEOS 128 mouse driver header for the driver'…
kfox Oct 23, 2026
0d20dc1
firmware: a TR block FLUSH the card fails reports $E4 instead of done
kfox Oct 23, 2026
fbfaad4
firmware: every SD.begin closes the TR block image around it and reop…
kfox Oct 23, 2026
b0d365e
firmware: GeoRAM polls the TR block device, and unmounts its image wh…
kfox Oct 23, 2026
f3fe5f1
firmware: keep the TR block device's main-loop side out of ITCM
kfox Oct 23, 2026
745cdf7
docs: the TR block device is GeoRAM's only, at $DF00
kfox Oct 23, 2026
7d4bda8
Merge branch 'geos-mailbox' into geos-launch
kfox Oct 23, 2026
0f60089
firmware: keep the GEOS 64 launcher's messages in flash
kfox Oct 23, 2026
9d41320
firmware: GeoRAM rotates georam.ram to .bak only when there is one, a…
kfox Oct 23, 2026
76c13e5
firmware: a remote launch finds its TR menu target before freeing the…
kfox Oct 23, 2026
9f0c8f8
tests: drive the USB mouse registers on the host
kfox Oct 23, 2026
e266422
tools: the GEOS disk driver looks for the TR block device at $DF00 only
kfox Oct 23, 2026
e7d0866
fix: review findings for 9f0c8f8
kfox Oct 23, 2026
f43c8b4
firmware: SDFullInit alone closes the TR block image around SD.begin
kfox Oct 23, 2026
48aed54
Merge branch 'georam' into usb-mouse
kfox Oct 23, 2026
bfa3e5f
Merge branch 'usb-mouse' into geos-launcher
kfox Oct 23, 2026
18042b7
firmware: a TR block reopen refuses an image that is not the one mounted
kfox Oct 23, 2026
51f5d34
firmware: a TR block flush the card fails stays dirty and is retried
kfox Oct 23, 2026
45ceadb
firmware: a TR block flush that keeps failing is logged again after t…
kfox Oct 23, 2026
d60d6cd
Merge branch 'geos-launcher' into geos-mailbox
kfox Oct 23, 2026
f93e6e2
Merge branch 'geos-mailbox' into geos-launch
kfox Oct 23, 2026
8b09ed7
firmware: the GEOS launcher retypes CONFIGURE as a system file, not a…
kfox Oct 25, 2026
3bc93c6
firmware: the GEOS 64 launcher looks only for a D81 boot disk image
kfox Oct 25, 2026
5ec90dd
Merge remote-tracking branch 'upstream/main' into georam
kfox Oct 26, 2026
169d10a
Merge branch 'georam' into usb-mouse
kfox Oct 26, 2026
4210842
fix: review findings for 5ec90dd
kfox Oct 26, 2026
3a6ba8c
Merge branch 'usb-mouse' into geos-launcher
kfox Oct 26, 2026
156f4a4
test: a PSTR("...") message format counts as a literal
kfox Oct 26, 2026
2d86bdc
Merge branch 'georam' into usb-mouse
kfox Oct 26, 2026
7ed2134
Merge branch 'usb-mouse' into geos-launcher
kfox Oct 26, 2026
5ad3d95
Merge branch 'geos-launcher' into geos-mailbox
kfox Oct 26, 2026
2a12889
Merge branch 'geos-mailbox' into geos-launch
kfox Oct 26, 2026
852acec
firmware: each GEOS launcher message passes its format as a literal
kfox Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
# Generated by tools/build-c64.mjs with LF endings; check them out as LF too so a
# rebuild on Windows (core.autocrlf=true) doesn't flag unchanged headers as modified
Source/Teensy/TRMenuFiles/ROMs/*.h text eol=lf

# Generated by tools/geos/trmouse.py --c-header with LF endings, kept LF for the same reason
Source/Teensy/GEOS/TRMouse128.h text eol=lf
1 change: 1 addition & 0 deletions Source/C64/MainMenuCRT/source/Menu_Regs.i
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@
rtBinC128 = 18
rtFileREU = 19
rtFileTRH = 20
rtGEOS = 21

;63 max: rRegItemTypePlusIOH uses bit 7 (assigned IOH) and bit 6 (/VMS claim),
;and TblItemType's mult by 4 limits it to 63 as well
Expand Down
1 change: 1 addition & 0 deletions Source/C64/MainMenuCRT/source/StringsMsgs.s
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,4 @@ TblItemType: ;must match regItemTypes (rtNone, rtBin16k, etc) order!
!tx 0, "128" ; rtBinC128 = 18
!tx 0, "REU" ; rtFileREU = 19
!tx 0, "TRH" ; rtFileTRH = 20
!tx 0, "GEO" ; rtGEOS = 21
161 changes: 161 additions & 0 deletions Source/Teensy/BlockDevice/TRBlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// SPDX-License-Identifier: MIT
// The register side of the TR block device, free of Arduino so a host test can drive it.
// The contract is docs/TR_Block_Device.md; offsets here are from the base that doc names.
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#define TRBLOCK_SIZE 256
#define TRBLOCK_WINDOW_SIZE 64
#define TRBLOCK_INFO_SIZE 5

enum TRBlockOffset
{
TRBlockCmd = 0x08,
TRBlockAddr0 = 0x09,
TRBlockAddr1 = 0x0a,
TRBlockPage = 0x0b,
TRBlockToken = 0x0c,
TRBlockStatus = 0x0d,
TRBlockEcho = 0x0e,
TRBlockId = 0x10,
TRBlockWindow = 0x40,
};

enum TRBlockCommand
{
TRBlockRead = 1,
TRBlockWrite = 2,
TRBlockFlush = 3,
TRBlockInfo = 4,
};

enum TRBlockStatusValue
{
TRBlockNeverRun = 0x00,
TRBlockBusy = 0x80,
TRBlockDone = 0x5a,
TRBlockNoImage = 0xe1,
TRBlockBadAddress = 0xe2,
TRBlockReadFailed = 0xe3,
TRBlockWriteFailed = 0xe4,
TRBlockReadOnly = 0xe5,
TRBlockBadCommand = 0xe6,
};

static const char TRBlockIdText[] = "TRB";
#define TRBLOCK_ID_SIZE (sizeof TRBlockIdText - 1)

// Where the ISR and the main loop meet: the ISR only fills registers and the window and starts a
// job, the main loop does the card's work.
struct TRBlock
{
uint8_t Buffer[TRBLOCK_SIZE];
uint8_t *Window; // the page of Buffer the window shows, kept by page writes so a read does no arithmetic
uint8_t Addr0, Addr1, Token;
uint8_t JobCmd, JobAddr0, JobAddr1, JobToken;
volatile uint8_t Status, Echo;
volatile bool Pending;
};

struct TRBlockBackend
{
void *Context;
uint8_t (*Transfer)(void *Context, bool Write, uint8_t Addr0, uint8_t Addr1, uint8_t *Block);
uint8_t (*Info)(void *Context, uint8_t *Out); // TRBLOCK_INFO_SIZE bytes
uint8_t (*Flush)(void *Context);
};

// ISR and main loop run on one core, so only the compiler's ordering matters
#define TRBLOCK_ORDER() __atomic_signal_fence(__ATOMIC_SEQ_CST)

static inline void TRBlockReset(struct TRBlock *Dev)
{
memset((void *)Dev, 0, sizeof *Dev);
Dev->Window = Dev->Buffer;
}

#define TRBLOCK_UNSERVED (-1)

// The IO ISR's side: a read answers from the window or a register, else TRBLOCK_UNSERVED
static inline int TRBlockReadAt(const struct TRBlock *Dev, uint8_t Offset)
{
if (Offset >= TRBlockWindow)
{
if (Offset >= TRBlockWindow + TRBLOCK_WINDOW_SIZE) return TRBLOCK_UNSERVED;
return Dev->Window[Offset - TRBlockWindow];
}
if (Offset == TRBlockStatus) return Dev->Status;
if (Offset == TRBlockEcho) return Dev->Echo;
if ((uint8_t)(Offset - TRBlockId) < TRBLOCK_ID_SIZE) return (uint8_t)TRBlockIdText[Offset - TRBlockId];
return TRBLOCK_UNSERVED;
}

// ...and writes go to registers or the window. The caller reads the data byte only when this says
// the offset takes one.
static inline bool TRBlockTakes(uint8_t Offset)
{
return (Offset >= TRBlockCmd && Offset <= TRBlockToken) ||
(Offset >= TRBlockWindow && Offset < TRBlockWindow + TRBLOCK_WINDOW_SIZE);
}

static inline void TRBlockWriteAt(struct TRBlock *Dev, uint8_t Offset, uint8_t Data)
{
bool Busy = Dev->Status == TRBlockBusy;

if (Offset >= TRBlockWindow)
{
if (Offset < TRBlockWindow + TRBLOCK_WINDOW_SIZE && !Busy) Dev->Window[Offset - TRBlockWindow] = Data;
return;
}
if (Offset == TRBlockAddr0) Dev->Addr0 = Data;
else if (Offset == TRBlockAddr1) Dev->Addr1 = Data;
else if (Offset == TRBlockPage) Dev->Window = Dev->Buffer + (Data & 3) * TRBLOCK_WINDOW_SIZE;
else if (Offset == TRBlockToken) Dev->Token = Data;
else if (Offset == TRBlockCmd && !Busy)
{
Dev->JobCmd = Data;
Dev->JobAddr0 = Dev->Addr0;
Dev->JobAddr1 = Dev->Addr1;
Dev->JobToken = Dev->Token;
TRBLOCK_ORDER();
Dev->Status = TRBlockBusy;
TRBLOCK_ORDER();
Dev->Pending = true;
}
}

static uint8_t TRBlockRun(struct TRBlock *Dev, const struct TRBlockBackend *Backend)
{
if (!Backend || !Backend->Context) return TRBlockNoImage;
switch (Dev->JobCmd)
{
case TRBlockRead:
return Backend->Transfer(Backend->Context, false, Dev->JobAddr0, Dev->JobAddr1, Dev->Buffer);
case TRBlockWrite:
return Backend->Transfer(Backend->Context, true, Dev->JobAddr0, Dev->JobAddr1, Dev->Buffer);
case TRBlockFlush:
return Backend->Flush(Backend->Context);
case TRBlockInfo:
return Backend->Info(Backend->Context, Dev->Buffer);
}
return TRBlockBadCommand;
}

// The main loop's side: runs a started command, true if there was one. The echo is published
// before the status, so a status that is not busy always comes with its token.
static inline bool TRBlockService(struct TRBlock *Dev, const struct TRBlockBackend *Backend)
{
uint8_t Result;

if (!Dev->Pending) return false;
TRBLOCK_ORDER();
Result = TRBlockRun(Dev, Backend);
Dev->Pending = false;
TRBLOCK_ORDER();
Dev->Echo = Dev->JobToken;
TRBLOCK_ORDER();
Dev->Status = Result;
return true;
}
65 changes: 65 additions & 0 deletions Source/Teensy/BlockDevice/TRBlockImage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
// A CBM disk image (D64, D71, D81) as the block device's backend: the track and sector the driver
// sends become an offset in the image file.
#pragma once
#include "../GEOS/GeosDiskPatch.h"
#include "TRBlock.h"

#define TRBLOCK_IMAGE_WRITABLE 0x01

struct TRBlockImage
{
const struct GeosFormat *Format;
bool Writable;
void *Context;
bool (*Read)(void *Context, uint32_t Offset, uint8_t *Block);
bool (*Write)(void *Context, uint32_t Offset, const uint8_t *Block);
bool (*Flush)(void *Context);
};

static inline bool TRBlockImageHasSector(const struct GeosFormat *Format, uint8_t Track, uint8_t Sector)
{
return Track >= 1 && Track <= Format->Tracks && Sector < GeosSectorsOnTrack(Format, Track);
}

FLASHMEM static uint8_t TRBlockImageTransfer(void *Context, bool Write, uint8_t Track, uint8_t Sector, uint8_t *Block)
{
struct TRBlockImage *Image = (struct TRBlockImage *)Context;
uint32_t Offset;

if (!Image->Format) return TRBlockNoImage;
if (!TRBlockImageHasSector(Image->Format, Track, Sector)) return TRBlockBadAddress;
Offset = GeosOffset(Image->Format, Track, Sector);
if (!Write) return Image->Read(Image->Context, Offset, Block) ? TRBlockDone : TRBlockReadFailed;
if (!Image->Writable) return TRBlockReadOnly;
return Image->Write(Image->Context, Offset, Block) ? TRBlockDone : TRBlockWriteFailed;
}

FLASHMEM static uint8_t TRBlockImageInfo(void *Context, uint8_t *Out)
{
struct TRBlockImage *Image = (struct TRBlockImage *)Context;
uint32_t Blocks;

if (!Image->Format) return TRBlockNoImage;
Blocks = Image->Format->Size / GEOS_SECTOR_SIZE;

Out[0] = (uint8_t)(Image->Format - GeosFormats + 1);
Out[1] = Image->Writable ? TRBLOCK_IMAGE_WRITABLE : 0;
Out[2] = (uint8_t)Blocks;
Out[3] = (uint8_t)(Blocks >> 8);
Out[4] = (uint8_t)(Blocks >> 16);
return TRBlockDone;
}

FLASHMEM static uint8_t TRBlockImageFlush(void *Context)
{
struct TRBlockImage *Image = (struct TRBlockImage *)Context;

if (!Image->Format) return TRBlockNoImage;
return Image->Flush(Image->Context) ? TRBlockDone : TRBlockWriteFailed;
}

static inline struct TRBlockBackend TRBlockImageBackend(struct TRBlockImage *Image)
{
return (struct TRBlockBackend){ Image, TRBlockImageTransfer, TRBlockImageInfo, TRBlockImageFlush };
}
7 changes: 6 additions & 1 deletion Source/Teensy/DriveDirLoad.ino
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ FLASHMEM void HandleExecution()
return;
}

if (MenuSelCpy.ItemType == rtGEOS)
{
if (!LaunchGeos((const struct GeosLauncher*)MenuSelCpy.Code_Image, &MenuSelCpy)) return;
}

SendMsgPrintfln("%s", MenuSelCpy.Name);
if (MenuSelCpy.ItemType == rtFileCrt)
{ //load the CRT into RAM
Expand Down Expand Up @@ -322,7 +327,7 @@ FLASHMEM void HandleExecution()

else
{ //non-CRT: copy the whole thing from flash into the RAM1 buffer
memcpy(RAM_Image, MenuSelCpy.Code_Image, MenuSelCpy.Size);
if (MenuSelCpy.Code_Image != RAM_Image) memcpy(RAM_Image, MenuSelCpy.Code_Image, MenuSelCpy.Size);
MenuSelCpy.Code_Image = RAM_Image;
}
SendMsgPrintfln("Copied to RAM");
Expand Down
Loading
Loading