65816-llvm-mos/demos/rsrcProbe.c
Scott Duensing 09f7405362 Updates
2026-06-03 16:08:42 -05:00

137 lines
4.6 KiB
C

// rsrcProbe.c - Phase 3.4 real Resource Manager smoke probe.
//
// Replaces the stub-only probe. Builds a tiny in-memory .rsrc fixture,
// registers it with mfsRegister, opens it via openResourceFile, loads
// a known rText resource, and verifies the bytes match the expected
// payload. This exercises the real parser path top-to-bottom without
// needing a ProDOS resource fork.
//
// Markers (page-1 direct page, per cursorProbe convention):
// $70 := 0x99 end-of-main success sentinel
// $71 := 0x01 if openResourceFile succeeded (refnum != 0)
// $72 := 0x01 if loadResource returned a non-NULL handle whose
// bytes match "HELLO" and size is 5
// $73 := 0x01 if loadResource second call returned the SAME handle
// (cache hit) and closeResourceFile returned RES_OK
//
// Build: bash demos/build.sh rsrcProbe
// Run: bash scripts/runViaFinder.sh demos/rsrcProbe.omf \
// --check 0x70=0x99 0x71=0x01 0x72=0x01 0x73=0x01
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "iigs/resource.h"
// rResourceMap fixture: header + 5-byte rText payload + one rIndex entry.
//
// Header (24 bytes, little-endian):
// rmVersion = 0x0000
// rmToIndex = 0x0000001D (29)
// rmFileNum = 0
// rmID = 0
// rmIndexSize = 0x00000014 (20 bytes = 1 entry)
// rmIndexUsed = 0x00000001
// rmFreeListSize = 0
// rmFreeListUsed = 0
// rmPad = 0
// Payload (5 bytes) at offset 24: "HELLO"
// rIndex entry (20 bytes) at offset 29:
// rType = 0x8014 (rText)
// rID = 0x00000001
// rOffset = 0x00000018 (24)
// rAttr = 0
// rSize = 0x00000005
// rHandle = 0
static const uint8_t kFixture[49] = {
// header
0x00, 0x00, // rmVersion
0x1D, 0x00, 0x00, 0x00, // rmToIndex = 29
0x00, 0x00, // rmFileNum
0x00, 0x00, // rmID
0x14, 0x00, 0x00, 0x00, // rmIndexSize = 20
0x01, 0x00, 0x00, 0x00, // rmIndexUsed = 1
0x00, 0x00, // rmFreeListSize
0x00, 0x00, // rmFreeListUsed
0x00, 0x00, // rmPad
// payload at offset 24: "HELLO"
0x48, 0x45, 0x4C, 0x4C, 0x4F,
// rIndex entry at offset 29
0x14, 0x80, // rType = 0x8014
0x01, 0x00, 0x00, 0x00, // rID = 1
0x18, 0x00, 0x00, 0x00, // rOffset = 24
0x00, 0x00, // rAttr
0x05, 0x00, 0x00, 0x00, // rSize = 5
0x00, 0x00, 0x00, 0x00 // rHandle
};
static const char kFixturePath[] = "rsrc.fixture";
static const char kExpectedText[] = "HELLO";
static const uint32_t kExpectedSize = 5;
int main(void) {
volatile uint8_t *mark0 = (volatile uint8_t *)0x70;
volatile uint8_t *mark1 = (volatile uint8_t *)0x71;
volatile uint8_t *mark2 = (volatile uint8_t *)0x72;
volatile uint8_t *mark3 = (volatile uint8_t *)0x73;
*mark0 = 0x10;
*mark1 = 0x00;
*mark2 = 0x00;
*mark3 = 0x00;
// Stage the fixture as a read-only memory-backed file. Cast away
// const for the mfsRegister buffer pointer; the resource manager
// only ever reads.
if (mfsRegister(kFixturePath, (void *)kFixture, sizeof(kFixture), sizeof(kFixture), 0) != 0) {
while (1) {
}
}
resourceProbeInit();
int rcOpen = 0;
ResourceRefNumT ref = openResourceFile(kFixturePath, 0, 0, &rcOpen);
if (ref != 0 && rcOpen == RES_OK) {
*mark1 = 0x01;
}
int rcLoad = 0;
void **h = loadResource(RES_TYPE_RTEXT, 1, &rcLoad);
if (h && rcLoad == RES_OK) {
const uint8_t *bytes = (const uint8_t *)*h;
uint32_t sz = getResourceSize(h);
int match = (sz == kExpectedSize);
if (match) {
for (uint32_t i = 0; i < kExpectedSize; i++) {
if (bytes[i] != (uint8_t)kExpectedText[i]) {
match = 0;
break;
}
}
}
if (match) {
*mark2 = 0x01;
}
}
// Second load - cache hit must return the SAME handle. Then
// close the file, which must report RES_OK.
int rcLoad2 = 0;
void **h2 = loadResource(RES_TYPE_RTEXT, 1, &rcLoad2);
int sameHandle = (h2 == h && h2 != 0);
int rcClose = closeResourceFile(ref);
if (sameHandle && rcClose == RES_OK) {
*mark3 = 0x01;
}
*mark0 = 0x99;
while (1) {
}
return 0;
}