HTTP/1.1 200 OK Date: Mon, 04 Jul 2011 03:11:34 GMT Server: Apache Last-Modified: Thu, 30 Jun 2005 09:30:46 GMT ETag: "38331-160ce-3fabf27f1fd80" Accept-Ranges: bytes Content-Length: 90318 Content-Type: text/x-csrc Connection: close /* SEGA Dreamcast Japanese boot-ROM v1.004 * * Hacked by Lars Olsson * * Questions, corrections etc: * jlo@ludd.luth.se * * Notes: * ~~~~~~ * * reg[REG] = access to register REG (including both normal * CPU registers aswell as CPU-related memory-mapped * registers, but NOT other hardware registers) * * * Most names have been made up by me and can be very misleading, * even to the point of being downright incorrect with regards to * their actual functions * * Beware: this source code is only meant to illustrate the funtion * of the BootROM. It is not a 100% translation of the actual BootROM * but a number of short cuts and simplifications have been made in order * to clarify the operation, which was the purpose of this whole exercise. * * Compiling this source (in so far it is possible at all) will NOT * produce a proper BootROM! * */ #include "types.h" #include "bootROM.h" void boot() /* 0xa0000000 - start of bootROM */ { uint32_t exception, exception_mask; uint16_t *src, *dst; exception = reg[EXPEVT]; exception_mask = exception ^ 0x00000fff; if (exception * exception_mask == 0) { reg[MMUCR] = 0x00000000; reg[CCR] = 0x00000929; reg[WCR1] = (uint16_t)0x0001; reg[WCR2] = 0x618066d8; reg[BCR2] = 0xa3020008; reg[WCR1] = 0x01110111; reg[MCR] = 0x800a0e24; *(uint8_t *)0xff940190 = 0x90; /* write to SDMR */ reg[RFCR] = (uint16_t)0xa400; reg[RTCOR] = (uint16_t)0xa504; reg[RTCSR] = (uint16_t)0xa510; while((volatile uint16_t)reg[RFCR] <= 0x0010); reg[RTCOR] = (uint16_t)0xa55e; reg[MCR] = 0xc00a0e24; *(uint8_t *)0xff940190 = 0x90; /* write to SDMR */ *HW16(0xa05f7480) = 0x0400; /* copy small routine to RAM */ src = (uint16_t *)romcopy; dst = (uint16_t *)0x8c0000e0; for (i = 0; i < sizeof(romcopy); i++) *(dst++) = *(src++); /* copy BootROM to RAM and continue executing at boot2(0) */ (*(void (*)(void *, void *))0x8c0000e0)((void *)0x80000100, (void *)0x8c000100); } if (exception_mask == 0x0fdf) /* soft-reset */ _8c000018(_ac004000); /* = return (_ac004000) */ system_reset(); } void exception_handler_100() /* _8c000100 */ { irq_handler2(reg[EXPEVT]); } void system_reset() /* _a0000116 */ { /* Reset the system */ *HW32(0xa05f6890) = 0x00007611; while(1); } void boot2(debug_handler) /* _8c000120 */ uint32_t debug_handler; { uint32_t i; reg[DBR] = debug_handler; init_machine(0); /* clear irq callbacks */ for (i = 0; i < sizeof(irq_callback); i++) irq_callback[i] = 0x00000000; reg[SR] &= 0xdfffffff; /* setup a default debug handler if one isn't already installed */ if (reg[DBR] >= 0) { reg[DBR] = &sysvars->rte_code[0]; if (*(volatile uint32_t)0xff000030 == 0x00000080) { reg[WTCSR] = (uint16_t)0xa500; reg[WTCSR] = (uint16_t)0xa507; reg[WTCNT] = (uint16_t)0x5a00; reg[FRQCR] = (uint16_t)0x0000; } } __asm__("rte\n\t"); /* on power on reset, execution jumps to */ /* sys_do_bioscall(-3) = boot3() */ } void RTE() /* 8c000170 */ { _8c000010(); /* rte */ } void sys_do_bioscall2(func) /* _ac000178 */ sint32_t func; { func += 3; if (func > 7) func = 7; (*sys_callback[func])(func - 3); } void syBtExit(mode) /* _8c0002c8 */ sint32_t command; { uint32_t i; uint64_t *src, *dst; /* turn off cache if it is enabled; details omitted */ reg[SR] = 0x700000f0; reg[GBR] = 0x8c000000; sysvars->select_menu = command; reg[R15] = 0x8d000000; reg[VBR] = _8c000000; flush_cache(); reg[MMUCR] = 0x00000000; reg[CCR] = 0x00000929; *HW32(0xa05f6938) = 0x00000000; *HW32(0xa05f6934) = 0x00000000; *HW32(0xa05f6930) = 0x00000000; reg[IPRC] = (uint16_t)0x0000; *HW32(0xa05f6928) = 0x00000000; *HW32(0xa05f6924) = 0x00000000; *HW32(0xa05f6920) = 0x00000000; reg[IPRB] = (uint16_t)0x0000; *HW32(0xa05f6918) = 0x00000000; *HW32(0xa05f6914) = 0x00000000; *HW32(0xa05f6910) = 0x00000000; reg[IPRA] = (uint16_t)0x0000; reg[ICR] = (uint16_t)0x0000; (void)*HW32(0xa05f6908); (void)*HW32(0xa05f6900); /* disable display */ *HW32(0xa05f8044) &= 0xfffffffe; /* reset rendering and registration */ *HW32(0xa05f8008) = 0x00000003; /* disable PVR DMA */ *HW32(0xa05f6808) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*(volatile uint32_t *)0xa05f6808 == 0x01) break; /* ??? (other direction perhaps?) */ *HW32(0xa05f6820) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f6820) == 0x01) break; /* disable Maple DMA */ *HW32(0xa05f6c14) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f6c14) == 0x01) break; /* disable GDROM DMA */ *HW32(0xa05f7414) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7414) == 0x01) break; /* disable SPU DMA */ *HW32(0xa05f7814) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7814) == 0x01) break; /* disable expansion port 1 DMA */ *HW32(0xa05f7834) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7834) == 0x01) break; /* disable expansion port 2 DMA */ *HW32(0xa05f7854) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7854) == 0x01) break; /* disable expansion port 3 DMA */ *HW32(0xa05f7874) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7874) == 0x01) break; /* ??? */ *HW32(0xa05f7c14) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f7c14) == 0x01) break; /* ??? */ *HW32(0xa05f001c) &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (*HW32(0xa05f001c) == 0x01) break; reg[CHCR1] &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (reg[CHCR1] == 0x01) break; reg[CHCR2] &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (reg[CHCR2] == 0x01) break; reg[CHCR3] &= 0xfffffffe; for (i = 0; i < 0x7f; i++) if (reg[CHCR3] == 0x01) break; /* initialize ROM checksum */ *HW32(0xa05f74e4) = 0x001fffff; /* switch to double precision (for 64bit copying below) */ reg[FPSCR] = 0x00140001; /* Copy various parts from ROM to RAM */ /* This is done for two reasons: * First, code and data must be available to be executed from RAM * secondly, the data read from ROM are passed through some type * of "checksum". Unless a specific value is computed, a flag is * set to disable the GDROM drive. Sega must have put this in there * to "discourage" people from replacing the BootROM with their custom * versions! */ src = (uint64_t *)0xa0000000; dst = (uint64_t *)0x8c000000; for (i = 0; i < 32; i++) { /* skip the system variables */ (void)*src++; dst++; } for (i = 0; i < 2016; i++) /* copy a0000100-a0004000 to 8c000100 */ *dst++ = *src++; for (i = 0; i < 2048; i++) { (void)*(src++); dst++; } for (i = 0; i < 258048; i++) /* copy a0008000-a0200000 to 8c008000 */ *(dst++) = *(src++); /* back to single precision */ reg[FPSCR] = 0x00040001; boot2(reg[DBR]); } void exception_handler_400() /* _8c000400 */ { irq_handler2(reg[EXPEVT]); } void _8c000408() { sw = sysvars->debug_switches.u0.switches.unknown0; if (sw != -1 && sw != '1') reg[PR] = _8c000000; /* go to sleep */ } void boot3() /* _8c000420 */ { reg[GBR] = (uint32_t *)0x8c000000; boot4(); wait_timer(); wait_timer(); reg[SR] |= 0x000000f0; flush_cache(); reg[MMUCR] = 0x00000000; reg[CCR] = 0x00000800; /* correct code in IP.BIN */ for (i = 0; i < sizeof(patch_data); i++) { patch_data[i]->addr = patch_data[i].opcode; } /* start executing IP.BIN */ _ac008300(); } void copy_security_stuff() /* _8c000462 */ { unsigned int *src, *dst; unsigned int old_SR, i; src = _a0004300; dst = _8ce00000; for (i = 0; i < 0x0400; i++) { *(dst++) = *(src++); } flush_cache(); } void flush_cache() /* _8c000472 */ { /* turn off cache; details omitted */ old_SR = reg[SR]; reg[SR] = reg[SR]|0x00f0; if (reg[CCR] & 0x20) i = 0x1000; else i = 0x2000; while(i) { i -= 0x20; *(_f4002000 + (i & 0xfffffffd)) = 0; *(_f4000000 + (i & 0xfffffffd)) = 0; } __asm__( "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); reg[SR] = old_SR; } void clear_sector_buf(buf) /* _8c0004d8 */ unsigned int *buf; { unsigned int i; for (i = 0; i < 0x80; i++) { *(buf++) = 0x00000000; *(buf++) = 0x00000000; *(buf++) = 0x00000000; *(buf++) = 0x00000000; } } int process_IP(ip_buf) /* _8c0004f4 */ ip_t *ip_buf; { if (memcmp(ip_buf->hardware_ID, "SEGA SEGAKATANA ", 16) != 0) return (-1); if (memcmp(ip_buf->code, (uint8_t *)0xa0008000, 0x3400) != 0) return (-1); if (memcmp(ip_buf->area, (uint8_t *)0xa000b400, 0x20) != 0) return (-1); if (ip_buf->country_codes[0] != 'J') return (-1); sysvars->boot_file = ip_buf->boot_file; sysvars->OS_type = convert_WinCE(ip_buf->WinCE); sysvars->display_cable &= (convert_VGA(ip_buf->VGA) - 2); return (0); } int memcmp(s1, s2, n) /* _8c000548 */ uint8_t *s1, *s2; int n; { while(*(s1++) == *(s2++) && --n); return (n); } char ascii2char(digit) /* _8c00055e */ uint8_t digit; { if (digit =< 0x39) return (digit - 0x30); return (digit - 0x37); } char convert_VGA(digit) /* _8c00056c */ uint8_t digit; { if (digit == 0) return (1); if (ascii2char(digit) & 0x01 == 0) return (0); return (1); } char convert_WinCE(digit) /* _8c000570 */ uint8_t digit; { if (digit == 0) return (0); if (ascii2char(digit) & 0x01 == 0) return (0); return (1); } int check_ISO_PVD(type, id) /* _8c000590 */ uint8_t type; uint8_t *id; { if (type != 1) return (6); return (memcmp(id, "CD001", 5)); } void check_filename(s1, s2) /* _8c000598 */ uint8_t *s1, *s2; { if (memcmp(s1, s2, 12) == 0) return (0); if (s2[0] != 0x20) return (-1); if (s1[0] != 0x3b) return (-1); return (0); } void enter_gd_params(src) /* _8c0005b8 */ uint32_t *src; { uint32_t *dst = &sysvars->gd_param4; /* fill in gd params and command in reverse order */ for (i = 0; i < 5; i++) *(dst--) = *(src++); } void irq_handler() /* _8c000600 */ { irq_handler2(reg[INTEVT]); } void irq_handler2(interrupt) /* _8c000606 */ uint32_t interrupt; { uint32_t irq; irq = (interrupt>>5)-2; if (irq >= 0x41) RTE(); if (irq_callback[irq] == NULL) RTE(); /* save various system registers; details omitted */ reg[SR] = reg[SR] & 0xdfffffff; /* save registers details omitted */ reg[FPSCR] = 0x00140001; /* save floating-point registers; details ommitted */ (*irq_callback[irq])(); reg[FPSCR] = 0x00140001; /* restore all registers; details omitted */ __asm__("rte\n\t"); } void clear_IrqCallbacks() /* _8c0006aa */ { sysvars->irq_sem0 = 0; sysvars->irq_sem1 = 0; sysvars->irq_sem2 = 0; sysvars->irq_sem3 = 0; sysvars->irq_callback0 = NULL; sysvars->irq_callback0 = NULL; sysvars->irq_callback0 = NULL; sysvars->irq_callback0 = NULL; } void do_IrqCallbacks() /* _8c0006c0 */ { uint32_t old_SR = reg[SR]; uint8_t *sem = &sysvars->irq_sem0; uint32_t *cb = sysvars->irq_callback0; reg[GBR] = _8c000000; /* atomic test and set */ if (*sem != 0) { *sem = 0x80; return; } *sem = 0x80; reg[SR] = reg[SR]&0xefffff0f; for (i = 0; i < 4; i++) { if (cb != NULL) (*cb)(); sem++; cb++; /* atomic test and set */ if (*sem != 0) { *sem = 0x80; break; } *sem = 0x80; } *(--sem) = 0; reg[SR] = old_SR; } void _8c000728() { _8c00073e(0x10); } void _8c000730() { _8c00073e(0x20); } void _8c000738() { _8c00073e(0x30); } void _8c00073e(irq) uint32_t irq; { *HW32(0xa05f6900) &= *HW32(0xa05f6900 + irq); *HW32(0xa05f6908) &= *HW32(0xa05f6908 + irq); (void)*HW32(0xa05f6908); do_IrqCallbacks(); } void set_IrqCallback1() /* _8c000768 */ { sysvars->timer_count = 0; sysvars->irq_callback0 = (uint32_t *)increase_TimerCount; } void wait_timer() /* _8c000772 */ { uint32_t old_timer = sysvars->timer_count; while (sysvars->timer_count == old_timer); } void increase_TimerCount() /* _8c000780 */ { sysvars->timer_count++; } void sys_do_bioscall(func) /* _ac000800 */ { sys_do_bioscall2(func); } void _8c000804() { wait_timer(); } uint32_t toggle_endian(data) /* _8c00080a */ uint8_t *data; { uint32_t i; uint8_t buf[4]; for (i = 0; i < 4; i++) buf[i] = data[3-i]; return (*(uint32_t *)buf); } void boot5() /* _8c000820 */ { if (sysvars->gd_param3 == 0) { clear_IrqCallback3(); if (sysvars->OS_type == 2) { security_stuff(2); } else { security_stuff(0); } } else { reg[SR] = reg[SR] & 0xefffff0f; sysvars->gd_unknown1 = 0x000a; sysvars->gd_unknown0 = 0x0258; if (exec_GdCmd(1) == 1) { clear_IrqCallback3(); sys_do_bioscall(1); /* syBtExit(1) */ } clear_IrqCallback3(); } sysvars->gdhn = 0; *_a05f8040 = 0x00c0bebc; /* set border color to light grey */ sysvars->current_color = 0x00c0bebc; } void _8c00087a() { int i, result = 0, dummy; unsigned int *hwreg = _a05f6904; unsigned int old_SR = reg[SR]; reg[SR] = reg[SR] | 0x00f0; *OldGdVector2 = *GdVector2; *GdVector2 = _8c001168; for (i = 0; i < 3; i++) { hwreg += 0x0c; result = result | ((*hwreg & 0x00004000)<> (i+1)) & 0x00004000); irqreg += 4; *irqreg = *irqreg | ((*_8c000098 >> (i+1)) & 0x00000001); irqreg += 0x0c; } dummy = *_a05f6934; *_a05f6900 = *_a05f6900 & 0x00004000; reg[SR] = old_SR; } int check_GdDrvStatus() /* _8c00095c */ { switch (sysvars->gd_drv.stat) { case STAT_OPEN: case STAT_NODISK: case STAT_ERROR: return (-1); break; default: return (0); } } int check_ipvector_media() /* _8c000978 */ { if (sysvars->IP_vector != (uint32_t *)0x8c008000) { return (0); } if (sysvars->gd_drv.media == TYPE_XA) { return (0); } return (1); } int syBtCheckDisc() /* _8c000900 */ { int disc; /* R14 */ unsigned int old_GBR = reg[GBR]; reg[GBR] = _8c000000; if (*DiscType < 0) { gdGdcExecServer(); } /* _8c0009ae */ switch (*DiscType) { case -8: /* _8c000a98 */ if (process_IP(*IPVector) == 0) { disc = 0; } else { disc = 126; } break; case -7: case -4: /* _8c000a14 */ result = exec_GdCmd3(1); /* this is fucked...rewrite this later */ if (result == -2 || result != 0) { disc -= 2; if (result == 1) { if (check_GdDrvStatus() == -1) { disc = -1; } else { switch (*GdStatus) { case 2: /* _8c000a72 */ disc += 2; break; case 6: /* _8c000a6e */ disc = -2; break; case 16: /* _8c000a76 */ if (check_ipvector_media() != 0) { disc = 0; } break; default: /* _8c000a82 */ disc = -1; break; } } } } break; case -6: case -3: /* _8c0009fe */ result = _8c00ec8(0); if (result == 1) { disc = -1; } else { if (result == 0) { *_8c000044 = 0x0258; disc--; } } break; case -5: /* _8c000a86 */ enter_gd_params(_8c000fc4); /* GdParam4 = 0x00000000 GdParam3 = 0x8c008000 GdParam2 = 0x00000007 GdParam1 = 0x0000b05e GdCmd = CMD_DMAREAD */ *GdParam3 = *IPVector; *_8c000044 = 0x0268; disc = -6; /* _8c0009fe */ result = exec_GdCmd3(0); if (result == 1) { disc = -1; } else { if (result == 0) { *_8c000044 = 0x0258; disc--; } } break; case -2: /* _8c0009f6 */ *GdCmd = 24; *_8c000044 = 0x0258; disc = -3; result = exec_GdCmd3(0); if (result == 1) { disc = -1; } else { if (result == 0) { *_8c000044 = 0x0258; disc--; } } break; case -1: /* _8c0009e4 */ if (*GdStatus > 0) { disc = *GdStatus; } else { disc = 127; } break; default: _8c00087a(); *DisplayCable |= 0x01; *_8c000046 = 0x000a; disc = -1; break; } /* _8c000aaa */ if (disc < *OldDiscType) disc = 0; if (disc < 0) _8c0008e0(); *DiscType = disc; reg[GBR] = old_GBR; return (disc); } int syBtCheckDisc() /* _8c000990 */ { short disc; int result; unsigned int old_GBR = reg[GBR]; reg[GBR] = _8c000000; disc = (short)*DiscType; if (disc < 0) { _8c000c86(); } switch (disc) { case -8: /* _8c000a98 */ if (process_IP(*IPVector) == 0) { disc = 0; } else { disc = 0x7e; } break; case -7: case -4: /* _8c000a14 */ result = exec_GdCmd3(1); if (result != -2) { /* _8c000a2c */ if (result == 0) { if (*GdMedia != TYPE_GDROM) { if (check_ipvector_media() == 0) { /* _8c000a48 */ result = 1; } else { disc = 0; } /* _8c000a4a */ } else { disc--; } } } /* _8c000a4a */ if (result == 1) { if (check_GdDrvStatus() == -1) { disc = -1; } else { switch (*GdStatus) { case 2: disc += 2; break; case 6: disc = -1; break; case 16: if (check_ipvector_media() != 0) { disc = 0; } break; default: disc = -1; break; } } } break; case -6: case -3: /* _8c0009fe */ result = exec_GdCmd3(0); if (result == 1) { disc = -1; } else { if (result == 0) { *_8c000044 = (short)0x0258; disc--; } } break; case -5: /* _8c000a86 */ enter_gd_params(_8c000fc4); /* GdParam4 = 0x00000000 GdParam3 = 0x8c008000 GdParam2 = 0x00000007 GdParam1 = 0x0000b05e GdCmd = CMD_DMAREAD */ *GdParam3 = *IPVector; *_8c000044 = 0x258; disc = -6; result = exec_GdCmd3(0); if (result == 1) { disc = -1; } else { if (result == 0) { *_8c000044 = 0x258; disc--; } } break; case -2: /* _8c0009f6 */ *GdCmd = 24; *_8c000044 = 0x258; disc = -3; result = exec_GdCmd3(0); if (result = 1) { disc = -1; } else { if (result == 0) { *_8c000044 = 0x258; disc--; } } break; case -1: /* _8c0009e4 */ if (*GdStatus > 0) { disc = *GdStatus; } else { disc = 0x7f; } break; default: /* _8c0009d6 */ _8c00087a(); *DisplayCable |= 0x01; *_8c000046 = 0x000a; disc = -1; break; } /* _8c000aaa */ if (disc < *OldDiscType) { disc = 0; } if (disc > 0) { _8c0008e0(); } *DiscType = disc; reg[GBR] = old_GBR; return (disc); } void boot4() /* _8c000ae4 */ { uint32_t delayed_cmd; /* R13 */ uint32_t CD_boot; /* R11 */ uint32_t sct; /* R10 */ uint32_t sector_of_PVD; /* disable interrupts */ reg[SR] = (reg[SR] & 0xefffff0f) | 0x00f0; gdGdcInitSystem(0, 0); sysvars->old_disc_type = -128; delayed_cmd = INIT; /* R13 */ if (sysvars->select_menu == OPENMENU) { sysvars->menu_param = 1; sysvars->display_cable |= 1; /* _8c000b9c */ sysvars->IP_vector = (uint32_t *)0x8c008000; sysvars->old_disc_type = -128; _8c00c000(OPENMENU); flush_cache(); if (sysvars->gd_drv.media == TYPE_XA || sysvars->gd_stat.stat0 == 0x10) sys_do_bioscall(4); /* no_return() */ sys_do_bioscall(3); /* syBtExit(3) */ } else if (sysvars->select_menu != OPENCDMENU) { sysvars->menu_param = 0; _8c00c000(INIT); _8c00c000(UNKNOWN1); delayed_cmd = UNKNOWN2; sysvars->IP_vector = (uint32_t *)0x8c008000; } /* _8c000b36 */ set_interrupts(); wait_timer(); CD_boot = -1; copy_security_stuff(); CheckDisc(-4); if (sysvars->gd_drv.media == TYPE_XA) { sysvars->irq_callback2 = NULL; sct = security_stuff(1); if (sct != 0) { CD_boot = 0; if (process_IP(sysvars->IP_vector) == 0) { sysvars->OS_type = 0x02; set_IrqCallback3(); goto check_passed; } } } /* _8c000b74 */ set_IrqCallback3(); sysvars->old_disc_type = -128; syBtCheckDisc(); sysvars->disc_type = -5; newdisc = CheckDisc(-128); set_IrqCallback3(); if (newdisc == 0) goto check_passed; check_failed: clear_IrqCallback3(); reg[SR] = (reg[SR] & 0xefffff0f) | 0x00000f0; sysvars->IP_vector = (uint32_t *)0x8c008000; if (delayed_cmd >= 0) { _8c00c000(delayed_cmd); _8c00c000(SETDATE); } delayed_cmd = INIT; sysvars->old_disc_type = -128; _8c00c000(OPENMENU); flush_cache(); if (sysvars->gd_drv.media == TYPE_XA || sysvars->gd_stat.stat0 == 0x10) sys_do_bioscall(4); /* no_return() */ /* _8c000bcc */ sys_do_bioscall(3); /* syBtExit(3) */ check_passed: if (sysvars->display_cable == 0) goto check_failed; if (delayed_cmd >= 0) { _8c00c000(delayed_cmd); _8c00c000(SETDATE); } /* 8c000bea */ flush_cache(); enter_gd_params((uint32_t *)0x8c000fd8); /* GdParam4 = 0x00000000 GdParam3 = 0x8c00b800 GdParam2 = 0x00000009 GdParam1 = 0x0000b065 GdCmd = CMD_DMAREAD */ if (CD_boot == 0) { sysvars->gd_param1 = sct + 7; } if (exec_GdCmd2() != 0) { sys_do_bioscall(1); /* syBtExit(1) */ } if (CD_boot == 0) { PVD_sector = sct + 16; } else { PVD_sector = 45166; } if (load_BootFile((uint32_t *)0x8c010000, PVD_sector) == 0) sys_do_bioscall(1); /* syBtExit(1) */ sysvars->old_disc_type = -128; sysvars->IP_vector = (uint32_t *)0x8c008100; } void set_interrupts() /* _8c000c3e */ { reg[SR] = reg[SR] | 0x100000f0; reg[VBR] = _8c000000; clear_IrqCallbacks(); /* clear _8c000080 to _8c00008c */ /* set interrupt vector */ *(uint32_t *)0x8c000234 = (uint32_t *)0x8c000728; *HW32(0xa05f6910) = 0x00000008; (void)*HW32(0xa05f6910); reg[SR] = reg[SR] & 0xefffff0f; set_IrqCallback1(); } uint32_t clear_IrqCallback3() /* _8c000c6c */ { reg[SR] |= 0x100000f0; sysvars->irq_callback3 = NULL; *HW32(0xa05f6910) = 0x00000000; return (*HW32(a05f6910)); } void set_IrqCallback3() /* _8c000c80 */ { sysvars->irq_callback3 = (uint32_t *)irq_ExecServer; } void irq_ExecServer() /* _8c000c86 */ { gd_do_bioscall(0, 2, 0, 0); /* gdGdcExecServer(0, 0) */ } void irq_InitSystem() /* _8c000c92 */ { gd_do_bioscall(0, 3, 0, 0); /* gdGdcInitSystem(0, 0) */ } void _8c000cfc() { sysvars->gd_unknown0 = 0x0258; } int CheckDisc(olddisc) /* _8c000d02 */ sint32_t old_disc; { sint32_t new_disk; sysvars->old_disc_type = old_disc; while (1) { wait_timer(); new_disk = syBtCheckDisc(); if (new_disk >= 0) break; } return (new_disk); } void load_BootFile(buf, sct) /* _8c000d1c */ uint8_t *buf; uint32_t sct; { struct primary_iso_descripter *vol_desc; struct iso_directory_record *dir_record; uint32_t extent, size; uint8_t old_char; clear_sector_buf(buf); /* GD params to read PVD */ sysvars->gd_cmd = CMD_DMAREAD; sysvars->gd_param1 = sct; sysvars->gd_param2 = 1; sysvars->gd_param3 = buf; sysvars->gd_param4 = 0; if (exec_GdCmd2() != 0) /* read PVD */ return (0); vol_desc = (struct primary_iso_descriptor *)buf; if (check_ISO_PVD(vol_desc->type, vol_desc->id) != 0) { return (0); } extent = toggle_endian(&vol_desc->root_directory_record.extent2); /* GD params to read root directory */ sysvars->gd_param1 = extent + 150; /* lead-in added */ sysvars->gd_param2 = 1; sysvars->gd_param3 = buf; sysvars->gd_param4 = 0; sysvars->gd_cmd = CMD_DMAREAD; exec_GdCmd2(); /* read root directory */ dir_record = (struct iso_directory_record *)buf; while (dir_record->length != 0 && dir_record < buf+2048) { if (dir_record->flags & 0x02 == 0) { old_char = dir_record->name[dir_record->name_len]; dir_record->name[dir_record->name_len] = ';'; if (check_filename(dir_record->name, *BootFile) == 0) { size = toggle_endian(dir_record->size2); extent = toggle_endian(dir_record->extent2) + 150; if (extent < 450000) /* 100 min check */ /* check for backdoor */ if (sysvars->OS_type != 0x02) sys_do_bioscall(1); /*syBtExit*/ sysvars->gd_param1 = extent; sysvars->gd_param2 = size/2048; if (OS_type == 0) { sysvars->gd_param3 = buf; sysvars->gd_param4 = 0; } else { sysvars->gd_param3 = 0; sysvars->gd_param4 = size; } sysvars->gd_unknown1 = 0x000a; sysvars->gd_unknown2 = 0x0258; if (sysvars->OS_type == 0) { sysvars->gd_cmd = CMD_DMAREAD; } else { sysvars->gd_cmd = CMD_PIOREAD; } exec_GdCmd(0); _8c000804(); return (size); } dir_record->name[dir_record->name_len] = old_char; } dir_record = dir_record + dir_record->length; } return (0); } uint32_t exec_GdCmd(mode) /* _8c000e7c */ uint32_t mode; { uint32_t result; do { wait_timer(); } while ((result = exec_GdCmd3(mode)) < 0); return (result); } uint32_t exec_GdCmd2() /* _8c000e98 */ { uint32_t result; sysvars->gd_unknown1 = 0x000a; while(1) { sysvars->gd_unknown0 = 0x0258; result = exec_GdCmd(0); if (result != 0) return (result); while(1) { sysvars->gd_unknown0 = 0x0258; wait_timer(); /* _8c000804() */ result = exec_GdCmd3(1); if (result == -2) break; /* break inner loop */ if (result >= 0) return (result); } } } uint32_t exec_GdCmd3(mode) /* _8c000ec8 */ uint32_t mode; { uint32_t result = 1; switch (mode) { case 0: sysvars->gdhn = gdGdcReqCmd(*GdCmd, GdParam1); if (sysvars->gdhn != 0) { result = 0; } break; default: sysvars->gd_cmd_stat = gdGdcGetCmdStat(sysvars->gdhn, sysvars->gd_stat); switch (sysvars->gd_cmd_stat) { case 0: case 2: result = 0; break; case 1: case 3: result = -1; break; case -1: sysvars->gd_unknown0 = 0x0000; switch (sysvars->gd_stat.stat0) { case 0: case 1: case 2: case 5: case 6: case 11: case 16: /* _8c0000f3c */ sysvars->gd_unknown1 = 0x0000; break; default: break; } break; default: break; } /* _8c000f58 */ if (result != -1) { if (gdGdcGetDrvStat(sysvars->gd_drv, 0) != 0) { if (check_GdDrvStatus() == -1) { sysvars->gd_unknown0 = 0x0000; sysvars->gd_unknown1 = 0x0000; } } } break; } /* _8c000f80 */ if (result == -1) return (-1); if (sysvars->gd_unknown0 != 0) { sysvars->gd_unknown0--; return (-1); } if (sysvars->gd_unknown1 != 0) { sysvars->gd_unknown1--; sysvars->gd_unknown0 = 0x0258; return (-1); } return (result); } int _8c001000(arg1, arg2, func1, func2) { if (func1 == -1) { return (init_bioscall_vectors(arg1, arg2, func1, func2)); } if (func1 >= 8) { return (-1); } return ((*_8c0000c0[func1])(arg1, arg2, func1, func2)); /* func1 = 0 gives gd_do_bioscall */ } int init_bioscall_vectors(arg1, arg2, value, cmd) /* _8c001020 */ unsigned int arg1, arg2, value, cmd; { unsigned int *dst = _8c0000c0; switch (cmd) { case 0: /* gdBtGdc(Re)InitEntry */ for (i = 0; i < 7; i++) *(dst++) = 0x00000000; /* clear _8c0000c0 to _8c0000dc */ *GdVector2 = gd_do_bioscall; *GdVector = _8c001000; *FlVector = _8c003d00; *FntVector = _8c003b80; *KcfgVector = _8c003c00; *GdBaseReg = _a05f7000; *_8c0000a8 = _a0200000; *_8c0000a4 = _a0100000; *_8c0000a0 = 0x00000000; *_8c00002e = 0x0000; *_8c00002d = 0x00; *SystemVector = sys_do_bioscall; return (0); break; case 1: /* gdBtGdcAddDesc */ if (arg1 > 7) { return (-1); } if (arg2 == 0) { _8c0000c0[arg1] = 0; return (0); } if (_8c0000c0[arg1] == 0) { _8c0000c0[arg1] = arg2; return (0); } return (-1); break; default: return (-1); break; } } int * _8c0010b0(init) int init; { if (init != 0) { return (*_8c000050); } *_8c00005c = _8c3002e8; *_8c000058 = _8c010b42; *_8c000054 = _8c010b6e; *_8c000050 = _8c010b58; } void gd_do_bioscall(func1, func2, arg1, arg2) /* _8c0010f0 */ int func1, func2, arg1, arg2; { if (func2 > 16) { return; } (*_8c001180[func2])(arg1, arg2); } int get_GdBaseReg() /* _8c001108 */ { return (*GdBaseReg); } int _8c001118(mode) int mode; { if (mode != 0) { *_8c00002d = 0x01; if (*_8c00002e > 0x0000) { *_8c00002d = 0x00; return (-1); } else { return (0); } } /* _8c001142 */ *_8c00002d = 0x00; } void gd_do_cmd(param, my_gds, cmd) /* _8c0011ec */ int *param; GDS *my_gds; int cmd; { if (cmd > 48) { return; } (*gd_cmd[cmd])(param, my_gds); } GDS * get_GDS() /* _8c0012de */ { return (gd_gds); } int gdGdcInitSystem() /* _8c001890 */ { *_8c001994 = 1; *reg[--R15] = reg[PR]; *reg[--R15] = reg[MACH]; *reg[--R15] = reg[MACL]; *reg[--R15] = reg[R14]; *reg[--R15] = reg[R13]; *reg[--R15] = reg[R12]; *reg[--R15] = reg[R11]; *reg[--R15] = reg[R10]; *reg[--R15] = reg[R9]; *reg[--R15] = reg[R8]; *_8c00198c = reg[R15]; *_8c001990 = _8c001acc; return (_8c003570()); } void _8c0018c0() { int i; int *ptr; i = (*_8c00198c - reg[R15])>>2; ptr = *_8c001990; *(--ptr) = reg[PR]; *(--ptr) = reg[MACH]; *(--ptr) = reg[MACL]; *(--ptr) = reg[R14]; *(--ptr) = reg[R13]; *(--ptr) = reg[R12]; *(--ptr) = reg[R11]; *(--ptr) = reg[R10]; *(--ptr) = reg[R9]; *(--ptr) = reg[R8]; for (j = 0; j != i; j++) { *(--ptr) = *reg[R15+]; } *(--ptr) = i; *_8c001990 = ptr; reg[R8] = *reg[R15++]; reg[R9] = *reg[R15++]; reg[R10] = *reg[R15++]; reg[R11] = *reg[R15++]; reg[R12] = *reg[R15++]; reg[R13] = *reg[R15++]; reg[R14] = *reg[R15++]; reg[MACL] = *reg[R15++]; reg[MACH] = *reg[R15++]; reg[PR] = *reg[R15++]; *_8c001994 = 0; } int gdGdcExecServer() /* _8c001918 */ { int size; int *addr; /* the following is atomic */ if (*_8c001994 != 0) { *_8c001994 = 0x80; return (1); } *(--reg[R15]) = reg[PR]; *(--reg[R15]) = reg[MACH]; *(--reg[R15]) = reg[MACL]; *(--reg[R15]) = reg[R14]; *(--reg[R15]) = reg[R13]; *(--reg[R15]) = reg[R12]; *(--reg[R15]) = reg[R11]; *(--reg[R15]) = reg[R10]; *(--reg[R15]) = reg[R9]; *(--reg[R15]) = reg[R8]; *_8c00198c = reg[R15]; size = **_8c001990; addr = *_8c001990 + 4; while (size-- != 0) *(--reg[R15]) = *(addr++); } reg[R8] = *(addr++); reg[R9] = *(addr++); reg[R10] = *(addr++); reg[R11] = *(addr++); reg[R12] = *(addr++); reg[R13] = *(addr++); reg[R14] = *(addr++); reg[MACL] = *(addr++); reg[MACH] = *(addr++); reg[PR] = *(addr++); *_8c001990 = addr; } int allocate_GD() /* _8c001970 */ { /* the following is atomic */ if (*_8c001994 = 0) { *_8c001994 = 0x80; return (0); } else { *_8c001994 = 0x80; return (1); } } void release_GD() /* _8c00197e */ { *_8c001994 = 0; } void gd_dmaread(param, my_gds) /* _8c001b2c */ int *param; GDS *my_gds; { int result; _8c0026fe(my_gds); result = _8c001118(1); if (result == 0) { /* _8c001b4e */ _8c00266c(my_gds, param[1], param[0], param[3]); *_a05f74b8 = 0x8843307f; *_a05f7404 = param[2]; *_a05f7408 = param[1] * my_gds->sector_size; *_a05f740c = 1; result = _8c002c44(my_gds); _8c001118(0); return (_8c002948(result, my_gds)); } /* _8c001bae */ my_gds->_0018 = 0x20; return (result); } void gd_gettoc(param, my_gds) /* _8c001c34 */ int *params; GDS *my_gds; { if (my_gds->drvmedia != TYPE_GDROM && param[0] != 1) { my_gds->_0018 = 0x00000005; return; } /* _8c001c50 */ param[1][0] = (*((int *)(my_gds->TOCS[param[0]].toc_buf + 0x0190)) & 0x00ff0000)>>16; /* _8c001c74 */ i = 1; do { param[1][i] = ((int *)(my_gds->TOCS[param[0]].toc_buf)[i-1] & 0xff000000)>>24 } while (i++ < param[1]); } void gd_gettoc2(param, my_gds) /* _8c001ca8 */ int *param; GDS *my_gds; { if (my_gds->drvmedia == TYPE_GDROM || param[0] != 1) for (i = 0; i < 408; i++) param[1][i] = my_gds->TOCS[param[0]].toc_buf[i]; else my_gds->gd_cmd_stat = 5; } int _8c00223e(size, my_gds) int *size; GDS *my_gds; { if (*_a05f7418 == 1) { *size = *_a05f74f8; return (1); } *size = my_gds->size; return (0); } /* This initiates a DMA transfer prolly */ /* arg1[0] is destination area * arg1[1] is size * int _8c002266(arg1, my_gds) int *arg1; GDS *my_gds; { if (arg1[1] != my_gds->size) { return (-1); } *_a05f74b8 = 0x8843407f; *_a05f7404 = arg1[0]; *_a05f7408 = arg1[1]; *_a05f740c = 0x00000001; my_gds->size -= arg1[1]; *_a05f7414 = 0x00000001; *_a05f7418 = 0x00000001; return (0); } int _8c002362(arg1, my_gds) int *arg1; GDS *my_gds; { if (my_gds->_00e4 != 0) { arg1[0] = my_gds->_00a4; return (1); } arg1[0] = my_gds->size; return (0); } int _8c002380(arg1, my_gds) int *arg1; GDS *my_gds; { if (arg1[1] > my_gds->size) { return (-1); } my_gds->size -= arg1[1]; my_gds->_00e0 = arg1[0]; my_gds->_00e4 = arg1[1]; return (0); } void _8c0023a4(param, my_gds) int *param; GDS *my_gds; { int result; my_gds->_0000 = (short)(my_gds->_0054 + (param[0]>>8)); my_gds->_0002 = (short)(param[1] & 0xff00); my_gds->_0004 = (short)(param[1] & 0x00ff); my_gds->_0006 = (short)0x0000; my_gds->_0008 = (short)0x0000; my_gds->_000a = (short)0x0000; result = _8c002b4c(param[2], param[1], 0, my_gds); _8c002948(result); } void _8c0025bc(param, my_gds) int *param; GDS *my_gds; { my_gds->_0000 = my_gds->_000e; my_gds->_0002 = param[0]; my_gds->_0004 = 0x0006; my_gds->_0006 = 0x0000; my_gds->_0008 = 0x0000; my_gds->_000a = 0x0000; result = _8c002b4c(&my_gds->_00e8, 6, 0, my_gds); if (result & 0x01 == 0) { param[1] = (char)(my_gds->_00ea & 0x00ff); param[2] = ((my_gds->_00ea & 0xff00)<<8) + ((my_gds->_00ec & 0x00ff)<<8) + ((my_gds->_00ec & 0xff00)>>8); } _8c002948(result); } void _8c00262c(param, my_gds) int *param; GDS *my_gds; { if (_8c0037b2(1) == 0) { return; } if (my_gds->_0018 != 0) { return; } my_gds->_0018 = 2; } void _8c00266c(my_gds, param1, param2, param3) GDS *my_gds; int param1, param2, param3; { int i; /* R1 */ i = ((param2 & 0x00ff0000)>>16) | (param2 & 0x0000ff00); if (param3 == 0) { my_gds->_0000 = my_gds->_004c + my_gds->sector_mode; my_gds->_0002 = ((param2 & 0x00ff0000)>>16) | (param2 & 0x0000ff00); my_gds->_0004 = (param2 & 0x000000ff); my_gds->_0006 = 0x0000; my_gds->_0008 = ((param1 & 0x00ff0000)>>16) | (param1 & 0x0000ff00); my_gds->_000a = (param1 & 0x000000ff); } /* _8c0026c4 */ my_gds->_0000 = my_gds->_0050 + my_gds->sector_mode; my_gds->_0002 = ((param2 & 0x00ff0000)>>16) | (param2 & 0x0000ff00); my_gds->_0004 = (param2 & 0x000000ff); my_gds->_0006 = (param1>>8) | (param1<<8); my_gds->_0008 = ((param3 & 0x00ff0000)>>16) | (param3 & 0x0000ff00); my_gds->_000a = (param7 & 0x000000ff); } int _8c0026fe(my_gds) GDS *my_gds; { if (*_a05f7418 == 0x00000001) { *_a05f7414 = 0x00000000; while (*_a05f7418 & 0x00000001 != 0); } /* _8c002722 */ my_gds->_00c4 = 0x00000000; return (_8c001118(0)); } void _8c002774(my_gds) GDS *my_gds; { while (1) { if ((*_a05f7018 & 0x88) == 0) { my_gds->_00a8 = 0; return; } else { /* _8c0027a2 */ my_gds->_00a8 = 2; _8c0018c0(); } } } /* this is called after gdrom-controller has given result methinks */ void _8c002948(result, my_gds) int result; GDS *my_gds; { if (result == 0xdeaddead) { my_gds->_0018 = 0x00000002; my_gds->_001c = 0x0000003a; return; } if (result & 0x01 == 0) { my_gds->_0018 = 0x00000000; my_gds->_001c = 0x00000000; return; } if (my_gds->cmdabort == 0x02) { my_gds->_0018 = 0x00000000; my_gds->_001c = 0x00000000; return; } _8c002126(my_gds->_00e8, my_gds); my_gds->_0018 = (int)(my_gds->_00e8->_0002 & 0x000f); my_gds->_001c = (int)(my_gds->_00e8->_0008); if (my_gds->_0018 != 11) { return; } if (my_gds->_001c == 0) my_gds->_0018 = 0x00000000; } int _8c0029a8(param1, param2, my_gds) int param1, param2; GDS *my_gds; { int i; /* R8 */ int j; /* 1, R15 */ int temp; /* R13 */ _8c002818(0, my_gds); major_loop: if (my_gds->cmdabort == 0) { /* _8c0029e2 */ i = (char )*_a05f709c; } else { my_gds->cmdabort = 2; i = _8c00377c(0, my_gds); } /* _8c0029f0 */ j = i & 0x08; if (j == 0x08) { temp = ((char)(*_a05f7094)<<8) | (*_a05f7090); if (param2 != 0x04) { do { if (my_gds->_00e4 > 0x00000001) { *my_gds->_00e0 = (short)*_a05f7080; my_gds->_00e0 += 2; temp -= 2; my_gds->_00a4 += 2; my_gds->_00e4 -= 2; } else { /* _8c002a78 */ if (my_gds->_00d8 == 0) { if (my_gds->cmdabort != 0) goto major_loop; _8c0018c0(); } else { /* _8c002a92 */ (*my_gds->_00d8)(my_gds->_00dc); } /* _8c002aaa */ do { /* _8c002a9e */ if (my_gds->cmdabort != 0) goto major_loop; _8c0018c0(); } while (my_gds->_00e4 == 0); } } while (temp > 0x01); } else { /* _8c002aba */ if ((param2 & 0x02) != 0) { APAAA } } } /* _8c002b12 */ } int _8c002b4c(param1, param2, param3, my_gds) int param1, param2; int param3; GDS *my_gds; { char *ptr; _8c002774(my_gds); *_a05f7090 = (char)param2 & 0x000000ff; *_a05f7094 = (char)((param2 & 0x0000ff00)>>8); *_a05f7084 = (char)0x00; if (_8c002880(my_gds) != 0) { return (0xdeaddead); } /* _8c002ba0 */ return (_8c0029a8(param1, param3, my_gds)); } int _8c002c44(my_gds) GDS *my_gds; { int i; /* R13 */ _8c002774(my_gds); *_a05f7084 = 0x01; _8c002774(my_gds); if (_8c002880(my_gds) != 0) { return (0xdeaddead); } my_gds->_00c4 = 0x0000001; *_a05f7414 = 0x00000001; *_a05f7418 = 0x00000001; _8c002818(1, my_gds); if (my_gds->cmdabort == 0) { /* _8c002c94 */ if (my_gds->sector_size + my_gds->_00a4 > *_a05f7408) { _8c0027ba(my_gds); } else { /* _8c002cb4 */ my_gfs->_00b8 = 0x00000002; i = _8c00377c(0, my_gds); if (my_gds->_00d0 == 0) return (i); if ((i & 0x00000001) == 1) { if ((*_a05f7084 & 0x04) == 0x04) return (i); } /* _8c002ce6 */ _8c0027ba(my_gds); i = (char)*_a05f709c; _8c002774(my_gds); return (i); } /* _8c002cf8 */ } /* _8c002cf8 */ i = (char)*_a05f709c; _8c0026fe(my_gds); _8c002774(my_gds); return (i); } int gdGdcReqCmd(cmd, param) /* _8c002ff4 */ int cmd; int *param; { GDS *my_gds; int gd_chn; if (allocate_GD() != 0) { return (0); } my_gds = get_GDS(); gd_chn = 0; if (my_gds->gd_cmd_stat == 0) { my_gds->gd_cmd = cmd; for (i = 0; i < my_gds->_04e8[cmd] ; i++) { my_gds->_0060[i] = *(param++); } my_gds->gd_cmd_stat = 2; if ((my_gds->gd_chn++) == 0) { my_gds->gd_chn++; } gd_chn = my_gds->gd_chn; } release_GD(); return (gd_chn); } int gdGdcGetCmdStat(gd_chn, status) /* _8c003072 */ int gd_chn; int *status; { GDS *my_gds; if (allocate_GD() != 0) { return (4); } my_gds = get_GDS(); status[0] = 0; status[1] = 0; status[2] = 0; status[3] = 0; if (gd_chn == 0) { if (my_gds->gd_cmd_stat == 0) { release_GD(); return (0); } release_GD(); return (1); } if (my_gds->gd_chn != gd_chn) { status[0] = 5; release_GD(); return (-1); } switch (my_gds->gd_cmd_stat) { case 0: release_GD(); return (0); break; case 1: case 2: status[2] = my_gds->_00a4; status[3] = my_gds->_00a8; release_GD(); return (1); break; case 3: if (my_gds->_0018 != 0) { status[2] = my_gds->_00a4; status[0] = my_gds->_0018; status[1] = my_gds->_001c; status[3] = my_gds->_00a8; my_gds->gd_cmd_stat = 0; release_GD(); return (-1); } status[2] = my_gds->_00a4; status[3] = my_gds->_00a8; my_gds->gd_cmd_stat = 0; release_GD(); return (2); break; case 4: if (my_gds->_0018 != 0) { status[2] = my_gds->_00a4; status[0] = my_gds->_0018; status[1] = my_gds->_001c; status[3] = my_gds->_00a8; release_GD(); return (-1); } status[2] = my_gds->_00a4; status[3] = my_gds->_00a8; release_GD(); return (3); break; default: release_GD(); return (0); break; } } int gdGdcGetDrvStat(status) /* _8c003174 */ int *status; { GDS *my_gds; char stat1, stat2, stat3; if (allocate_GD() != 0) { return (4); } my_gds = get_GDS(); if (my_gds->_00c4 == 0) { if (*_a05f7018 & 0x80 == 0) { stat1 = *_a05f708c; stat2 = *_a05f708c; stat3 = *_a05f708c; if (*_a05f7018 & 0x80 != 0) { release_GD(); return (1); } if (stat1 != stat2) { stat1 = stat3; } my_gds->_00ac = stat1 & 0x000f; status[0] = stat1 & 0x000f; my_gds->drvmedia = stat1 & stat2; status[1] = stat1 & stat2; release_GD(); return (0); } } /* _8c00320c */ if (my_gds->_00c4 == 0) { release_GD(); return (1); } my_gds->_00ac = GDD_DRVSTAT_PLAY; status[0] = GDD_DRVSTAT_PLAY; status[1] = my_gds->drvmedia; release_GD(); return (0); } void gdGdcG1DmaEnd(func, param) /* _8c003238 */ int *func, *param; { GDS *my_gds; my_gds = get_GDS(); *_a0606900 = 0x00004000; if (func == NULL) { return; } (*func)(param); } int gdGdcCheckDmaTrans(gd_chn, arg2) /* _8c00326a */ int gd_chn; int arg2; { GDS *my_gds; my_gds = get_GDS(); if (gd_chn != my_gds->gd_chn) { return (-1); } if (my_gds->gd_cmd_stat != 4) { return (-1); } return (_8c00223e(arg2, my_gds)); } int gdGdcReqDmaTrans(gd_chn, arg2) /* _8c0032a2 */ int gd_chn; int *arg2; { GDS *my_gds; my_gds = get_GDS(); if (gd_chn != my_gds->gd_chn) { return (-1); } if (my_gds->gd_cmd_stat != 4) { return (-1); } return (_8c002266(arg2, my_gds)); } /* This is probably for some type of callback stuff */ void _8c0032da(arg1, arg2) int arg1; int arg2; { GDS *my_gds; my_gds = get_GDS(); if (arg1 != 0) { my_gds->_00d8 = arg1; my_gds->_00dc = arg2; } else { my_gds->_00d8 = 0; my_gds->_00dc = 0; } } int _8c00333c(gd_chn, arg2) int gd_chn; int *arg2; { GDS *my_gds; my_gds = get_GDS(); if (gd_chn != my_gds->gd_chn) { return (-1); } if (my_gds->gd_cmd_stat != 4) { return (-1); } return (_8c002362(arg2, my_gds)); } int _8c003374(arg1, arg2) int arg1; int *arg2; { GDS *my_gds; my_gds = get_GDS(); if (arg1 != my_gds->gd_chn) { return (-1); } if (my_gds->gd_cmd_stat != 4) { return (-1); } return (_8c002380(arg2, my_gds)); } int gdGdcReadAbort(gd_chn) /* _8c0033c0 */ Sint32 gd_chn; { GDS *my_gds; my_gds = get_GDS(); if (gd_chn != my_gds->gd_chn) { return (-1); } if (my_gds->cmdabort != 0) { return (-1); } switch (my_gds->gd_cmd) { case 16: case 17: case 20: case 21: case 22: case 27: case 28: case 29: case 32: case 33: case 34: case 37: case 38: case 39: switch (my_gds->gd_cmd_stat) { case 1: case 2: case 4: my_gds->cmdabort = 1; return (0); break; default: return (0); break; } break; default: return (-1); } } void gdGdcReset() /* _8c003450 */ { GDS *my_gds; my_gds = get_GDS(); if (*_a05f7418 == 0x00000001) { *_a05f7414 = 0x00000000; while (*_a05f7418 & 0x00000001); my_gds->_00c4 = 0; } *_a05f709c = (char)0x08; while (*_a05f7018 & 0x80); } int gdGdcChangeDataType(arg1) /* _8c0034a6 */ int *arg1; { GDS *my_gds; if (allocate_GD() != 0) { return (4); } my_gds = get_GDS(); switch (arg1[0]) { case 0: if (arg1[1] & 0x1000 == 0) { switch (arg1[2]) { case 0x0200: case 0x0400: case 0x0600: case 0x0800: case 0x0a00: case 0x0c00: break; default: release_GD(); return (-1); break; } } my_gds->sector_mode = arg1[1] | arg1[2]; my_gds->sector_size = arg1[3]; release_GD(); return (0); break; case 1: arg1[1] = my_gds->sector_mode & 0xf000; arg1[2] = my_gds->sector_mode & 0x0e00; arg1[3] = my_gds->sector_size; release_GD(); return (0); break; default: release_GD(); return (-1); break; } } void _8c003570() { GDS *my_gds; my_gds = get_GDS(); my_gds->gd_cmd = 0; my_gds->_0018 = 0; my_gds->_001c = 0; my_gds->_00a0 = get_GdBaseReg(); my_gds->_00a4 = 0; my_gds->_00a8 = 0; my_gds->_00ac = 0; my_gds->drvmedia = 0; my_gds->_00b4 = 1; my_gds->cmdabort = 0; my_gds->size = 0; my_gds->gd_chn = 1; my_gds->_00c4 = 0; my_gds->sector_mode = 0x00002400; my_gds->sector_size = 0x00000800; my_gds->_00d0 = 2; my_gds->_00d4 = 0; my_gds->_00d8 = 0; my_gds->_00dc = 0; my_gds->_00e0 = 0; my_gds->_00e4 = 0; ptr = _8c0010b0(1); if (ptr[14] != 0) { for (i = 0; i < 16; i++) { my_gds->_0020[i] = ptr[i]; } } else { my_gds->_0020 = 0; my_gds->_0024 = 0x00000010; my_gds->_0028 = 0x00000011; my_gds->_002c = 0x00000012; my_gds->_0030 = 0x00000013; my_gds->_0034 = 0x00000014; my_gds->_0038 = 0x00000015; my_gds->_003c = 0x00000016; my_gds->_0040 = 0x00000020; my_gds->_0044 = 0x00000021; my_gds->_0048 = 0x00000022; my_gds->_004c = 0x00000030; my_gds->_0050 = 0x00000031; my_gds->_0054 = 0x00000040; } /* _8c003660 */ for (i = 0; i < 16; i++) { my_gds->_0060[i] = 0; } for (i = 0; i < 48; i++) { my_gds->_00e8[i] = 0; } for (i = 0; i < 104; i++) { my_gds->_01a8[i] = 0xffffffff; } for (i = 0; i < 104; i++) { my_gds->_0348[i] = 0xffffffff; } for (i = 0; i < 48; i++) { my_gds->_04e8[i] = 0; } my_gds->_0528 = 4; my_gds->_052c = 4; my_gds->_0530 = 2; my_gds->_0534 = 2; my_gds->_0538 = 3; my_gds->_053c = 3; my_gds->_0554 = 1; my_gds->_0558 = 2; my_gds->_0570 = 3; my_gds->_055c = 4; my_gds->_0564 = 4; my_gds->_0560 = 1; my_gds->_0568 = 2; my_gds->_0574 = 3; my_gds->_0578 = 4; my_gds->_057c = 2; my_gds->_0580 = 3; my_gds->_0584 = 3; my_gds->_0588 = 1; my_gds->gd_cmd_stat = 0; while(1) { if (my_gds->gd_cmd_stat == 2) { my_gds->gd_cmd_stat = 1; my_gds->_0018 = 0; my_gds->_001c = 0; my_gds->_00a4 = 0; if (my_gds->_00d4 != 1) { gd_do_cmd(my_gds->_0060, my_gds, my_gds->gd_cmd); } else { if (my_gds->gd_cmd != 24) { gd_do_cmd(my_gds->_0060, my_gds, my_gds->gd_cmd); } else { my_gds->_0018 = 6; } } my_gds->gd_cmd_stat = 3; my_gds->cmdabort = 0; if (my_gds->_0018 == 6) { my_gds->_00d4 = 1; } } _8c0018c0(); } } void _8c003774(param, my_gds) int *param; GDS *my_gds; { my_gds->_0018 = 5; } int _8c0037b2(arg1, my_gds) int arg1; GDS *my_gds; { char i; if (my_gds->_00d0 == 1) { _8c001148(); } if (_8c002f7e(my_gds) & 0x0081 != 0) { my_gds->_0018 = 2; return (1); } i = 0; if (arg1 != 0) { i = i | 0x80; } i = i | 0x01; i = i | 0x02; i = i | 0x04; i = i | 0x08; i = i | 0x10; if (_8c003944(i, my_gds) != 0) { return (2); } /* _8c003828 */ if (_8c002f7e(my_gds) & 0x0081 != 0) { my_gds->_0018 = 2; return (3); } if (_8c00399c(&i, my_gds) != 0) { return (4); } if (i & 0x10 == 0x10) { return (0); } return (-1); } int _8c003944(arg1, my_gds) unsigned char arg1; GDS *my_gds; { int result; my_gds->_0000 = (short)((arg1 & 0x9f)<<8 + 0x70); my_gds->_0002 = (short)0x0000; my_gds->_0004 = (short)0x0000; my_gds->_0006 = (short)0x0000; my_gds->_0008 = (short)0x0000; my_gds->_000a = (short)0x0000; result = _8c002bb6(my_gds); _8c002948(result); if (result & 0x81 != 0) { return (-1); } return (0); } int _8c00399c(arg1, my_gds) char *arg1; GDS *my_gds; { int result, i, j; my_gds->_0000 = (short)(((*arg1 & 0x1f)<<8) + 0x71); my_gds->_0002 = (short)0x0000; my_gds->_0004 = (short)0x0000; my_gds->_0006 = (short)0x0000; my_gds->_0008 = (short)0x0000; my_gds->_000a = (short)0x0000; my_gds->_00a4 = 0; result = _8c002b4c(my_gds); i = my_gds->_00a4; _8c002948(result, my_gds); if (result & 0x81 != 0) { return (-1); } j = 1; *arg1 = (char)0; if (_8c003b04(i, &j) != 0) { return (-1); } return (0); } void _8c003c00(arg1, arg2, arg3, func) int arg1, arg2, arg3; /* arg3 is discarded */ int func; { if (func >= 4) return (-1); switch (func) { case 0: /* 8c003c38 */ _8c003ca8(0x0001a056, _8c000068, 8); _8c003ca8(0x0001a000, _8c000070, 5); _8c000075 = 0; _8c000076 = 0; _8c000077 = 0; _8c000078 = 0; _8c000079 = 0; _8c00007a = 0; _8c00007b = 0; _8c00007c = 0; _8c00007e = 0; _8c00007f = 0; __asm__("ocbwb 0x8c000060"); return (0); break; case 1: /* 8c003c20 */ /* not valid */ break; case 2: /* 8c003c78 */ if (arg1 >= 10) return (-1); return (_8c003ca8(0x0001a480 + arg1 * 0x2c0, arg2, 0x2c0)); break; case 3: /* 8c003ca0 */ return (0x8c010068); break; } } int _8c003ca8(arg) int arg; { (*_8c0000b8)(); } void _8c008300() { reg[CCR] = 0x0000092b; reg[R15] = 0x7e001000; /* use cache as memory for stack */ _8c0083a8(); __asm__("jmp 0xac00b700\n\t"); } void _8c0083a8() { _8c0083c0(); _8ced3d9c = 0; /* hmm :/ */ _8c0083f8(); } void _8c0083c0() { char *dst = *_8c009d38; while (*_8c009d3c < dst) *(dst++) = 0; } void _8c0083f8() { int old_SR; int result; int i; /* 8, R15 */ int j; /* 7, R15 */ int k; /* 6, R15 */ int l; /* 5, R15 */ int m; /* 4, R15 */ int n; /* 3, R15 */ int o; /* 2, R15 */ int p; /* 1, R15 */ _8c009dec(); old_SR = (reg[SR]>>4) & 0x000f; reg[SR] = (reg[SR] & 0xff0f) | 0x00f0; result = _8c009858(); reg[SR] = ((old_SR & 0x000f)<<4) | (reg[SR] & 0xff0f); switch (result) { case 1: case 3: i = 8; break; case 4: i = 9; break; default: i = 6; break; } /* _8c008460 */ old_SR = (reg[SR]>>4) & 0x000f; reg[SR] = (reg[SR] & 0xff0f) | 0x00f0; _8c009074(i); reg[SR] = ((old_SR & 0x000f)<<4) | (reg[SR] & 0xff0f); _8c00853c(i); _8c00908c(1); j = _8c009e12(); p = 0; n = 0; while (1) { k = _8c009e12(); l = _8c009e1c(j, k); m = _8c009e24(l); o = 0; while (o++ < 1000); if (p++ >= 4000) n = 1; if (m >= 6000000) break; if (n != 0) break; } /* 8c00851e */ sys_do_bioscall(0); /* 8c000820() */ } void _8c009074(arg) int arg; { _8c009830(arg); } int _8c0090f8(arg) int arg; { int result, i, fog; result = *_a05f8000; *_a05f8008 = 0x00000000; *_8ced3d18 = (*_ac00002c<<16) | 0x08; *_8ced3d24 = 0x0000000c; if (arg == 9) *_8ced3d24 |= 0x00800000; *_a05f8040 = 0x00c0c0c0; /* border color to light white */ _8c00908c(0); *_a05f8030 = 0x00000101; *_a05f80b0 = 0x007f7f7f; *_a05f80b4 = 0x007f7f7f; *_a05f80b8 = 0x0000ff07; fog = 0xfffe; for (i = 0; i < 128; i++) { _a05f8200[i] = fog; fog = fog - 0x0101; } *_a05f8008 = 0x00000001; *_a05f8008 = 0x00000000; *_a05f6884 = 0x00000000; *_a05f6888 = 0x00000000; return (result); } void _8c009214(arg) int arg; { *_a05f8124 = 0x000c2680; *_a05f812c = 0x0009e800; *_a05f8128 = 0x00000000; *_a05f8130 = 0x0009e740; *_a05f813c = 0x000e0013; *_a05f8140 = 0x00100203; *_a05f8164 = 0x000c2680; *_a05f8144 = 0x80000000; *_a05f8068 = ((*_8ced3d00-1)<<16) & 0x07ff0000; *_a05f806c = ((*_8ced3d04-1)<<16) & 0x07ff0000; *_a05f8110 = 0x00093f39; *_a05f80d0 = *_8ced3d44; *_a05f80d4 = *_8ced3d4c; *_a05f80dc = *_8ced3d50; *_a05f80d8 = *_8ced3d54; *_a05f80e0 = *_8ced3d58; *_a05f8060 = *_8ced3d38; *_a05f8064 = *_8ced3d40; *_a05f8048 = *_8ced3d28; *_a05f804c = *_8ced3d2c; *_a05f8050 = *_8ced3d34; *_a05f8054 = *_8ced3d3c; *_a05f805c = *_8ced3d30; *_a05f80c8 = *_8ced3d48; *_a05f8074 = 0x00000001; *_a05f807c = 0x0027df77; *_a05f8080 = 0x00000007; *_a05f8118 = 0x00008040; *_a05f8078 = 0x3f800000; *_a05f8084 = 0x00000000; *_a05f8088 = (float)*_8c009448; /* 0x38d1b717 */ *_a05f808c = 0x01000000; *_a05f80bc = 0xffffffff; *_a05f80c0 = 0xff000000; *_a05f80e4 = *_8ced3d10; *_a05f8040 = *_8ced3d14; *_a05f80f4 = *_8ced3d5c; } void _8c00940a(arg) int arg; { if (arg == 9) { *_a0702c00 = *_a0702c00 & 0x01; } else { } } void _8c0097b4(arg) int arg; { _8c00940a(arg); switch (arg) { case 6: _8c009488(0x00008212); break; case 8: _8c009488(0x00008214); break; case 9: _8c009488(0x00008111); break; default: _8c009488(0x00008212); break; } } void _8c009830(arg) int arg; { _8c0090f8(arg); _8c0097b4(arg); _8c009214(arg); } int _8c009858() { int result; char flash_stuff1; result = _8c008380(); flash_stuff1 = *_ac000074; if (result == 0) return (4); switch (flash_stuff1) { case 0x30: return (0); break; case 0x31: return (1); break; case 0x32: return (2); break; case 0x33: return (3); break; default: return (0); break; } } void _8c009dec() { reg[TOCR] = 0x00; reg[TSTR] = reg[TSTR] & 0xfe; reg[TCR0] = 0x0002; reg[TCOR0] = 0xffffffff; reg[TCNT0] = 0xffffffff; reg[TSTR] = reg[TSTR] | 0x01; } void init_machine(mode) /* _8c00b500 */ int mode; { unsigned time, gd_status; reg[R15] = 0x8c00b700; /* default floating point registers here */ reg[SR] = 0x500000f0; reg[FPSCR] = 0x00140001; /* reset all floating point registers; details omitted */ reg[FPUL] = 0x00000000; reg[FPSCR] = 0x00140001; reg[R0] = 0x00000000; reg[R1] = 0x00000000; reg[R2] = 0x00000000; reg[R3] = 0x00000000; reg[R4] = 0xfffffffd; reg[R5] = 0x00000000; reg[R6] = 0x00000000; reg[R7] = 0x00000000; reg[SR] = 0x700000f0; /* does this change banks? */ reg[R2] = 0x8cfffff8; reg[R3] = 0x00000000; reg[R4] = 0x00000000; reg[R5] = 0x00000000; reg[R6] = 0x00000000; reg[R7] = 0x00000000; reg[R8] = 0x00000000; reg[R9] = 0x00000000; reg[R10] = 0x00000000; reg[R11] = 0x00000000; reg[R12] = 0x00000000; reg[R13] = 0x00000000; reg[R14] = 0x00000000; reg[MACH] = 0x00000000; reg[MACL] = 0x00000000; reg[PR] = 0x8c000128; reg[GBR] = 0x8c000000; reg[VBR] = 0x8c000000; reg[SSR] = 0x500000f0; reg[SPC] = (uint32_t *)sys_do_bioscall; reg[R15] = 0x8d000000; _8cfffffc = 0x00000000; _8cfffff8 = 0x8c000128; reg[R14] = 0x00000000; lmemset(0, (uint64_t *)0x8cffffff8, 0x001bffff); /* clear memory above bootROM in RAM */ /* check for initial boot ( = no debug handler installed) */ if (reg[DBR] >= 0) { lmemset(0, (uint64_t *)0x8c000100, 0x20); /* clear system variables */ _8c00b800(0, mode); _8c00b800(4, mode); } else { _8c00b800(2, mode); wait_for_vsync(); } _8c00b800(6, mode); if (mode != 0) { i = *_a05f74b0; *_8c000076 = (char)i; *_8c000072 = (char)(((i & 0x0c)>>2)|0x30); *_8c000074 = (char)((i & 0x03) | 0x30); } _8c00b800(8, mode); if (mode == 0 || reg[DBR] >= 0) { lmemset(0, _ac008000, 0x0800); /* clear mem _ac004000 to _ac008000 */ /* check for initial boot */ if (reg[DBR] >= 0) { *SelectMenu = -3; } } /* _8c00b5da */ /* Save R3-R8, R12,R13 on stack; details omitted */ init_bioscall_vectors(0, 0, mode); if (reg[DBR] >= 0) { _8c0010b0(0); } gdGdcInitSystem(0); /* gd_do_bioscall(0, 3, 0) */ *GdCmd = CMD_INIT; *GdHn = gdGdcReqCmd(CMD_INIT, NULL); /* gd_do_bioscall(0, 0, CMD_INIT, 0) */ gdGdcExecServer(); /* gd_do_bioscall(0, 2) */ *_8c000020 = reg[TCNT0] + 0xff88ca6c; /* _8c00b61c - warning: messy code */ gdGdcExecServer(); /* gd_do_bioscall(0, 2) */ *GdCmdStat = gdGdcCheckDmaTrans(*GdHn, GdStatus); /* gd_do_bioscall(0, 7, *_8c000040, _8c000030) */ gd_status = 0; while (*GdCmdStat == 1) { /* _8c00b620 */ time = reg[TCNT0]; if (time > 0) { /* _8c00b634 */ if (*_8c000020 > 0) { if (time < *_8c000020) { /* _8c00b694 */ *TimerCount = reg[TCNT0]; *GdDrvStatus = -1; *GdMedia = -1; *GdHn = -1; return; } } else if (time < *_8c000020) { /* _8c00b694 */ *TimerCount = reg[TCNT0]; *GdDrvStatus = -1; *GdMedia = -1; *GdHn = -1; return; } } else if (*_8c000020 > 0) { /* _8c00b638 */ if (time < *_8c000020) { /* _8c00b694 */ *TimerCount = reg[TCNT0]; *GdDrvStatus = -1; *GdMedia = -1; *GdHn = -1; return; } } else if (time < *_8c000020) { /* _8c00b694 */ *TimerCount = reg[TCNT0]; *GdDrvStatus = -1; *GdMedia = -1; *GdHn = -1; return; } /* _8c00b63c */ time = reg[TCNT0]; if (time > 0) { /* _8c00b650 */ if (*TimerCount > 0) { /* _8c00b64a */ if (time > *TimerCount) { /* _8c00b658 */ gd_status |= 0x02; if (gd_status == 0x03) { break; /* goto _8c00b684 */ } } } else if (time < *TimerCount) { /* _8c00b658 */ gd_status |= 0x02; if (gd_status == 0x03) { break; /* goto _8c00b684 */ } } } else if (*TimerCount > 0) { /* _8c00b654 */ if (time < *TimerCount) { /* _8c00b658 */ gd_status |= 0x02; if (gd_status == 0x03) { break; /* goto _8c00b684 */ } } } else if (time > *TimerCount) { /* _8c00b658 */ gd_status |= 0x02; if (gd_status == 0x03) { break; /* goto _8c00b684 */ } } /* _8c00b662 */ gdGdcExecServer(); /* gd_do_bioscall(0, 2) */ *GdCmdStat = gdGdcGetCmdStat(*GdHn, GdStatus); /* gd_do_bioscall(0, 1, *_8c000040, _8c000030) */ if (*GdCmdStat != 1) { gd_status |= 0x01; if (gd_status != 0x03) { *GdCmdStat = 1; } } } /* _8c00b684 */ *TimerCount = reg[TCNT0]; GdDrvStatus = gdGdcGetDrvStat(); /* gd_do_bioscall(0, 4) */ *GdHn = 0; } int lmemset(value, start, n) /* _8c00b6b8 */ long value, long *start; int n; { while(n--) *(--start) = value; } void wait_for_vsync() /* 8c00b6c2 */ { while (*_a05f810c & 0x2000); } /* Bah! this is a messy function; see below for rewritten version of this void _8c00b800(function) short function; { int *dst; short *src, *func; short arg1, arg2; src = _8c00bb9c + _8c00bb9c[function]; for (;;) { src += 3; src = (src>>2)<<2; arg1 = *(src++); if (arg1 == 0) { arg1 = *(src++); if (arg1 != 0) { src += arg1; } else { return; } } else { func = *(src++); if ((func & 0x8000) != 0) { func = func ^ (func & 0x8000); } else { dst = *(src++); } if (func & 0x6000 != 0) { func = func ^ (func & 0x6000); func += 0x0c; arg2 = src; for (src += *src + 1; arg1--; dummy += 4) { (*func)(arg1, arg2); } src = arg2; } else { for (; arg1--; dst += 4) { (*func)(arg1, dst); } } } } } */ void _8c00b800(function, mode) short function; int mode; { unsigned int *dst; switch (function) { case 0: reg[WCR3] = 0x07777777; reg[PCR] = 0x0000; reg[PDTRA] = 0x0000; reg[PCTRA] = 0x000a03f0; reg[PCTRB] = 0x00000000; reg[PDTRB] = 0x0000; reg[GPIOIC] = 0x0000; reg[PTEH] = 0x00000000; reg[PTEL] = 0x00000000; reg[TTB] = 0x00000000; reg[TEA] = 0x00000000; reg[TRA] = 0x00000000; reg[EXPEVT] = 0x00000000; reg[INTEVT] = 0x00000000; reg[PTEA] = 0x00000000; reg[QACR0] = 0x00000000; reg[QACR1] = 0x00000000; reg[RMONAR] = 0x00; reg[RCR1] = 0x00; reg[STBCR] = 0x03; reg[WTCNT] = 0x5a00; reg[WTCSR] = 0x5a00; reg[STBCR2] = 0x00; reg[TOCR] = 0x00; reg[TSTR] = 0x00; reg[TCOR0] = 0xffffffff; reg[TCNT0] = 0xffffffff; reg[TCR0] = 0x0002; reg[TCOR1] = 0xffffffff; reg[TCNT1] = 0xffffffff; reg[TCR1] = 0x0000; reg[TCOR2] = 0xffffffff; reg[TCNT2] = 0xffffffff; reg[TCR2] = 0x0000; reg[TSTR] = 0x01; reg[SAR1] = 0x00000000; reg[DAR1] = 0x00000000; reg[DMATCR1] = 0x00000000; reg[CHCR1] = 0x00005440; reg[SAR2] = 0x00000000; reg[DAR2] = 0x00000000; reg[DMATCR2] = 0x00000000; reg[CHCR2] = 0x000052c0; reg[SAR3] = 0x00000000; reg[DAR3] = 0x00000000; reg[DMATCR3] = 0x00000000; reg[CHCR3] = 0x00005440; reg[DMAOR] = 0x00008201; reg[SCSMR2] = 0x0000; reg[SCBRR2] = 0xff; reg[SCSCR2] = 0x0000; reg[SCFCR2] = 0x0000; reg[SCSPTR2] = 0x0000; reg[ICR] = 0x0000; reg[IPRA] = 0x0000; reg[IPRB] = 0x0000; reg[IPRC] = 0x0000; reg[BBRA] = 0x0000; reg[BBRB] = 0x0000; reg[BRCR] = 0x0000; *_a05f6800 = 0x11ff0000; *_a05f6804 = 0x00000020; *_a05f6808 = 0x00000000; *_a05f6810 = 0x0cff0000; *_a05f6814 = 0x0cff0000; *_a05f6818 = 0x00000000; *_a05f681c = 0x00000000; *_a05f6820 = 0x00000000; *_a05f6840 = 0x00000000; *_a05f6844 = 0x00000000; *_a05f6848 = 0x00000000; *_a05f684c = 0x00000000; *_a05f6884 = 0x00000000; *_a05f6888 = 0x00000000; *_a05f68a0 = 0x80000000; *_a05f68a4 = 0x00000000; *_a05f68ac = 0x00000000; *_a05f6910 = 0x00000000; *_a05f6914 = 0x00000000; *_a05f6918 = 0x00000000; *_a05f6920 = 0x00000000; *_a05f6924 = 0x00000000; *_a05f6928 = 0x00000000; *_a05f6930 = 0x00000000; *_a05f6934 = 0x00000000; *_a05f6938 = 0x00000000; *_a05f6940 = 0x00000000; *_a05f6944 = 0x00000000; *_a05f6950 = 0x00000000; *_a05f6954 = 0x00000000; *_a05f6c04 = 0x0cff0000; *_a05f6c10 = 0x00000000; *_a05f6c14 = 0x00000000; *_a05f6c18 = 0x00000000; *_a05f6c80 = 0xc3500000; *_a05f6c8c = 0x61557f00; *_a05f6ce8 = 0x00000001; *_a05f7404 = 0x0cff0000; *_a05f7408 = 0x00000020; *_a05f740c = 0x00000000; *_a05f7414 = 0x00000000; *_a05f7418 = 0x00000000; *_a05f7484 = 0x00000400; *_a05f7488 = 0x00000200; *_a05f748c = 0x00000200; *_a05f7490 = 0x00000222; *_a05f7494 = 0x00000222; *_a05f74a0 = 0x00002001; *_a05f74a4 = 0x00002001; *_a05f74b4 = 0x00000001; *_a05f74b8 = 0x88437f00; *_a05f7800 = 0x009f0000; *_a05f7804 = 0x0cff0000; *_a05f7808 = 0x00000020; *_a05f780c = 0x00000000; *_a05f7810 = 0x00000005; *_a05f7814 = 0x00000000; *_a05f7818 = 0x00000000; *_a05f781c = 0x00000000; *_a05f7820 = 0x009f0000; *_a05f7824 = 0x0cff0000; *_a05f7828 = 0x00000020; *_a05f782c = 0x00000000; *_a05f7830 = 0x00000005; *_a05f7834 = 0x00000000; *_a05f7838 = 0x00000000; *_a05f783c = 0x00000000; *_a05f7840 = 0x009f0000; *_a05f7844 = 0x0cff0000; *_a05f7848 = 0x00000020; *_a05f784c = 0x00000000; *_a05f7850 = 0x00000005; *_a05f7854 = 0x00000000; *_a05f7858 = 0x00000000; *_a05f785c = 0x00000000; *_a05f7860 = 0x009f0000; *_a05f7864 = 0x0cff0000; *_a05f7868 = 0x00000020; *_a05f786c = 0x00000000; *_a05f7870 = 0x00000005; *_a05f7874 = 0x00000000; *_a05f7878 = 0x00000000; *_a05f787c = 0x00000000; *_a05f7890 = 0x00000fff; *_a05f7894 = 0x00000fff; *_a05f7898 = 0x00000000; *_a05f789c = 0x00000001; *_a05f78a0 = 0x00000000; *_a05f78a4 = 0x00000000; *_a05f78a8 = 0x00000000; *_a05f78ac = 0x00000000; *_a05f78b0 = 0x00000000; *_a05f78b4 = 0x00000000; *_a05f78b8 = 0x00000000; *_a05f78bc = 0x46597f00; *_a05f7c00 = 0x04ff0000; *_a05f7c04 = 0x0cff0000; *_a05f7c08 = 0x00000020; *_a05f7c0c = 0x00000000; *_a05f7c10 = 0x00000000; *_a05f7c14 = 0x00000000; *_a05f7c18 = 0x00000000; *_a05f7c80 = 0x67027f00; *_a05f6900 = 0xffffffff; *_a05f6908 = 0xffffffff; _8c00b8fa(); break; case 2: reg[PTEH] = 0x00000000; reg[PTEL] = 0x00000000; reg[TTB] = 0x00000000; reg[TEA] = 0x00000000; reg[TRA] = 0x00000000; reg[EXPEVT] = 0x00000000; reg[INTEVT] = 0x00000000; reg[PTEA] = 0x00000000; reg[QACR0] = 0x00000000; reg[QACR1] = 0x00000000; reg[RMONAR] = 0x00; reg[RCR1] = 0x00; reg[STBCR] = 0x03; reg[WTCNT] = 0x5a00; reg[WTCSR] = 0x5a00; reg[STBCR2] = 0x00; reg[TOCR] = 0x00; reg[TSTR] = 0x00; reg[TCOR0] = 0xffffffff; reg[TCNT0] = 0xffffffff; reg[TCR0] = 0x0002; reg[TCOR1] = 0xffffffff; reg[TCNT1] = 0xffffffff; reg[TCR1] = 0x0000; reg[TCRO2] = 0xffffffff; reg[TCNT2] = 0xffffffff; reg[TCR2] = 0x0000; reg[TSTR] = 0x0001; reg[SAR1] = 0x00000000; reg[DAR1] = 0x00000000; reg[DMATCR1] = 0x00000000; reg[CHCR1] = 0x00005440; reg[SAR2] = 0x00000000; reg[DAR2] = 0x00000000; reg[DMATCR2] = 0x00000000; reg[CHCR2] = 0x000052c0; reg[SAR3] = 0x00000000; reg[DAR3] = 0x00000000; reg[DMATCR3] = 0x00000000; reg[CHCR3] = 0x00005440; reg[DMAOR] = 0x00008201; reg[SCSMR2] = 0x0000; reg[SCBRR2] = 0xff; reg[SCSCR2] = 0x0000; reg[SCFCR2] = 0x0000; reg[SCSPTR2] = 0x0000; reg[ICR] = 0x0000; reg[IPRA] = 0x0000; reg[IPRB] = 0x0000; reg[IPRC] = 0x0000; reg[BBRA] = 0x0000; reg[BBRB] = 0x0000; reg[BRCR] = 0x0000; *_a05f6800 = 0x11ff0000; *_a05f6804 = 0x00000020; *_a05f6808 = 0x00000000; *_a05f6810 = 0x0cff0000; *_a05f6814 = 0x0cff0000; *_a05f6818 = 0x00000000; *_a05f681c = 0x00000000; *_a05f6820 = 0x00000000; *_a05f6840 = 0x00000000; *_a05f6844 = 0x00000000; *_a05f6848 = 0x00000000; *_a05f684c = 0x00000000; *_a05f6884 = 0x00000000; *_a05f6888 = 0x00000000; *_a05f68a0 = 0x80000000; *_a05f68a4 = 0x00000000; *_a05f68ac = 0x00000000; *_a05f6910 = 0x00000000; *_a05f6914 = 0x00000000; *_a05f6918 = 0x00000000; *_a05f6920 = 0x00000000; *_a05f6924 = 0x00000000; *_a05f6928 = 0x00000000; *_a05f6930 = 0x00000000; *_a05f6934 = 0x00000000; *_a05f6938 = 0x00000000; *_a05f6940 = 0x00000000; *_a05f6944 = 0x00000000; *_a05f6950 = 0x00000000; *_a05f6954 = 0x00000000; *_a05f6c04 = 0x0cff0000; *_a05f6c10 = 0x00000000; *_a05f6c14 = 0x00000000; *_a05f6c18 = 0x00000000; *_a05f6c80 = 0xc3500000; *_a05f6c8c = 0x61557f00; *_a05f6ce8 = 0x00000001; *_a05f7404 = 0x0cff0000; *_a05f7408 = 0x00000020; *_a05f740c = 0x00000000; *_a05f7414 = 0x00000000; *_a05f7418 = 0x00000000; *_a05f7484 = 0x00000400; *_a05f7488 = 0x00000200; *_a05f748c = 0x00000200; *_a05f7490 = 0x00000222; *_a05f7494 = 0x00000222; *_a05f74a0 = 0x00002001; *_a05f74a4 = 0x00002001; *_a05f74b4 = 0x00000001; *_a05f74b8 = 0x88437f00; *_a05f7800 = 0x009f0000; *_a05f7804 = 0x0cff0000; *_a05f7808 = 0x00000020; *_a05f780c = 0x00000000; *_a05f7810 = 0x00000005; *_a05f7814 = 0x00000000; *_a05f7818 = 0x00000000; *_a05f781c = 0x00000000; *_a05f7820 = 0x009f0000; *_a05f7824 = 0x0cff0000; *_a05f7828 = 0x00000020; *_a05f782c = 0x00000000; *_a05f7830 = 0x00000005; *_a05f7834 = 0x00000000; *_a05f7838 = 0x00000000; *_a05f783c = 0x00000000; *_a05f7840 = 0x009f0000; *_a05f7844 = 0x0cff0000; *_a05f7848 = 0x00000020; *_a05f784c = 0x00000000; *_a05f7850 = 0x00000005; *_a05f7854 = 0x00000000; *_a05f7858 = 0x00000000; *_a05f785c = 0x00000000; *_a05f7860 = 0x009f0000; *_a05f7864 = 0x0cff0000; *_a05f7868 = 0x00000020; *_a05f786c = 0x00000000; *_a05f7870 = 0x00000005; *_a05f7874 = 0x00000000; *_a05f7878 = 0x00000000; *_a05f787c = 0x00000000; *_a05f7890 = 0x00000fff; *_a05f7894 = 0x00000fff; *_a05f7898 = 0x00000000; *_a05f789c = 0x00000001; *_a05f78a0 = 0x00000000; *_a05f78a4 = 0x00000000; *_a05f78a8 = 0x00000000; *_a05f78ac = 0x00000000; *_a05f78b0 = 0x00000000; *_a05f78b4 = 0x00000000; *_a05f78b8 = 0x00000000; *_a05f78bc = 0x46597f00; *_a05f7c00 = 0x04ff0000; *_a05f7c04 = 0x0cff0000; *_a05f7c08 = 0x00000020; *_a05f7c0c = 0x00000000; *_a05f7c10 = 0x00000000; *_a05f7c14 = 0x00000000; *_a05f7c18 = 0x00000000; *_a05f7c80 = 0x67027f00; *_a05f6900 = 0xffffffff; *_a05f6908 = 0xffffffff; _8c00b8fa(); break; case 4: *_a05f80a8 = 0x15d1c951; *_a05f80a0 = 0x00000020; sysvars->error_code[0] = 0x00090009; /* void _8c000000() { */ sysvars->error_code[1] = 0x001b0009; /* while (1) */ sysvars->error_code[2] = 0x0009affd; /* __asm__("sleep\n"); } */ sysvars->var1 = 0x0000; sysvars->var2 = 0x0000; sysvars->rte_code[0] = 0x00090009; /* void _8c000010() { */ sysvars->rte_code[1] = 0x0009002b; /* __asm__("rte\n"); } */ sysvars->rts_code[0] = 0x00090009; /* void _8c000018() { */ sysvars->rts_code[1] = 0x0009000b; /* __asm__("rts\n"); } */ sysvars->unknown0 = 0x16; sysvars->disc_type = 0; sysvars->old_disc_type = -128; sysvars->IP_vector = (uint32_t *)0x8c008100; break; case 6: *_a05f8008 = 0x00000000; _8c00b948(mode); break; case 8: _8c00b9d6(); break; case 10: /* _8c00bee0 */ *_a05f80e8 = 0x00160018; *_a05f80ec = 0x000000a8; /* H position: 0xa8 */ *_a05f80f0 = 0x00280028; /* V position: 0x28 */ *_a05f8044 = 0x00800000; *_a05f80c8 = 0x03450000; *_a05f80cc = 0x00150208; *_a05f80d0 = 0x00000100; /* enable video */ *_a05f80d4 = 0x007e0345; /* H border: 0x7e to 0x345 */ *_a05f80d8 = 0x020c0359; /* scanlines: 0x20c pixels: 0x359 */ *_a05f80dc = 0x00280208; /* V border: 0x280 to 0x208 */ *_a05f80e0 = 0x03f1933f; /* jump to _8c00bfac */ *_a0702800 = 0x00000000; *_a070289c = 0x00000000; *_a07028a4 = 0x000007ff; *_a07028b4 = 0x00000000; *_a07028bc = 0x000007ff; dst = _a0703000; /* zero a0703000 to a0703300 */ for (i = 0; i < 24; i++) { for (j = 0; i < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0703400; /* zero a0703400 to a0703600 */ for (i = 0; i < 64; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0704000; /* zero a0704000 to a0704170 */ for (i = 0; i < 46; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } _8c00ba42(); break; case 12: /* _8c00bf28 */ *_a05f80e8 = 0x00160008; *_a05f80ec = 0x000000a4; /* H position: 0xa4 */ *_a05f80f0 = 0x00120012; /* V position: 0x12 */ *_a05f8044 = 0x00000000; *_a05f80c8 = 0x03450000; *_a05f80cc = 0x00150104; *_a05f80d0 = 0x00000150; /* enable video */ *_a05f80d4 = 0x007e0345; /* H border: 0x7e to 0x345 */ *_a05f80d8 = 0x020c0359; /* scanlines: 0x20c pixels: 0x359 */ *_a05f80dc = 0x00240204; /* V border: 0x240 to 0x204 */ *_a05f80e0 = 0x07d6c63f; /* jump to _8c00bfac */ *_a0702800 = 0x00000000; *_a070289c = 0x00000000; *_a07028a4 = 0x000007ff; *_a07028b4 = 0x00000000; *_a07028bc = 0x000007ff; dst = _a0703000; /* zero a0703000 to a0703300 */ for (i = 0; i < 24; i++) { for (j = 0; i < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0703400; /* zero a0703400 to a0703600 */ for (i = 0; i < 64; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0704000; /* zero a0704000 to a0704170 */ for (i = 0; i < 46; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } _8c00ba42(); break; case 14: /* _8c00bf6c */ *_a05f80e8 = 0x00160008; *_a05f80ec = 0x000000ae; /* H position: 0xae */ *_a05f80f0 = 0x002e002d; /* V position: 0x2d */ *_a05f8044 = 0x00000000; *_a05f80c8 = 0x034b0000; *_a05f80cc = 0x00150136; *_a05f80d0 = 0x00000190; /* enable video */ *_a05f80d4 = 0x008d034b; /* H border: 0x8d to 0x34b */ *_a05f80d8 = 0x0270035f; /* scanlines: 0x270 pixels: 0x24b */ *_a05f80dc = 0x002c026c; /* V border: 0x2c0 to 0x26c */ *_a05f80e0 = 0x07d6a53f; *_a0702800 = 0x00000000; *_a070289c = 0x00000000; *_a07028a4 = 0x000007ff; *_a07028b4 = 0x00000000; *_a07028bc = 0x000007ff; dst = _a0703000; /* zero a0703000 to a0703300 */ for (i = 0; i < 24; i++) { for (j = 0; i < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0703400; /* zero a0703400 to a0703600 */ for (i = 0; i < 64; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } dst = _a0704000; /* zero a0704000 to a0704170 */ for (i = 0; i < 46; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } _8c00ba42(); break; } } void _8c00b8fa() { unsigned int time; if (*_a0600004 == 0x10) { *_a0600480 = 0x00; dummy = *_a0600480; time = reg[TCNT0]; while (reg[TCNT0] >= (time - 3)); *_a0600480 = 0x01; dummy = *_a0600480; } sysvars->timer_count = 0xfffb3b4b + reg[TCNT0]; } void _8c00b92c(arg1) int arg1; { sysvars->var1 = reg[PDTRA]; for (i = 0; i < 4; i++) { sysvars->var2 = reg[PDTRA]; if (arg1 == sysvars->var2 & 0x03) { return; } } reg[PR] = (uint32_t *)0x8c000000; /* loop forever */ } void _8c00b948(mode) int mode; { int old_PCTRA, i; if (mode == 0) { old_PCTRA = reg[PCTRA]; i = old_PCTRA | 0x08; reg[PCTRA] = i; reg[PDTRA] = reg[PDTRA] | 0x03; _8c00b92c(3); reg[PCTRA] = i | 0x03; _8c00b92c(3); reg[PDTRA] = reg[PDTRA] & 0xfffe; _8c00b92c(0); reg[PCTRA] = i; _8c00b92c(3); reg[PCTRA] = i | 0x04; _8c00b92c(3); reg[PDTRA] = reg[PDTRA] & 0xfffd; _8c00b92c(0); reg[PCTRA] = old_PCTRA; } i = reg[PDTRA] & 0x0300; *_a0702c00 = i | (*_a0702c00 & 0x0000fcff); *DisplayCable = i>>2; *_8c000070 = (int)*_a021a000; /* get stuff from flash */ *_8c000074 = (char)*_a021a004; *_8c000068 = (short)*_a021a056; *_8c00006a = (short)*_a021a058; *_8c00006c = (short)*_a021a05a; *_8c00006e = (short)*_a021a05c; } void _8c00b9d6() { int i; switch (*_8c000074) { case 0x33: i = 0x0014; break; case 0x32: i = 0x000c; break; case 0x31: i = 0x0004; break; default: i = 0x0000; break; } reg[PDTRA] = i & 0x001c; if ((*DisplayCable>>6) == 0) { i = 0x0a; } else switch (*_8c000074) { case 0x33: case 0x31: i = 0x0e; break; default: i = 0x0c; break; } _8c00b800(i); *BorderCol = *_a05f8040; } void wait_aica_fifo() /* _8c00ba26 */ { for (i = 0; i < 0x1800; i++) { if (*_a05f688c & 0x01 == 0) break; } } void _8c00ba42() { unsigned int *dst; *_a07045c0 = 0x00000000; *_a07045c4 = 0x00000000; dst = _a0700000; for (i = 0; i < 65; i++) { for (j = 0; j < 3; j++) { *(dst) = 0x00000000; *(dst + 0x04) = 0x00000000; *(dst + 0x08) = 0x00000000; *(dst + 0x0c) = 0x00000000; *(dst + 0x10) = 0x00000000; *(dst + 0x14) = 0x00000000; wait_aica_fifo(); dst += 0x80; } } _8c00bab8(1); dst = _a0800000; for (i = 0; i < 65536; i++) { for (j = 0; j < 8; j++) *(dst++) = 0x00000000; wait_aica_fifo(); } *_a0800000 = 0xea000007; *_a0800004 = 0xea000010; *_a0800008 = 0xea00000f; *_a080000c = 0xea00000e; *_a0800010 = 0xea00000d; *_a0800014 = 0xea00000c; *_a0800018 = 0xea00000b; *_a080001c = 0xea00000a; wait_aica_fifo(); *_a0800020 = 0xe1a00000; *_a0800024 = 0xe59fd040; *_a0800028 = 0xe10fa000; *_a080002c = 0xe38aa040; *_a0800030 = 0xe129f00a; *_a0800034 = 0xe59f000c; *_a0800038 = 0xe2800001; *_a080003c = 0xe58f0004; wait_aica_fifo(); *_a0800040 = 0xeafffffb; *_a0800044 = 0xe1a00000; *_a0800048 = 0x00000000; *_a080004c = 0xe24ee004; *_a0800050 = 0xe28fd008; *_a0800054 = 0xe58de000; *_a0800058 = 0xe8dd8000; *_a080005c = 0xe1a00000; wait_aica_fifo(); *_a0800060 = 0x00000000; *_a0800064 = 0x00000000; *_a0800068 = 0x00000000; *_a080006c = 0x00000068; *_a0800070 = 0x00000000; *_a0800074 = 0x00000000; *_a0800078 = 0x00000000; *_a080007c = 0x00000000; wait_aica_fifo(); *_a0702c00 &= 0xfffffffe; } struct _time_str { uint16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t min; uint8_t sec; }; uint32_t 8c00c000(cmd) uint32_t cmd; { uint32_t *start, *end; uint8_t buf1[12], /* R15 + 0x40 */ buf2[12], /* R15 + 0x34 */ buf3[12], /* R15 + 0x28 */ buf4[12]; /* R15 + 0x1c */ struct _time_str str; /* R15 + 0x10 */ uint32_t i, /* R15 + 3 */ j; /* R15 + 2 */ uint32_t var1; /* R15 */ uint32_t var2; /* R15 + 0x04 */ register uint32_t retval; /* R14 */ /* bounds checking */ if (cmd >= 5) { return (-1); } switch (cmd) { case INIT: /* 8c00c020 - clear area at 8c00ee00-8c00ee50 */ start = (uint32_t *)0x8c00ee00; end = (uint32_t *)0x8c00ee50; while (start != end) { *start++ = 0; } return; /* no return value? */ break; case UNKNOWN1: /* 8c00cbb2 */ if (sysvars->gd_drv.stat == STAT_OPEN || sysvars->gd_drv.stat == STAT_NODISK || sysvars->gd_drv.stat == RETRY || sysvars->gd_drv.stat == STAT_ERROR) { return (_8c00c040(1, 1, 0)); } else { return (_8c00c040(0, 1, 0)); } break; case UNKNOWN2: /* 8c00cbc6 */ if (sysvars->gd_drv.stat == STAT_OPEN || sysvars->gd_drv.stat == STAT_NODISK || sysvars->gd_drv.stat == RETRY || sysvars->gd_drv.stat == STAT_ERROR) { for (i = 0; i < 100; i++) { wait_for_new_frame(); } } return (_8c00c040(2, 2, 0)); break; case SETDATE: /* 8c00cbec */ if (*(uint8_t *)0x8c000027 != 0) { /* 8c00ccf2 */ return (0); } R13 = 0; retval = _8c00cb80(); i = 0x00278d00 + retval; /* i = R15 + 0x0c */ j = 0x001e5280 + retval; /* j = R15 + 0x08 */ _8c00d340(); _8c00d4f4(retval, buf1); /* buf1 = R15 + 0x40 */ _8c00d4f4(j, buf2); /* buf2 = R15 + 0x34 */ _8c00d4f4(i, buf3); /* buf3 = R15 + 0x28 */ _8c00d38c(buf4); /* buf4 = R15 + 0x1c */ j = (uint32_t)sysvars->IP_vector; _8c00d474(buf4, &var1); /* var1 = R15 */ if (retval == -1) { R13 = 0x20; _8c00cd64(&str); /* str = R15 + 0x10 */ _8c00d474(&str, &var2); /* var2 = R15 + 0x04 */ /* 8c00cc62 */ if ((uint32_t)(var1 + 0xff000000) < 0x00ed4e00) { var1 = var1 + var2 + 0xff000000; } /* 8c00cc7a */ } /* 8c00cc7a */ sysvars->IP_vector = var1; if (_8c00d438(buf1, buf4) != 1 && _8c00d438(buf3, buf4) == -1) { /* 8c00cca6 */ if (_8c00d438(buf2, buf4) == -1) { _8c00d474(buf4, &var1); /* check up on this later! */ *(uint32_t *)0x8c000078 = var1; R13 = R13 | 0x10; R0 = 3; } else { /* 8c00ccc8 */ R0 = 1; } /* 8c00ccca */ sysvars->date_set = R0; } else { /* 8c00cca0 */ sysvars->date_sate = 0; } /* 8c00cccc */ if (sysvars->date_set == 0) { sysvars->current_color = *HW32(0xa05f8040); /* this should pop up menu and ask for date */ _8c00c040(2, 3, 1); } /* 8c00cce4 */ if (R13 != 0) { _8c00cdf0(R13, 0x8cfe0000); } /* 8c00ccee */ sysvars->IP_vectpr = (uint32_t *)j; return (0); break; case OPENMENU: /* 8c00cd00 */ sysvars->current_color = *HW32(0xa05f8040); if (sysvars->display_cable == 0) { _8c00c040(3, 3, 1); } /* 8c00cd1a */ return (_8c00c040(sysvars->menu_param, 3, 1)); break; } } uint32_t _8c00c040(a, b, c) uint32_t a, b, c; { return (_8c00c880(a, b, c)); } uint32_t _8c00c880(a, b, c) uint32_t a, b, c; { reg[SR] |= 0x00f0; if (b & 0x00000001 != 0) { _8c00c9e2(); } for (i = 0; i < 8; i++) { (uint32_t *)0x8c00ee04[i] = *(uint32_t *)0x8c00d30c[i]; } *(uint32_t *)0x8c00ee00 = reg[VBR]; reg[VBR] = 0x8c00c000; if (b & 0x00000001 != 0) { _8c00c9b8(); _8c00dd60(0, 0); for (i = 0; i < 8; i++) { (uint32_t *)0x8c00d30c[i] = 0; } } else { /* 8c00c8fa */ for (i = 0; i < 8; i++) { (uint32_t *)0x8c00d30c[i] = (uint32_t *)0x8c00ee28[i]; } } /* 8c00c90c */ *(uint32_t *)0xa05f6920 = *(uint32_t *)0xa05f6920 & 0xbfff; reg[SR] = reg[SR] & 0xff0f; _8c00ca78(a, b, c); reg[SR] = reg[SR] | 0x00f0; if (b & 0x02 != 0) { _8c00c9da(); for (i = 0; i < 8; i++) { (uint32_t *)0x8c00ee28[i] = 0; } } else { /* 8c00c94c */ for (i = 0; i < 8; i++) { (uint32_t *)0x8c00ee28[i] = *(uint32_t *)0x8c00d30c[i]; } } /* 8c00c95e */ reg[VBR] = *(uint32_t *)0x8c00ee00; for (i = 0; i < 8; i++) { (uint32_t *)8c00d30c[i] = (uint32_t *)0x8c00ee04; } reg[SR] = reg[SR] & 0xff0f; } void _8c00ca78(a, b, c) uint32_t a; /* R11 */ uint32_t b; uint32_t c; { uint32_t i = 0; /* R4 */ wait_for_new_frame(); if (*(uint16_t *)0xff800030 & 0x0300) { /* 8c00ca9c */ switch (sysvars->debug_switches.u0.switches.levelLo) { case '1': case '3': /* 8c00cab6 */ i = 0x0200; break; case '0': case '2': default: /* 8c00cab0 */ i = 0x0100; break; } } /* 8c00cab8 */ if (c == 1) { /* 8c00cad4 */ clear_8c200000_to_8c300000() check_lib_handles(8c090000); check_lib_handles(8c010000); _8c010000(a | i); _8c00dcb6(8c010000); _8c00dcb6(8c090000); } else { /* 8c00cae6 */ if (a < 2) { clear_8c200000_to_8c300000() check_lib_handles(8c090000); check_lib_handles(8c184000); _8c184000(a | i); /* this plays animation */ } else { /* 8c00cb02 */ reg[SR] = reg[SR] & 0xff0f; /* 8c00cb0c */ _8c184000(a | i); _8c00dcb6(8c184000); _8c00dcb6(8c090000); } } /* 8c00cb0c */ } void wait_for_new_frame() /* 0x8c00cb2a */ { while (*HW32(0xa05f810c) & 0x2000 == 0); while (*HW32(0xa05f810c) & 0x2000 != 0); } void clear_8c200000_to_8c300000() /* 0x8c00cb3e */ { uint32_t i; uint32_t *p = 0x8c200000; for (i = 0; i < 0x40000; i++) { *p++ = 0; } } uint32_t _8c00cb80() { _8c00cdf0(0, 0x8cfe0000); } /* Really! This function is BUGGED! Compared with a Euro bootrom and * that one makes sense! Check if it can be exploited somehow! */ uint32_t _8c00cd28(addr, size) sint8_t *addr; sint32_t size; { uint32_t bug; /* bug = R6, used uninitialized! */ sint32_t i; for (i = 0; i < size; i++) { if (*addr > 57) { bug = (bug<<4) | (*addr - 55) & 0x0f; } else { bug = (bug<<4) | (*addr - 48) & 0x0f; } } return (bug); } /* Corrected version from euro bootrom */ /* uint32_t _8c00cd2a(addr, size) sint8_t *addr; sint32_t size; { int val = 0; // val = R6 int i; // i = R14 for (i = 0; i < size; i++) { if (*addr > 57) { val = (val<<4) | (*addr++ - 55) & 0x0f; } else { val = (val<<4) | (*addr++ - 48) & 0x0f; } } return (val); } */ void _8c00cd64(str) struct _time_str *str; { str->year = (uint16_t)_8c00cd28((uint8_t *)0xa021a02d, 4); str->month = (uint8_t)_8c00cd28((uint8_t *)0xa021a031, 2); str->day = (uint8_t)_8c00cd28((uint8_t *)0xa021a033, 2); str->hour = (uint8_t)_8c00cd28((uint8_t *)0xa021a035, 2); str->min = (uint8_t)_8c00cd28((uint8_t *)0xa021a037, 2); str->sec = 0; } void _8c00cdf0(arg, addr) uint32_t arg; uint32_t addr; { uint32_t retval; char buf[60]; retval = _8c00e39e(2); if (retval == -8 && _8c00e4a4(0)) { return (-1); } else { /* 8c00ce1a */ if (retval) { return (-1); } } /* 8c00ce1e */ if (_8c00e534(5, buf)) { return (-1); } retval = _8c00e5b2(0); while (retval == 2) { retval = _8c00e5b2(2); } /* 8c00ce3e */ if (retval != 1) { return (-1); } if (arg == 0) { p = (uint8_t *)0x8c000078; for (i = 0; i < 8; i++) { *p++ = buf[i]; } return (0); } /* 8c00ce60 */ p = (uint8_t *)0x8c00007f; /* R5 */ p2 = buf + 7; /* p2 = R4 */ for (i = 0; i < 5; i++) { if (arg & 0x01) { *p2-- = *p--; if (i == 4) { *p2-- = *p--; *p2-- = *p--; *p2-- = *p--; } /* 8c00ce90 */ } /* 8c00c090 */ arg = arg>>1; if (i == 4) { p -= 3; p2 -= 3; } } /* 8c00cea6 */ if (arg & 0x01) { p2 += 12; *--p2 = *--p; *--p2 = *--p; *--p2 = *--p; *--p2 = *--p; } /* 8c00cec4 */ if (_8c00e570(5, buf) != 0) { return (-1); } retval = _8c00e5b2(0); while (retval == 2) { retval = _8c00e5b2(retval); } if (retval != 1) { return (-1); } return (0); } void _8c00d240(size, buf, data) uint32_t size; uint32_t *buf; uint32_t *data; { uint32_t val = *(uint32_t *)(data + size - 4); switch (size) { case 64: buf[15] = val; buf[14] = data[14]; val = data[13]; case 56: buf[13] = val; buf[12] = data[12]; val = data[11]; case 48: buf[11] = val; buf[10] = data[10]; val = data[9]; case 40: buf[9] = val; buf[8] = data[8]; val = data[7]; case 32: buf[7] = val; buf[6] = data[6]; val = data[5]; case 24: buf[5] = val; buf[4] = data[4]; val = data[3]; case 16: buf[3] = val; buf[2] = data[2]; val = data[1]; case 8: buf[1] = val; buf[0] = data[0]; case 0: break; } } void _8c00d474(str, var) struct _time_str *str; uint32_t *var; { uint32_t buf[12]; uint32_t a, b; uint32_t time; /* time = R6 */ _8c00d240(sizeof(buf), buf, _8c00eac0); /* passing args in r0, r1, r2 for some reason... */ a = str->year - 1950; b = a + 2; time = (b / 4) + (a * 365); if (b & 0x03 && str->month <= 2) { time--; } /* 8c00d4ae */ time = time + buf[str->month - 1]; time = time + str->day - 1; time = time * 24; time = time + str->hour; time = time * 60; time = time + str->min; time = time * 60; time = time + str->sec; *var = time; } sint32_t memcmp(ptr1, ptr2, n) /* 8c00d2bc */ void *ptr1; void *ptr2; uint32_t n; { if (n == 0) { return (0); } for (i = 0; i < n; i++) { if (*ptr1++ != *ptr2++) { break; } } return (*--ptr1 - *--ptr2); } sint32_t check_lib_handles(arg) /* 8c00dc38 */ void *arg; /* R10 */ { uint32_t i = 16; /* R6 */ void *addr; if (memcmp((void *)(arg + 0x30), (void *)0x8c00eb58, 16) != 0) { return (-1); } /* 8c00dc80 */ for (i = 1;; i++) { addr = (void *)((i * 32) + (arg + 32)); if (memcmp((void *)(addr + 16), (void *)0x8c00eb68, 16) == 0) { break; } _8c00dae0(); } return (0); } /* days in the months */ uint32_t _8c00eac0[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; uint8_t _8c00eb58[] = { "Lib Handle Start" }; /* 8c00eb58 */ uint8_t _8c00eb68[] = { "Lib Handle End " }; /* 8c00eb68 */ /* ----------------------------------------------------------------- */ /* Really, really old version here */ void _8c00c000(func) /* this _might_ play animation && open shell aswell */ unsigned int func; { if (func >= 5) { return; /* actually seems to want to return -1 but this functions returns void...prolly an asm-programmer messed it up...doesnt make any difference though */ } switch (func) { case 0: /* clear _8c00ee00 to _8c00ee50 */ /* _8c00c020 */ ptr1 = _8c00ee00; ptr2 = _8c00ee50; size = ptr2 - ptr1; for (i = 0; i < size/4; i++) { *(ptr1++) = 0x00000000; } return; break; case 1: /* _8c00cbb2 */ if (*GdDrvStatus >= STAT_OPEN) _8c00c040(1, 1, 0); else _8c00c040(0, 1, 0); break; case 2: /* _8c00cbc6 */ if (*GdDrvStatus >= STAT_OPEN) { for (i = 0; i < 100; i++) wait_vsync(); } _8c00c040(2, 2, 0); break; case 3: /* _8c00cbec */ if (*_8c000027 != 0) { return (0); } i = _8c00cb80(); saved1 = i + 0x00278d00; saved2 = i + 0x001e5280; _8c00d340(); _8c00d4f4(i, buf1); _8c00d4f4(saved2, buf2); _8c00d4f4(saved1, buf3); _8c00d38c(buf4); saved2 = *IPVector; if (_8c00d474(buf4, /* R15 */) == -1) { _8c00cd64(R15 + 4); /* bah..need to work out what these really are */ } /* _8c00cc7a */ break; case 4: /* _8c00cd00 */ *BorderCol = *_a05f8040; if (*DisplayCable == 0) { _8c00c040(3, 3, 1); } /* _8c00cd1a */ _8c00c040(*MenuParam, 3, 1); break; } } void _8c00c040(arg1, arg2, arg3) unsigned int arg1, arg2, arg3; { _8c00c880(arg1, arg2, arg3); } void _8c00c880(arg1, arg2, arg3) unsigned int arg1, arg2, arg3; { reg[SR] |= 0x00f0; if (arg2 & 0x01 != 0) { _8c00c9e2(); } for (i = 0; i < 9; i++) { _8c00ee04[i] = *_8c00d30c[i]; } *_8c00ee00 = reg[VBR]; reg[VBR] = _8c00c000; if (arg2 & 0x01 != 0) { _8c00c9b8(); _8c00dd60(0, 0); for (i = 0; i < 9; i++) { *_8c00d30c[i] = 0x00000000; } } else { for (i = 0; i < 9; i++) { *_8c00d30c[i] = _8c00ee28[i]; } } /* _8c00c90c */ *_a05f6920 = *_a05f6920 & 0x0000bfff; reg[SR] = reg[SR] & 0xff0f; _8c00ca78(arg1, arg2, arg3); reg[SR] = reg[SR] | 0x00f0; if (arg2 != 2) { _8c00c9da(); for (i = 0; i < 9; i++) { _8c00ee28[i] = 0x00000000; } } else { for (i = 0; i < 9; i++) { _8c00ee28[i] = *_8c00d30c[i]; } } /* _8c00c95e */ reg[VBR] = *_8c00ee00; for (i = 0; i < 9; i++) { *_8c00d30c[i] = _8c00ee04[i]; } reg[SR] = reg[SR] & 0xff0f; } int _8c00c9da() { return (_8c00dcb6(*_8c00ea9c)); } void wait_vsync() /* _8c00cb2a */ /* this is _not_ vsync...change later */ { while (*_a05f810c & 0x2000 == 0); while (*_a05f810c & 0x2000 != 0); } int _8c00d2bc(arg1, addr, arg3) int arg1, *addr, arg3; { if (arg3 == 0) { return (0); } if (arg3 < 0) { /* bah...fucked up function */ } } int _8c00dcb6(arg1) int arg1; { if (_8c00d2bc(arg + 0x30, _8c00eb58, 0x10) != 0) { return (-1); } for (i = 1;; i++) { if (_8c00d2bc((i<<5) + 0x10, _8c00eb68, 0x10) == 0) { break; } _8c00db52(i<<5); } return (0); }