00000000 reset entry point 00000028 reset exception (supervisor mode): -- reset_handler() 0000002c undefined instruction exception (undef mode): 00000034 -- branch to undef_handler() 0000003c software interrupt exception (supervisor mode): there is only one syscall code (0xff). syscall 0xff switches execution to supervisor mode. 00000050 -- if (code != 0xff) return; 00000060 -- switch to supervisor mode 00000064 -- return from exception 00000068 prefetch abort exception (abort mode): 00000070 -- prefetch_abort_handler() 0000007c data abort exception (abort mode): 00000084 -- data_abort_handler() 00000094 interrupt exception (interrupt mode): 00000098 -- interrupt_handler() 000000a0 -- return from exception 000000a4 fast interrupt exception (fast interrupt mode): 000000a8 -- fast_interrupt_handler() 000000b0 -- return from exception 00000484 484(): 0000088c 88c(): 00000a84 a84(): 00000b10 b10(): 00001180 1180(): 000011b4 11b4(arg1=r0): 000014e0 14e0(): 00001530 return_0(): 00001534 -- return 0 00001538 literal pool 00001574 -- end of literal pool 000017e0 literal pool 000017f0 -- end of literal pool 000017f4 Return the offset of the subchunk with the specified id in the RIFF data. int riff_find_subchunk(uint8_t *riff_data=r0, int riff_length=r1, uint8_t *subchunk_id=r2): 000017fc -- r3 = 12 do { 00001834 -- if (riff_data[r3] == subchunk_id[0] && riff_data[r3 + 1] == subchunk_id[1] && riff_data[r3 + 2] == subchunk[2] && riff_data[r3 + 3] == subchunk[3]) { return r3 } 00001864 -- r3 = bswap32(riff_data[r3 + 4]) + 8 } while (r3 <= riff_length) 0000186c -- return 0 00001870 1870(): 00001880 -- if (byte [22000164] == 0) return 0; 000018ac -- fun = [4aabc + (byte [22000165] << 2)]; r0 = fun(0xd, [220000cc], byte [22000166], 0, 0); 000018b4 -- byte [22000164] = 0; 000018bc int? 18bc(int arg1=r0, uint_t arg2=r1, FILE *arg3=r2): 000018e0 -- r4 = arg1; r7 = 0x22000164; [sp+8] = 0; r6 = arg3; r5 = arg2; if (byte [22000164] != 0) return 0; 000018f0 -- if (arg2 & 0x3) { if (~arg2 & 0x3 == 0) return 0; } else return 0; i.e. continue iff bit 0 != bit 1 in arg2 000018f8 -- if (arg2 & 0x2) { 00001900 -- if (arg1 == -1) { 0000190c -- r0 = 19c0(arg3, sp+8); 00001918 -- r4 = r0; if (r0 == -1) return 0; 0000191c -- } } else { 00001924 -- if (arg1 == -1) { 00001928 -- r4 = 0; 0000192c do { 00001938 -- r0 = 18bc(r4, 1, arg3); /* recursive call */ 00001940 -- if (r0 != 0) break; 0000194c -- r4 += 1; } while (r4 < 5); 00001954 -- if (r4 == 5) return 0; 00001958 -- 1870(); 00001964 -- r0 = fseek(arg3, 0); } } 0000196c -- if (r4 >= 5) { 00001974 -- return 0; } 000019ac -- byte [22000164] = 1; byte [22000165] = r4; byte [22000166] = arg2; fun = [4aabc + (r4 << 2)]; r0 = fun(7, [220000cc], [sp+8], arg2, arg3); guess: fun(7, ..) checks if the file can be played with the decoder 00019bc -- if (r0 == 0) byte [22000164] = 0; return r0; 000019c0 if file is an riff wave file, set data_offset to the offset in the file where audio data begins and return 0 if it is MP3 audio and 2 if it is WMA. if the file is not riff wave, then use 18bc to determine the file type and set data_offset to 0. returns -1 on error int 19c0(FILE *f=r0, size_t *data_offset=r1): 000019d8 -- r4 = 0x2203d800 r6 = data_offset r5 = f r0 = fread(f, 0x2203d800, 0x1000); 000019e0 -- if (r0 == 0) return -1 000019ec -- fseek(f, 0); 00001a28 -- if (memcmp(0x2203d800, "RIFF", 4) || memcmp(0x2203d808, "WAV", 3) goto 0x1ab0 00001a34 -- if ([2203d80b] != 'E') goto 0x1ab0 00001a44 -- fmt_chunk = riff_find_subchunk(0x2203d800, 0x1000, "fmt ") 00001a4c -- if (fmt_chunk == 0) return -1 00001a6c -- fmt_chunk += 0x2203d800 audio_format = bswap16(fmt_chunk[8]) if (audio_format == 0x55) { /* WAVE_FORMAT_MPEGLAYER3 */ r5 = 0 } else { 00001a78 -- if (audio_format != 0x161) { /* WAVE_FORMAT_MSAUDIO2 */ return -1 } r5 = 2 } 00001a8c -- data_chunk = riff_find_subchunk(r4, 0x1000, "data") 00001aa8 -- if (data_chunk != 0) { *data_offset += data_chunk + 8 return r5 } 00001aac -- return -1 00001b14 literal pool 00001b24 asciz: "fmt " (RIFF, WAVE ??): 00001b2c asciz: "data": 00001b30 -- end of literal pool 00001b34 1b34(arg1=r0): 00001b44 -- [arg1] = byte [22000165] return 0x1 00001b48 int 1b48(char **arg1=r0): 00001b58 -- if (byte [22000164] == 0) return 0; 00001b88 -- fun = [4aabc + (byte [22000165] << 2)]; r0 = fun(0, [220000cc], arg1, 0, 0); 00001b90 int 1b90(unknown *arg1=r0): 00001ba0 -- if (byte [22000164] == 0) return 0; 00001bd0 -- fun = [4aabc + (byte [22000165] << 2)]; r0 = fun(1, [220000cc], arg1, 0, 0); 00001bd8 int 1bd8(unknown *arg1): 00001be8 -- if (byte [22000164] == 0) return 0; 00001c18 -- fun = [4aabc + (byte [22000165] << 2)]; r0 = fun(2, [220000cc], arg1, 0, 0); 00001c20 int 1c20(unknown *arg1=r0): 00001c68 int 1c68(unknown *arg1=r0): 00001cb0 int 1cb0(unknown *arg1=r0): 00001cc0 -- [arg1] = [220073e8]; return 1; 00001cc4 void 1cc4(arg1=r0, FILE *f=r1): 00001d84 1d84(): 00001e9c literal pool 00001ea0 -- end of literal pool 00001ea4 -- return 45878(..); 00001eb0 1eb0(): 00001ee8 1ee8(..): -- return 45b7c(..); 00001ef0 literal pool 00001ef4 -- end of literal pool 00002054 firmware decode function all references are indirectly from 2178 and 25c8 return value == 0 means error firmware_decode(u8_t *src=r0, u8_t *dest=r1): 00002060 -- r3 = 0; r2 = 0; 00002064 while (r2 < 256) { 00002078 -- r2 += 1; r3 = (r3 + src[r2]) & 0xFFFF; } 00002088 -- if (r3 & 0xff != src[255]) return 0; 00002090 -- r14 = 0x4acdc; /* table3 */ r2 = 0; 00002094 while (r2 < 256) { 000020a8 -- byte [sp + r2] = table3[src[r2]]; r2 += 1; } 00002178 2178(): 00002274 /* first 256 bytes of decoded firmware are at r4, sp+8 == "T10N.HEX" and r0 == 0 */ while (byte [sp+8 + r0] != '\0') { 00002284 -- if ([r4 + r0] != [sp+8 + r0]) { 0000228c -- fclose(sp+0x38); 00002294 -- return 10; } 000022ac -- r0 += 1; } 00002310 -- r8 = 0xff0000; r9 = 0xff00; r6 = (byte [r4 + 0x10] << 24) | (byte [r4 + 0x20] << 16) | (byte [r4 + 0x30] << 8) | byte [r4 + 0x40]; r7 = (byte [r4 + 0x50] << 24) | (byte [r4 + 0x60] << 16) | (byte [r4 + 0x70] << 8) | byte [r4 + 0x80]; r0 = fsize(sp+38); 00002318 -- if (r0 != r6) { 00002320 -- fclose(sp+38); 00002328 -- return 11; } 000025c8 guess: read firmware file to memory (0x22018000) int? 25c8(): 00002650 filesystem related verify: return value != 0 means error? int? 2650(unknown *arg1=r0, unknown *arg2=r1, unknown *arg3=r2, uint_t arg4=r3, fat_file *arg5=[sp], arg6=[sp+4], arg7=[sp+8]): 00002678 -- r6 = arg3 r5 = arg2 r4 = arg1 r0 = arg5 r1 = arg6 r2 = arg7 r8 = 0x4b170 r7 = arg7 & 0xff switch (arg4) { 0000267c -- default: /* return 0 */ 00002680 -- 0: /* return something */ 00002684 -- 1: /* return 0 */ 00002688 -- 2: /* return 0 */ 0000268c -- 3: /* guess: open file */ 00002698 -- 6: /* guess: read from file */ 0000269c -- 7: /* guess: also read from file */ 000026a4 -- 9: /* guess: write to file */ 000026a8 -- 10: /* guess: seek file to absolute position */ 000026ac -- 11: /* called from 31b0 */ 000026b0 -- 12: /* guess: return file size */ 000026b4 -- 13: /* return 0 */ 000026b8 -- 14: /* guess: close file */ 000026bc -- 15: /* guess: delete file */ 000026c0 -- 16: /* called from 3314 */ 000026c4 -- 17: /* called from 3390 */ 000026c8 -- 18: /* called from 33ec */ 000026cc -- 19: /* called from 3448 */ 000026d4 -- 21: /* called from 34f4 */ 000026d8 -- 22: /* guess: return total size of filesystem */ 000026dc -- 23: /* called from 3578 */ 000026e0 -- 24: /* guess: format NAND */ 000026e4 -- 25: /* may also be related to NAND format, called from fs_format */ 000026e8 -- 26: /* also called from fs_format */ 000026ec -- 27: /* also called from fs_format */ 000026f0 -- 28: /* also called from fs_format */ 000026f4 -- 29: /* return 0 */ 000026f8 -- 30: /* return 0 */ 000026fc -- 31: /* return 0 */ 00002700 -- 32: /* called from 38fc */ 00002708 -- 34: /* called from 3948 */ 00002710 -- 36: /* called from 3990 */ 00002714 -- 37: /* called from 3a18 */ 00002af4 -- r6 = 0x4addc; r5 = 0x22000168; r4 = 0; 00002af8 do { 00002b18 -- fun = [0004addc + (r4 << 2)]; fun([22000170], [22000174], 0, 0, 0, 0); 00002b20 -- r4 += 1; } while (r4 == 0); 00002b34 -- hword [22000168] = 0; hword [2200016a] = 0; byte [2200016c] = 0; return 0; 00002b40 2b40(..): 00002bc0 literal pool 00002bc8 asciz: " M 3T10050095": 00002bdc -- end of literal pool 00002c20 flags: 1 seems to mean 'for reading', 7 'for writing' arg5 is often 0x20 verify: fopen int fopen(FILE *f=r0, int fs_type=r1, wchar_t *path=r2, int flags=r3, int arg5=[sp]): 00002c40 -- ... if (arg2 != 0) return 0; 00002cac int? 2cac(FILE *arg1=r0, uint_t arg2=r1, arg3=r2, arg4=r3): 00002cbc -- ... if (arg2 != 0) return 0; 00002d8c verify: read size bytes of data to dest from file f. int fread(FILE *f=r0, u8_t *dest=r1, size_t size=r2): 00002dd0 -- [22001d68] |= 0x20; if (byte [2200016c] == 0) byte [arg1 + 0x20] = 0; e108(); 00002df8 -- fun = [4addc + (byte [arg1] << 2)]; r0 = fun([22000170], [22000174], 6, arg1 + 4, buffer, size); 00002e0c -- r4 = r0; [22001d68] &= ~0x20; ... 00002e18 2e18(..): 00002e70 verify: write size bytes from src to file f. void? fwrite(FILE *f=r0, u8_t *src=r1, uint_t size=r2): 00002edc verify: seek file f to absolute position pos int fseek(FILE *f=r0, uint_t arg2=pos): 00002efc -- r5 = 0x22000168; if (byte [2200016c] == 0) byte [arg1 + 0x20]; e108(); 00002f2c -- fun = [4addc + (byte [arg1] << 2)]; r0 = fun([22000170], [22000174], 10, arg1 + 4, arg2, byte [arg1 + 1]); 00002f40 return byte size of file f int fsize(FILE *f=r0): 00002f8c 2f8c(..): 000031b0 31b0(FILE *f=r0): 00003258 verify: fclose void fclose(FILE *f=r0): 000032c4 verify: delete file from filesystem int? fs_delete(int fs_type=r0, wchar_t *path=r0): 00003314 verify: arg3 is a path void 3314(unknown *arg1=r0, int arg2=r1, wchar_t *arg3=r2): 00003390 verify: return value depends on the type of the file at path arg2 0: error, 2: folder? int 3390(unknown *arg1=r0, wchar_t *arg2=r1, int arg3=r2): 000033d8 -- if (byte [2200016c] == 0) byte [arg1+0x14] = 0; fun = [4addc + (byte [arg1] << 2)]; r0 = fun([22000170], [22000174], 0x11, arg1 + 4, arg2, arg3); 00003448 void 3448(FILE *arg1=r0): 000034b4 int 34b4(uint_t arg1=r0): 000034f4 int? 34f4(uint_t arg1=r0, arg2=r1): 00003534 guess: return total space on file I/O system with type id arg1 if > 0x4b000000 returned, 75fc writes "T10N-2GB" if > 0x2bc00000 returned, 75fc writed "T10N-1GB" if > 0x12c00000 returned, 75fc writes "T10N-512MB" if > 0x9600000 returned, 75fc writes "T10N-256MB" else 75fc writes "T10N-128MB" int fs_total_space(uint_t arg1=r0): 00003544 -- if (arg1 != 0) return 0; 00003570 -- fun = [0004addc + (arg1 << 2)] r0 = fun([22000170], [22000174], 22, 0, 0, 0) 00003574 -- return r0; 00003578 int? 3578(uint_t arg1=r0): 000035c0 int 35c0(wchar_t *path=r0): 000035e4 -- r4 = 0xff; r0 = fopen(sp+4, 0, path, 1, 0x20); 000035f4 -- if (r0 != 0) { r4 = byte [sp+4 + 0x22]; fclose(sp+4); } 00003600 -- return r4; 00003604 int 3604(wchar_t *path=r0, arg2=r1): 0000363c -- byte [2200016c] = 1; byte [sp+8 + 0x20] = 1; byte [sp+8 + 0x21] = arg2; r4 = 0xff; r0 = fopen(sp+8, 0, path, 1, 0x20); 0000364c -- if (r0 != 0) { r4 = byte [sp+8 + 0x22]; fclose(sp+8); } 00003660 -- byte [2200016c] = 0; return r4; 000036f0 guess: format filesystem identified by arg1 int? fs_format(uint_t arg1=r0): 000038fc int? 38fc(uint_t arg1=r0, arg2=r1): 00003948 int? 3948(uint_t arg1=r0): 00003990 int? 3990(uint_t arg1=r0, unknown *arg2=r1, arg3=r2, arg4=r3, arg5=[sp]): 00003a18 int? 3a18(uint_t arg1=r0, arg2=r1, arg3=r2): 00003d38 writes some data to dest, probably size bytes verify: void 3d38(void *dest=r0, arg2=r1, arg3=r2, size_t size=r3): 00003fe8 return value != 0 means error int 3fe8(FILE *f=r0, arg2=r1): 000040ec possibly related to id3 tags (comparison with "TXXX") 40ec(FILE *f=r0, arg2=r1): 00004690 literal pool 000046a0 -- end of literal pool 000046a4 46a4(FILE *f=r0, arg2=r1): 00004a08 something to do with id3 (comparison with "ID3") 4a08(FILE *f=r0, arg2=r1): 00004b70 return value == -1 means error int ogg_vorbis_do_something(FILE *f=r0): 00004b8c -- r5 = arg1; memcpy(r13 + 0x40c, "OggS", 4); 00004ba0 -- memcpy(r13 + 0x404, "vorbis", 6); 00004bd4 -- ... if (..) return 0; 00004bfc -- if (r0 == 0) return -1; 00004c0c -- r0 = 2d8c(arg1, r13 + 4, 0x400); 00004c14 -- if (r0 == 0) return -1; 00004c1c do { 00004c38 -- r1 = byte [r13 + 4 + r4 + r0]; r2 = byte [r13 + 0x40c + r0]; if (r1 != r2) return -1; 00004c44 -- r0 += 1; } while (r0 < 4); 00004ee4 if a valid asf header is found in the file, look for an 'extended content description' chunk. There is also a comparison with the string "WM/Lyrics". return value is 0 or 1 (0 means error?) int asf_wma_do_something(FILE *f=r0): 0000543c literal pool 0000544c -- end of literal pool 000054a0 54a0(): 000054a8 -- memclr(0x22000178, 0x80) 000054ac 54ac(): 000054b8 -- if (!([22001d68] & 0x100000)) return 0x1 000054c4 -- if (([22001d78] & 0xff) != 0) return 0x1 000054d0 -- if ([22001d74] & 0x8000000) return 0x1 000054d8 -- if (!([22001d74] & 0x10000000)) return 0x1 000054e0 -- if ([22001d74] & 0x800) return 0x1 000054f4 -- if ([22001d74] & 0x10) return 0x1 000054fc -- 1a57c() 00005504 -- return 0x0 00005508 5508(): 0000550c -- r0 = 54ac() 00005514 -- if (54ac() != 0x0) return 0000552c 552c(arg1=r0): 0000554c -- [22001d6c] = ([22001d6c] & ~0x400000) | (arg1 >= 0x1 ? 0x0 : 0x400000) i.e. if arg1 is 0, set bit 22 of [22001d6c] else clear it 00005560 -- [22001d70] = ([22001d70] & ~0x4000) | ((arg1 & 0x1) ? 0x4000 : 0x0) i.e. if arg1 is _1_, set bit 14 of [22001d70] else clear it 0000556c -- r0 = c238([22001fb4]) 00005578 -- if (r0) != 0x4) return 5508() 0000557c -- return r0 000055c4 void 55c4(FILE *arg1=r0, u8_t *arg2=r1, int? arg3=r2): 000057d0 int 57d0(FILE *f=r0, arg2=r1): 00005f28 literal pool 00005f3c asciz: " ": 00005f50 asciz: ?? "...": 00005f60 asciz: "Searching...": 00005f6c -- end of literal pool 00006120 6120(FILE *f=r0, arg2=r1): 00006e68 literal pool 00006e74 -- end of literal pool 00006e78 6e78(FILE *f=r0): 00006fd4 literal pool 00006fd8 -- end of literal pool 00006fdc busy wait for a period of time and service the watchdog while sleeping actual sleep time equals the time between irq5 interrupts times time divided by 2 int busy_wait_watchdog(uint_t time=r0): 00006fec -- r4 = [2200c0ec]; 00006ff0 while (delta [2200c0ec] < (time / 2)) { -- watchdog_service(); 00007000 -- } 00007008 -- return 1; 0000700c busy wait for a period of time actual sleep time equals the time between irq5 interrupts times TIME divided by 2. guess: time between interrupts is 2ms (i.e. sleep time is TIME ms). void busy_wait(uint_t time=r0): 00007010 -- r1 = [2200c0ec]; 00007014 do { 00007020 -- /* nothing */ } while (delta [2200c0ec] < (arg1 / 2)); 0000706c 706c(): 000070e8 -- [3cf00004] = 0x20; [3cf00000] = 0xa551; [3cf00014] = 0x40; [3cf00010] = 0x11051111; [3cf00020] = 0x55555555; [3cf00034] = 0; [3cf00030] = 0x11111111; [3cf00044] = 0; [3cf00040] = 0x15551151; [3cf00054] = 0x20; [3cf00050] = 0x11111111; [3cf00064] = 0x20; [3cf00060] = 0x51155555; [3cf00074] = 0; [3cf00070] = 0x12222211; [3cf000a4] = 0; [3cf000a0] = 0xa; [3cf000f4] = 0; return; 000070ec setup and install irq handler for irq5 70ec(): 000070fc -- r0 = [22000104] / 25000; 00007144 -- [3c700008] = [22000104] / 25000; [3c700000] = 0x71800; [3c700010] = 0x18; [3c700004] = 3; [39c00000] = 0x20; [39c00010] |= 0x20; irq_install_handler(0x5, 0x23164); 00007158 -- [39c00008] |= 0x20; return; 00007240 -- ... irq_install_handler(7, 0x231a4) 00007258 7258(): 00007260 -- r0 = [3c500004] 00007274 -- r2 = ([3c500004] & 0xff) + 8 00007278 -- r1 = (([3c500004] >> 1) & 0x1f8000) + 0x10000 00007294 -- r4 = (((([3c500004] & 0xff) + 8) * ((([3c500004] >> 1) & 0x1f8000) + 0x10000)) & 0xffffffff) / (1 << ([3c500004] & 0x3)) 00007298 -- [22000218] = ((r2 * r1) & 0xffffffff) / (1 << ([3c500004] & 0x3)) 000072a0 -- r0 = [3c500008] 000072b4 -- r2 = ([3c500008] & 0xff) + 8 000072b8 -- r1 = (([3c500008] >> 1) & 0x1f8000) + 0x10000 000072cc -- [2200021c] = ((r2 * r1) & 0xffffffff) / (1 << ([3c500008] & 0x3)) 000072d4 -- r5 = [3c500000] 000072d8 -- r1 = ([3c500000] << 3) 000072e4 -- if (r1 < 0) { 000072e8 -- [22000220] = (((([3c500004] & 0xff) + 8) * ((([3c500004] >> 1) & 0x1f8000) + 0x10000)) & 0xffffffff) / (1 << ([3c500004] & 0x3)) 000072ec -- } else { 000072fc -- [22000220] = ((((([3c500004] & 0xff) + 8) * ((([3c500004] >> 1) & 0x1f8000) + 0x10000)) & 0xffffffff) / (1 << ([3c500004] & 0x3))) / (([3c500000] & 0xf) + 1) } ... TODO ... 0000737c 737c(): 0000738c -- [3c500028] |= 0x1000 0000739c -- [22007400] = [3d100000] 000073a4 -- [22007404] = [3d100004] 000073b0 -- [3c500028] |= 0x1000 000073bc -- 45da8(220000dc, 22007400, 8, 3d100000) 000073c0 -- cache_and_mpu_init() 000073d8 -- e1a4(0x1) 00007514 7514(): 00007518 -- e0ec() 00007524 -- [sp] (lr on stack) = 0x0 ?? r0 = sp 0000756c literal pool 000075e4 -- end of literal pool 000075e8 void 75e8(byte *arg1=r0): 000075f0 -- r0 = 1a208(); 000075f8 -- byte [arg1] = r0; return; 000075fc write a text string to dest the string is determined by hex_path and the return value of 3534 if hex_path is 1, write "T10N.HEX" and return 0 if bit 31 of [22001d64] is set, write "T10N-0GB" and return 0 else the string is determined by the return value of the call to 3534 if > 0x4b000000 returned, write "T10N-2GB" and return 6 if > 0x2bc00000 returned, write "T10N-1GB" and return 5 if > 0x12c00000 returned, write "T10N-512MB" and return 4 if > 0x9600000 returned, write "T10N-256MB" and return 3 else write "T10N-128MB" and return 2 int write_t10n_string(char *dest=r0, int hex_path=r1): 00007774 7774(): 00007aec 7aec(FILE *f=r0, arg2=r1, arg3=r2): 00007c98 7c98(FILE *f=r0): 00008070 literal pool 000080a0 -- end of literal pool 00008390 8390(): 00008398 -- return fs_delete(0, 0x22001ff6); 00008480 8480(): 000085b0 85b0(): 000086a0 86a0(): 000086dc 86dc(): 00008874 8874(): 00008970 literal pool 0000898c -- end of literal pool 00008990 8990(): 00008b20 8b20(FILE *f=r0, arg2=r1): 00008cac 8cac(): 00008df8 8df8(FILE *f=r0): 0000915c 915c(): 000091d4 91d4(): 00009220 9220(): 000092b8 literal pool 000092d8 -- end of literal pool 00009310 9310(): 000093e4 related to firmware upgrade 93e4(): 000095b8 95b8(): 00009600 9600(): 00009af4 9af4(): 00009cc4 literal pool 00009cd0 -- end of literal pool 00009d60 9d60(): 00009ddc 9ddc(): 0000adc4 guess: mp3 related adc4(FILE *f=r0, ..): 0000ae74 int file_is_riff_wave(FILE *f=r0): 0000b02c reference in array at 0x4aabc arg2 is same type as arg2 in 30ac8 b02c(arg1=r0, unknown *arg2=r1, arg3=r2, arg4=r3, FILE *arg5=[sp]): 0000b09c -- r0 = "MP3 MPEG Layer 3"; goto 0xb0bc; 0000b2f4 literal pool 0000b30c asciz: "MP3 MPEG Layer 3" 0000b32c -- end of literal pool 0000b330 only called indirectly address found at 0x4addc b330(arg1=r0, arg2=r1, arg3=r2, arg4=r3, arg5=[sp], arg6=[sp+4]): 0000b40c literal pool 0000b41c -- end of literal pool 0000b420 int wcscasecmp(const wchar_t *s=r0, const wchar_t *t=r1): 000b454 -- if (r2 >= L'A' && r2 <= L'Z') r2 = tolower(r2); 000b464 -- else if (r2 >= L'a' && r2 <= L'z') r2 = toupper(r2); 0000b498 arg1 and arg2 will be modified int? b498(unknown *arg1=r0, unknown *arg2=r1, unknown *arg3=r2, int? arg4=r3, int? arg5=[sp]): 0000b628 hword? b628(int? arg1=r0, int? arg2=r1, int? arg3=r2); 0000b67c -- r6 = wcslen(r13 + 0x48); [r13 + 0x46c] = r13 + 0x48 + (r6 << 1); 0000b6f4 -- r0 = wcscmp(r13 + 0x258, L"VOICE"); 0000b71c -- r0 = wcscmp(r13 + 0x258, L"RECORD"); 0000b878 -- hword r13[4] = L'\0'; r0 = wcscmp(r13, L".MP3"); 0000b8b8 -- r0 = wcscmp(r13, L".WMA"); 0000b8d0 -- r0 = wcscmp(r13, L".ASF"); 0000b8e8 -- r0 = wcscmp(r13, L".IRM"); 0000b940 -- r0 = wcscmp(r13, L".OGG"); 0000ba14 ba14(): 0000ba20 -- [22000290] = 0x22000298; return; 0000ba24 ba24(arg1=r0): 0000ba38 -- r9 = 0x22001d64; r4 = 0xffff; r1 = [22001d6c]; if (([22001d6c] & 0x80000000) == 0) { 0000ba40 -- if (arg1 != 0) { 0000ba60 -- 1a98c("Scan Music Files ...", 0x4e, 6, 0x12, 0x78, 0); 0000ba64 -- 1f08c(); 0000ba68 -- } else { 0000ba78 -- r0 = 1b61c("SCAN MUSIC FILE ...", 0, 0x38); 0000ba88 -- r5 = r0; if ([22001d78] < 0) { 0000baa4 -- 1a914(0xffff, 0x14, 0x28, 0x5a, 9); 0000bac8 -- [sp+4] = 0x580c0; r3 = 0x2a; } else { 0000bae8 -- [sp+4] = 0x58096; r3 = 0x37; } 0000baf8 -- r2 = (((0x80 - r5) + ((r5 > 0x80) ? 1 : 0)) >> 1) & 0xff; 1ae60("SCAN MUSIC FILE ...", 0, r2, r3, 0x38, [sp+4]); } } 0000bcfc literal pool 0000bd38 asciz: "Scan Music Files ..." 0000bd50 asciz: "SCAN MUSIC FILE ..." 0000bd70 -- end of literal pool 0000bea0 bea0(..): 0000bee4 return_arg1(arg1=r0): -- return arg1 0000c108 void c108(unknown *arg1=r0, int? arg2=r1, arg3=r2, unknown *arg4=r3, unknown *arg5=[sp]): 0000c238 c238(arg1=r0): 0000c248 -- return [[22000290] + (arg1 << 2)] & 0xf 0000c24c c24c(): 0000c25c -- return hword [[22000290] + 0x1a92] 0000c260 c260(): 0000c270 -- return hword [[22000290] + 0x1a90] 0000c274 c274(arg1=r0): 0000c2e0 c2e0(arg1=r0): 0000c328 hword? c328(arg1=r0): 0000c380 c380(arg1=r0): 0000cb08 literal pool 0000cb20 -- end of literal pool 0000cb24 int? cb24(wchar_t *arg1=r0): 0000cba8 -- memclr(r0, r1) 0000cc24 -- memclr(r0, r1) 0000cc38 void? cc38(arg1=r0): 0000d1a8 d1a8(): 0000d1b0 -- return hword [22002226] 0000d1b4 int? d1b4(unknown *arg1=r0): 0000d3a8 literal pool 0000d3c0 utf16bez: "\" 0000d3c4 -- end of literal pool 0000d3c8 int? d3c8(unknown *arg1=r0, ...): 0000d4b8 return 0 if path is "\VOICE", "VOICE", "\RECORD" or "RECORD" int path_is_voice_record(wchar_t *path=r0): 0000d504 return 1 if path is "\TUNER.DAT" or "TUNER.DAT", or if path is "T10.SYS" or "\T10.SYS". int path_is_sys_file(wchar_t *arg1=r0): 0000d51c -- r4 = arg1; memcpy(sp+4, L"\x20\x20\x20.SYS\0\0", 20); 0000d528 -- write_t10n_string(sp+24, 0); /* sp+24 ~= "T10N-?GB" */ 0000d560 -- hword [sp+4] = byte [sp+24]; hword [sp+6] = byte [sp+25]; hword [sp+8] = byte [sp+26]; r4 = arg1 + ((arg1[0] == L'\') ? 2 : 0); r0 = wcscmp(sp+4, r4); 0000d568 -- if (!r0) return 0; 0000d574 -- r0 = wcscmp("TUNER.DAT", r4); 0000d580 -- if (r0) return 1; 0000d590 int? d590(): 0000d5a8 -- r6 = 0x22001f58; r0 = 3314(r13 + 0x214, 0, [2200221c]); 0000d5c4 -- r1 = [2200221c]; r4 = 0; 0000d5d8 -- r4 = wcslen(r1); 0000d60c -- if (r4 > 0) { r1[r4] = L'\'; r4 += 1; } r10 = r6; r6 += 0x200; r9 = 0; r11 = 0x22001d64; r7 = hword [22002220] + 1; goto 0xd630; 0000d620 -- r0 = 3390(r13 + 0x214, [2200221c] + (r4 << 1), 3); 0000d64c -- memcpy(r13 + 0x1f8, L"WMPInfo.xml\0", 26); 0000d880 d880(arg1=r0): 0000d894 -- return [[22000290] + (arg1 << 2)] & 0xfff 0000d898 d898(): 0000d908 d908(): 0000d9c4 literal pool 0000d9d8 -- end of literal pool 0000d9dc d9dc(): 0000d9e8 -- [22001d6c] |= 0x20 0000d9ec -- return /* 0x22001d64 */ 0000d9f0 d9f0(): 0000d9fc -- [22001d6c] &= ~0x20 0000da00 -- return /* 0x22001d64 */ 0000dac8 literal pool 0000dad0 -- end of literal pool 0000dad4 dad4(): 0000dd88 void dd88(): 0000ddc8 -- [22001f60] &= ~0x1400000; [22001f78] = 0; [22001fb4] = 0; hword [22001f7c] 0; byte [22001f81] 0; [22001f88] = 0; [22001f8c] = 0; byte [22001f93] = 0; byte [22001f94] = 0; byte [22001f70] = 0; byte [22001f71] = 1; 36348(); return; 0000ddcc int ddcc(): 0000de50 comparison with "ReignCom" de50(): 0000dee0 literal pool 0000df04 -- end of literal pool 0000e00c interrupt handler for watchdog (irq6) void watchdog_irq6_handler(): 0000e04c -- [22001db8] += 1 if ([22001db8] < [22001db4]) { [3c800000] = 0xaa00; } [39c00000] = 0x40; [39c00010] |= 0x40; return; 0000e06c void watchdog_enable(): 0000e080 -- r0 = [22000104] / 0x3333; 0000e0d4 -- [22001db4] = [22000104] / 0x3333; if ([22000100] != [22000104]) { [22001db4] = ([22000104] / 0x3333) * 2; } [22001db8] = 0; [3c800000] = 0xaa00; [39c00000] = 0x40; [39c00010] |= 0x40; irq_install_handler(6, 0xe00c); 0000e0e8 -- [39c00008] |= 0x40; return; 0000e0ec void watchdog_disable(): 0000e104 -- [3c800000] = ([3c800000] & 0xf7f00) | 0xa5; return; 0000e108 possibly watchdog timer service void watchdog_service(): 0000e12c -- [3c800000] = ([3c800000] & 0xff0ff) | 0xa00; [22001db8] = 0x0; return; 0000e130 int? e130(): 0000e138 -- return [3c800004]; 0000e13c literal pool 0000e154 -- end of literal pool 0000e158 e158(arg1=r0): 0000e1a4 void e1a4(arg1=r0): 0000e1b4 -- [3ce00000] = 0x4781 + (arg1 << 3); return; 0000e1b8 e1b8(): 0000e3f4 e3f4(): 0000e5c4 e5c4(): 0000e5cc -- return [22001d48] 0000e5d0 e5d0(): 0000e60c e60c(): 0000e648 literal pool 0000e660 -- end of literal pool 0000ea04 ea04(): 0000ea44 huge function, ends at 0x11ac4 related to drawing settings screens ea44(): 0000efc0 literal pool 0000f020 asciz: "OFF": 0000f028 -- end of literal pool 0000ffb4 literal pool 00010010 -- end of literal pool 00010674 literal pool 000106a0 asciz: "-": 000106a4 asciz: ":": 000106b8 -- end of literal pool 00010e24 literal pool 00010e40 asciz: ".": -- end of literal pool 00011178 literal pool asciz: "0": 0001117c asciz: "5": 00011180 asciz: "MHz": 00011184 asciz: "MIN": 00011188 -- end of literal pool 000115cc literal pool 000115d0 asciz: "FIRMWARE" 000115e0 asciz: "FREE SPACE" 000115ec asciz: "TOTAL TRACKS" 00011610 -- end of literal pool 00011ac8 draw play mode select screen void? gui_draw_play_mode_screen(arg1=r0): 00011ea4 literal pool 00011ee8 -- end of literal pool 00012260 literal pool 00012274 asciz: "CH": 0001227c asciz: "EMPTY": 00012288 asciz: "MHz": -- end of literal pool 000125d8 guess: draw formatting screen void? gui_draw_formatting_screen(): 00012658 literal pool 00012664 asciz: "iriver": 0001266c asciz: "FORMATTING": 00012678 asciz: ??: 00012684 -- end of literal pool 00012688 guess: Draw "Initilaizing.." screen, probably not in use 00012704 literal pool asciz: "Initilaizing.." [sic] 00012714 asciz: ?? 00012720 -- end of literal pool 00012724 Draw (weird) "Rebooting..." screen. Not actually in use, I think. void? gui_draw_rebooting_screen(): 000127a0 literal pool asciz: "Rebooting.." 000127ac asciz: ?? 000127b8 -- end of literal pool 00012860 guess: draw file/folder related confirmation dialog 12860(): 00012ae4 literal pool asciz: "Add to Quick List" 00012af8 asciz: "Delete from the list" 00012b10 asciz: "Delete File" 00012b1c asciz: "Delete Folder" 00012b2c asciz: ??: 00012b40 asciz: ??: 00012b4c asciz: ??: 00012b5c asciz: ??: 00012b68 asciz: ??: 00012b74 asciz: ??: 00012b7c -- end of literal pool 00012b80 guess: draw some error messages 12b80(..): 00012cc4 literal pool asciz: ??: 00012cd4 asciz: ??: 00012ce4 asciz: ??: 00012cf4 asciz: ??: 00012d04 asciz: ??: 00012d1c asciz: ??: 00012d30 asciz: ??: 00012d44 asciz: ??: 00012d4c asciz: ??: 00012d60 asciz: ??: 00012d70 asciz: ??: 00012d80 asciz: ??: 00012d8c asciz: ??: 00012da0 asciz: ??: 00012dac asciz: ??: 00012dc0 asciz: ??: 00012dd4 asciz: ??: 00012de4 asciz: ??: 00012df4 asciz: ??: 00012e00 asciz: ??: 00012e10 -- end of literal pool 00012ec0 literal pool asciz: ??: 00012ecc asciz: ??: 00012ee0 asciz: ??: 00012ef0 asciz: ??: 00012f04 asciz: ??: 00012f18 asciz: "Delete Error" 00012f28 asciz: "Cannot delete" 00012f38 asciz: "system folder" 00012f48 asciz: "system file" 00012f54 asciz: "The folder still" 00012f68 asciz: "has file(s)" 00012f74 asciz: "Record Error" 00012f84 asciz: "Memory not enough" 00012f98 asciz: "Battery Error" 00012fa8 asciz: "Not enough for" 00012fb8 asciz: "recording" 00012fc0 -- end of literal pool 00013138 literal pool asciz: "View Error" 00013144 asciz: "Not supported" 00013154 asciz: "BMP format" 00013160 asciz: "firmware upgrade" 00013174 asciz: "File Error" 00013180 asciz: "No Firmware" 00013190 asciz: "Link Error" 0001319c asciz: "The file" 000131a8 asciz: "does not exist" 000131b8 asciz: "during playing" 000131c8 asciz: "Quicklist Error" 000131d8 asciz: "Memory or file" 000131e8 asciz: "number is full" 000131f4 -- end of literal pool 000133ac literal pool 000133bc asciz: ??: 000133d0 asciz: "File Check Error" 000133e4 asciz: "FAT" + ??: 000133f0 asciz: ??: 00013400 asciz: "FAT" 00013404 asciz: "Support Only" 00013414 asciz: "Please Format" 00013424 asciz: "No Music File" 00013434 asciz: ??: 00013440 -- end of literal pool 00013444 guess: draw "sync to PC" message screen 13444(): 000134f8 literal pool asciz: "To play this track," 0001350c asciz: "you must sync your" 00013520 asciz: "device to your PC" 00013534 returns a value between 0 and 4 based on the language 2 byte: (0: english, 1: korean, 2: japanese, 3: chinese(s), 4: chinese(t)) lang_get_lang1(): 00013544 -- if ([22001f92] == 0) return 1; 00013550 -- if ([22001f92] == 1) return 2; 0001355c -- if ([22001f92] == 9) return 3; 0001356c -- if ([22001f92] == 10) return 4; return 0; 00013570 sets the language 1 and 2 byte based on the value of the language 3 byte lang_init_lang1_lang2(): 00013588 -- byte [22001f92] = byte [00057e44 + byte [22001f9c]]; r0 = lang_get_lang1(); 00013594 -- byte [22001d97] = r0; /* set language 1 byte to r0 */ return; 00013598 set language 3 to english and update lang 1 and lang 2 bytes void lang_set_lang_english(): 000135a8 draw the text strings of the power off screen on the display void gui_draw_poweroff_text(): 000135b8 -- write_t10n_string(sp+13, 0); /* sp+13 ~= "T10N-?GB" */ 000135bc -- r1 = 7; 000135c0 do { 000135cc -- if (byte [sp+12 + r1] == '\0') break; 000135dc -- r1 += 1; } while (r1 < 10); len = r1; 00013634 -- byte [sp+12 + len] = '/'; byte [sp+12 + len + 1] = 'E'; byte [sp+12 + len + 2] = 'U'; byte [sp+12 + len + 3] = '\0'; r0 = 1b61c("POWER OFF", 2, 0x30); 00013664 -- r2 = (((0x80 - r0) + ((r0 > 0x80) ? 1 : 0)) >> 1) & 0xff; r0 = 1ae60("POWER OFF", 2, r2, 0x2e, 0x30, 0x5809c); 00013674 -- r0 = 1b61c(sp+12, 2, 0x30); 000136a4 -- r2 = (((0x80 - r0) + ((r0 > 0x80) ? 1 : 0)) >> 1) & 0xff; r0 = 1ae60(sp+12, 2, r2, 0x38, 0x30, 0x580a2); 000136ac -- return; 000136b0 literal pool 000136b4 asciz: "POWER OFF" 000136c4 -- end of literal pool 000136c8 void 136c8(): 000136f0 -- byte [22001d8d] = 2 byte [22001da7] = 1; hword [22001f26] = 0x19a; hword [22001f28] = 0x222e; return; 000136f4 136f4(): 00013858 13858(): 00013abc 13abc(): -- r1 = 0x22001d64 00013ac8 -- if (!([22001d74] & 0x800)) return /* [22001d74] << 20 */ 00013ad4 -- hword [22001dbc] = 0x0 hword [22001dbe] = 0x0 00013ad8 -- return /* 0x0 */ 00013adc 13adc(): 00013cc8 return 1 if string returned by 1b48 starts with "AAC" or "aac" int 13cc8(): 00013fd0 literal pool 00014008 -- end of literal pool 0001400c 1400c(arg1=r0): 00014188 14188(): 000141b4 141b4(arg1=r0): 000143c4 143c4(): 00014464 14464(): 000144f8 144f8(): 00014580 14580(arg1=r0): 00014ce8 14ce8(): 00014cf4 -- if (shword [22001dce] <= 0) return /* 0x22001d64 */ 00014cfc -- hword [22001dce] = 0x0 00014d0c -- [2200c0e4] &= ~0x4000 00014d10 -- return 38878() 00014e10 14e10(): 00014ed0 literal pool 00014edc -- end of literal pool 00014ee0 14ee0(): 00014f40 14f40(): -- r0 = 0x22001d64 00014f44 -- r1 = byte [22001d7c] 00014ff8 14ff8(): -- r1 = 0x22001d64 00015000 -- ip = byte [22001d78] 00015004 -- r0 = shword [22001dcc] 00015008 -- r3 = 0x0 0001500c -- r2 = 0x4b 00015014 -- if (byte [22001d78] > 0x11) return /* shword [22001dcc] */ switch ... ends at 150bc 000150bc -- switch (byte [22001d78]) { case 0x2: return /* shword [22001dcc] */ case 0x3: return /* shword [22001dcc] */ case 0x4: return /* shword [22001dcc] */ case 0xe: return /* shword [22001dcc] */ case 0xf: return /* shword [22001dcc] */ case 0x10: return /* shword [22001dcc] */ case 0x6: if (shword [22001dcc] > 0) return /* shword [22001dcc] */ hword [22001dcc] = 0x4b case 0x5: r0 = 0x1 break case 0x8: if (shword [22001dcc] > 0) return /* shword [22001dcc] */ hword [22001dcc] = 0x4b case 0x7: r0 = 0x0 break case 0xa: if (shword [22001dcc] > 0) return /* shword [22001dcc] */ hword [22001dcc] = 0x4b case 0x9: r0 = 0x3 break case 0xc: if (shword [22001dcc] > 0) return /* shword [22001dcc] */ hword [22001dcc] = 0x4b case 0xb: r0 = 0x4 break case 0x1: case 0xd: hword [22001dee] = 0x0 return /* shword [22001dcc] */ case 0x11: r0 = 0x5 break } 000150c0 -- return 141b4(r0) 000150c4 150c4(): 00015188 15188(): 000151b4 151b4(arg1=r0): 000151e0 151e0(): 000153bc 153bc(): 00015480 15480(arg1=r0): 00015520 15520(): 00015550 15550(): 00015578 15578(): 000157e8 literal pool 000157f0 -- end of literal pool 000157f4 157f4(): 00015814 -- if (byte [22001d9c] == 1 && byte [22001d9e] == 4) { byte [22001d8a] = byte [22001f9c]; } return; 00015818 15818(): 000158cc 158cc(arg1=r0): 00015f3c -- byte [22001d8a] -= 1; if (byte [22001d8a] < 0) byte [22001d8a] = 39; goto 0x15f54; 00015f50 -- byte [22001d8a] += 1; if (byte [22001d8a] > 39) byte [22001d8a] = 0; 00015f5c -- byte [22001f9c] = byte [22001d8a]; i.e. set lang3 to byte [22001d8a] and update lang1 and lang2 00016fe8 16fe8(): 000170a0 170a0(): 000170f4 170f4(): 000173c0 173c0(): 000174dc 174dc(): 00017810 17810(arg1=r0): 00017930 17930(): 00017eb0 17eb0(arg1=r0): 0018018 literal pool 00018044 -- end of literal pool 000180a0 180a0(): 000180d4 180d4(): 00018460 18460(): 00018474 -- memclr(r0, r1) 000184bc 184bc(): 00018518 18518(): 00018784 18784(): 00018884 18884(): 000188f4 188f4(): 00018bb4 literal pool 00018bc8 -- end of literal pool 00018bcc 18bcc(): 00018bd4 -- hword [22001dbc] = 0x0 00018bd8 -- return /* 0x0 */ 00018bdc 18bdc(arg1=r0): 00018c08 guess: battery related int 18c08(..): 00018d0c set language 3 to english void lang_set_lang3_english(): 00018d18 -- byte [22001f9c] = 0xc; return; 00018db8 18db8(): 00018e68 18e68(): 0001999c reference in table at 0x57e70 int? 1999c(unknown *arg1=r0, arg2=r1, int arg3=r2): 0001a000 literal pool 0001a038 -- end of literal pool 0001a03c void 1a03c(arg1=r0, arg2=r1, arg3=r2, arg4=r3): 0001a064 -- byte [2c000000] = 0x32; byte [2c000001] = arg2; byte [2c000001] = arg1 + 2; byte [2c000001] = arg4; byte [2c000001] = arg3 + 2; return; 0001a068 void 1a068(arg1=r0, arg2=r1): 0001a090 -- byte [2c000000] = 0x2a; byte [2c000001] = arg1 + 2; byte [2c000000] = 0x2b; byte [2c000001] = arg2; byte [2c000000] = 0; return; 0001a094 1a094(arg1=r0): 0001a0d4 void 1a0d4(arg1=r0, arg2=r1): 0001a0f0 -- if (arg2 != 0x1) byte [2c000001] = arg1; else byte [2c000000] = arg1; if (!([22001d74] & 0x10000000)) return 0001a100 -- if (byte [22001f95] == 0x0) { 23300(); return; } 0001a10c -- if (!([22001d78] & 0x80000000)) return 0001a110 -- 23300() return 0001a114 1a114(): 0001a11c -- 1a0d4(0x34, 0x1) return 0001a120 1a120(): 0001a134 -- byte [22006c60] = 0x0 byte [22006c61] = 0x0 byte [22006c62] = 0x0 byte [22006c6f] = 0x0 0001a138 -- return /* 0x0 */ 0001a1ec void 1a1ec(byte *arg1=r0): 0001a204 -- r1 = byte [240ff004] if (byte [240ff004] >= 0x64) r1 = 0x36 byte [arg1] = r1; return; 0001a208 1a208(): 0001a23c 1a23c(arg1=r0): 0001a500 void 1a500(): 0001a514 -- byte [22006c84] = 0x0 byte [22006c80] = 0x0 byte [22006c7f] = 0x0 byte [22006c74] = 0x0 0001a520 -- byte [22006c7e] = 0xff byte [22006c7d] = 0xff 0001a528 -- hword [22006c82] = 0x80 0001a52c -- return 0001a530 void 1a530(): 0001a538 -- 2a23c(0x0) 0001a540 -- 1a500() 0001a544 1a544(): 0001a564 1a564(): 0001a56c -- byte [22006c70] = byte [22006c6f] 0001a574 -- byte [22006c6f] &= ~0x2 0001a578 -- return /* byte [22006c6f] & ~0x2 */ 0001a57c 1a57c(): 0001a588 -- if (byte [22006c6f] & 0x2) return 1a564() 0001a58c -- return /* byte [22006c6f] */ 0001a604 1a604(arg1=r0): 0001a650 1a650(arg1=r0): 0001a660 -- 1a0d4(0xb1, 0x1) 0001a670 -- 1a0d4(arg1, 0x1) 0001a8d0 literal pool 0001a910 -- end of literal pool 0001a914 arg4 is the low byte of the 16-bit value preceeding a utf-16 string. void 1a914(int? arg1=r0, int arg2=r1, int arg3=r2, int arg4=r3, int arg5=[sp]): 0001a98c Guess: Draw the UTF-16BE string in arg1. Position is somehow specified by the rest of the args. arg4 is possibly vertical position. void gui_draw_string(void *arg1=r0, int arg2=r1, int arg3=r2, int arg4=r3, int arg5=[sp], int arg6=[sp+4]): 0001adc0 int 1adc0(char *arg1=r0, int arg2=r1): 0001ae60 void 1ae60(char *arg1=r0, int arg2=r1, int arg3=r2, int=arg4=r3, int arg5=[sp], unknown *arg6=[sp+4]): 0001b5ec literal pool 0001b618 -- end of literal pool 0001b61c int 1b61c(char *arg1=r0, int arg2=r1, int arg3=r2): 0001c7f8 literal pool 0001c804 -- end of literal pool 0001e26c void 1e26c(unknown *arg1=r0, int arg2=r1, int arg3=r2, int arg4=r3, int arg5=[sp], int arg6=[sp+4], int arg7=[sp+8]): 0001e35c 1e35c(arg1=r0, arg2=r1): 0001e3d0 1e3d0(): 0001e414 void 1e414(): 0001e420 -- memclr_aligned(0x22006758, 0x51c); 0001e43c -- byte [22001e51] = 0xff; byte [22001e50] = 0xff; byte [22001da2] = 0; return; 0001e51c int 1e51c(): 0001e630 1e630(): 0001f05c literal pool 0001f088 -- end of literal pool 0001f08c void 1f08c(): 0001f098 -- if (([22001d74] & 0x1000000) == 0) return; 0001f0a4 -- r5 = 0x22006758; r4 = 0; 0001f0a8 do { 0001f0b0 -- if (byte [22006c62] == 0) break; 0001f0b4 -- 1e630(); 0001f0c0 -- r4 += 1; } while (r4 < 0x40); 0001f0c4 -- return; 0001f540 void 1f540(): 0001f54c -- memset(0x22001e46, 0xff, 0xc) 0001f550 1f550(): 0001f864 1f864(): 0001fd14 literal pool 0001fde0 -- end of literal pool 0001fde4 1fde4(): 0001fe44 -- return 0001fe4c 1fe4c(arg1=r0, arg2=r1): 000206c0 literal pool 000206e8 -- end of literal pool 000206ec 206ec(arg1=r0): 00020794 draw sample rate in right corner of display followed by "KHz" void? gui_draw_sample_rate_text(arg1=r0): 00020844 literal pool 0002084c asciz: "KHz" -- end of literal pool 00020944 literal pool asciz: "K" 00020948 asciz: "VBR" -- end of literal pool 0002094c 2094c(arg1=r0): 00020c54 20c54(arg1=r0, arg2=r1): 00021128 related to settings menu lists 21128(arg1=r0, arg2=r1): 00021538 literal pool 00021614 -- end of literal pool 00021814 -- return 00021ccc literal pool 00021cf0 asciz: "CH" -- end of literal pool 00021fa8 -- return 00021fac 21fac(): 00021ffc 21ffc(): 0002208c 2208c(): 000220d0 220d0(): 00022164 Has the only reference to "Hold"-string. draw hold (lock) screen void? 22164(): 00022168 -- 1a120(); 00022188 -- 1e26c(0xa04407c, 0, 0, 0, 0, 0x20, 1); 00022194 -- le32enc(0x22011000, (u32_t *)0x22006c75); 00022198 -- 1f08c(); 000221d8 -- r2 = (((0x80 - hword [[0x9d48c + (byte [22001d97] << 2)]]) + (0x80 - hword [[0x9d48c + (byte [22001d97] << 2)]]) >> 0x1f) >> 1) & 0xff; 1a98c([0x9d48c + (byte [22001d97] << 2)] + 2 /* "Hold" */, 0x1c, r2, 0x32, hword [[0x9d48c + (byte [22001d97] << 2)]] & 0xff, 0x79); 000221e0 draw low battery screen void? gui_draw_low_battery_screen(): 00022260 draw firmware upgrade screen void? gui_draw_firmware_upgrade_screen(): 000222e0 draw usb connect screen void? gui_draw_usb_connect_screen(): 00022360 guess: draw another usb connect screen void? gui_draw_usb_connect_screen_2(arg1=r0): 0002241c draw "Transferring data" usb connect screen void? gui_draw_usb_transfer_screen(): 000224c0 224c0(arg1=r0): 0002250c literal pool 00022554 -- end of literal pool 00022558 22558(): 000225f4 225f4(): 00022744 22744(arg1=r0, arg2=r1, arg3=r2): 0002297c 2297c(arg1=r0): 00022d74 literal pool 00022d9c -- end of literal pool 00023124 literal pool 00023160 -- end of literal pool 00023164 irq handler for irq 5 void irq5_handler(): 000231a0 -- [3c700000] |= 0x10000; [2200c0ec] += 1; [39c00000] = 0x20; [39c00010] |= 0x20; return; 000231a4 irq handler for irq 7 void irq7_handler(): 000231e0 -- [3c700020] |= 0x10000; [2200c0ec] += 1; [39c00000] = 0x80; [39c00010] |= 0x80; return; 000231e4 void 231e4(): 000231f0 -- [39c0000c] = 0x7f; return; 000231f4 initialize interrupt jump table set handler for 0x20 interrupts (all interrupts?) to 232a8() called from 0x23244 void irq_init_table(): 000231fc -- r0 = 0; 00023200 do { 0002320c -- [22006c90 + (r0 << 2)] = 0x232a8; r0 += 1; } while (r0 < 0x20); 00023210 -- return; 00023214 void 23214(): 00023238 -- [39c00004] = 0: [39c00008] = 0; [39c00020] = 0; [39c00000] = 0xffffffff; [39c00010] = 0xffffffff; [39c0001c] = 0xffffffff; return; 0002323c void 2323c(): 00023240 -- 23214(); 00023244 -- irq_init_table(); 00023250 -- [39c0000c] = 0x7f; enable irqs?? 00023254 -- return; 00023258 install irq handler in irq jump table void irq_install_handler(uint_t irq_id=r0, func *handler=r1): 00023260 -- [22006c90 + (irq_id << 2)] = handler; return; 00023264 return current handler for irq_id irq_get_handler(uint_t irq_id): 0002326c -- return [22006c90 + (irq_id << 2)]; 00023270 -- infinite loop 00023274 -- infinite loop 00023278 -- infinite loop 00023280 22006c90 is a jump table for different interrupts 39c00014 identifies the highest priority pending interrupt branch to entry [39c00014] in interrupt jump table 00023290 -- fun = [22006c90 + ([39c00014] << 2)]; fun(); 00023294 branch to entry [39c00014] in interrupt jump table normal interrupts and fast interrupts are not handled differently 000232a4 -- fun = [22006c90 + ([39c00014] << 2)]; fun(); 000232a8 initial target for all interrupts void irq_default_handler(): 000232bc -- [39c00000] = 0; [39c00010] = 0; [39c0001c] = 0; acknowledge interrupt ?? return; 000232c0 literal pool 000232d0 -- end of literal pool 000232d4 logging printf function (ifdef'ed out) void log_printf(char *s, ...): -- return 000232d8 void 232d8(): 000232e8 -- [39000000] |= 0x40; return; 000232ec void 232ec(): 000232fc -- [39000000] &= ~0x40; return; 0002337c byte 2337c(): 00023384 -- return byte [22006d11] 00023388 23388(): 00023390 -- byte [22006d11] = 0x0 00023394 -- return /* 0x0 */ 00023398 23398(): 000233a0 -- byte [22006d11] = 0x1 000233a4 -- return /* 0x1 */ 000233a8 233a8(arg1=r0): 00023418 irq handler for irq 20 void 23418() 0002341c -- r4 = 0x39000000 00023428 -- r5 = 0x0 0002342c -- if (!([39000004] & 0x40)) goto 0x2349c 00023434 -- [39000004] = 0x6 00023438 -- r0 = [39000030] /* value unused? */ 00023448 -- if ([39000034] > 0x2) loop infinitely 00023450 -- [39000004] = 0x2 00023470 -- [22006e60] = [22006e5c] + ((([22006e50] * [39000034]) & 0xffffffff) >> 1) [22006e54] = 0x0 00023480 -- if ([22001d68] & 0x20) goto 0x2349c 00023484 -- r6 = 0x22000230 00023498 -- do { r0 = 24cd8(0x22000230, 0x200) } while (r0 == 0x1) 000234a8 -- lr = 0x22006d10 000234b0 -- if ([39000004] & 0x20) { [39000004] = 0x5 byte [22006d10] = 0x0 } 000234b8 -- ip = 0x39000000 000234c0 -- if (!([39000004] & 0x10)) goto 0x23544 000234c8 -- [39000004] = 0x4 000234a8 -- r0 = 0x0 do { r3 = [39000034] r0 += 1 hword [[22006d14] + 2] = [39000034] } while (r0 <= 0x8) 00023500 -- r3 = 0x1 0002350c -- if ((hword [[22006d14]] >> 8) != 0x23) goto 0x23528 if ((hword [[22006d14]] >> 8) == 0x23 && hword [[22006d14] + 2] >> 8) != 0x24) goto 0x23528 0002351c -- byte [22006e97] |= 0x10 00023524 -- [22006d11] = 0x1 00023528 -- r2 = 0x22006d40 0002353c -- [22006d14] = min([22006d14] + 0x10, 0x22006d40) 00023540 -- [39000004] = 0x1 0002354c -- [39c00000] = 0x100000 0002355c -- [39c00010] |= 0x100000 00023560 -- return 00023564 void 23564(): 00023570 -- irq_install_handler(20, 0x23418) 0002358c -- [39000004] = 0x4 [39000004] = 0x5 [39000004] = 0x6 000235a8 -- [39c00000] = 0x100000 [39c00010] = 0x100000 [39c00008] |= 0x100000 000235ac -- return 000235b0 word 235b0(): 000235b4 -- 23564() 000235bc -- 233a8(0x2) 000235c8 -- 233a8(0x0) return 000235cc 235cc(): 000235d8 -- [22006d14] = 0x22006d40 [22006d18] = 0x22006d40 000235dc -- return /* 0x22006d40 */ 000235e0 235e0(): 000235f8 -- [39000004] = 0x4 [39000004] = 0x5 [39000004] = 0x6 00023604 -- [39000000] |= 0x70 00023608 -- return 0002360c 2360c(): 0002367c 2367c(): 00023750 23750(hword *arg1=r0): -- 00023764 -- r1 = [22006d18]; if ([22006d18] == [22006d14]) return 5; 0002376c -- r2 = arg1; r0 = 0; 00023770 do { 00023780 -- hword [r2] = hword [r1]; r0 += 1; r1 += 2; r2 += 2; } while (r0 < 8); 000237a4 -- if ([22006d18] + 0x10 >= 0x22006e40) [22006d18] = 0x22006d40; else [22006d18] += 0x10; return 4; 000237a8 237a8(FILE *f=r0): 00023a48 verify: signature 23a48(FILE *f=r0): 00023b60 literal pool 00023bd8 -- end of literal pool 00023bdc 23bdc(arg1=r0, arg2=r1, arg3=r2): 00023c28 23c28(arg1=r0): 00023c5c 23c5c(): 00023ce4 23ce4(arg1=r0): 00023f74 23f74(): 00023fb8 23fb8(): 000241f8 void 241f8(): 00024ab8 void 24ab8(): 00024ac4 -- r0 = 23750(0x22006e80); 00024acc -- if (r0 == 5) return; 00024ae0 -- if ((hword [22006e80] >> 8) == 0x23) { 241f8(); return; } 00024ae4 -- return; 00024b5c 24b5c(): 00024b6c -- [22006e60] = [22006e5c] [22006e64] = [22006e5c] 00024b78 -- memclr([22006e5c], [22006e50]) 00024b88 -- [22006e68] = 0x0 [22006e54] = 0x0 byte [22006e6d] = 0x0 00024b90 -- [22006e9c] = 0x0 00024ba0 -- [22001d64] &= ~0x1000 00024ba4 -- return /* 0x22001d64 */ 00024ba8 reference at 0x23bb0 24ba8(FILE *f=r0, int arg2=r1): 00024cd8 24cd8(FILE *f=r0, arg2=r1): 00024d68 24d68(arg1=r0, arg2=r1): 00024e28 24e28(FILE *f=r0): 00024eb0 24eb0(arg1=r0, arg2=r1): 00024fe8 literal pool 00025014 -- end of literal pool 00025980 literal pool 00025aac -- end of literal pool 000265d0 void 265d0(FILE *f=r0): 00026b34 26b34(FILE *f=r0, arg2=r1): 00026d80 void le32conv(u32_t *data=r0): 00026cfc read size bytes to dest from FILE at 0x22000230 starting at offset - ([22006f38] * 0x1000). void file_read(u8_t *dest=r0, size_t offset=r1, size_t size=r2): 00026d14 -- r7 = offset; r6 = 0; 00026d18 while (r6 < size) { 00026d3c while ([22006f38] < (r7 / 0x1000)) { 00026d48 -- fread(0x22000230, 0x22039e00, 0x1000); 00026d4c -- [22006f38] += 1; 00026d54 -- } 00026d6c -- byte [dest + r6] = byte [22039e00 + (r7 % 0x1000)]; r7 += 1; r6 += 1; 00026d78 -- } 00026db0 26db0(arg1=r0, arg2=r1, arg3=r2, unknown *arg4=r3, unknown *arg5=[sp]): 00026dec -- r4 = arg1; r6 = arg5; [sp+8] = 0; [sp+4] = 0; [sp+12] = 0; *arg5 = 0; *arg4 = 0; r8 = arg3; r7 = arg2; r5 = arg4; file_read(arg4, arg1 + 24, 2); 00026df4 -- le32conv(arg4); 000275b8 275b8(arg1=r0): 000275f0 poiter to static GUID for unknown ASF chunk: {b7dc0791-0043-4451-9237-daefbc484f50} 00027604 pointer to static GUID for ASF file header chunk: {8cabdca1-a947-11cf-8ee4-00c00c205365} 0002735c arg1 points to an ASF (file header?) chunk void 2735c(unknown *arg1=r0): 00027c50 literal pool 00027c70 asciz: "BAD-CLEAR_FEATURE %x\r\n": 00027c84 -- end of literal pool 00027d10 -- return 2993c(..); 00027d14 int? 27d14(unknown *arg1=r0): 00028de0 do nothing (arg1 * 100) / 6 times void loop_wait(arg1=r0): 0002915c This is thought to be one (of several) USB related functions. Some USB related strings have been traced to this function (through pointer at 0x2969c). It is thought it is responsible for somehow programming the iManufacturer and iProduct strings, that are visible from the USB host. void? 2915c(): 000291c0 -- r4 = 0x38800000; [38800000] = 0; [38800024] |= 1; r1 = min([22007044], [2200702c]); [22007044] -= r1; r0 = [2200703c] + [22007040]; [22007040] += r1; if ([2200702c] != r1) byte [22007029] = 4; [38800038] = r1; r2 = 0; 000291c4 do { 000291e0 -- if (r2 < r1) { [38800060] = bswap16(hword [r0]); r0 += 2; r2 += 2; } else break; } while (1); 00029450 guess: related to USB void irq16_handler(): 0002946c -- r7 = 0x38800000; r4 = [38800004]; r6 = [38800018]; r0 = [3880001c]; r1 = r0 & ~0x70; r5 = 1; if ((r0 & ~0x70) == 0) { ... ... 00029740 -- ... irq_install_handler(16, 0x29450) 00029820 int 29820(): 000299ac 299ac(arg1=r0, arg2=r1): 0002adc0 2adc0(FILE *f=r0): 0002b104 initialise cache and memory protection unit by disabling both, then invalidating the caches, then reenabling them 0002b99c -- ... irq_install_handler(10, 0x2b74c) 0002ba54 -- ... irq_install_handler(10, 0x2b7dc) 0002cbd4 int? 2cbd4(unknown *arg1=r0)): 0002d5c0 2d5c0(unknown *arg1=r0, arg2=r1): 0002d808 2d808(FILE *f=r0, arg2=r1): 0002d9b8 returns offset of first ogg page header found or -1 if not found also updates some fields in arg2 int 2d9b8(u8_t *data=r0, unknown *arg2=r1): 0002fcd0 guess: power off no return void 2fcd0(): 0002fcd4 -- ddcc(); 0002fcdc -- busy_wait(500); 0002fce0 -- r1 = 0x3cf00004; 0002fcf0 -- [3cf00004] &= ~0x10 power off infinite loop 00030578 guess: draw "ready to play"/"ready to record" screen 30578(): 00030604 literal pool 00030610 asciz: "Ready to Play": 00030624 asciz: "Ready to Record": 00030630 -- end of literal pool 00030ac8 reference in array at 0x4aabc arg1 <= 0xd [arg2] is a FILE pointer return value is 0 or 1 int 30ac8(uint_t arg1=r0, unknown *arg2=r1, unknown *arg3=r2, arg4=r3, FILE *arg5=[sp]): 00030b28 -- r0 = "Ogg Vorbis Player"; goto 0x30b84; 00030d58 literal pool 00030d60 asciz: "Ogg Vorbis Player" 00030d78 -- end of literal pool 00030dfc reference in array at 0x4aabc arg1 <= 0xe arg2 is same type as arg2 in 30ac8 30dfc(uint_t arg1=r0, unknown *arg2=r1, arg3=r2, arg4=r3, FILE *arg5=[sp]): 00030e64 -- r0 = "WMA Windows Media(tm) Audio"; goto 0x30e9c; 0003101c literal pool 00031028 asciz: "WMA Windows Media(tm) Audio" 00031044 -- end of literal pool 00031160 31160(arg1=r0, arg2=r1, arg3=r2, arg4=r3) 00031178 -- ip = [000b41f0 + ((byte [000b4270 + (r0 << 2) + 2]) << 2)] 000311ac -- r0 = ([000b4248 + (([000b4220 + ((byte [000b4270 + (r0 << 2) + 3]) << 2)]) << 2)] & 0x1) + (([000b4220 + ((byte [000b4270 + (r0 << 2) + 3]) << 2)] | ([3c500000] & 0xff)) & 0xf) 000311c0 -- r2 = (r3 & 0x1) + (r2 & 0xf) 000311c4 -- lr = r2 & 0xf000000 000311c8 -- r4 = [000b4220 + ((byte [000b4270 + (r0 << 2) + 3]) << 2)] & 0xf000000 000311d0 -- if (r1 != ip) goto 0x311e0 000311d8 -- if (r0 > r2) goto 0x31208 000311dc -- goto 0x311f4 000311e4 -- if (r4 <= lr) goto 311fc 000311f0 -- if (r0 > r2) return 0x1 000311f8 -- return 0x2 00031204 -- if (r0 < r2) return 0x10 0003120c -- return 0x20 00031240 31240(arg1=r0): 00031244 -- ip = [220000f0] 0003124c -- if (arg1 == [220000f0]) return 00031258 -- [220000f0] = arg0 0003126c -- fp = 0x3c500000 00031270 -- r7 = [000b41d8 + ((byte [000b4270 + (arg0 << 2)]) << 2)] 00031284 -- r8 = [000b41d8 + ((byte [000b4270 + (arg0 << 2) + 1]) << 2)] 00031290 -- r1 = [000b41f0 + ((byte [000b4270 + (arg0 << 2) + 2]) << 2)] 00031294 -- [220000f4] = [000b41f0 + ((byte [000b4270 + (arg0 << 2) + 2]) << 2)] 000312a0 -- r9 = [000b4208 + ((byte [0xb4270 + (arg0 << 2) + 2]) << 2)] 000312a8 -- r6 = [000b4248 + ((byte [0xb4270 + (arg0 << 2) + 3]) << 2)] 000312b0 -- sl = [000b4220 + ((byte [0xb4270 + (arg0 << 2) + 3]) << 2)] 000312bc -- r5 = [000b4220 + ((byte [0xb4270 + (arg0 << 2) + 3]) << 2)] | ([3c500000] & 0xff) 000312c0 -- r2 = [000b4220 + ((byte [0xb4270 + (arg0 << 2) + 3]) << 2)] | ([3c500000] & 0xff) 000312c4 -- r0 = [220000f0] & 0xff /* old value before arg0 was written here */ 000312c8 -- r3 = [000b4248 + ((byte [0xb4270 + (arg0 << 2) + 3]) << 2)] 000312cc -- r0 = 31160(r0, r1, r2, r3) 000314a8 314a8(): 000314b0 -- 31240(0x4) 000314b8 -- 31240(0x6) 000314c0 -- return 313f8() 000314f0 literal pool 00031544 -- end of literal pool 00032008 comparison with "FAT16 " return value is 0 on error, 1 on success initialize fields in arg1 based on data read from FAT boot sector. arg1 is a struct (at 0x2200025c) arg2 array is empty space for 0x200 bytes int fat_info_update(fat_info_t *arg1=r0, u8_t *arg2=r1): 0003203c -- r5 = arg1; r4 = arg2; r6 = 0; fun = [arg1]; r0 = fun([arg1+4], arg2, 2, 0, 1, arg2); /* guess: read first sector from NAND (read func: 2, offset 0 sectors, size 1 sector, to arg2)? */ 00032044 -- if (r0 == 0) return 0; 00032068 -- r7 = 0x22001d64; if (memcmp(&arg2[0x1fe], "\x55\xaa", 2)) { [0x22001d64] |= 2; return 1; } 00032084 -- if (!memcmp(arg2, "\x00\x00\x00", 3)) { 0003208c -- fs_format(0); 000320b0 -- fun = [arg1]; r0 = fun([arg1+4], arg2, 2, 0, 1, arg2); 000320b8 -- if (r0 == 0) return 0; } 000320c8 -- r0 = (arg2[0x14] << 8) | arg2[0x13]; /* FAT: total sectors */ if (r0 == 0) { /* use 32-bit value instead */ 000320e8 -- r0 = (arg2[0x23] << 24) | (arg2[0x22] << 16) | (arg2[0x21] << 8) | arg2[0x20]; /* FAT: total sectors */ } 00032138 -- [22001d64] &= ~0x4; if (memcmp(&arg2[0x36], "FAT1? ", 8)) { /* <- `?' is wildcard */ [22001d64] |= 0x4; return 0; } 0003214c -- if (arg2[0x3a] == 0x32) { /* if FAT12 */ r1 = byte [arg1+8] | 1; } else { 00032154 -- if (arg2[0x3a] != 0x36) return 0; /* if ! FAT16 */ 0003215c -- r1 = byte [arg1+8] & ~1; } 000321e0 -- byte [arg1+8] = r1; hword [arg1+0x1c] = bswap16([arg2+0xe]); /* reserved sector count */ byte [arg1+9] = arg2[0x10]; /* number of FATs */ [arg1+0xc] = bswap16([arg2+0x16]); /* sectors per FAT */ [arg1+0x20] = (bswap16([arg2+0x16]) * arg2[0x10]) + bswap16([arg2+0xe]); /* FAT + reserved sector count */ [arg1+0x18] = bswap16([arg2+0x11]); /* root dir entries */ [arg1+0x24] = (bswap16([arg2+0x16]) * arg2[0x10]) + bswap16([arg2+0xe]) + (bswap16([arg2+0x11]) / 16); /* FAT reserved + reserved sector count + root dir entries div 16 */ [arg1+0x10] = arg2[0xd]; /* sectors per cluster */ if (arg2[0xd] == 0) [22001d64] |= 2; r0 = (r0 - ((bswap16([arg2+0x16]) * arg2[0x10]) + bswap16([arg2+0xe]) + (bswap16([arg2+0x11]) / 16))) / arg2[0xd]; /* min free clusters */ 000321e8 -- [arg1+0x14] = ...; /* min free clusters plus 2 */ 00034e78 somehow seek to specified position int fat_file_seek(arg1=r0, arg2=r1, arg3=r2, fat_file *f=r3, arg5=[sp], arg6=[sp+4]): 00034e84 -- r8 = arg2; r1 = arg6; r6 = arg5; 00034fd4 return size of FAT file system file f uint_t fat_file_size(fat_file *f=r0): 00035b10 int? 35b10(arg1=r0, arg2=r1, arg3=r2, wchar_t *arg4=r3, arg5=[sp]): 00035e64 verify: update the fields 'sectors per FAT' and 'total sectors (32bit)' based on the values in 'sectors per cluster', 'reserved sector count', 'number of FATs' and 'root dir entries' in the FAT parameter block at arg1. void fat_update_sector_count(u8_t *fat_parm_block): 00035eec verify: format NAND with FAT filesystem arg1 is a struct (at 0x2200025c) arg2 is probably empty space, at least 0x200 bytes arg3 is probably also empty space, at least 0x200 bytes int fat_blockdev_format(fat_info_t *arg1=r0, u8_t *arg2=r1, u8_t *arg3=r2): 00035f18 -- r4 = arg1; r5 = arg3; r7 = arg2; fun = [arg1]; r0 = fun([arg1+4], arg2, 7, 0, 0, 0); 00035f20 -- if (r0 == 0) return 0; 00035f3c -- /* Copy first part of FAT parameter block to space at arg3. There is a first part for each size of NAND (512M, 1G, 2G, ..?). The result from the function call determines which first part to use. */ 00035f4c -- /* Copy second part of FAT paramter block to space at arg3. */ 00035f54 -- /* Update 'sectors per FAT' and 'total sectors (32bit)'. */ fat_update_sector_count(arg3); 00035f78 -- fun = [arg1]; r0 = fun([arg1+4], arg2, 5, 0, 1, arg3); /* guess: write to NAND (write func: 5, at sector 0, size: 1 sector, from arg3)? */ 00035f80 -- if (r0 == 0) return 0; 00035f8c -- r0 = fat_info_update(arg1, arg2); /* update fields in arg1 based on arg2 */ 00035f94 -- if (r0 == 0) return 0; 00035fa0 -- memclr(arg3, 0x200); 00035fe4 -- fun = [arg1]; r0 = fun([arg1+4], arg2, 5, arg1->reserved_sects + r6, 1, arg3); /* guess: write to NAND (write func: 5, offset: sector arg1->reserved_sects + r6, size: 1 sector, from arg3) */ 00036014 -- r0 = 32264(arg1, arg2, arg3, 0, 0xfff8); 00036038 -- r0 = 32264(arg1, arg2, arg3, 1, 0xffff); 0003642c seek to entry then read 512 bytes from playlist file (path at 0x22002228), to data. if entry is -1, then update a field at 0x2200243a based on the size of the playlist file (possibly number of entries in file), then read playlist header (512 bytes) to data. return value == 0 means error int playlist_read_entry(int_t entry=r0, u8_t* data=r1): 000365bc gui related (calls to gui_draw_string) playlist related (reference to `iriver UMS PLA' string) possibly playlist drawing/gui update routine? arg1 is current cursor position void gui_playlist_redraw(uint_t cursor=r0): 000365e0 -- r0 = playlist_read_entry(-1, sp+0x14); /* read header */ 00036650 -- ... r0 = wcslen(0x22002228); 00036e78 playlist related (reference to `iriver UMS PLA' string) int? 36e78(): 00036e8c -- memcpy(sp+0x450, L"iriver.tmp", 0x14); 00036e9c -- memclr_aligned(sp+0x464, 0x2c); 00036ed8 -- (hword *)(sp+8) = ...; r0 = fopen(sp+0x42c, 0, L"iQuickList.pla", 1, 0x20); 00036f0c -- r0 = fopen(sp+0x42c, 0, L"iQuickList.pla", 7, 0x20); 00036f44 -- r0 = fread(sp+0x42c, sp+0x208, 0x200); /* read header */ 00036f54 -- r6 = r0; fclose(sp+0x42c); 00036f90 -- r0 = fsize(sp+0x42c); 00036fb8 -- r0 = fun_36d38(L"iQuickList.pla", sp+0x450); 00036fc4 -- r0 = fs_delete(0, L"iQuickList.pla"); 00037000 -- r0 = fsize(sp+0x408); 00037024 -- r6 = r0; r0 = fopen(sp+0x42c, 0, L"iQuickList.pla", 7, 0x20); 00037038 -- fclose(sp+0x408); 00037098 -- fseek(sp+0x408, 0x200); 000371e4 remove all non-existing tracks from the quicklist (iQuickList.pla) by first copying all entries for existing files to iriver.tmp, then deleting iQuickList.pla and recreating it. int quicklist_fixup(): 000371f8 -- memcpy(sp+0x270, L"iriver.tmp", 0x14); 00037204 -- memclr_aligned(sp+0x284, 0x2c); 00037224 -- r0 = fopen(sp+0x24c, 0, L"iQuickList.pla", 1, 0x20); 00037234 -- r0 = fsize(sp+0x24c); 00037254 -- r0 = fread(sp+0x24c, sp+4, 0x200); /* read header */ 00037268 -- r9 = "iriver UMS PLA"; r0 = 0; 000372c0 -- r0 = fopen(sp+0x228, 0, L"iriver.tmp", 7, 0x20); 000372d8 while (r5 < r6) { 000372e4 -- r0 = fread(sp+0x24c, sp+4, 0x200); /* read next entry */ 0003730c -- r0 = fopen(sp+0x204, 0, sp+6, 9, 0x20); /* open music file */ 0003731c -- fclose(sp+0x204); 0003732c -- fwrite(sp+0x228, sp+4, 0x200); /* r7 is always 0x200 */ 0003733c -- } 00037344 -- fclose(sp+0x24c); 0003734c -- fclose(sp+0x228); 00037358 -- fs_delete(0, L"iQuickList.pla"); 0003737c -- r0 = fopen(sp+0x228, 0, L"iriver.tmp", 1, 0x20); 0003738c -- r0 = fsize(sp+0x228); 000373b0 -- r0 = fopen(sp+0x24c, 0, L"iQuickList.pla", 7, 0x20); 000373c8 -- memclr_aligned(sp+4, 0x200); 000373e8 -- ... /* build playlist header at sp+4 */ 000373f8 -- ... /* copy "Quick List\0\0\0\0\0\0" into header at sp+4 */ 00037408 -- fwrite(sp+0x24c, sp+4, 0x200); 000379a4 -- looped infinitely 00037a50 -- looped infinitely 000382c0 draw media type icon, volume, sample rate etc. in display. (this happens when the volume is adjusted) void? gui_draw_media_and_volume_info(byte arg1=r0): 00038878 38878(): 0003947c other function reports "[FTL:ERR] there is error on _StoreFTLCxt!" if this fails, error occurs if return value == 0 int StoreFTLCxt(int arg1=r0): 000394b8 -- r5 = [r4+12] OAM_Assert((r0 > r5), "D:\work\T10_BLUES\working\whimory_update\" "T10N_BLUES_20060712\whimoryv2\Core\FTL\FTLInterface.c", 444); 00039960 other function reports "[FTL:ERR] there is error on _ConvertL2V!" if this fails, error occurs if return value == 0 int ConvertL2V(int arg1=r0, int *arg2=r1): 00039a14 other function reports "[FTL:ERR] there is error on _LoadFTLCxt!" if this fails, error occurs if return value == 0 int LoadFTLCxt(): 00039a88 -- if (r6 == -1) log_printf("[FTL:ERR] Can not find context!") 00039d14 ModifyECTbl(int nVbn=r0): 00039d3c -- log_printf("[VFL:ERR] _ModifyECTbl(nVbn:%d) input overflow!", nVbn) 00039d7c -- r4 = r0 OAM_Assert((r0 < 0x100), "D:\work\T10_BLUES\working\whimory_update\" "T10N_BLUES_20060712\whimoryv2\Core\FTL\FTLInterface.c", 2395); 00039e7c -- ... OAM_Assert((r0 > r6), "D:\work\T10_BLUES\working\whimory_update\" "T10N_BLUES_20060712\whimoryv2\Core\FTL\FTLInterface.c", 1648); 00039eb0 -- ... OAM_Assert((r5 > r6), "D:\work\T10_BLUES\working\whimory_update\" "T10N_BLUES_20060712\whimoryv2\Core\FTL\FTLInterface.c", 1648); 00039f00 other function reports "[FTL:ERR] there is error on _GetEC!" if this fails, error occurs if return value == 0 int GetEC(nLbn=r0, unknown *arg2=r1): 00039f28 -- log_printf("[VFL:ERR] _GetEC(nLbn:%d) input overflow!", nLbn) 00039fc4 other function reports "[FTL:ERR] there is error on _GetFreeVb!" if this fails, error occurs if return value == 0 int GetFreeVb(arg1=r0, arg2=r1, arg3=r2): 0003a154 other function reports "[FTL:ERR] there is error on _DoSimpleMerge!" if this fails, error occurs if return value == 0 int DoSimpleMerge(int arg1=r0): 0003a364 literal pool 0003a3fc -- end of literal pool 0003a55c other function reports "[FTL:ERR] there is error on _MakeLogMap!" if this fails, error occurs if return value == 0 int MakeLogMap(): 0003a898 -- log_error("[FTL:LOG] Sudden power off Occurs!") 0003a940 -- log_error("[FTL:LOG] Sudden power off Occurs!") 0003ab70 literal pool 0003ab9c -- end of literal pool 0003ac08 other function reports "[FTL:ERR] there is error on _ModifyReclaimMap!" if this fails, error occurs if return value == 0 int ModifyReclaimMap(arg1=r0, arg2=r1): 0003acb4 other function reports "[FTL:ERR] there is error on _MoveD2F!" if this fails, error occurs if return value == 0 int MoveD2F(arg1=r0, arg2=r1, arg3=r2, arg4=r3, ..): 0003ae70 int 3ae70(): 0003b274 other function reports "[FTL:ERR] there is error on _DoCopyMerge!" if this fails, error occurs if return value == 0 int DoCopyMerge(arg1=r0, ..): 0003b4e0 other function reports "[FTL:ERR] there is error on _DoMoveMerge!" if this fails, error occurs if return value == 0 int DoMoveMerge(arg1=r0, ..): 0003b6e8 other function reports "[FTL:ERR] there is error on _Merge!" if this fails, error occurs if return value == 0 int Merge(arg1=r0): 0003c724 return value != 0 means error int FTL_Init(): 0003b8c8 literal pool 0003b97c -- end of literal pool 0003b980 other function reports "[FTL:ERR] there is error on _PrepareLog!" if this fails, error occurs if return value == 0 int? PrepareLog(arg1=r0): 0003bae0 return value != 0 means error int FTL_Open(arg1=r0): 0003bb80 read from NAND through FTL offset (nLsn) and size (nNumOfScts?) is in 512-byte sectors buffer (pBuf) is empty space large enough to hold read data int FTL_Read(size_t offset=r0, size_t size=r1, void *buffer=r2): 0003bba0 -- ... if (buffer == NULL) { log_printf("[FTL:ERR] pBuf == NULL!"); return ..; } 0003bbd4 -- log_printf("[FTL:ERR] FTL_Read(nLsn:%d, nNumOfScts:%d)" " input parameters are invalid!", offset, size) 0003bebc offset (nLsn) and size (nNumOfScts) is in 512-byte sectors buffer (pBuf) is data to be written int FTL_Write(size_t offset=r0, size_t size_t=r1, void *buffer=r2): 0003bedc -- ... if (buffer == NULL) { log_printf("[FTL:ERR] pBuf == NULL!"); return ..; } 0003bf08 -- log_printf("[FTL:ERR] FTL_Write(nLsn:%d, nNumOfScts:%d)" " input parameters are invalid!", offset, size) 0003c4d4 return value != 0 means error int FTL_Format(): 0003c744 -- pstLOGCxt = OAM_Malloc(0xe0) 0003c76c -- ... paPOffsetL2P = OAM_Malloc(r0) 0003c784 -- ... paSecBitmap = OAM_Malloc(r0) 0003c7c4 -- pstFTLMeta = OAM_Malloc(0x800) 0003c7e8 -- ... pTempSpare = OAM_Malloc(r0) 0003cb00 int 3cb00(): 0003cb08 -- return [220074c0] 0003cb14 void 3cb14(int arg1=r0): 0003cb24 -- [22000110] = (arg1 ? 1 : 0) 0003cb28 other function reports "[FTL:ERR] there is error on _ModifyMap!" if this fails, error occurs if return value == 0 int ModifyMap(arg1=r0, arg2=r1): 0003cb6c unknown *BUF_Init(): 0003cb90 -- BUFCxt = OAM_Malloc(0x28) 0003cba0 -- ... if (BUFCxt == NULL) { log_printf("[BUF:ERR] BUF_Init(VOID) BUFCxt Init Failure"); return ...; } 0003cba8 -- BUFCxt->pBufferList = OAM_Malloc(0x20) 0003cbbc -- if (BUF->pBufferList == NULL) { log_printf("[BUF:ERR] BUF_Init(VOID) BUFCxt->pBufferList Init Failure"); return ...; } 0003cc08 -- ... if (r1 == 0) { log_printf("[BUF:ERR] BUF_Init(VOID) pBufIdx->pData, pBufIdx->pSpare" " Init Failure") return ...; } 0003cc50 literal pool 0003cccc -- end of literal pool 0003ccd0 other function reports "[FTL:ERR] there is error on BUF_Get!" if this fails, error occurs if return value != 0 int? BUF_Get(int eType=r0): 0003ccec ... if (r0 == 0) { log_printf("[BUF:ERR] BUF_Get(eType = %d) Buffer manager " is not initialized, eType); return 0; } 0003cd54 -- r0 = ... if (r0 == 0) { log_printf("[BUF:ERR] BUF_Get(eType = %d) No free buffer", eType); return 0; } 0003cd90 -- log_printf("[BUF:ERR] BUF_Get(eType = %d) Can't find a free buffer", eType) 0003cdf4 literal pool 0003ce64 -- end of literal pool 0003ce68 void 3ce68(arg1=r0): 0003cf70 3cf70(arg1=r0, arg2=r1): 0003d0c8 other function reports "[VFL:ERR] _StoreVFLCxt(nBank:%d) fail!" if this fails, error occurs if return value == 0 int StoreVFLCxt(int nBank=r0, ..): 0003d14c log_printf("[VFL:ERR] there is no spare to write VFL context"); 0003d388 literal pool 0003d3cc -- end of literal pool 0003d60c other function reports "[VFL:ERR] _GetReservedBlk(nBank:%d, nSrcPbn:%d) fail!" if this fails, error occurs if return value != 0 ? int? GetReservedBlk(int nBank=r0, int nScrPbn=r1, ..): 0003d738 other function reports "[VFL:ERR] _ReplaceBadBlk(nBank:%d) fail!" if this fails, error occurs if return value != 0 int ReplaceBadBlk(int nBank=r0, arg2=r1, arg3=r2, arg4=r3, ..): 0003d798 -- log_printf("[VFL:ERR] _GetReservedBlk(nBank:%d, nSrcPbn:%d) fail!", nBank, nScrPbn); 0003d840 -- log_printf("[VFL:ERR] there is no reserved block!!!"); 0003d880 -- log_printf("[VFL:ERR] there is no reserved block!!!"); 0003d8cc -- log_printf("[VFL:ERR] there is no reserved block!!!"); 0003d9d8 -- log_printf("[VFL:ERR] there is no reserved block!!!"); 0003dab8 -- log_printf("[VFL:ERR] erase fail occurs when replaces bad block!!!"); 0003dac4 literal pool 0003db6c -- end of literal pool 0003dfbc int 3dfbc(int nBank=r0): 0003e000 -- log_printf("[VFL:INF] erase fail occurs (nPbn original=%d)!!!", [r4]) 0003e088 -- if (r0 == 0) { log_printf("[VFL:ERR] _ReplaceBadBlk(nBank:%d) fail!", nBank) } 0003e0a0 -- log_printf("[VFL:ERR] _StoreVFLCxt(nBank:%d) fail!", nBank) 0003e164 return value == 0 means error int DoSync(int nBank=r0): 0003e2c8 return value == 0 means error int CheckInitialBad(..): 0003e4d4 literal pool 0003e500 -- end of literal pool 0003e504 other function reports "[FTL:ERR] there is error on VFL_Sync!" if this fails, error occurs if return value != 0 int? VFL_Sync(): 0003e550 literal pool 0003e578 -- end of literal pool 0003e57c return value != 0 means error int VFL_Init(): 0003e5c0 -- pstVFLCxt = OAM_Malloc([r6] << 11); 0003e5e8 -- pstAsyncOp = OAM_Malloc([r6] << 5); 0003e610 -- pVFLSpare = OAM_Malloc([220074cc]); 0003e77c return value != 0 means error int VFL_Open(): 0003e7f4 other function reports "[FTL:ERR] there is error on VFL_Read!" if this fails, error occurs if return value != 0 (0xffff0000 ?) int? VFL_Read(arg1=r0, arg2=r1, arg3=r2): 0003e9dc literal pool 0003ea0c -- end of literal pool 0003ea10 other function reports "[FTL:ERR] there is error on VFL_Write!" if this fails, error occurs if return value != 0 int? VFL_Write(arg1=r0, arg2=r1, arg3=r2): 0003ec1c literal pool 0003ec70 -- end of literal pool 0003ec74 other function reports "[FTL:ERR] there is error on VFL_Erase!" if this fails, error occurs if return value != 0 int? VFL_Erase(arg1=r0): 0003eff0 literal pool 0003f054 -- end of literal pool 0003f0e8 other function reports "[FTL:ERR] there is error on VFL_Copyback!" if this fails, error occurs if return value != 0 int? VFL_Copyback(arg1=r0, arg2=r1, arg3=r2): 0003f788 literal pool 0003f7bc -- end of literal pool 0003f7fc return value != 0 means error int VFL_Format(): 0003fc58 other function reports "[FTL:ERR] there is error on VFL_ChangeFTLCxtVbn !" if this fails, error occurs if return value != 0 int VFL_ChangeFTLCxtVbn(arg1=r0): 0003fcc0 literal pool 0003fce4 -- end of literal pool 0003fce8 return value == 0 means error int WriteInitBadList(..): 0003fe18 arg1 is on the stack for a while int 3fe18(arg1=r0): 000403dc void WMR_EraseAll(): 000406a8 void NAND_Reset(): 000406cc int? NAND_Sync(arg1=r0): 00040acc void Read_ID(arg1=r0, arg2=r1, arg3=r2): 00040c74 int? NAND_Init(): 00041030 unknown *NAND_Read(..): 00041a0c -- wait for interrupt? 00041a44 -- ... log_printf("[FIL : ERR] Uncorrectable Main ECC Error" " [nBank:%d, nPbn:%d, nPpn:%d]", r1, r2, r3); 00041cb4 -- wait for interrupt? 00041d00 -- ... log_printf("[FIL : ERR] Uncorrectable Spare ECC Error" " [nBank:%d, nPbn:%d, nPpn:%d]", r1, r2, r3); 00041f54 void NAND_Write(arg1=r0, arg2=r1, arg3=r2): 000423bc -- wait for interrupt? 00042440 -- wait for interrupt? 0004274c -- wait for interrupt? 000428ac -- wait for interrupt? 00042a84 void NAND_Erase(arg1=r0): 00042d74 initialize NAND, then set up fil_func_table at 0x2200785c return value != 0 means error int FIL_Init(): 00042dc0 return value == NULL means error fil_func_table_t *FIL_GetFuncTbl(..): 00042de4 verify: seems to be ogg vorbis (or tremor) codebook.c: bitreverse(). void? 42de4(unknown *arg1=r0, unknown *arg2=r1): 00043074 verify: seems to be ogg vorbis (or tremor) sharedbook.c: bitreverse(). void? 43074(unknown *arg1=r0, unknown *arg2=r1): 00043684 allocate size bytes of memory there is probably no OAM_Free void *OAM_Malloc(size_t size=r0): size_words -> r4 next_offset -> r1 000436a8 -- size_words = size >> 2 + ((size & 0x3) ? 1 : 0) next_offset = [22007874] + size_words [22007874] += size_words if (next_offset > 0x1100) { 000436b8 -- log_printf("[OAM:ERR] OAM_Malloc Error [%d:%d:%d]!", next_offset, size, size_words) return 0 } 000436d0 -- log_printf("[OAM:OK] OAM_Malloc OK [%d:%d:%d]!, next_offset, size, size_words) 000436e4 -- return 0x22007878 + (([22007874] - size_words) << 2) 000436e8 literal pool 00043744 -- end of literal pool 00043830 if test is false print error then loop infinitely void OAM_Assert(int test=r0, char *filename=r1, int line=r2): 00043840 -- if (!test) { 00043850 -- log_printf("[FTL:ERR] OAM_Assert Error [%s:%d]!", filename, line); 00043860 -- log_printf("", filename, line); 00043864 -- while (1) {} /* loop infinitely */ } 000438d8 reference at 0xb414 verify: size and offset are in 512-byte sectors ftl_access_handler(unknown *arg1=r0, u8_t *arg2=r1, uint_t func=r2, size_t offset=r3, size_t size=[sp], u8_t *arg6=[sp+4]): 0004551c int 4551c(arg1=r0): -- r1 = 0xfff; 00045524 -- do { r1 -= 1; } while (r1 >= 0); 0004553c -- r2 = 0x3c900000; [3c90000c] = arg1; [3c900004] = 0xf0; r1 = 0; 00045540 do { 00045550 -- r0 = r1; r1 += 1; if (r0 > 0x186a0) break; 0004555c -- } while (!([3c900000] & 0x10)); 00045568 -- return ([3c900004] & 1); 00045d0c clear (set to 0) n bytes of memory starting from dest memclr(dest=r0, n=r1): -- equivalent of a tail call to memset_word(dest, n, 0x0) 00045d10 assign the value val to n bytes of memory starting from dest requires: (val & 0xff) == ((val & 0xff00) >> 8) == ((val & 0xff0000) >> 16) == ((val && 0xff000000) >> 24) memset_word(dest=r0, n=r1, val=r2): 00045d14 -- if (n < 0x4) goto 0x45d3c 00045d1c -- if (n & 0x3) memset_word_aligned(dest, n, val) 00045d20 -- ip = 0x4 - (n & 0x3) 00045d28 -- byte [n] = val r0 = n + 1 00045d2c -- if ((n & 0x3) >= 0x2) { byte [n + 1] = val r0 += 1 } 00045d30 -- if ((n & 0x3 > 0x2) { /* == 0x3 */ byte [r0] = val r0 += 1 } 00045d38 -- memset_word_aligned(r0, r1, val) /* r0 == aligned(dest) */ 00045d3c -- ip = r1 << 31 if (r1 > 0x1) { 00045d44 -- byte [r0] = val byte [r0+1] = val r0 += 2 } if (r1 & 0x1) { 00045d48 -- byte [r0] = val r0 += 1 } 00045d4c -- return 00045d50 clear (set to 0) n bytes of memory starting from dest requires: dest & 0x3 == 0x0 memclr_aligned(dest=r0, n=r1): -- equivalent of a tail call to memset_word_aligned(dest, n, 0x0) 00045d54 assign the value val to n bytes of memory starting from dest requires: dest & 0x3 == 0x0 requires: (val & 0xff) == ((val & 0xff00) >> 8) == ((val & 0xff0000) >> 16) == ((val && 0xff000000) >> 24) memset_word_aligned(dest=r0, n=r1, val=r2): -- push lr to stack 00045d60 -- r3 = 0 ip = 0 lr = 0 00045d64 -- r1 = arg2 + (arg1 & 0x3) - 0x24 00045d68 while (r1 > 0) { 00045d70 -- set [r0 .. r0+0x20] to val r0 += 0x20 r1 -= 0x20 00045d74 -- } 00045d78 -- r1 = r1 << 0x1c 00045d7c if (r1 >= 0x10) { -- set 0x10 more bytes to val 00045d80 } else if (r1 >= 0x8) { -- set 0x8 more bytes to val } 00045d84 -- restore lr from stack 00045d88 -- r1 = r1 << 2 00045d8c -- if (r1 ...) 00045d90 -- return 00045d98 -- set two more 00045da0 -- set last byte 00045da4 -- return 00045da8 void *memcpy(void *dest=r0, void *src=r1, size_t n=r2): 00045e5c dest and src must be word aligned void *memcpy_aligned(void *dest=r0, void *src=r1, size_t n=r2): 00045f08 assign the value val to n bytes of memory starting from dest void memset(dest=r0, val=r1, n=r2): 00045f18 -- memset_word(dest, n, (val & 0xff) | ((val & 0xff) << 8) | ((val & 0xff) << 16) | ((val & 0xff) << 24)) return 00045f1c return the byteswaped value stored at src u32_t le32dec(u32_t *src): 00045f3c store the byteswapped value of src at dest void le32enc(u32_t src, u32_t *dest): 0004646c r0:r1=int 4646c(int arg1=r0:r1, int arg2=r2:r3): 00047940 usually swi 0x123456 is syscall swi syscall 0x3 with arg r13 are syscalls for debugging purposes thus ifdef'ed out? syscall_0x3(byte arg1=r0): 00047a2c integer division (p / q) the value of ip is never used int_div(q, p): -- r2 = 0 00047a34 -- if ((r1 >> 3) <= r0) goto 0x47abc 00047a78 -- if ((r1 >> 8) > r0) { r0 <<= 8 r2 |= 0xff000000 if ((r1 >> 4) <= r0) goto 0x47ab0 if ((r1 >> 8) > r0) { r0 <<= 8 r2 |= 0xff0000 if ((r1 >> 8) > r0) { r0 <<= 8 r2 |= 0xff00 } if ((r1 >> 4) <= r0) goto 0x47ab0 if (r0 < 0) return r0 /* ?? */ } } 00047ae0 -- do { /* unwound loop in compressed form... */ for (i = 7; i >= 0; i--) { r2 <<= 1 if ((r1 >> i) > r0) { r1 -= (r0 << i) r2 += 1 } } r0 >>= 8 /* from 47a7c (never executed in first iteration) */ } while (last r2 overflowed into carry) 00047ae8 -- return r2 000480dc int memcmp(const void *s1=r0, const void *s2=r1, size_t n=r2): 0004814c size_t strlen(const char *s): 00048168 size_t wcslen(const wchar_t *s): 00048184 size_t wcscmp(const wchar_t *arg1=r0, const wchar_t *arg2=r1): 00048194 -- while (*arg1 != L'\0' && *arg1 == *arg2) { arg1 += 2; arg2 += 2; } 0004819c -- return (r2 - r3); 000481a0 int 481a0(arg1=r0, arg2=r1): 0004835c double copysign_4835c(double x=r0:r1, double y=r2:r3): 0004836c double copysign_4836c(double x=r0:r1, double y=r2:r3): 00048554 reset handler (supervisor mode): reset_handler(): -- indirect jump to 0x48558 00048564 -- p15:cr1 |= 0x80: switch memory access to big-endian 000485cc -- [3c800000] = 0xa5 disable the watchdog timer(?) [39c00008] = 0x0 [39c00020] = 0x0 [39c00000] = 0xffffffff [39c00010] = 0xffffffff [39c0001c] = 0xffffffff reset IRQ controller ?? [3c400000] = 0x0 [3c400004] = 0x2 [3c500040] = 0x2f8072a5 [3c500044] = 0x0 00048608 -- [3c500004] = 0x36d201 [3c500008] = 0x36d201 [3c500020] = 0xfd2 [3c500024] = 0xfd2 [3c500036] = 0x3 00048614 -- loop until [3c500032] == 0x3 00048640 -- [3c500000] = 0x2131313b [3c50003c] = 0x100 with 2 nop after each write 0004866c -- [38200034] = 0x100000 [38200038] = 0x110711 [3820003c] = 0x110711 00048698 -- [38200054] = 0x0 [38200050] = 0x0 [3820004c] = 0x0 [38200060] = 0x77 000486ac -- p15:cr1 |= 0xc00000f8: enable write buffer, disable 26-bit backwards compat., disable obsolete ARMv3 abort model, switch memory access to big-endian. (the effect of bits 30 and 31 are unknown) 000486c0 -- value in r1 apparently unused 000486e0 -- [3c500040] = 0x0 [3c500044] = 0x0 000486f4 if (mode != supervisor) { -- switch to supervisor mode 00048704 -- p15:cr1 &= ~0x1: disable memory protection unit } 00048710 -- set fast interrupt mode stack to 2200ce70 0004871c -- set interrupt mode stack to 2200ce50 00048728 -- set abort mode stack to 2200c650 00048734 -- set undefined mode stack to 2200c630 00048740 -- set supervisor mode stack to 2200f8f0, and enable interrupts 00048758 -- r1 = 114 + b4d44 while (r0 > 22000000) { 00048760 -- r0 -= 4, r1 -= 4 [r0] = [r1] } 00048764 -- copy 114 words from b4d44 to 22000000 i.e.: memcpy(0x22000000, 0xb4d44, 0x114) 0004876c -- r1 = 2200f8f0 00048778 while (r3 < 2200f8f0) { -- [r3] = 0 r3 += 4 } 0004877c -- clear 0x22000114 - 0x2200f8f0 i.e. memset(0x22000114, 0x0, 0x2200f8f0 - 0x22000114) 00048790 -- end of reset handler 00048794 enable protection unit, enable data cache, enable write buffer, disable 26-bit backwards compat., disable obsolete ARMv3 abort model, switch memory access to big-endian, enable intruction cache. (the effect of bits 30 and 31 are unknown) void cache_and_mpu_enable(): 00048798 -- p15:cr1 = 0xc00010fd 0004879c -- return 000487a0 enable instruction cache void cache_instr_enable(): 000487ac -- p15:cr1 |= 0x1000 000487b0 -- return 000487b4 enable data cache void cache_data_enable(): 000487c0 -- p15:cr1 |= 0x4 000487c4 -- return 000487c8 disable protection unit void mpu_disable(): 000487d4 -- p15:cr1 &= ~0x1 000487d8 -- return 000487dc disable instruction cache void cache_instr_disable(): 000487e8 -- p15:cr1 &= ~0x1000 000487ec -- return 000487f0 disable data cache void cache_data_disable(): 000487fc -- p15:cr1 &= ~0x4 00048800 -- return 00048804 invalidate entire instruction cache void cache_instr_invalidate(): 00048808 -- p15:cr7 function 0, cr5, 0 00048818 -- return 0004881c invalidate entire data cache void cache_data_invalidate(): 00048820 -- p15:cr7 function 0, cr6, 0 00048830 -- return 00048834 clean and invalidate som data cache lines 48834(): -- r1 = 0 00048838 do { -- r0 = 0 0004883c do { 0004884c -- r2 = r0 | r1 p15:cr7 function 0, cr14, 1 with parameter r2: clean and invalidate data cache line r0 += 0x10 } while (r0 != 0x40) /* r0 = 0, 0x10, 0x20, 0x30 */ 00048858 -- r1 += 0x4000000 } while (r1 != 0) /* r1 = 0, 0x4000000, 0x8000000, ..., 0xfc000000 */ 00048860 -- return 00048864 initialise memory protection unit void mpu_init(): 00048898 -- p15:cr6 function 0, cr0, 1 with param 0x0000003f: set instruction protection region 0 (0x00000000 - 0xffffffff, enabled) p15:cr6 function 0, cr1, 1 with param 0x00000023: set instruction protection region 1 (0x00000000 - 0x0003ffff, enabled) p15:cr6 function 0, cr2, 1 with param 0x00000027: set instruction protection region 2 (0x00000000 - 0x000fffff, enabled) p15:cr6 function 0, cr3, 1 with param 0x08000029: set instruction protection region 3 (0x08000000 - 0x081fffff, enabled) p15:cr6 function 0, cr4, 1 with param 0x24000027: set instruction protection region 4 (0x24000000 - 0x240fffff, enabled) p15:cr6 function 0, cr5, 1 with param 0x22000023: set instruction protection region 5 (0x22000000 - 0x2203ffff, enabled) p15:cr6 function 0, cr6, 1 with param 0x2c000029: set instruction protection region 6 (0x2c000000 - 0x2c1fffff, enabled) 0004889c -- p15:cr7 function 0, cr7, 1 with param 0x08000035: invalidate unified cache line (details..?) 000488e0 -- p15:cr6 function 0, cr0, 0 with param 0x0000003f: set data protection region 0 (0x00000000 - 0xffffffff, enabled) p15:cr6 function 0, cr1, 0 with param 0x24000027: set data protection region 1 (0x24000000 - 0x240fffff, enabled) p15:cr6 function 0, cr2, 0 with param 0x08140023: set data protection region 2 (0x08140000 - 0x0817ffff, enabled) p15:cr6 function 0, cr3, 0 with param 0x08180025: set data protection region 3 (0x08180000 - 0x081fffff, enabled) p15:cr6 function 0, cr4, 0 with param 0x08200029: set data protection region 4 (0x08200000 - 0x083fffff, enabled) p15:cr6 function 0, cr5, 0 with param 0x0840002b: set data protection region 5 (0x08400000 - 0x087fffff, enabled) p15:cr6 function 0, cr6, 0 with param 0x0880002d: set data protection region 6 (0x08800000 - 0x08ffffff, enabled) p15:cr6 function 0, cr7, 0 with param 0x0900002f: set data protection region 7 (0x09000000 - 0x09ffffff, enabled) 000488f0 -- p15:cr2 function 0, cr0, 1 with param 0x000000ff: set instruction region cachability (enable for all instruction regions) p15:cr2 function 0, cr0, 0 with param 0x00000000: set data region cachability (disable for all data regions) 000488f8 -- p15:cr3 function 0, cr0, 0 with param 0x00000000: set data region bufferability (disable for all regions) 00048908 -- p15:cr5 function 0, cr0, 1 with param 0x00000fff: set instruction region access permissions (0-5: read/write, 6-7: no access) p15:cr5 function 0, cr0, 0 with param 0x0000ffff: set data region access premissions (0-7: read/write) 0004890c -- return; 00048910 no return from this function 48190(..): 00048948 literal pool 00048998 initial value for p15:cr1: 000489a0 fast interrupt mode stack address: 000489a4 interrupt mode stack address: 000489a8 abort mode stack address: 000489ac undefined mode stack address: 000489b0 supervisor mode stack address: 000489bc seems to be some kind of offset: 000489c8 copied to p15:cr1 (ref: 48784): 00048a08 -- end of literal pool 00048a0c r0:r1=int 48a0c(..): 00048f88 48f88(int arg1=r0:r1, int arg2=r2:r3): 00049488 literal pool 00049514 -- end of literal pool 00049594 literal pool -- end of literal pool 0004963c r0:r1=int 4963c(int arg1=r0): 00049790 r0:r1=int 49790(arg1=r0:r1, arg2=r2:r3): 00049a38 literal pool 00049a40 -- end of literal pool 00049f80 literal pool 00049fa0 -- end of literal pool 0004addc Array of function pointers (File I/O related) (length = 1): 0004aabc Array of function pointers (length = 5): 0: AUDIO_FILE_(WAV?)_MP3: 0004aac0 1: guess: AUDIO_FILE_MPEG_MP3: 0004aac4 2: AUDIO_FILE_(WAV?)_WMA: 0004aac8 3: guess: AUDIO_FILE_ASF_WMA: 0004aacc 4: guess: AUDIO_FILE_OGG_VORBIS: 00057e44 Byte array for language id mapping (length = 41): 00057e70 Array of function pointers (language related) (length = 11): 0: LANG_KOREAN: 00057e74 1: LANG_JAPANESE: 00057e78 2: LANG_ENGLISH_1: 00057e7c 3: LANG_ENGLISH_2: 00057e80 4: LANG_ENGLISH_3: 00057e84 5: LANG_ENGLISH_4: 00057e88 6: LANG_ENGLISH_5: 00057e8c 7: LANG_ENGLISH_6: 00057e90 8: LANG_ENGLISH_7: 00057e94 9: LANG_CHINESE_S: 00057e98 10: LANG_CHINESE_T: 0005809c Probably not firmware version