Firmware Fn 0x1f95d0 - krcenov/RNS510-Map-Viewer GitHub Wiki
0x1f95d0 — unnamed
Part of Firmware Reversing.
- File offset:
0x1f95d0 - VA:
0xf6a872c4(= 0x1f95d0 + 0xf688dcf4) - Status: 🟢 Fully traced (prologue to
blr) - Real name source: not found in the symbol table under any name searched so far
History
The project's oldest lead: found via a Unicorn-emulator candidate
classifier searching for functions reading mg4's id/byte1/
length fields (from a pool of 7,757 real function-prologue
candidates). Real, complete, understood function — just no confirmed
compiler-assigned name.
Disassembly
0x1f95d0: stwu r1, -0x40(r1)
0x1f95d4: mflr r0
0x1f95d8: stw r21, 0x14(r1)
0x1f95dc: stw r22, 0x18(r1)
0x1f95e0: stw r23, 0x1c(r1)
0x1f95e4: stw r24, 0x20(r1)
0x1f95e8: stw r25, 0x24(r1)
0x1f95ec: stw r26, 0x28(r1)
0x1f95f0: stw r27, 0x2c(r1)
0x1f95f4: stw r28, 0x30(r1)
0x1f95f8: stw r29, 0x34(r1)
0x1f95fc: stw r30, 0x38(r1)
0x1f9600: stw r31, 0x3c(r1)
0x1f9604: stw r0, 0x44(r1)
0x1f9608: mr r29, r3 ; arg1 = seg_list-shaped record ptr
0x1f960c: mr r27, r4 ; arg2 = output param
0x1f9610: lhz r3, 0(r29) ; record+0 = "id"
0x1f9614: lbz r4, 2(r29) ; record+2 = "byte1"
0x1f9618: li r26, 0xff
0x1f961c: li r25, 0
0x1f9620: bl 0x1f6c64
0x1f9624: li r30, 0
0x1f9628: lwz r4, 4(r29) ; record+4 = "length" (4-byte field)
0x1f962c: li r21, 0
0x1f9630: bl 0x1f70d0
0x1f9634: mr r28, r3
0x1f9638: lhz r4, 8(r29)
0x1f963c: bl 0x1f7738
0x1f9640: clrlwi r9, r28, 0x10
0x1f9644: clrlwi r0, r3, 0x10
0x1f9648: xori r9, r9, 0xffff
0x1f964c: xori r0, r0, 0xffff
0x1f9650: neg r9, r9
0x1f9654: neg r0, r0
0x1f9658: srwi r9, r9, 0x1f
0x1f965c: srwi r0, r0, 0x1f
0x1f9660: and. r11, r9, r0
0x1f9664: beq 0x1f9678
0x1f9668: lis r9, -0x95a
0x1f966c: addi r9, r9, -0xc48 ; table A base (byte-flag lookup)
0x1f9670: lbzx r0, r9, r3
0x1f9674: rlwinm r21, r0, 0x1f, 0x1f, 0x1f ; extract low bit
0x1f9678: cmpwi r21, 0
0x1f967c: beq 0x1f9828
0x1f9680: mulli r0, r3, 0x78 ; index * 0x78 (120-byte stride)
0x1f9684: lis r9, -0x95b
0x1f9688: addi r31, r9, 0x7878 ; table B base (0x78-byte records)
0x1f968c: add r29, r0, r31
0x1f9690: lis r9, -0x968
0x1f9694: lhz r3, 4(r29)
0x1f9698: addi r0, r9, -0x6b4
0x1f969c: mtlr r0
0x1f96a0: addi r4, r1, 8
0x1f96a4: blrl ; virtual call
0x1f96a8: lbz r0, 8(r1)
0x1f96ac: cmpwi r0, 0
0x1f96b0: bne 0x1f96c4
0x1f96b4: lhz r0, 0x66(r29)
0x1f96b8: andi. r25, r0, 1
0x1f96bc: beq 0x1f9774
0x1f96c0: lbz r26, 6(r29)
0x1f96c4: cmpwi r25, 0
0x1f96c8: beq 0x1f9774
0x1f96cc: mulli r11, r28, 0x60 ; index * 0x60 (96-byte stride)
0x1f96d0: lis r9, -0x95b
0x1f96d4: addi r9, r9, 0x1878 ; table C base
0x1f96d8: add r11, r11, r9
0x1f96dc: lha r3, 0x5c(r11)
0x1f96e0: cmpwi r3, -1
0x1f96e4: beq 0x1f9774
0x1f96e8: lis r9, -0x95a
0x1f96ec: lis r11, -0xd8
0x1f96f0: addi r22, r9, -0xc48
0x1f96f4: addi r23, r11, 0x1538
0x1f96f8: lis r24, -0x960
0x1f96fc: lis r25, -0x960
0x1f9700: mulli r9, r3, 0x78
0x1f9704: mr r29, r9
0x1f9708: add r9, r9, r31
0x1f970c: lhz r0, 0x66(r9)
0x1f9710: andi. r11, r0, 1
0x1f9714: beq 0x1f975c
0x1f9718: lbz r0, 6(r9)
0x1f971c: cmpw r26, r0
0x1f9720: bne 0x1f975c
0x1f9724: lbzx r0, r22, r3
0x1f9728: andi. r11, r0, 2
0x1f972c: bne 0x1f975c
0x1f9730: lis r3, 0x6a14
0x1f9734: mtlr r23
0x1f9738: ori r3, r3, 0x202
0x1f973c: lhz r0, 4(r9)
0x1f9740: addi r4, r24, -0x1cf0
0x1f9744: sth r0, 0(r27) ; write result to *arg2
0x1f9748: addi r5, r25, -0x1cc4
0x1f974c: mr r6, r26
0x1f9750: li r30, 1
0x1f9754: crclr cr1eq
0x1f9758: blrl ; another virtual call
0x1f975c: add r9, r29, r31
0x1f9760: lha r3, 0x74(r9) ; "next" pointer / chain link
0x1f9764: cmpwi r3, -1
0x1f9768: beq 0x1f9774
0x1f976c: cmpwi r30, 0
0x1f9770: beq 0x1f9700 ; loop: walk the chain
0x1f9774: cmpwi r30, 0
0x1f9778: bne 0x1f9828
0x1f977c: mr r3, r28
0x1f9780: bl 0x1fa8d8
0x1f9784: cmpwi r3, -1
0x1f9788: beq 0x1f97a4
(the function continues to a real blr around 0x1f9858, restoring
r21-r31 in the standard way — omitted here for length, same
epilogue shape as getId.)
Analysis
Reads id, byte1, and length from arg1 — exactly mg4's
already-cracked seg_list record layout (research/ map_compressed_reader.py). Walks 3 different lookup tables:
- resolves
byte1(+2) through a byte-flag table (table A), extracting its low bit, - resolves
length(+0) through a second cache table (table B, 0x78-byte records), - uses the resolved index to walk a THIRD table (
table C, 0x60-byte records) via a-1-terminated linked chain (nextpointer at record offset 0x74,0x1f9760/0x1f9770), testing 2 different flag bits (&1,&2) at each step.
On a match, writes a halfword (record offset 4) into the function's own
2nd argument and calls a formatting/lookup routine tagged with a fixed
constant 0x6a140202. Consistent with a name/label or junction-
connectivity resolver — byte1 acts as a lookup KEY feeding a
multi-table resolution chain, not a standalone boolean read directly
off the struct. This refines (does not overturn) the project's
already-established "divided-road signal" correlation for byte1: the
correlation may be a downstream EFFECT of whatever byte1 indexes
into, not a direct flag bit read in isolation.
table C's own base (0xf6a51878 as a VA) resolves — via the
recovered load base — to the exact same file offset as a real,
independently-confirmed UI button-label table
("PLAY...SEARCHBACK...SEARCHFOR...STOP..."), treated here as a
0x60-byte-stride struct array (name + binary fields per record), not
flat padded strings — a real named-item descriptor table.
Caller
Not found. 3 independent methods, full 24MB region, plus a whole-file literal-pointer scan — genuine dead end.