86 lines
2.9 KiB
C
86 lines
2.9 KiB
C
// qdProbe.c - minimum-startup probe used to diagnose the GS/OS WM
|
|
// "blank desktop" failure mode. Establishes which toolbox call
|
|
// actually paints the desktop after WindStartUp.
|
|
//
|
|
// Result (2026-05-16): WindStartUp does NOT paint. Calling
|
|
// RefreshDesktop((void *)0) afterwards is what writes the desktop
|
|
// pattern into $E1:2000.. Verified by ZP probe markers ($80..$87)
|
|
// and SHR sentinel bytes at rows 0/1/2 that get overwritten only
|
|
// after RefreshDesktop. See [[orca-window-render-broken]] +
|
|
// [[loader-creloc-threshold]] memories.
|
|
//
|
|
// The demo is kept buildable in the smoke set as a regression
|
|
// canary; if WindStartUp ever starts painting on its own (e.g. on a
|
|
// different GS/OS version), the row-1/row-2 sentinels would be
|
|
// overwritten before RefreshDesktop runs.
|
|
//
|
|
// Probe markers (read via `scripts/probeQdStartup.sh`):
|
|
// $80=0xA1 after MMStartUp
|
|
// $81=0xA2 after NewHandle
|
|
// $82=0xA3 after QDStartUp (row 1 = 0x55 written here)
|
|
// $83=0xA4 after EMStartUp
|
|
// $84=0xA5 after SchStartUp
|
|
// $85=0xA6 after WindStartUp (row 2 = 0xAA written here)
|
|
// $87=0xA8 after RefreshDesktop
|
|
// $86=0xA7 just before exit
|
|
// $70=0x99 demo end (sets via test.sh)
|
|
|
|
#include "iigs/toolbox.h"
|
|
|
|
|
|
static unsigned short blockAddrLo(void *handle) {
|
|
return (unsigned short)(unsigned long)*(void **)handle;
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
// Paint a "before any toolbox call" marker into SHR row 0.
|
|
{
|
|
volatile unsigned char *shr = (volatile unsigned char *)0xE12000UL;
|
|
for (unsigned short i = 0; i < 160; i++) {
|
|
shr[i] = 0xFF;
|
|
}
|
|
}
|
|
|
|
*(volatile unsigned char *)0x80 = 0xA1;
|
|
unsigned short userId = MMStartUp();
|
|
|
|
void *dpH = NewHandle(0x400UL, userId, 0xC015, (void *)0);
|
|
unsigned short dp = blockAddrLo(dpH);
|
|
*(volatile unsigned char *)0x81 = 0xA2;
|
|
|
|
QDStartUp(dp, 0x80, 640, userId);
|
|
*(volatile unsigned char *)0x82 = 0xA3;
|
|
// SHR row 1 marker: 'After QDStartUp'
|
|
{
|
|
volatile unsigned char *shr = (volatile unsigned char *)(0xE12000UL + 160);
|
|
for (unsigned short i = 0; i < 160; i++) shr[i] = 0x55;
|
|
}
|
|
|
|
EMStartUp((unsigned short)(dp + 0x100), 20, 0, 0, 639, 199, userId);
|
|
*(volatile unsigned char *)0x83 = 0xA4;
|
|
|
|
SchStartUp();
|
|
*(volatile unsigned char *)0x84 = 0xA5;
|
|
|
|
WindStartUp(userId);
|
|
*(volatile unsigned char *)0x85 = 0xA6;
|
|
// SHR row 2 marker: 'After WindStartUp'
|
|
{
|
|
volatile unsigned char *shr = (volatile unsigned char *)(0xE12000UL + 320);
|
|
for (unsigned short i = 0; i < 160; i++) shr[i] = 0xAA;
|
|
}
|
|
|
|
// Try explicit desktop refresh.
|
|
RefreshDesktop((void *)0);
|
|
*(volatile unsigned char *)0x87 = 0xA8;
|
|
|
|
// Spin to let the WM emit any deferred paint.
|
|
for (unsigned long i = 0; i < 200000UL; i++) {
|
|
__asm__ volatile ("nop");
|
|
}
|
|
|
|
*(volatile unsigned char *)0x86 = 0xA7;
|
|
*(volatile unsigned char *)0x70 = 0x99;
|
|
return 0;
|
|
}
|