Firmware 4.03 re-disassembly of the drawup bodies fixes three
transliteration errors:
- Option1Flags[1] is 0x3000, not 0x2000: the option1 jump table at
0x37fcc routes index 1 to case code that ors 0x2000 then falls into
or 0x1000.
- Sealed paths run the shared error epilogue (store at frame+4 and
invoke the registered callback), like every other error path; use
DrawupRecordError instead of a bare return.
- DrawupPoolAllocate returns memory + completingNodeIndex*slotSize
(0x1bcc0 marks slots start..start+count but returns the node whose
span finished the run), not the run's first slot.
The 13.42 emulator report matches on all three; its callback
suppression and +0x20 pool entries are firmware differences, not
deviations here.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Firmware 4.03 bodies at 0x20cb0 (image) and 0x20f50 (pattern) recovered:
frame magic/sticky/parameter checks with error store at +4 and hook,
record-pool u16 free-run allocation under the pool mutex, 0x80 record
header (type 0x40/0x50, sequence, payload at +0x80), descriptor memcpy
of mode bytes, and same-sequence queue append bumping frame+0x28.
libSceFont links libkernel for scePthreadMutexLock/Unlock; guest test
covers validation, record bytes, queue order and the allocator.
Firmware 4.03 body at 0x20f50 takes ten integer arguments with the\noutput pointer last - the PPSA20397 libSceFontGsm.prx caller rotates\nsix registers and pushes four stack arguments, no float registers.\nUpdate the declaration, stub and signature assertion, and record the\nverified offsets and record/queue semantics in the debt file.