The Apple Video Decoder (AVD) is an oddball. Fellow accelerator engines of comparable, if not less, complexity (Video Encoder, Neural Engine) come with a beefy ARM64 coprocessor running 15MiB RTOS firmware. Perhaps the problem lies at the core — for all the complexity of video codecs, AVD’s coprocessor is the 32-bit no-MMU ARM Cortex-M3 (CM3).
Setup
J293AP, AVD revision “Viola”.
Supports AVC, HEVC, AV1, VP9 (codenamed “Longhorn”/”Lghrn”/”Lgh” for reasons beyond me).
Test input is a dead simple red 128×64 x264 (hi DCP guy) single-frame “video”.
ffmpeg -f lavfi -i "color=c=0xff0000" -s 128x64 -r 1 -c:v libx264 -crf 31 -t 1 -pix_fmt yuv420p test.h264
Which looks like:
NALU bytepos: [0, 31]
NALU offset: 0 Bytes
NALU length: 32 Bytes (including start code)
NALU type: 7 (Sequence parameter set)
NALU bytes:
00000000: 0000 0001 6764 000a acd9 4209 bff0 0020 ....gd....B....
00000010: 0031 0000 0300 0100 0003 0002 0f12 2596 .1............%.
SPS (payload size: 25.0 Bytes)
NALU bytepos: [32, 41]
NALU offset: 32 Bytes
NALU length: 10 Bytes (including start code)
NALU type: 8 (Picture parameter set)
NALU bytes:
00000000: 0000 0001 68eb e152 c8b0 ....h..R..
PPS (payload size: 5.0 Bytes)
NALU bytepos: [730, 778]
NALU offset: 730 Bytes
NALU length: 49 Bytes (including start code)
NALU type: 5 (Coded slice of an IDR picture)
NALU bytes:
00000000: 0000 0165 8884 0015 fffe e103 f814 cf7b ...e...........{
00000010: f98c 6add 5165 a615 cb91 b712 974c d9f3 ..j.Qe.......L..
00000020: 9042 2792 45b1 e374 db60 b76b bf34 8003 .B'.E..t.`.k.4..
00000030: d7 .
CodedSliceIDR (payload size: 45.0 Bytes)
SPS+PPS change, keyframes, frame order, pixel formats, tiling, scaling, and basically everything other than getting a wall of 0x51 (Y), 0x5a (U), and 0xf0 (V) pixels is a later problem.
Memory Map
Pointers in one address space is hard. Let’s make that five.
# dart-stream-1 (0x0..0xb83fff)
00004000: 027def15 00000001 00000010 00000000 00000001 deadcafe 00010101 00000001
00004020: 0008b4c0 00000000 0007000f 01002881 00000000 2db032e0 01000000 003f007f
00004040: 00000000 00100000 000003de 00000000 00000000 003f007f 0030000a 00000040
00004060: 00001080 000020c0 00003100 00004140 00005180 000061c0 00100000 00100000
00004080: 00100000 00100000 00100000 00100000 00100000 00000000 00000000 000080c0
000040a0: 00008140 000081c0 00008240 00000000 00000000 00000000 000082c0 000074c0
000040c0: 0000e6d0 0000e680 0000e6fa 0000e6d2 00000000 00000000 00000000 00000000
00004200: 00000000 00000000 00000000 00000000 000073c1 000073e1 00000008 00000008
00004280: 00000000 01de28b5 00000000 00000000 00000000 00000000 00000000 00000000
00004460: 00000000 00000000 01de28b5 00000000 00000000 00000000 00000000 00000000
00004640: 00000000 00000000 00000000 00764099 00000000 00000000 00000000 00000000
000046c0: 00000000 00000000 00124111 00000000 00000000 00000000 00000000 00000000
000046e0: 03adf199 2d020000 00000000 00000000 00000000 00000000 00000000 00000000
00004760: 00000000 00000000 00000000 2dd00040 00000000 00000000 00000000 00000000
00004a60: 00000000 00000000 00000000 00000000 2d902800 2da30000 00000000 2d800000
00004a80: 00000000 0074400a 00000028 00000000 00000000 00000000 00000000 00000000
0008f4c0: 0021fcb5 00000000 00000000 000f0000 00000000 0074400a 00000028 00000000
# piodma (0x269070000..0x269073fff)
01070000: 00000000 00000040 00000000 00040010 0000fff3 0000fff3 0000fff3 0000fff0
01070040: 00000000 00000000 00000000 0008f4c0 00000000 00000a10 00000000 00000000
01070080: 00000000 00000000 00000000 00000000 0008f4c0 00000000 00000000 00000000
010700a0: 00000000 00000000 6908fcd4 00000002 00000000 00030000 00000000 00000000
010700c0: 00000000 00000000 03000000 00000003 00000000 00000000 00000000 00000000
010700e0: 00000003 00000000 00000000 0000019e 00000000 00000000 00000000 00000000
# cm3-sram (0x26908c000..0x269097fff)
0108c000: 6e69614d 746f6f62 454e6e49 00000000 454e6e49 00000001 6f636544 00000001
0108c020: 72467453 00000001 32567453 00000001 44707641 08800001 44707641 1100000d
0108c040: 44707641 22000012 44707641 42400004 44707641 48000006 4e707041 00020000
0108c060: 6e443256 ffffffff 6e443050 00010001 6e567746 8febab74 00000000 00000000
0108d080: 0108eb90 00000002 00000003 00000020 00000000 00000000 00000000 00000000
0108d0e0: 00000000 00000000 00000000 00000421 00000000 00004000 00000001 00010003
0108d100: 00000001 00000000 0108ef38 00004284 0108ef44 00004468 000046e0 0008f4c0
0108d120: 00000000 0108ef6c 0108f130 0108f18c 0000464c 000046c8 00000000 00000000
0108d140: 00000000 00000000 00000000 00000004 00000001 000038f5 00000000 00000000
0108e880: 00000000 00000000 00000000 00000001 00000001 00000401 00000000 00004000
0108e8a0: 00000001 00010003 00000001 00000000 0108ef38 00004284 0108ef44 00004468
0108e8c0: 000046e0 0008f4c0 00000000 0108ef6c 0108f130 0108f18c 0000464c 000046c8
0108ea00: 00000000 00000000 00000000 00000000 00000000 00000000 000003ff 00000000
0108ea20: 00000000 00000000 00000000 a18e8c0d ffffffff ffffffff ffffffff 00000000
0108eb80: 00000000 00000000 00000000 00000000 00000401 00000000 00004000 00000001
0108eba0: 00010003 00000001 00000000 0108ef38 00004284 0108ef44 00004468 000046e0
0108ebc0: 0008f4c0 00000000 0108ef6c 0108f130 0108f18c 0000464c 000046c8 00000000
0108ee80: 00000000 00000000 00000000 00000000 04020002 00020002 04020002 04020002
0108eea0: 04020002 00070007 00070007 00070007 00070007 00070007 04020002 00020002
0108eec0: 04020002 04020002 04020002 00070007 00070007 00070007 00070007 00070007
0108eee0: 04020002 02020202 04020002 04020002 04020202 00070007 00070007 00070007
0108ef00: 00070007 00070007 00000000 00000000 00000000 00000001 00000010 00000000
0108ef20: 00000001 deadcafe 00010101 00000001 0008b4c0 00000000 0007000f 01002881
0108ef40: 00000000 2db032e0 01000000 003f007f 00000000 00100000 000003de 00000000
0108ef60: 00000000 003f007f 0030000a 00000040 00001080 000020c0 00003100 00004140
0108ef80: 00005180 000061c0 00100000 00100000 00100000 00100000 00100000 00100000
0108efa0: 00100000 00000000 00000000 000080c0 00008140 000081c0 00008240 00000000
0108efc0: 00000000 00000000 000082c0 000074c0 0000e6d0 0000e680 0000e6fa 0000e6d2
0108f120: 000073c1 000073e1 00000008 00000008 00000000 00000000 00000000 00000000
0108f180: 00000000 00000000 00000000 00000000 00000000 00000000 2d020000 00000000
0108f220: 2dd00040 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0108f520: 00000000 2d902800 2da30000 00000000 2d800000 00000000 0074400a 00000028
0108f540: 00000000 00000000 00000000 2d020000 00000000 00000000 00000000 00000000
0108f5c0: 00000000 00000000 00000000 00000000 00000000 2dd00040 00000000 00000000
0108f8c0: 00000000 00000000 00000000 00000000 00000000 00000000 2d902800 2da30000
0108f8e0: 00000000 2d800000 00000000 0074400a 00000028 00000000 00000000 00000000
0108fca0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000f0000
0108fcc0: 00000000 0074400a 00000028 00000000 00000000 00000000 00000000 00000000
0108fce0: 00000000 000f0000 00000000 0074400a 00000028 00000000 00000000 00000000
0108fd20: 00000000 00000000 00000000 00000000 00000000 000f0000 00000000 0074400a
0108fd40: 00000028 00000000 00000000 00000000 00000000 00000000 00000000 00000000
01098060: b93bffe7 0108d0ec 000a0001 2fa36de4 2fa36de4 000a0001 4be7ffff 4be7ffff
# dart-stream-0 (0x0..0x997fff)
00004000: 2db0b2e0 01000000 003f007f 00000000 0007000f 01002881 00100000 000003de
00004020: 04020002 04020002 00000000 00008140 000081c0 00008240 00070007 0000e6d0
00004040: 0000e680 0000e6fa 0000e6d2 000073c1 00000008 000073e1 00000008 00000000
00004060: 003f007f 00000000 2d902800 2da30000 2a000000 00003007 2d020000 01000000
00004080: 020c0000 0508a000 10428408 0c000001 2f080178 0c000001 2f0800b9 0c000001
000040a0: 2f000225 00800000 01000001 02041000 0508a000 10028408 0c000000 00800000
- PHWDS A111
- PHWDS ED11 / Slice Registers
- PHWDS A11
- DART stream 1
- PIODMA
- DART stream 0
- Firmware Logs
- Kext-Firmware IPC
- DMA Configuration
Humble first draft. Yes I rewrote it in HTML.
Physical/MMIO Map
Physical addresses are referred to by their offset from base.
Hits from mmio_sweep.py
after enabling CM3 power:
0000000 - 0004000 | avd[0] pmgr[36] | AXI2AF
0008000 - 000c000 | avd[0] pmgr[36] | Voltage/Temps, PMGR managed
1000000 - 1004000 | avd[0] | Power (not PMGR)
1010000 - 1014000 | avd[0] dart-avd[0] | DART
1020000 - 1024000 | avd[0] | Not used
1070000 - 1074000 | avd[0] | PIODMA
1080000 - 109c000 | avd[0] | CM3
1100000 - 1110000 | avd[0] | DMA/Decode ctrl
1400000 - 1404000 | avd[0] | Wrap, supposedly an IRQ too
Everything that concerns us lies between 0x1070000 and 0x1110000.
CM3 Physical Map (0x1080000 – 0x109c000)
1080000 - 108c000 | CM3 Code
108c000 - 1090000 | CM3 SRAM
1090000 - 1097e80 | CM3 SRAM but we pinky-promise to not touch it
1097e80 - 1098000 | CM3 System Regs (pls..)
1098000 - 109c000 | CM3 Private Peripheral Bus
CM3 memory has to be somewhere, but I didn’t think that’d be the registers. I guess it can’t be anywhere else. Only because this has been bothering me: if one is tasked with copying 48KiB of raw Cortex blob to a contiguous region of MMIO space — every time, because this range is flushed on a power-gated power domain (non-PMGR and not in the device tree btw) — would you not, at the very least, consider a 64-bit write?
[cpu5] MMIO: W.4 0x269080000 (avd[0], offset 0x1080000) = 0x1000c000
[cpu5] MMIO: W.4 0x269080004 (avd[0], offset 0x1080004) = 0x141
[cpu5] MMIO: W.4 0x269080008 (avd[0], offset 0x1080008) = 0x195
[cpu5] MMIO: W.4 0x26908000c (avd[0], offset 0x108000c) = 0x199
That would our MSP at 0x1000c000 (see CM3 aliases below) followed by VTOR. The firmware is embedded in the kext. I’m starting to miss RTKSTACKRTSTACK.
Now we can kick up CM3:
[cpu4] MMIO: W.4 0x269098008 (avd[0], offset 0x1098008) = 0xe // CM3 CLK enable
[cpu4] MMIO: W.4 0x269098010 (avd[0], offset 0x1098010) = 0x0 // reset
[cpu4] MMIO: W.4 0x269098048 (avd[0], offset 0x1098048) = 0x0 // reset
[cpu4] MMIO: W.4 0x269098010 (avd[0], offset 0x1098010) = 0x0 // reset again
[cpu4] MMIO: W.4 0x269098048 (avd[0], offset 0x1098048) = 0x0 // reset again
[cpu4] MMIO: W.4 0x269098050 (avd[0], offset 0x1098050) = 0x1 // more NVIC init stuff
[cpu4] MMIO: W.4 0x269098068 (avd[0], offset 0x1098068) = 0x1
[cpu4] MMIO: W.4 0x26909805c (avd[0], offset 0x109805c) = 0x1
[cpu4] MMIO: W.4 0x269098074 (avd[0], offset 0x1098074) = 0x1
[cpu4] MMIO: W.4 0x269098010 (avd[0], offset 0x1098010) = 0x2 // enable interrupts
[cpu4] MMIO: W.4 0x269098048 (avd[0], offset 0x1098048) = 0x8 // enable interrupts
CM3 Alias Map
0x00000000 - 0x3FFFFFFF | SRAM
0x40000000 - 0x4FFFFFFF | MMIO1: Peripheral
0x50000000 - 0x5FFFFFFF | MMIO2: Private Peripheral Bus
CM3 SRAM starts at 0x10000000 but the first 0xc000 is code (recall 0x1080000 – 0x108c000), hence the MSP 0x1000c000. You probably won’t get far trying to linearly map/translate CM3 SRAM alias addresses; just poke the physical address directly. MMIO1 maps “Not used”, “PIODMA”, “DMA”, and “Wrap” at +0x3f000000 (e.g. 0x1104084 -> 0x40104084). MMIO2 maps “CM3 Private Peripheral Bus” at +0x4ef78004 (e.g. 0x1098054 -> 0x50010058, off by one!). This is all in accordance with the CM3 spec.
Notice how the CM3 has less MMIO than we do. Everything the CM3 can do — and much more — we can do ourselves.
The Apple Way
CM3 IPC
The first 0x400 (I need to check; we’re off to a great start here) of CM3 SRAM is a FIFO used to “print” “logs”, a cryptic fourcc (0x44707641: “AvpD”) followed by another useless 4 bytes of god-knows-what variables.
# cm3-sram (0x26908c000..0x269097fff): firmware "logs"
0108c000: 6e69614d 746f6f62 454e6e49 00000000 MainbootInNE....
0108c010: 454e6e49 00000001 6f636544 00000001 InNE....Deco....
0108c020: 72467453 00000001 32567453 00000001 StFr....StV2....
0108c030: 44707641 08800001 44707641 1100000d AvpD....AvpD....
0108c040: 44707641 22000012 44707641 42400004 AvpD..."AvpD..@B
0108c050: 44707641 48000006 4e707041 00020000 AvpD...HAppN....
0108c060: 6e443256 ffffffff 6e443050 00010001 V2Dn....P0Dn....
The firmware command or mailbox message is a size 0x60 struct with the first 4 bytes reserved for a status flag and opcode, and the remaining space the arguments for each opcode handler (padded to 0x60). But we only have two opcodes, and the first opcode, which I’ve named AVD_CM3_CMD_INIT, takes void args, so, safe to say, 0x5c is the size of the args for the other opcode, AVD_CM3_CMD_DECODE. Here is an AVD_CM3_CMD_DECODE command queued in the “inbound queue” at index n=1
, addr 0x108eb30 + 0x60*n
:
# cm3-sram (0x26908c000..0x269097fff): inbound queue
0108eb90: 00000401 00000000 00004000 00000001 00010003 00000001 00000000 0108ef38
0108ebb0: 00004284 0108ef44 00004468 000046e0 0008f4c0 00000000 0108ef6c 0108f130
0108ebd0: 0108f18c 0000464c 000046c8 00000000
Poor man’s IPC: the kext writes the command directly into CM3 SRAM, then rings the “doorbell” by literally asserting NVIC with the physical offset of the command it just wrote to.
[cpu1] MMIO: W.4 0x269098054 (avd[0], offset 0x1098054) = 0x108eb90
CM3 jumps to the ISR at +0x619d (IRQ #4), which is the only ISR we care about. This handler starts by saving the ISR value (0x108eb90) into 0x108d080, then incrementing queue index/counts at 0x108d084/0x108d088, then deasserting the line. Now 0x108d080 is ***deferenced to copy the contents of the inbound mail into the “outbound queue” at 0x108d08c + 0x60*n
.
0108d080: 0108eb90 00000002 00000003 00000020 00000000 00000000 00000000 00000000
0108d0e0: 00000000 00000000 00000000 00000421 00000000 00004000 00000001 00010003
0108d100: 00000001 00000000 0108ef38 00004284 0108ef44 00004468 000046e0 0008f4c0
0108d120: 00000000 0108ef6c 0108f130 0108f18c 0000464c 000046c8 00000000 00000000
Then it’s an opcode switch case, the opcode being the 0x1 of 0x401. When the per-opcode handlers are done, CM3 flags the outbound mail status (bit 5 is “done, ok”). CM3 then raises an interrupt (not AIC, we’ll have to look at this) either by/after writing to 0x1098064 with the, once agian, the offset of the outbound mail for the kext to read.
[cpu1] MMIO: R.4 0x269098064 (avd[0], offset 0x1098064) = 0x108d0ec
Re: state of logs. The CM3 firmware obviously has no symbols or even any human-readable strings (even the 0x44707641 stuff is bitmasked). Fine. But the kext is dead silent too. Usually I start by gathering some logs, triggering error messages if I can’t, but the kext only ever prints the same two lines about userland “encryption”, which I think is about DRM, sadly.
AppleAVD: codecType: AVC, encryptionScheme 6, 128 x 64, tryAllFrames = 0, iChatUsage: 0, session: 0x12600f220
Six DRM schemes is impressive, seems like they’ve put a bit of work into that. Not relevant to us though, things have to be decrypted to get decoded. It only makes it slightly harder to trace back the input.
This is the most verbose log I’ve ever gotten, via hv_set_time_stealing(0, 1)
while messing up interrupt lines.
AppleAVD: ## [42] [40]
AppleAVD: [40]: clientID 0 cmdID 0 frameNumber -1 decodeBufferSize 0x00000000
AppleAVD: [41]: clientID 0 cmdID 1 frameNumber 1 decodeBufferSize 0x000b34c0
AppleAVD: SoftReset(): enter soft reset total_wait_time=(350 ms x 3)
AppleAVD: timeoutHandler(): Timeout source found! Core0 timeout!!
AppleAVD: timeoutHandler(): Decode lagging 0xfffffe2a45c04dc0 - CoreID: 0 (cnt = 4)
AppleAVD: ## [42] [40]
AppleAVD: [40]: clientID 0 cmdID 0 frameNumber -1 decodeBufferSize 0x00000000
AppleAVD: [41]: clientID 0 cmdID 1 frameNumber 1 decodeBufferSize 0x000b34c0
AppleAVD: SoftReset(): Already in SoftReset state...
AppleAVD: ################ACK HISTORY##########################
AppleAVD: Current index: [12]
AppleAVD: Index 0: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 1: cid 0 codec 0 cmd type 1, DECODE FRAME:32, ACK 1
AppleAVD: Index 2: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 3: cid 0 codec 0 cmd type 1, DECODE FRAME:33, ACK 1
AppleAVD: Index 4: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 5: cid 0 codec 0 cmd type 1, DECODE FRAME:34, ACK 1
AppleAVD: Index 6: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 7: cid 0 codec 0 cmd type 1, DECODE FRAME:35, ACK 1
AppleAVD: Index 8: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 9: cid 0 codec 0 cmd type 1, DECODE FRAME:36, ACK 1
AppleAVD: Index 10: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 11: cid 0 codec 0 cmd type 2, STOP:-1, ACK 1
AppleAVD: Index 12: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 13: cid 0 codec 0 cmd type 1, DECODE FRAME:22, ACK 1
AppleAVD: Index 14: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 15: cid 0 codec 0 cmd type 1, DECODE FRAME:23, ACK 1
AppleAVD: Index 16: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 17: cid 0 codec 0 cmd type 1, DECODE FRAME:24, ACK 1
AppleAVD: Index 18: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 19: cid 0 codec 0 cmd type 1, DECODE FRAME:25, ACK 1
AppleAVD: Index 20: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 21: cid 0 codec 0 cmd type 1, DECODE FRAME:26, ACK 1
AppleAVD: Index 22: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 23: cid 0 codec 0 cmd type 1, DECODE FRAME:27, ACK 1
AppleAVD: Index 24: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 25: cid 0 codec 0 cmd type 1, DECODE FRAME:28, ACK 1
AppleAVD: Index 26: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 27: cid 0 codec 0 cmd type 1, DECODE FRAME:29, ACK 1
AppleAVD: Index 28: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 29: cid 0 codec 0 cmd type 1, DECODE FRAME:30, ACK 1
AppleAVD: Index 30: cid 0 codec 0 cmd type 4, DECODE FRAME DONE:0, ACK 0
AppleAVD: Index 31: cid 0 codec 0 cmd type 1, DECODE FRAME:31, ACK 1
AppleAVD: ################ACK HISTORY##########################
AppleAVD: HardReset(): invalid cid -1 - Core0
AppleAVD: StatusLogging(): [DmaTop] 00000000 00000000 00000000 00000000
AppleAVD: StatusLogging(): [AvpCfg] 00000008 00003007 0000003f 00000028
AppleAVD: StatusLogging(): [Hv0Cfg] 00000000 00000000 00000000 00000000
AppleAVD: StatusLogging(): [Hv1Cfg] 00000000 00000000 00000000 00000000
AppleAVD: StatusLogging(): [DmaIRQ] 00000000
But this makes no sense. Both inbound/outbound queue wraps around at 8 (inbound 0x108eb30 – 0x108ee30). 0xb34c0 isn’t the “decodeBuffer” either. And what is “frameNumber -1”?? Why is everything turbo hard mode???
AVD_CM3_CMD_INIT
The kext queues the first command:
[cpu6] MMIO: W.4 0x269098054 (avd[0], offset 0x1098054) = 0x108eb30
No, I didn’t forget about what the command is. This command is completely zeroed because 1) it takes void args and 2) incidentally, its opcode is zero too: AVD_CM3_CMD_INIT. I don’t know if this is an optimization, but they don’t even pretend to write this command into the inbound queue. Seemingly they were ringing the doorbell on a nonexistent command, which confused me for a bit.
# cm3-sram (0x26908c000..0x269097fff)
0108c000: 6e69614d 746f6f62 454e6e49 00000000 6e567746 8febab74 00000000 00000000 | MainbootInNE....FwVnt...........
0108d080: 0108eb30 00000001 00000001 00000020 00000000 00000000 00000000 00000000 | 0........... ...................
0108ea00: 00000000 00000000 00000000 00000000 00000000 00000000 000003ff 00000000 | ................................
01093c80: 00000000 00000000 00000000 00000000 00000000 00000000 10101010 10101010 | ................................
01093ca0: 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 | ................................
01093cc0: 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 | ................................
...
01094040: 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 | ................................
01094060: 10101010 10101010 10101010 10101010 10101010 10101010 10101010 10101010 | ................................
01094080: 10101010 10101010 10101010 10101010 10101010 10101010 00000000 00000000 | ................................
01094140: 00000000 10000000 00000000 00000000 00000000 00000000 00000000 00000000 | ................................
010943e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000 | ................................
01094620: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000 | ................................
01094860: 00000000 00000000 00000000 00000000 00000004 00000000 00000000 00000000 | ................................
01094880: 00000000 00000000 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff | ................................
010948a0: ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff | ................................
010948c0: ffffffff ffffffff 10000000 00000000 00000000 00000000 00000000 00000000 | ................................
01094ac0: 00000000 00000000 10000000 00000001 00000000 00000000 00000000 00000000 | ................................
Notice the queue counts are incremented and the first (empty) outbound mail is flagged done. There’s nothing in this command so obviously it is codec-agnostic. The AVD_CM3_CMD_INIT handler sets some hardcoded tunables, including
- Memset some
1010101
s andffffffff
s throughout SRAM. Not very important considering everything works without it. - Write
0x10000000
in various locations around +0x1094400. This is used to mask physical offset -> CM3 SRAM alias address. Why this is dynamic I’m not sure. Why they need five copies of these I’m not sure either. - Write hard-coded DMA tunables. These are actually stored as the correct physical offset in the little firmware __DATA section, so they do a funny +0x3f000000. The emulator is a T8103 fork of R’s avd_emu.py (discussed later).
EMU: PC 000051d4: W32 @ 4010c044 value 00000040 EMU: PC 000051d4: W32 @ 4010c084 value 00400040 EMU: PC 000051d4: W32 @ 4010c244 value 00800034 ... EMU: PC 000051d4: W32 @ 4010cc44 value 044000c0
- This one is technically done by the kext but it fits in well here. The kext write32’s a stream of “DMA Configure” values directly into CM3 SRAM. These very much indeed concern DMA configuration, but not the way you think it does (i.e. these are hardware registers). You’d be surprised. We’ll visit these again. It’s written right before the doorbell but that order doesn’t matter. This feels like a hack.
# cm3-sram (0x26908c000..0x269097fff) 0108ee90: 04020002 00020002 04020002 04020002 04020002 00070007 00070007 00070007 0108eea0: 00070007 00070007 04020002 00020002 04020002 04020002 04020002 00070007 0108eec0: 00070007 00070007 00070007 00070007 04020002 02020202 04020002 04020002 0108eee0: 04020202 00070007 00070007 00070007 00070007 00070007
If we’re submitting to the firmware, we need to call AVD_CM3_CMD_INIT one-time at init or set (2), (3), and (4) ourselves. To decode ourselves we only need (3). I mean kinda (4) too, but, I mean, eh. We’ll get to it.
IOMMU
Each DART stream is its own private address space with its own page tables. AVD has two independent DMA controllers, each hooked up to DART stream 0 and DART stream 1 (DS0/DS1).
The kext foremost initializes two FIFO pools in IOMMU space — one in DS0 and one in DS1 — all at once (“burst map”). Both pools start at iova 0x4000 (null handling sucks) and skip 0x4000 between each block. The DS0 pool is block size 0x100000 7x. This 0x100000 DS0 block will later bounce the actual hardware decode stream (HWDS). The DS1 pool is block size 0xb4000 16x. Recall 0xb34c0 “decodeBuffer” from earlier. This is NOT a “decodeBuffer”, it is the kext-written/prepared PROTO-hardware decode stream (PHWDS) which forms the basis of the actual hardware decode stream. We’re at frame index #0, so both HWDS/PHWDS blocks are iova 0x4000. DS1 will only ever have this PHWDS pool, whereas DS0 is where we map all the input/output tiles to come.
Indeed, next up, the kext maps the IDR coded slice (i.e. input) at 0x744000 and maps surfaces for all of our intermediate and output tiles from there up. They also allocate a 0x10000 surface and bundle the SPS+PPS there, but this it doesn’t seem like it’s ever used by the hardware; that information seems to be encoded in the decode stream already.
# dart-stream-0 (0x0..0x997fff): IDR coded slice
00744000: 2e000000 00848865 e1feff15 cf14f803 6a8cf97b a66551dd b791cb15 d94c9712
00744020: 274290f3 e3b14592 b760db74 8034bf6b 0000d703 00000000 00000000 00000000
The kext then prepares the proto decode stream and writes it into the DS1 slot:
# dart-stream-1 (0x0..0xb83fff): PHWDS
00004000: 027def15 00000001 00000010 00000000 00000001 deadcafe 00010101 00000001
00004020: 0008b4c0 00000000 0007000f 01002881 00000000 2db032e0 01000000 003f007f
...
00004080: 00100000 00100000 00100000 00100000 00100000 00000000 00000000 000080c0
...
000046e0: 03adf199 2d020000 00000000 00000000 00000000 00000000 00000000 00000000
...
00080000: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00080020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
...
0008f4c0: 0021fcb5 00000000 00000000 000f0000 00000000 0074400a 00000028 00000000
They calls these “registers”, but from deadcafe/cafebabe it’s obvious that these are not what’s actually piped into the hardware. I won’t go into PHWDS much, but know it’s a macOS kext-firmware shared frame metadata struct — a 0.7MiB struct indeed. It also wildly differs per codec. And SoC. PHWDS roughly consists of codec-specific metadata (height, width, stride, pixfmt), the DS0 iovas we just mapped, kext-computed proto decode stream slices, and more DMA logic. Also, kext bloat. The giant gap in the middle would be the slots for all the slices, which happens to be pretty empty for our 128×64 case (look what happens when you make PHWDS a static struct).
Now to embark on the long, long journey — cross many address spaces — of how PHWDS becomes HWDS. To emphasize, how a proto decode command stream ends up in a completely different address space not-so-proto anymore. Spoiler, we take a layover in yet another address space.
PIODMA
PIODMA was the first thing I RE’d — and pretty quickly, too — because it was a name familiar from the ANE days. My guess is that ‘P’ stands for ‘Peripheral’, as in both detached from the IP and that it DMAs to -> peripheral/MMIO space. ANE’s PIODMA was specialized for fetching the ANE hardware command stream, one-way from DART (stream 0) to its configuration registers. ANE PIODMA is actually quite complex, and, if we really strech it, a decoder in its own right, because it parses and decompresses the ANE command stream “codec” (it’s just a stream deliminated by a word of type/count; though it gets some credibility as a codec because it’s patented, US20190340014A1). Seemingly AVD PIODMA would also play a critical role in command submission.
AVD PIODMA source is hooked up to DART stream one, which is already interesting (recall: no input/output there). And unlike ANE PIODMA, it’s just a straight memcpy from ds1_src_iova + 0x4
(where “src_iova” is written to the PIODMA “src_iova” hardware register) to the destination physical offset sourced from the first (dereferenced) word at “src_iova”. The transfer is triggered by a “PIODMA command” x & 0xff == 0x11
(e.g. 0xa11, 0xed11, 0x8a11) which dictates the number of bytes transferred. Other than that sneaky off by one, the logic is simple. A bit too simple.
AVD_CM3_CMD_DECODE
Memory snapshot after a successful firmware decode command:
# dart-stream-1 (0x0..0xb83fff): proto hardware decode stream
00004000: 027def15 00000001 00000010 00000000 00000001 deadcafe 00010101 00000001
000046e0: 03adf199 2d020000 00000000 00000000 00000000 00000000 00000000 00000000
0008f4c0: 0021fcb5 00000000 00000000 000f0000 00000000 0074400a 00000028 00000000
# cm3-sram (0x26908c000..0x269097fff): decode cmd @ inbound queue n=1
0108eb90: 00000401 00000000 00004000 00000001 00010003 00000001 00000000 0108ef38
0108ebb0: 00004284 0108ef44 00004468 000046e0 0008f4c0 00000000 0108ef6c 0108f130
0108ebd0: 0108f18c 0000464c 000046c8 00000000
# cm3-sram (0x26908c000..0x269097fff): sram post-decode cmd
0108ef10: 00000000 00000001 00000010 00000000 00000001 deadcafe 00010101 00000001
0108f190: 00000000 00000000 2d020000 00000000 2dd00040 00000000 00000000 00000000
0108fcb0: 00000000 00000000 00000000 000f0000 00000000 0074400a 00000028 00000000
0x27def15 & ~0x3fd0001 | 0x1080000 == 0x108ef14
0x3adf199 & ~0x3fd0001 | 0x1080000 == 0x108f198
0x021fcb5 & ~0x3fd0001 | 0x1080000 == 0x108fcb4
Notice AVD_CM3_CMD_DECODE args are just a list of PIODMAs to perform. The other stuff in the firmware command a kext IPC quirk we don’t care about, ignore that. Specifically, these PIODMAs:
-
PIODMA 0xa111 from DS1 src iova +0x0, 0x280 bytes.
EMU: PIODMA: src iova: 0x4000 cmd: 0xa111 word: 0x108fcb4 size: 0x280 EMU: PIODMA: copying 0x280 bytes to 0x108ef14 00000000: 00000001 00000010 00000000 00000001 00000010: deadcafe 00010101 00000001 0008b4c0
-
PIODMA 0xa11 from DS1 src iova +0x8b4c0, grand total of 0x14 bytes.
EMU: PIODMA: src iova: 0x8f4c0 cmd: 0xa11 word: 0x108fcb4 size: 0x14 EMU: PIODMA: copying 0x14 bytes to 0x108fcb4 00000000: 00000000 00000000 000f0000 00000000 00000010: 0074400a 00000028
-
PIODMA 0xed11 from DS1 src iova +0x6e0, 0x3a0 bytes.
EMU: PIODMA: src iova: 0x46e0 cmd: 0xed11 word: 0x3adf199 size: 0x3a0 EMU: PIODMA: copying 0x3a0 bytes to 0x108f198 00000000: 2d020000 00000000 00000000 00000000 00000010: 00000000 00000000 00000000 00000000
Repeat step 3 for each slice.
Now that we have copied at most 0xb4000 bytes of the proto decode stream from DART stream 1 to -> CM3 SRAM, byte-for-byte, CM3 can start doing some actual work. Well, CM3 can’t access DART space. While CM3 SRAM happens to reside in the AVD MMIO space, that space has absolutely nothing to do with the decode block. Turns out PIODMA is completely irrelevant too. In fact, we cannot PIODMA to the actual decode hardware registers (it faults), only to the CM3 range. So now we know DART stream 1 and PIODMA solely exists to chuck the work over to the firmware.
As to why they do this, and why they even use the CM3. I don’t know. I wouldn’t know. I don’t know the constraints they were under, but I’m sure they’ve made the best of it. And I say this because these people are not incompetent; unlike the video encoder, the driver-firmware is not flagrantly buggy and has pretty gracefully withstood all my (unintended) stress tests. From its existence alone it’s easy to call the firmware “bad” (like I did — “moronic m3 blob”), but if you actually look at it, it’s doing the best it can under its constraints. It’s just hampered at the architecture level.
As for us, we have options. We can bow to a 48KiB Cortex blob and all its idiosyncratic platform requirements from the non-PMGR power domains to the non-AIC interrupt line, do surgery on the kext/kernelcache and ship those non-iBoot blobs out to users without pissing anyone off (appleh13camerad: Electric Boogaloo), reverse-engineer a 0.7MiB macOS struct and somehow get that to work with the V4L2 framework, do that times four (codec), times six (SoC), oh, and, get that upstream.
Or we can decode it our own selves :)
Decode Hardware
The information below was obtained pretty damn squeaky cleanly, both out of my conscious efforts, but also that I had no alternative; I invite you to put the thing into Ghidra and see what you get. I RE’d most of this by looking ahead and stealing that decode submission doorbell. I triggered the stolen IRQ in the hypervisor console until I could reproduce the pre-IRQ environment myself (that is one winded way to say, “I could successfully send a firmware decode command”). With that, I damaged/fuzzed nearly every single parameter, seeing what causes a halt where, what comes before what, what depends on what, etc, incrementally mapping out the flow. I then forked R’s emulator to get it to spit out the exact register writes. Beyond the normal T8103 register layout/PIODMA/mailbox compatibility fixes, I added the missing decode control MMIO emulation, which includes the read/write hooks (obviously), setting the default values set on boot/reset, incrementing hardware counters, etc. It’s not done or perfect — and unicorn has not been great for MMIO emulation — but it was enough to get the findings below.
Decode MMIO
1104000 - 1105000 | Decode ctrl
110c000 - 1110000 | DMA status
Decode Stream DMA
Mystery: How do we arrive at our destination (DART stream 0) not-so-proto anymore?
Hardware!
Let’s run the emulator with my decode control MMIO hooks to see what exactly the firmware is doing with the PIODMA’d values. Following PIODMA 0xa111, the firmware obtains what would be the decode stream / DS0 Block iova and writes that into register 0x1104068 (that sounds important). It then resets two hardware accumulators/counters. This group is slot 0, and it looks like there’s 4-6 slots total.
EMU: PIODMA: src iova: 0x4000 cmd: 0xa111 dst: 0x108ef14 size: 0x280
00000000: 00000001 00000010 00000000 00000001
00000010: deadcafe 00010101 00000001 0008b4c0
EMU: PC 00002672: W32 @ 40104068 value 00000040 // stream_iova >> 8
EMU: PC 0000267a: W32 @ 40104084 value 00100000
EMU: PC 0000267e: W32 @ 401040a0 value 00000000
EMU: PC 00002680: W32 @ 401040bc value 00000000
The firmware then cherry-picks various bits and pieces from the PIODMA 0xa111 and the DMA Configuration chunk out of its own SRAM (recall pink already exists in its SRAM — hacky) and writes them into the decode configuration registers. Sorry, the. Same. Register.
EMU: PC 0000376a: W32 @ 4010400c value 2db032e0
EMU: PC 0000376a: W32 @ 4010400c value 01000000
EMU: PC 0000376a: W32 @ 4010400c value 003f007f
EMU: PC 0000376a: W32 @ 4010400c value 00000000
EMU: PC 0000376a: W32 @ 4010400c value 0007000f
EMU: PC 0000376a: W32 @ 4010400c value 01002881
EMU: PC 0000376a: W32 @ 4010400c value 00100000
EMU: PC 0000376a: W32 @ 4010400c value 000003de
EMU: PC 0000376a: W32 @ 4010400c value 0030000a
EMU: PC 0000376a: W32 @ 4010400c value 04020002
EMU: PC 0000376a: W32 @ 4010400c value 00020002
...
EMU: PC 0000376a: W32 @ 4010400c value 003f007f
EMU: PC 0000376a: W32 @ 4010400c value 00000000
Alright. Let’s try that.
# decode ctrl (0x269100000..0x26910bfff)
01102000: c0000000 00000000 00000000 00000000 00000000 00000000 00000000 0000001b | ................................
01102020: d1377edf 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | .~7.............................
011040a0: 00000068 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | h...............................
011040e0: 00000000 00000007 00000007 00000007 00000000 00000000 00000000 00000000 | ................................
# dma status (0x26910c000..0x26910ffff)
0110c380: c00007ff 00fc0038 ddd88792 00000001 3f7ff374 00000000 00000000 00000000 | ....8...........t..?............
Looks like DMA line 0x380 is now enabled and the 0xa0 counter has incremented to 0x68, which is about the same as the aggregated number of bytes we just wrote to 0x110400c (wink wink, cached in the DMA controller). But no changes yet in IOMMU space, of course. Next up, PIODMA 0xa11 and 0xed11:
EMU: PIODMA: src iova: 0x8f4c0 cmd: 0xa11 dst: 0x108fcb4 size: 0x14
00000000: 00000000 00000000 000f0000 00000000
00000010: 0074400a 00000028
EMU: PIODMA: src iova: 0x46e0 cmd: 0xed11 dst: 0x108f198 size: 0x3a0
00000000 2d020000 00000000 00000000 00000000
00000010 00000000 00000000 00000000 00000000
EMU: PC 0000376a: W32 @ 4010400c value 2d800000
EMU: PC 0000376a: W32 @ 4010400c value 0074400a
EMU: PC 0000376a: W32 @ 4010400c value 00000028
EMU: PC 0000376a: W32 @ 4010400c value 2c000000
EMU: PC 0000376a: W32 @ 4010400c value 2d902800
EMU: PC 0000376a: W32 @ 4010400c value 2da30000
EMU: PC 0000376a: W32 @ 4010400c value 2a000000
EMU: PC 0000376a: W32 @ 4010400c value 00003007
EMU: PC 0000376a: W32 @ 4010400c value 2d020000
EMU: PC 0000376a: W32 @ 4010400c value 2b000400
This time it parses the orange and yellow blocks. If you remember, 0x744000
was our IDR coded slice iova. Aha. Turns out very good things happen if we keep on banging on this register.
# decode ctrl (0x269100000..0x26910bfff)
01102000: c0000000 057abd60 00000000 00000008 00003007 0000003f 00000028 000000e5 | ....`.z..........0..?...(.......
01102020: 689324b7 00000000 00000000 00000101 00000000 00008d01 00000000 00000000 | .$.h............................
01104060: 00843108 00000003 00000040 00000000 00000000 00000000 00000000 00000000 | .1......@.......................
011040a0: 00000390 00000000 00000000 00000000 00000000 00000000 00000000 00000000 | ................................
011040e0: 00000007 00000007 00000007 00000007 00000000 00000000 00000000 00000000 | ................................
# dma status (0x26910c000..0x26910ffff)
0110c240: c00007ff 00800034 fb15faf5 00000000 77507fcb 00000000 00000000 00000000 | ....4.............Pw............
0110c280: c00007ff 00000018 cbe7426d 00000000 7df3e690 00000000 00000000 00000000 | ........mB.........}............
0110c2c0: c00007ff 00b40020 cbe7426d 00000000 73de6e7e 00000000 00000000 00000000 | .... ...mB......~n.s............
0110c380: c00007ff 00fc0038 ccbbb558 00000000 3f7ff374 00000000 00000000 00000000 | ....8...X.......t..?............
# dart-stream-0 (0x0..0x997fff): actual final final final hardware decode stream
00004000: 2db0b2e0 01000000 003f007f 00000000 0007000f 01002881 00100000 000003de | ...-......?..........(..........
00004020: 04020002 04020002 00000000 00008140 000081c0 00008240 00070007 0000e6d0 | ............@.......@...........
00004040: 0000e680 0000e6fa 0000e6d2 000073c1 00000008 000073e1 00000008 00000000 | .............s.......s..........
00004060: 003f007f 00000000 2d902800 2da30000 2a000000 00003007 2d020000 01000000 | ..?......(.-...-...*.0.....-....
00004080: 020c0000 0508a000 10428408 0c000001 2f080178 0c000001 2f0800b9 0c000001 | ..........B.....x../......./....
000040a0: 2f000225 00800000 01000001 02041000 0508a000 10028408 0c000000 00800000 | %../............................
000040c0: 01000002 02041000 0508a000 10028408 0c000000 00800000 01000003 02041000 | ................................
000040e0: 0508a000 10028408 0c000000 00800000 01000004 02041000 0508a000 10028408 | ................................
00004100: 0c000000 00800000 01000005 02041000 0508a000 10028408 0c000000 00800000 | ................................
00004120: 01000006 02041000 0508a000 10028408 0c000000 00800000 01000007 02061000 | ................................
00004140: 0528a000 10028408 0c000000 00800008 01001000 02086880 05088000 10028408 | ..(..................h..........
00004160: 0c000000 00800000 01001001 0200f880 05088000 10028408 0c000000 00800000 | ................................
00004180: 01001002 0200f880 05088000 10028408 0c000000 00800000 01001003 0200f880 | ................................
000041a0: 05088000 10028408 0c000000 00800000 01001004 0200f880 05088000 10028408 | ................................
000041c0: 0c000000 00800000 01001005 0200f880 05088000 10028408 0c000000 00800000 | ................................
000041e0: 01001006 0200f880 05088000 10028408 0c000000 00800000 01001007 0202d800 | ................................
00004200: 05288000 10028408 0c000000 00800008 01002000 02086880 05088000 10028408 | ..(.............. ...h..........
00004220: 0c000000 00800000 01002001 0200f880 05088000 10028408 0c000000 00800000 | ......... ......................
00004240: 01002002 0200f880 05088000 10028408 0c000000 00800000 01002003 0200f880 | . ....................... ......
00004260: 05088000 10028408 0c000000 00800000 01002004 0200f880 05088000 10028408 | ................. ..............
00004280: 0c000000 00800000 01002005 0200f880 05088000 10028408 0c000000 00800000 | ......... ......................
000042a0: 01002006 0200f880 05088000 10028408 0c000000 00800000 01002007 0202d800 | . ....................... ......
000042c0: 05288000 10028408 0c000000 00800008 01003000 02096880 05188000 10028408 | ..(..............0...h..........
000042e0: 0c000000 00800000 01003001 0201f880 05188000 10028408 0c000000 00800000 | .........0......................
00004300: 01003002 0201f880 05188000 10028408 0c000000 00800000 01003003 0201f880 | .0.......................0......
00004320: 05188000 10028408 0c000000 00800000 01003004 0201f880 05188000 10028408 | .................0..............
00004340: 0c000000 00800000 01003005 0201f880 05188000 10028408 0c000000 00800000 | .........0......................
00004360: 01003006 0201f880 05188000 10028408 0c000000 00800000 01003007 0203d800 | .0.......................0......
00004380: 05388000 10028408 0c000000 0080003f 00000000 00000000 00000000 00000000 | ..8.........?...................
The bytes DMA’d to DART stream 0 would be our legitimate, final hardware decode stream (a bit slimmed down from 0xb34c0). The first 0x70 bytes is the decode header/configuration we wrote u32-by-u32 (from red/pink); what’s next comes from passing the (yellow) IDR coded slice iova + (orange) DMA commands through the hardware i.e. it’s the IDR slice hardware-decoded :). But it’s not quite yet our pixels :/.
Note: the “firmware cherry-picked PHWDS” we can honestly classify as proto decode stream #2, though this stream never quite exists in its entirety. I have a rough idea of what bits from red/pink/orange/yellow are actually used (cafebabe is not one of them), but I’m not going to write that out here now. The firmware also patches the individual u32s to be written. Note that proto decode stream #2 is not the same as the final DMA’d decode stream, the DMA block masks some bits along the way e.g. 0x2db032e0 | 0x8000 == 0x2db0b2e0
, but it’s not unrecognizable from the final stream. Better than cafebabe at least. If we’re rolling out our own thing, this proto decode stream #2 is what we’d aim at.
Magic
avd_w32(0x1104054, 0x10) # magic
# dma status (0x26910c000..0x26910ffff)
0110c240: c00007ff 00800034 fb15faf5 00000000 7e507ecb 00000000 00000000 00000000 | ....4............~P~............
0110c280: c00007ff 00000018 cbe7426d 00000000 7df76e90 00000000 00000000 00000000 | ........mB.......n.}............
0110c2c0: c00007ff 00b40020 cbe7426d 00000000 73de6e7e 00000000 00000000 00000000 | .... ...mB......~n.s............
0110c380: c00007ff 00fc0038 ccbbb558 00000000 3f7ff774 00000000 00000000 00000000 | ....8...X.......t..?............
0110c640: c00007ff 016c00b0 ccbbb558 00000000 6e61587b 00000000 00000000 00000000 | ......l.X.......{Xan............
0110c840: c00007ff 0164001c 547757e5 00000000 6ef5ce0c 00000000 00000000 00000000 | ......d..WwT.......n............
0110c880: c00007ff 02cc0028 547757e5 00000000 e408aefe 00000000 00000000 00000000 | ....(....WwT....................
0110c8c0: c00007ff 01b00024 55a6c986 00000000 f736dd3a 00000000 00000000 00000000 | ....$......U....:.6.............
0110c900: c00007ff 03300040 55a6c986 00000000 c2e39d6e 00000000 00000000 00000000 | ....@.0....U....n...............
0110c940: c00007ff 01d4001c 555e562a 00000000 d398ce4d 00000000 00000000 00000000 | ........*V^U....M...............
0110c980: c00007ff 0370002c 555e562a 00000000 6276c3ce 00000000 00000000 00000000 | ....,.p.*V^U......vb............
0110cac0: c00007ff 02480080 a18e8c0d 00000000 3fbff73a 00000000 00000000 00000000 | ......H.........:..?............
0110cc80: c00003f1 01000003 02f00060 02c80014 00000000 00000000 00000000 00000001 | ........`.......................
0110cca0: 00000001 00000000 768f23df 00000000 00000000 00000000 00000000 00000000 | .........#.v....................
# dart-stream-0 (0x0..0x997fff)
00734000: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00734400: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00734800: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00734c00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00735000: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00735400: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00735800: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00735c00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
00736800: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
00736820: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
00736840: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
00736860: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
00736880: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
007368a0: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
007368c0: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
007368e0: 60606060 60606060 60606060 60606060 60606060 60606060 60606060 60606060 | ````````````````````````````````
00736900: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00736b00: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00736d00: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00736f00: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00737100: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00737300: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00737500: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00737700: f05af05a f05af05a f05af05a f05af05a 00000000 00000000 00000000 00000000 | Z.Z.Z.Z.Z.Z.Z.Z.................
00737d00: 01010101 01010101 01010101 01010101 01010101 01010101 01010101 01010101 | ................................
00737d20: 01010101 01010101 01010101 01010101 01010101 01010101 01010101 01010101 | ................................
0073c100: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c120: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c140: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c160: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c180: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c1a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c1c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c1e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c200: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c220: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c240: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c260: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c280: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c2a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c2c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c2e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c300: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c320: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c340: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c360: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c380: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c3a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c3c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c3e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c400: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c420: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c440: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c460: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c480: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c4a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c4c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c4e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c500: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c520: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c540: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c560: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c580: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c5a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c5c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c5e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c600: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c620: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c640: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c660: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c680: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c6a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c6c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c6e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c700: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c720: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c740: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c760: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c780: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c7a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c7c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c7e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c800: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c820: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c840: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c860: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c880: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c8a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c8c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c8e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c900: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c920: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c940: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c960: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c980: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c9a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c9c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073c9e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ca00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ca20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ca40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ca60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ca80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073caa0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cac0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cae0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cb00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cb20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cb40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cb60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cb80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cba0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cbc0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cbe0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cc00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cc20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cc40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cc60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cc80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cca0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ccc0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cce0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cd00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cd20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cd40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cd60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cd80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cda0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cdc0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cde0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ce00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ce20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ce40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ce60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073ce80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cea0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cec0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cee0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cf00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cf20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cf40: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cf60: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cf80: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cfa0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cfc0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073cfe0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d000: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d020: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d040: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d060: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d080: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d0a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d0c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d0e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d100: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d120: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d140: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d160: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d180: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d1a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d1c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d1e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d200: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d220: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d240: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d260: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d280: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d2a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d2c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d2e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d300: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d320: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d340: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d360: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d380: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d3a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d3c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d3e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d400: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d420: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d440: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d460: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d480: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d4a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d4c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d4e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d500: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d520: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d540: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d560: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d580: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d5a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d5c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d5e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d600: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d620: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d640: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d660: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d680: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d6a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d6c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d6e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d700: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d720: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d740: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d760: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d780: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d7a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d7c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d7e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d800: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d820: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d840: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d860: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d880: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d8a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d8c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d8e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d900: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d920: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d940: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d960: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d980: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d9a0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d9c0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073d9e0: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073da00: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073da20: 51515151 51515151 51515151 51515151 51515151 51515151 51515151 51515151 | QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
0073da