DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

i_main.c (35906B)


      1 
      2 #include <ultra64.h>
      3 #include <PR/ramrom.h>	/* needed for argument passing into the app */
      4 #include <assert.h>
      5 
      6 #include "i_main.h"
      7 #include "doomdef.h"
      8 #include "st_main.h"
      9 
     10 // text for debug
     11 #include "graph.h"
     12 
     13 /*
     14  * Symbol genererated by "makerom" to indicate the end of the code segment
     15  * in virtual (and physical) memory
     16  */
     17 extern char _codeSegmentEnd[];
     18 
     19 /*
     20  * Symbols generated by "makerom" to tell us where the static segment is
     21  * in ROM.
     22  */
     23 
     24 /*
     25  * Stacks for the threads as well as message queues for synchronization
     26  * This stack is ridiculously large, and could also be reclaimed once
     27  * the main thread is started.
     28  */
     29 u64	bootStack[STACKSIZE/sizeof(u64)];
     30 
     31 extern u32 cfb[2][SCREEN_WD*SCREEN_HT]; // 8036A000
     32 
     33 extern int globallump; // 800A68f8 r_local.h
     34 extern int globalcm;   // 800A68fC r_local.h
     35 
     36 //"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91"
     37 //static char	sysmbols[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91};
     38 
     39 //----------
     40 
     41 #define SYS_THREAD_ID_IDLE 1
     42 #define SYS_THREAD_ID_MAIN 2
     43 #define SYS_THREAD_ID_TICKER 3
     44 
     45 #define SYS_IDLE_STACKSIZE 0x2020
     46 OSThread	idle_thread;                        // 800A4A18
     47 u64	idle_stack[SYS_IDLE_STACKSIZE/sizeof(u64)]; // 800979E0
     48 
     49 #define SYS_MAIN_STACKSIZE 0xA000
     50 OSThread	main_thread;                        // 800A4BC8
     51 u64	main_stack[SYS_MAIN_STACKSIZE/sizeof(u64)]; // 80099A00
     52 
     53 #define SYS_TICKER_STACKSIZE 0x1000
     54 OSThread	sys_ticker_thread;                          // 800A4D78
     55 u64	sys_ticker_stack[SYS_TICKER_STACKSIZE/sizeof(u64)]; // 800A3A00
     56 
     57 #define SYS_MSGBUF_SIZE_PI 128
     58 OSMesgQueue msgque_Pi;                  // 800A4FA0
     59 OSMesg msgbuf_Pi[SYS_MSGBUF_SIZE_PI];   // 800A4FD0
     60 
     61 #define	SYS_FIFO_SIZE	512
     62 
     63 #if __GNUC__ /* for GNU compiler */
     64 u64 fifo_buff[2][SYS_FIFO_SIZE] __attribute__((aligned (16)));          /* buffer for RDP DL */      // 800633E0
     65 u64 sys_rcp_stack[SP_DRAM_STACK_SIZE64] __attribute__((aligned (16)));  /* used for matrix stack */  // 800915E0
     66 #else /* for SGI compiler */
     67 u64 fifo_buff[2][SYS_FIFO_SIZE];            /* buffer for RDP DL */      // 800633E0
     68 u64 sys_rcp_stack[SP_DRAM_STACK_SIZE64];    /* used for matrix stack */  // 800915E0
     69 #endif
     70 
     71 #define	SYS_YIELD_SIZE  OS_YIELD_DATA_SIZE
     72 u64 gfx_yield_buff[SYS_YIELD_SIZE];     // 800919E0
     73 
     74 OSTask vid_rsptask[2] = // 8005A590
     75 {
     76     {
     77         M_GFXTASK,                          /* task type */
     78         NULL,                               /* task flags */
     79         (u64*) rspbootTextStart,            /* boot ucode pointer (fill in later) */
     80         0,                                  /* boot ucode size (fill in later) */
     81         (u64*) gspF3DEX_NoN_fifoTextStart,  /* task ucode pointer (fill in later) */
     82         SP_UCODE_SIZE,                      /* task ucode size */
     83         (u64*) gspF3DEX_NoN_fifoDataStart,  /* task ucode data pointer (fill in later) */
     84         SP_UCODE_DATA_SIZE,                 /* task ucode data size */
     85         &sys_rcp_stack[0],                  /* task dram stack pointer */
     86         SP_DRAM_STACK_SIZE8,                /* task dram stack size */
     87         &fifo_buff[0][0],                   /* task fifo buffer start ptr */
     88         &fifo_buff[0][0]+SYS_FIFO_SIZE,     /* task fifo buffer end ptr */
     89         NULL,                               /* task data pointer (fill in later) */
     90         0,                                  /* task data size (fill in later) */
     91         &gfx_yield_buff[0],                 /* task yield buffer ptr (not used here) */
     92         SYS_YIELD_SIZE                      /* task yield buffer size (not used here) */
     93     },
     94     {
     95         M_GFXTASK,                          /* task type */
     96         NULL,                               /* task flags */
     97         (u64*) rspbootTextStart,            /* boot ucode pointer (fill in later) */
     98         0,                                  /* boot ucode size (fill in later) */
     99         (u64*) gspF3DEX_NoN_fifoTextStart,  /* task ucode pointer (fill in later) */
    100         SP_UCODE_SIZE,                      /* task ucode size */
    101         (u64*) gspF3DEX_NoN_fifoDataStart,  /* task ucode data pointer (fill in later) */
    102         SP_UCODE_DATA_SIZE,                 /* task ucode data size */
    103         &sys_rcp_stack[0],                  /* task dram stack pointer */
    104         SP_DRAM_STACK_SIZE8,                /* task dram stack size */
    105         &fifo_buff[1][0],                   /* task fifo buffer start ptr */
    106         &fifo_buff[1][0]+SYS_FIFO_SIZE,     /* task fifo buffer end ptr */
    107         NULL,                               /* task data pointer (fill in later) */
    108         0,                                  /* task data size (fill in later) */
    109         &gfx_yield_buff[0],                 /* task yield buffer ptr (not used here) */
    110         SYS_YIELD_SIZE                      /* task yield buffer size (not used here) */
    111     }
    112 };
    113 
    114 Vp vid_viewport = // 8005A610
    115 {
    116     SCREEN_WD*2, SCREEN_HT*2, G_MAXZ,   0,		/* scale */
    117     SCREEN_WD*2, SCREEN_HT*2,      0,   0,		/* translate */
    118 };
    119 
    120 OSMesgQueue romcopy_msgque; // 800A4F70
    121 OSMesg		romcopy_msgbuf; // 800A51D0
    122 
    123 OSMesgQueue sys_msgque_joy; // 800A4F88
    124 OSMesg		sys_msg_joy;    // 800A51D4
    125 
    126 #define SYS_MSGBUF_SIZE_VID 16
    127 OSMesgQueue sys_msgque_vbi; // 800A4FB8
    128 OSMesg		sys_msgbuf_vbi[SYS_MSGBUF_SIZE_VID]; // 800A51E0
    129 
    130 #define SYS_MSGBUF_SIZE_VID2 2
    131 OSMesgQueue sys_msgque_vbi2; // 800A4F28
    132 OSMesg		sys_msgbuf_vbi2[SYS_MSGBUF_SIZE_VID2]; // 800A51D8
    133 
    134 OSMesgQueue sys_msgque_vbi3; // 800A4F40
    135 OSMesg		sys_msgbuf_vbi3[SYS_MSGBUF_SIZE_VID2]; // 800A5220
    136 
    137 OSMesgQueue sys_msgque_vbi4; // 800A4F58
    138 OSMesg		sys_msgbuf_vbi4[SYS_MSGBUF_SIZE_VID2]; // 800A5228
    139 
    140 OSContStatus gamepad_status[MAXCONTROLLERS]; // 800a5230
    141 OSContPad   *gamepad_data;    // 800A5240
    142 
    143 OSTask *vid_task;   // 800A5244
    144 u32 vid_side;       // 800A5248
    145 
    146 u32 video_hStart;   // 800A524c
    147 u32 video_vStart1;  // 800A5250
    148 u32 video_vStart2;  // 800A5254
    149 
    150 u32 GfxIndex;       // 800A5258
    151 u32 VtxIndex;       // 800A525C
    152 
    153 u8 gamepad_bit_pattern; // 800A5260 // one bit for each controller
    154 
    155 // Controller Pak
    156 OSPfs ControllerPak;        // 800A5270
    157 OSPfsState FileState[16];   // 800A52D8
    158 s32 File_Num;   // 800A54D8
    159 s32 Pak_Size;   // 800A54DC
    160 u8 *Pak_Data;   // 800A54E0
    161 s32 Pak_Memory; // 800A54E4
    162 
    163 char Pak_Table[256] = // 8005A620
    164 {
    165       '\0',// 0
    166       ' ', ' ', ' ', ' ', ' ',// 1
    167       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 6
    168       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 16
    169       'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',// 26
    170       'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',// 36
    171       'u', 'v', 'w', 'x', 'y', 'z', '!', '"', '#','\'',// 46
    172       '*', '+', ',', '-', '.', '/', ':', '=', '?', '@',// 56
    173       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 66
    174       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 76
    175       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 86
    176       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 96
    177       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 106
    178       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 116
    179       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 126
    180       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 136
    181       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 146
    182       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 156
    183       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 166
    184       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 176
    185       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 186
    186       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 196
    187       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 206
    188       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 216
    189       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 226
    190       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 236
    191       ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' // 246
    192 };
    193 
    194 char Game_Name[16] = // 8005A790
    195 {
    196     0x1D, 0x28, 0x28, 0x26, 0x0F, 0x16, 0x14, 0x00, // (doom 64) byte index from Pak_Table
    197     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    198 };
    199 
    200 boolean disabledrawing = false; // 8005A720
    201 
    202 s32 vsync = 0;              // 8005A724
    203 s32 drawsync2 = 0;          // 8005A728
    204 s32 drawsync1 = 0;          // 8005A72C
    205 u32 NextFrameIdx = 0;       // 8005A730
    206 
    207 s32 ControllerPakStatus = 1; // 8005A738
    208 s32 gamepad_system_busy = 0; // 8005A73C
    209 s32 FilesUsed = -1;                 // 8005A740
    210 u32 SystemTickerStatus = 0;  // 8005a744
    211 
    212 Gfx Gfx_base[2][MAX_GFX];    // 800653E0
    213 Mtx Mtx_base[2][MAX_MTX];    // 800793E0
    214 Vtx Vtx_base[2][MAX_VTX];    // 800795E0
    215 
    216 Gfx *GFX1;	// 800A4A00
    217 Gfx *GFX2;	// 800A4A04
    218 
    219 Vtx *VTX1;	// 800A4A08
    220 Vtx *VTX2;	// 800A4A0C
    221 
    222 Mtx *MTX1;	// 800A4A10
    223 Mtx *MTX2;	// 800A4A14
    224 
    225 Gfx *GfxBlocks[8] = {0,0,0,0,0,0,0,0}; // 8005A748
    226 Vtx *VtxBlocks[8] = {0,0,0,0,0,0,0,0}; // 8005A768
    227 
    228 extern OSTask * wess_work(void);
    229 
    230 void I_Start(void)  // 80005620
    231 {
    232     /* Re-initialize U64 operating system... */
    233     osInitialize();
    234 
    235     /* Create and start idle thread... */
    236     osCreateThread(&idle_thread, SYS_THREAD_ID_IDLE, I_IdleGameThread, (void *)0,
    237                    idle_stack + SYS_IDLE_STACKSIZE/sizeof(u64), 10);
    238     osStartThread(&idle_thread);
    239 }
    240 
    241 void I_IdleGameThread(void *arg) // 8000567C
    242 {
    243     /* Create and start the Pi manager... */
    244     osCreatePiManager( (OSPri)OS_PRIORITY_PIMGR, &msgque_Pi, msgbuf_Pi,
    245                         SYS_MSGBUF_SIZE_PI );
    246 
    247     /* Create main thread... */
    248     osCreateThread(&main_thread, SYS_THREAD_ID_MAIN, I_Main, (void *)0,
    249                    main_stack + SYS_MAIN_STACKSIZE/sizeof(u64), 10);
    250     osStartThread(&main_thread);
    251 
    252     osSetThreadPri(&idle_thread, (OSPri)OS_PRIORITY_IDLE);
    253 
    254     /* Idle loop... */
    255     do {
    256         osYieldThread();
    257     } while(TRUE);
    258 }
    259 
    260 void I_Main(void *arg) // 80005710
    261 {
    262     D_DoomMain();
    263 }
    264 
    265 void I_SystemTicker(void *arg) // 80005730
    266 {
    267     int vbi_msg;
    268     int vidside;
    269     int side, stat, ret;
    270     int current_fbuf, next_fbuf;
    271     OSTask *wess;
    272     OSTask *rspTask;
    273     OSTask *rspTaskPrev;
    274 
    275     //char str[64];
    276 
    277     rspTask = NULL;
    278     rspTaskPrev = NULL;
    279     side = 1;
    280 
    281     while(true)
    282     {
    283         osRecvMesg(&sys_msgque_vbi, (OSMesg *)&vbi_msg, OS_MESG_BLOCK);
    284 
    285         //sprintf(str, "SystemTickerStatus %d",SystemTickerStatus);
    286         //printstr(WHITE, 0, 13, str);
    287         //sprintf(str, "vbi_msg %d",vbi_msg);
    288         //printstr(WHITE, 0, 14, str);
    289         //sprintf(str, "vidside %d",vidside);
    290         //printstr(WHITE, 0, 15, str);
    291 
    292         switch (vbi_msg)
    293 		{
    294 		    case VID_MSG_RSP:				// end of signal processing
    295 		        {
    296 		            //sprintf(str, "VID_MSG_RSP");
    297                     //printstr(WHITE, 0, 28, str);
    298 
    299                     if(rspTask->t.type == M_AUDTASK)
    300                     {
    301                         SystemTickerStatus &= ~32;
    302 
    303                         if (SystemTickerStatus & 4)//OS_SC_YIELDED
    304                         {
    305                             SystemTickerStatus &= ~4;
    306                             SystemTickerStatus |= 1;
    307 
    308                             rspTask = rspTaskPrev;
    309                             osWritebackDCacheAll();
    310                             osSpTaskLoad(rspTask);
    311                             osSpTaskStartGo(rspTask);
    312                         }
    313                         else
    314                         {
    315                             if ((SystemTickerStatus & 24) == 0)
    316                             {
    317                                 ret = osRecvMesg(&sys_msgque_vbi3, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK);
    318                                 rspTask = (OSTask*)vbi_msg;
    319 
    320                                 if(ret != -1)
    321                                 {
    322                                     if(rspTask == vid_rsptask)
    323                                         vidside = 0;
    324                                     else
    325                                         vidside = 1;
    326 
    327                                     SystemTickerStatus |= 1;
    328 
    329                                     osWritebackDCacheAll();
    330                                     osSpTaskLoad(rspTask);
    331                                     osSpTaskStartGo(rspTask);
    332                                 }
    333                             }
    334                         }
    335                     }
    336                     else
    337                     {
    338                         SystemTickerStatus &= ~1;
    339 
    340                         if(SystemTickerStatus & 2)//OS_SC_YIELD
    341                         {
    342                             SystemTickerStatus &= ~2;
    343 
    344                             if (osSpTaskYielded(rspTask))
    345                             {
    346                                 rspTaskPrev = rspTask;
    347 
    348                                 SystemTickerStatus |= 4;//OS_SC_YIELDED
    349 
    350                                 osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK);
    351                                 rspTask = (OSTask*)vbi_msg;
    352 
    353                                 SystemTickerStatus |= 32;
    354 
    355                                 osWritebackDCacheAll();
    356                                 osSpTaskLoad(rspTask);
    357                                 osSpTaskStartGo(rspTask);
    358                             }
    359                         }
    360                         else
    361                         {
    362                             if ((SystemTickerStatus & 16) == 0)
    363                                 SystemTickerStatus |= 8;
    364 
    365                             ret = osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK);
    366                             rspTask = (OSTask*)vbi_msg;
    367 
    368                             if(ret!= -1)
    369                             {
    370                                 SystemTickerStatus |= 32;
    371 
    372                                 osWritebackDCacheAll();
    373                                 osSpTaskLoad(rspTask);
    374                                 osSpTaskStartGo(rspTask);
    375                             }
    376                         }
    377                     }
    378 		        }
    379 				break;
    380 
    381             case VID_MSG_RDP:				// end of display processing
    382 				{
    383 				    //sprintf(str, "VID_MSG_RDP");
    384                     //printstr(WHITE, 0, 28, str);
    385 
    386 				    SystemTickerStatus &= ~8;
    387 				    SystemTickerStatus |= 16;
    388 
    389                     osViSwapBuffer(cfb[vidside]);
    390 				}
    391 				break;
    392 
    393             case VID_MSG_PRENMI:
    394                 {
    395                     //sprintf(str, "VID_MSG_PRENMI");
    396                     //printstr(WHITE, 0, 28, str);
    397 				    disabledrawing = true;
    398                     S_StopAll();
    399                     osViBlack(TRUE);
    400                     I_MoveDisplay(0,0);
    401                 }
    402 				break;
    403 
    404             case VID_MSG_VBI:
    405                 {
    406                     //sprintf(str, "VID_MSG_VBI || vsync(%d) || side(%d)", vsync, side);
    407                     //printstr(WHITE, 0, 28, str);
    408 
    409                     vsync += 1;
    410 
    411                     if (sys_msgque_vbi4.validCount)
    412                     {
    413                         if (SystemTickerStatus & 1)
    414                         {
    415                             SystemTickerStatus |= 2; // GFX_YIELDED
    416                             osSpTaskYield();
    417                         }
    418                         else
    419                         {
    420                             if ((SystemTickerStatus & 32) == 0)
    421                             {
    422                                 osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK);
    423                                 rspTask = (OSTask*)vbi_msg;
    424 
    425                                 SystemTickerStatus |= 32;
    426 
    427                                 osWritebackDCacheAll();
    428                                 osSpTaskLoad(rspTask);
    429                                 osSpTaskStartGo(rspTask);
    430                             }
    431                         }
    432                     }
    433 
    434                     if (side & 1)
    435                     {
    436                         if (gamepad_system_busy)
    437                         {
    438                             osContGetReadData(gamepad_data);
    439                             gamepad_system_busy = 0;
    440                         }
    441 
    442                         // next audio function task
    443                         wess = wess_work();
    444                         if (wess)
    445                             osSendMesg(&sys_msgque_vbi4,(OSMesg) wess, OS_MESG_NOBLOCK);
    446                     }
    447                     side++;
    448 
    449                     if (SystemTickerStatus & 16)
    450                     {
    451                         if ((u32)(vsync - drawsync2) < 2) continue;
    452 
    453                         current_fbuf = (int)osViGetCurrentFramebuffer();
    454                         next_fbuf = (int)osViGetNextFramebuffer();
    455 
    456                         if (next_fbuf != current_fbuf) continue;
    457 
    458                         SystemTickerStatus &= ~16;
    459 
    460                         if (demoplayback || demorecording)
    461                         {
    462                             vsync = drawsync2 + 2;
    463                         }
    464 
    465                         //sprintf(str, "vsync %d | side %d",vsync, side);
    466                         //printstr(WHITE, 0, 29, str);
    467 
    468                         drawsync1 = vsync - drawsync2;
    469                         drawsync2 = vsync;
    470 
    471                         if ((ControllerPakStatus != 0) && (gamepad_system_busy == 0))
    472                         {
    473                             osContStartReadData(&sys_msgque_joy);
    474                             gamepad_system_busy = 1;
    475                         }
    476 
    477                         osSendMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK);
    478                     }
    479 
    480                     if(SystemTickerStatus == 0)
    481                     {
    482                         ret = osRecvMesg(&sys_msgque_vbi3, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK);
    483                         rspTask = (OSTask*)vbi_msg;
    484 
    485                         //sprintf(str, "ret %d", ret);
    486                         //printstr(WHITE, 0, 17, str);
    487 
    488                         if(ret != -1)
    489                         {
    490                             //sprintf(str, "rspTask->t.type %d",rspTask->t.type);
    491                             //printstr(WHITE, 0, 14, str);
    492                             //sprintf(str, "rspTask->t.type %x",(u64*)rspTask->t.ucode);
    493                             //printstr(WHITE, 0, 15, str);
    494 
    495                             if(rspTask == vid_rsptask)
    496                                 vidside = 0;
    497                             else
    498                                 vidside = 1;
    499 
    500                             SystemTickerStatus |= 1;
    501 
    502                             osWritebackDCacheAll();
    503                             osSpTaskLoad(rspTask);
    504                             osSpTaskStartGo(rspTask);
    505                         }
    506                     }
    507                 }
    508 				break;
    509 		}
    510     }
    511 }
    512 
    513 extern void S_Init(void);
    514 
    515 void I_Init(void) // 80005C50
    516 {
    517     OSViMode *ViMode;
    518 
    519     vid_rsptask[0].t.ucode_boot_size = (int)rspbootTextEnd - (int)rspbootTextStart;	// set ucode size (waste but who cares)
    520     vid_rsptask[1].t.ucode_boot_size = (int)rspbootTextEnd - (int)rspbootTextStart;	// set ucode size (waste but who cares)
    521 
    522     osCreateMesgQueue( &romcopy_msgque, &romcopy_msgbuf, 1 );
    523 
    524     osCreateMesgQueue( &sys_msgque_vbi, sys_msgbuf_vbi, SYS_MSGBUF_SIZE_VID );
    525 
    526     osCreateMesgQueue(&sys_msgque_vbi2, sys_msgbuf_vbi2, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_jam, sys_msgbuf_jam
    527     osCreateMesgQueue(&sys_msgque_vbi3, sys_msgbuf_vbi3, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_ser, sys_msgbuf_ser
    528     osCreateMesgQueue(&sys_msgque_vbi4, sys_msgbuf_vbi4, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_tmr, sys_msgbuf_tmr
    529 
    530     if(osTvType == OS_TV_PAL)
    531     {
    532         ViMode = &osViModeTable[OS_VI_PAL_LPN2];
    533     }
    534     else if(osTvType == OS_TV_NTSC)
    535     {
    536         ViMode = &osViModeTable[OS_VI_NTSC_LPN2];
    537     }
    538     else if(osTvType == OS_TV_MPAL)
    539     {
    540         ViMode = &osViModeTable[OS_VI_MPAL_LPN2];
    541     }
    542 
    543     video_hStart = ViMode->comRegs.hStart;
    544     video_vStart1 = ViMode->fldRegs[0].vStart;
    545     video_vStart2 = ViMode->fldRegs[1].vStart;
    546 
    547     // Create and start the Vi manager and init the video mode...
    548 
    549 	osCreateViManager( OS_PRIORITY_VIMGR );
    550     osViSetMode(ViMode);
    551     osViBlack(TRUE);
    552 
    553     osViSetSpecialFeatures(OS_VI_GAMMA_OFF|OS_VI_GAMMA_DITHER_OFF|OS_VI_DIVOT_OFF|OS_VI_DITHER_FILTER_OFF);
    554 
    555     osViSetXScale(1.0);
    556     osViSetYScale(1.0);
    557 
    558     D_memset(cfb, 0, ((SCREEN_WD*SCREEN_HT)*sizeof(u32))*2);
    559     osViSwapBuffer(cfb);
    560 
    561     if (osViGetCurrentFramebuffer() != cfb) {
    562 		do {
    563 		} while (osViGetCurrentFramebuffer() != cfb);
    564 	}
    565 
    566     osViBlack(FALSE);
    567 
    568     osSetEventMesg( OS_EVENT_SP, &sys_msgque_vbi, (OSMesg)VID_MSG_RSP );
    569     osSetEventMesg( OS_EVENT_DP, &sys_msgque_vbi, (OSMesg)VID_MSG_RDP );
    570     osSetEventMesg( OS_EVENT_PRENMI, &sys_msgque_vbi, (OSMesg)VID_MSG_PRENMI );
    571 
    572     osViSetEvent( &sys_msgque_vbi, (OSMesg)VID_MSG_VBI, 1 ); // last parm: 2 indicates 30 FPS (1=60)
    573 
    574     vid_side = 1;
    575 
    576     /* Serial/Joy queue */
    577 
    578     osCreateMesgQueue(&sys_msgque_joy, &sys_msg_joy, 1);
    579     osSetEventMesg(OS_EVENT_SI, &sys_msgque_joy, &sys_msg_joy);
    580 
    581     osContInit(&sys_msgque_joy, &gamepad_bit_pattern, gamepad_status);
    582 
    583     gamepad_data = (OSContPad *)idle_stack;
    584 
    585     if ((gamepad_bit_pattern & 1) != 0)
    586     {
    587         osContStartReadData(&sys_msgque_joy);
    588         osRecvMesg(&sys_msgque_joy, NULL, OS_MESG_BLOCK);
    589         osContGetReadData(gamepad_data);
    590     }
    591 
    592     S_Init();
    593 
    594     /* Create and start ticker thread... */
    595     osCreateThread(&sys_ticker_thread, SYS_THREAD_ID_TICKER, I_SystemTicker, (void *)0,
    596                    sys_ticker_stack + SYS_TICKER_STACKSIZE/sizeof(u64), 11);
    597     osStartThread(&sys_ticker_thread);
    598 
    599     osJamMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK);
    600 }
    601 
    602 #include "stdarg.h"
    603 
    604 void I_Error(char *error, ...) // 80005F30
    605 {
    606     char buffer[256];
    607     va_list args;
    608     va_start (args, error);
    609     D_vsprintf (buffer, error, args);
    610     va_end (args);
    611 
    612     while (true)
    613     {
    614         I_ClearFrame();
    615 
    616         gDPPipeSync(GFX1++);
    617         gDPSetCycleType(GFX1++, G_CYC_FILL);
    618         gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2);
    619         gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side]));
    620         gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ;
    621         gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1);
    622 
    623         ST_Message(err_text_x, err_text_y, buffer, 0xffffffff);
    624         I_DrawFrame();
    625     }
    626 }
    627 
    628 typedef struct
    629 {
    630 	int pad_data;
    631 } pad_t;
    632 
    633 int I_GetControllerData(void) // 800060D0
    634 {
    635     return ((pad_t*)gamepad_data)->pad_data;
    636 }
    637 
    638 void I_CheckGFX(void) // 800060E8
    639 {
    640 	memblock_t *block;
    641 
    642 	Gfx **Gfx_Blocks;
    643 	Vtx **Vtx_Blocks;
    644 
    645 	int i, index;
    646 	int block_idx;
    647 
    648 	index = (int)((int)GFX1 - (int)GFX2) / sizeof(Gfx);
    649 
    650 	if (index > MAX_GFX)
    651 		I_Error("I_CheckGFX: GFX Overflow by %d\n",index);
    652 
    653 	if ((index < (MAX_GFX-1024)) == 0)
    654 	{
    655 		Gfx_Blocks = GfxBlocks;
    656 		block_idx = -1;
    657 
    658 		for(i = 0; i < 8; i++)
    659 		{
    660 			block = (memblock_t *)((byte *)*Gfx_Blocks - sizeof(memblock_t));
    661 
    662 			if (*Gfx_Blocks)
    663 			{
    664 				if(((u32)block->lockframe < NextFrameIdx - 1) == 0)
    665                 {
    666                     Gfx_Blocks++;
    667                     continue;
    668                 }
    669 
    670                 block->lockframe = NextFrameIdx;
    671                 GFX2 = (Gfx *)*Gfx_Blocks;
    672                 goto move_gfx;
    673 			}
    674 
    675             block_idx = i;
    676 		}
    677 
    678 		if (block_idx < 0)
    679 			I_Error("I_CheckGFX: GFX Cache overflow");
    680 
    681 		GFX2 = (Gfx *)Z_Malloc(MAX_GFX * sizeof(Gfx), PU_CACHE, &GfxBlocks[block_idx]);
    682 
    683 	move_gfx:
    684 		gSPBranchList(GFX1,GFX2);
    685 		GFX1 = GFX2;
    686 		GfxIndex += index;
    687 	}
    688 
    689 	index = (int)((int)VTX1 - (int)VTX2) / sizeof(Vtx);
    690 
    691 	if (index > MAX_VTX)
    692 		I_Error("I_CheckVTX: VTX Overflow by %d\n",index);
    693 
    694 	if ((index < (MAX_VTX-615)) == 0)
    695 	{
    696 		Vtx_Blocks = VtxBlocks;
    697 		block_idx = -1;
    698 
    699 		for(i = 0; i < 8; i++)
    700 		{
    701 		    block = (memblock_t *)((byte *)*Vtx_Blocks - sizeof(memblock_t));
    702 
    703 			if (*Vtx_Blocks)
    704 			{
    705 				if(((u32)block->lockframe < NextFrameIdx - 1) == 0)
    706                 {
    707                     Vtx_Blocks++;
    708                     continue;
    709                 }
    710 
    711                 block->lockframe = NextFrameIdx;
    712                 VTX2 = (Vtx *)*Vtx_Blocks;
    713                 goto move_vtx;
    714 			}
    715 
    716             block_idx = i;
    717 		}
    718 
    719 		if (block_idx < 0)
    720 			I_Error("I_CheckGFX: VTX Cache overflow");
    721 
    722         VTX2 = (Vtx *)Z_Malloc(MAX_VTX * sizeof(Vtx), PU_CACHE, &VtxBlocks[block_idx]);
    723 
    724 	move_vtx:
    725 		VTX1 = VTX2;
    726 		VtxIndex += index;
    727 	}
    728 }
    729 
    730 void I_ClearFrame(void) // 8000637C
    731 {
    732     NextFrameIdx += 1;
    733 
    734     GFX1 = Gfx_base[vid_side];
    735     GFX2 = GFX1;
    736     GfxIndex = 0;
    737 
    738     VTX1 = Vtx_base[vid_side];
    739     VTX2 = VTX1;
    740     VtxIndex = 0;
    741 
    742     MTX1 = Mtx_base[vid_side];
    743 
    744     vid_task = &vid_rsptask[vid_side];
    745 
    746     vid_task->t.ucode = (u64 *) gspF3DEX_NoN_fifoTextStart;
    747     vid_task->t.ucode_data = (u64 *) gspF3DEX_NoN_fifoDataStart;
    748 
    749     gMoveWd(GFX1++, G_MW_SEGMENT, G_MWO_SEGMENT_0, 0);
    750 
    751     gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side]));
    752     gDPSetScissor(GFX1++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WD, SCREEN_HT);
    753 
    754     // [GEC] New Cheat Codes
    755     if (players[0].cheats & CF_FILTER) {
    756         gDPSetTextureFilter(GFX1++, G_TF_POINT); // <- Nearest texture
    757     }
    758     else {
    759         gDPSetTextureFilter(GFX1++, G_TF_BILERP); // <- Bilinear texture
    760     }
    761 
    762     gSPViewport(GFX1++, &vid_viewport);
    763 
    764     gSPClearGeometryMode(GFX1++, -1);
    765     gSPSetGeometryMode(GFX1++, G_SHADE|G_SHADING_SMOOTH|G_FOG );
    766 
    767     globallump = -1;
    768     globalcm = 0;
    769 }
    770 
    771 void I_DrawFrame(void)  // 80006570
    772 {
    773     int index;
    774 
    775     gDPFullSync(GFX1++);
    776     gSPEndDisplayList(GFX1++);
    777 
    778     index = (int)((int)GFX1 - (int)GFX2) / sizeof(Gfx);
    779 	if (index > MAX_GFX)
    780 		I_Error("I_DrawFrame: GFX Overflow by %d\n\n",index);
    781 
    782     index = (int)((int)VTX1 - (int)VTX2) / sizeof(Vtx);
    783 	if (index > MAX_VTX)
    784 		I_Error("I_DrawFrame: VTX Overflow by %d\n",index);
    785 
    786     vid_task->t.data_ptr = (u64 *) Gfx_base[vid_side];
    787     vid_task->t.data_size = (u32)((((int)((int)GFX1 - (int)GFX2) / sizeof(Gfx)) + GfxIndex) * sizeof(Gfx));
    788 
    789     osSendMesg(&sys_msgque_vbi3,(OSMesg) vid_task, OS_MESG_NOBLOCK);
    790     osRecvMesg(&sys_msgque_vbi2, NULL, OS_MESG_BLOCK);//retraceMessageQ
    791     vid_side ^= 1;
    792 }
    793 
    794 void I_GetScreenGrab(void) // 800066C0
    795 {
    796     if ((SystemTickerStatus & ~32) || (sys_msgque_vbi3.validCount != 0)) {
    797         osRecvMesg(&sys_msgque_vbi2, (OSMesg *)0, OS_MESG_BLOCK);
    798         osJamMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK);
    799     }
    800 }
    801 
    802 long LongSwap(long dat) // 80006724
    803 {
    804     return (u32)dat >> 0x18 | dat >> 8 & 0xff00U | (dat & 0xff00U) << 8 | dat << 0x18;
    805 }
    806 
    807 short LittleShort(short dat) // 80006750
    808 {
    809     return ((((dat << 8) | (dat >> 8 & 0xff)) << 16) >> 16);
    810 }
    811 
    812 short BigShort(short dat) // 80006770
    813 {
    814     return ((dat << 8) | (dat >> 8 & 0xff)) & 0xffff;
    815 }
    816 
    817 void I_MoveDisplay(int x,int y) // 80006790
    818 {
    819   int ViMode;
    820 
    821   ViMode = osViGetCurrentMode();
    822 
    823   osViModeTable[ViMode].comRegs.hStart =
    824        (int)(((int)video_hStart >> 0x10 & 65535) + x) % 65535 << 0x10 |
    825        (int)((video_hStart & 65535) + x) % 65535;
    826 
    827   osViModeTable[ViMode].fldRegs[0].vStart =
    828        (int)(((int)video_vStart1 >> 0x10 & 65535) + y) % 65535 << 0x10 |
    829        (int)((video_vStart1 & 65535) + y) % 65535;
    830 
    831   osViModeTable[ViMode].fldRegs[1].vStart =
    832        (int)(((int)video_vStart2 >> 0x10 & 65535) + y) % 65535 << 0x10 |
    833        (int)((video_vStart2 & 65535) + y) % 65535;
    834 }
    835 
    836 void I_WIPE_MeltScreen(void) // 80006964
    837 {
    838     u32 *fb;
    839     int y1;
    840     int tpos;
    841     int yscroll;
    842     int height;
    843 
    844     fb = Z_Malloc((SCREEN_WD*SCREEN_HT)*sizeof(u32), PU_STATIC, NULL);
    845 
    846     I_GetScreenGrab();
    847     D_memcpy(&cfb[vid_side][0], &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32));
    848 
    849     yscroll = 1;
    850     while( true )
    851     {
    852         y1 = 0;
    853         D_memcpy(fb, &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32));
    854 
    855         I_ClearFrame();
    856 
    857         gDPSetCycleType(GFX1++, G_CYC_1CYCLE);
    858         gDPSetTextureLUT(GFX1++, G_TT_NONE);
    859         gDPSetTexturePersp(GFX1++, G_TP_NONE);
    860         gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD);
    861         gDPSetBlendColor(GFX1++, 0, 0, 0, 0);
    862         gDPSetCombineMode(GFX1++, G_CC_D64COMB19, G_CC_D64COMB19);
    863         gDPSetRenderMode(GFX1++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
    864         gDPSetPrimColor(GFX1++, 0, 0, 15, 0, 0, 22); // 0x0f000016
    865 
    866         height = SCREEN_HT - (yscroll >> 2);
    867         tpos = 0;
    868         if (height > 0)
    869         {
    870             do
    871             {
    872                 gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b , SCREEN_WD, fb);
    873                 gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b,
    874                            (SCREEN_WD >> 2), 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    875 
    876                 gDPLoadSync(GFX1++);
    877                 gDPLoadTile(GFX1++, G_TX_LOADTILE,
    878                             (0 << 2), (tpos << 2),
    879                             ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2));
    880 
    881                 gDPPipeSync(GFX1++);
    882                 gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b,
    883                            (SCREEN_WD >> 2), 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0);
    884 
    885                 gDPSetTileSize(GFX1++, G_TX_RENDERTILE,
    886                                (0 << 2), (tpos << 2),
    887                                ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2));
    888 
    889                 gSPTextureRectangle(GFX1++,
    890                                     (0 << 2), (y1 << 2) + yscroll,
    891                                     (SCREEN_WD << 2), ((y1 + 3) << 2) + yscroll,
    892                                     G_TX_RENDERTILE,
    893                                     (0 << 5), (tpos << 5),
    894                                     (1 << 10), (1 << 10));
    895 
    896                 y1 += 2;
    897                 tpos += 2;
    898             } while (y1 < height);
    899         }
    900 
    901         yscroll += 2;
    902         if (yscroll >= 160) break;
    903         I_DrawFrame();
    904     }
    905 
    906     Z_Free(fb);
    907     I_WIPE_FadeOutScreen();
    908 }
    909 
    910 void I_WIPE_FadeOutScreen(void) // 80006D34
    911 {
    912     u32 *fb;
    913     int y1, tpos, outcnt;
    914 
    915     fb = Z_Malloc((SCREEN_WD*SCREEN_HT)*sizeof(u32), PU_STATIC, NULL);
    916 
    917     I_GetScreenGrab();
    918     D_memcpy(fb, &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32));
    919 
    920     outcnt = 248;
    921     do
    922     {
    923         I_ClearFrame();
    924 
    925         gDPSetCycleType(GFX1++, G_CYC_1CYCLE);
    926         gDPSetTextureLUT(GFX1++, G_TT_NONE);
    927         gDPSetTexturePersp(GFX1++, G_TP_NONE);
    928         gDPSetAlphaCompare(GFX1++, G_AC_NONE);
    929         gDPSetCombineMode(GFX1++, G_CC_D64COMB06, G_CC_D64COMB06);
    930         gDPSetRenderMode(GFX1++,G_RM_OPA_SURF,G_RM_OPA_SURF2);
    931         gDPSetPrimColor(GFX1++, 0, 0, outcnt, outcnt, outcnt, 0);
    932 
    933         tpos = 0;
    934         y1 = 0;
    935         do
    936         {
    937             gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b , SCREEN_WD, fb);
    938             gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b,
    939                        (SCREEN_WD >> 2), 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    940 
    941             gDPLoadSync(GFX1++);
    942             gDPLoadTile(GFX1++, G_TX_LOADTILE,
    943                         (0 << 2), (tpos << 2),
    944                         ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2));
    945 
    946             gDPPipeSync(GFX1++);
    947             gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b,
    948                        (SCREEN_WD >> 2), 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0);
    949 
    950             gDPSetTileSize(GFX1++, G_TX_RENDERTILE,
    951                            (0 << 2), (tpos << 2),
    952                            ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2));
    953 
    954             gSPTextureRectangle(GFX1++,
    955                                 (0 << 2), (y1 << 2),
    956                                 (SCREEN_WD << 2), ((y1+3) << 2),
    957                                 G_TX_RENDERTILE,
    958                                 (0 << 5), (tpos << 5),
    959                                 (1 << 10), (1 << 10));
    960 
    961             tpos += 3;
    962             y1 += 3;
    963         } while (y1 != SCREEN_HT);
    964 
    965         I_DrawFrame();
    966         outcnt -= 8;
    967     } while (outcnt >= 0);
    968 
    969     I_GetScreenGrab();
    970     Z_Free(fb);
    971 }
    972 
    973 
    974 int I_CheckControllerPak(void) // 800070B0
    975 {
    976     int ret, file;
    977     OSPfsState *fState;
    978     s32 MaxFiles [2];
    979     u8 validpaks;
    980 
    981     ControllerPakStatus = 0;
    982 
    983     if (gamepad_system_busy != 0)
    984     {
    985         do {
    986             osYieldThread();
    987         } while (gamepad_system_busy != 0);
    988     }
    989 
    990     FilesUsed = -1;
    991     ret = PFS_ERR_NOPACK;
    992 
    993     osPfsIsPlug(&sys_msgque_joy, &validpaks);
    994 
    995     /* does the current controller have a memory pak? */
    996     if (validpaks & 1)
    997     {
    998         ret = osPfsInit(&sys_msgque_joy, &ControllerPak, NULL);
    999 
   1000         if ((ret != PFS_ERR_NOPACK) &&
   1001             (ret != PFS_ERR_ID_FATAL) &&
   1002             (ret != PFS_ERR_DEVICE) &&
   1003             (ret != PFS_ERR_CONTRFAIL))
   1004         {
   1005             ret = osPfsNumFiles(&ControllerPak, MaxFiles, &FilesUsed);
   1006 
   1007             if (ret == PFS_ERR_INCONSISTENT)
   1008                 ret = osPfsChecker(&ControllerPak);
   1009 
   1010             if (ret == 0)
   1011             {
   1012                 Pak_Memory = 123;
   1013                 fState = FileState;
   1014                 file = 0;
   1015                 do
   1016                 {
   1017                     ret = osPfsFileState(&ControllerPak, file, fState);
   1018                     file += 1;
   1019 
   1020                     if (ret != 0)
   1021                       fState->file_size = 0;
   1022 
   1023                     Pak_Memory -= (fState->file_size >> 8);
   1024                     fState += 1;
   1025                 } while (file != 16);
   1026                 ret = 0;
   1027             }
   1028         }
   1029     }
   1030 
   1031     ControllerPakStatus = 1;
   1032 
   1033     return ret;
   1034 }
   1035 
   1036 int I_DeletePakFile(int filenumb) // 80007224
   1037 {
   1038     int ret;
   1039     OSPfsState *fState;
   1040 
   1041     ControllerPakStatus = 0;
   1042 
   1043     if (gamepad_system_busy != 0)
   1044     {
   1045         do {
   1046             osYieldThread();
   1047         } while (gamepad_system_busy != 0);
   1048     }
   1049 
   1050     fState = &FileState[filenumb];
   1051 
   1052     if (fState->file_size == 0) {
   1053         ret = 0;
   1054     }
   1055     else
   1056     {
   1057         ret = osPfsDeleteFile(&ControllerPak,
   1058             FileState[filenumb].company_code,
   1059             FileState[filenumb].game_code,
   1060             FileState[filenumb].game_name,
   1061             FileState[filenumb].ext_name);
   1062 
   1063         if (ret == PFS_ERR_INCONSISTENT)
   1064             ret = osPfsChecker(&ControllerPak);
   1065 
   1066         if (ret == 0)
   1067         {
   1068             Pak_Memory += (fState->file_size >> 8);
   1069             fState->file_size = 0;
   1070         }
   1071     }
   1072 
   1073     ControllerPakStatus = 1;
   1074 
   1075     return ret;
   1076 }
   1077 
   1078 int I_SavePakFile(int filenumb, int flag, byte *data, int size) // 80007308
   1079 {
   1080     int ret;
   1081 
   1082     ControllerPakStatus = 0;
   1083 
   1084     if (gamepad_system_busy != 0)
   1085     {
   1086         do {
   1087         osYieldThread();
   1088         } while (gamepad_system_busy != 0);
   1089     }
   1090 
   1091     ret = osPfsReadWriteFile(&ControllerPak, filenumb, (u8)flag, 0, size, (u8*)data);
   1092 
   1093     if (ret == PFS_ERR_INCONSISTENT)
   1094         ret = osPfsChecker(&ControllerPak);
   1095 
   1096     ControllerPakStatus = 1;
   1097 
   1098     return ret;
   1099 }
   1100 
   1101 #define COMPANY_CODE 0x3544     // 5D
   1102 #define GAME_CODE 0x4e444d45    // NDME
   1103 
   1104 int I_ReadPakFile(void) // 800073B8
   1105 {
   1106     int ret;
   1107     u8 *ext_name;
   1108 
   1109     ControllerPakStatus = 0;
   1110 
   1111     if (gamepad_system_busy != 0)
   1112     {
   1113         do {
   1114         osYieldThread();
   1115         } while (gamepad_system_busy != 0);
   1116     }
   1117 
   1118     Pak_Data = NULL;
   1119     Pak_Size = 0;
   1120     ext_name = NULL;
   1121 
   1122     ret = osPfsFindFile(&ControllerPak, COMPANY_CODE, GAME_CODE, Game_Name, ext_name, &File_Num);
   1123 
   1124     if (ret == 0)
   1125     {
   1126         Pak_Size = FileState[File_Num].file_size;
   1127         Pak_Data = (byte *)Z_Malloc(Pak_Size, PU_STATIC, NULL);
   1128         ret = osPfsReadWriteFile(&ControllerPak, File_Num, PFS_READ, 0, Pak_Size, Pak_Data);
   1129     }
   1130 
   1131     ControllerPakStatus = 1;
   1132 
   1133     return ret;
   1134 }
   1135 
   1136 int I_CreatePakFile(void) // 800074D4
   1137 {
   1138     int ret;
   1139     u8 ExtName [8];
   1140 
   1141     ControllerPakStatus = 0;
   1142 
   1143     if (gamepad_system_busy != 0)
   1144     {
   1145         do {
   1146           osYieldThread();
   1147         } while (gamepad_system_busy != 0);
   1148     }
   1149 
   1150     if (Pak_Memory < 2)
   1151         Pak_Size = 256;
   1152     else
   1153         Pak_Size = 512;
   1154 
   1155     Pak_Data = (byte *)Z_Malloc(Pak_Size, PU_STATIC, NULL);
   1156     D_memset(Pak_Data, 0, Pak_Size);
   1157 
   1158     *(int*)ExtName = 0;
   1159 
   1160     ret = osPfsAllocateFile(&ControllerPak, COMPANY_CODE, GAME_CODE, Game_Name, ExtName, Pak_Size, &File_Num);
   1161 
   1162     if (ret == PFS_ERR_INCONSISTENT)
   1163         ret = osPfsChecker(&ControllerPak);
   1164 
   1165     if (ret == 0)
   1166         ret = osPfsReadWriteFile(&ControllerPak, File_Num, PFS_WRITE, 0, Pak_Size, Pak_Data);
   1167 
   1168     ControllerPakStatus = 1;
   1169 
   1170     return ret;
   1171 }