├── .gitattributes ├── .github └── Logo.png ├── .gitignore ├── .gitmodules ├── Docs ├── Code Style Conventions.docx └── Design Document.pdf ├── Engine └── N64 │ ├── MemoryMap_HD.json │ ├── MemoryMap_HD.png │ ├── MemoryMap_SD.json │ ├── MemoryMap_SD.png │ ├── audio.c │ ├── audio.h │ ├── controller.c │ ├── controller.h │ ├── datatype │ ├── engine │ │ ├── bool.h │ │ ├── color.c │ │ ├── color.h │ │ ├── transform2d.c │ │ ├── transform2d.h │ │ └── transform3d.h │ └── math │ │ ├── octagon.h │ │ ├── quaternion.c │ │ ├── quaternion.h │ │ ├── vector2d.c │ │ ├── vector2d.h │ │ ├── vector3d.c │ │ └── vector3d.h │ ├── debug.c │ ├── debug.h │ ├── engine.c │ ├── engine.h │ ├── game │ └── levels │ │ ├── level_boot.c │ │ ├── levels.c │ │ └── levels.h │ ├── graphics.c │ ├── graphics.h │ ├── helper.c │ ├── helper.h │ ├── main.c │ ├── osconfig.h │ ├── platform.nbp │ ├── rcp.c │ ├── rcp.h │ ├── scheduler.c │ ├── scheduler.h │ ├── spec │ ├── types.h │ ├── usb.c │ └── usb.h ├── LICENSE ├── README.md ├── Tools └── Builder │ ├── Builder.fbp │ ├── Builder.rc │ ├── Builder.sln │ ├── Builder.vcxproj │ ├── Builder.vcxproj.filters │ ├── Builder.vcxproj.user │ ├── README.md │ ├── app.cpp │ ├── app.h │ ├── compunit.cpp │ ├── compunit.h │ ├── helper.cpp │ ├── helper.h │ ├── main.cpp │ ├── main.h │ ├── preferences.cpp │ ├── preferences.h │ ├── resource.h │ ├── resources │ ├── c.png │ ├── config.png │ ├── generate.bat │ ├── h.png │ ├── icon_c.h │ ├── icon_config.h │ ├── icon_h.h │ ├── icon_prog.h │ └── prog.ico │ ├── traverser.cpp │ └── traverser.h └── azure-pipelines.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/.github/Logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.a 4 | *.out 5 | *.cvt 6 | *.exe 7 | *.n64 8 | *.aps 9 | Tools/*/Debug/* 10 | Tools/*/Release/* 11 | Tools/*/.vs -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Tools/NRDC"] 2 | path = Tools/NRDC 3 | url = https://github.com/buu342/N64-NRDC.git 4 | branch = master 5 | ignore = dirty 6 | [submodule "Tools/UNFLoader"] 7 | path = Tools/UNFLoader 8 | url = https://github.com/buu342/N64-UNFLoader.git 9 | branch = master 10 | ignore = dirty 11 | [submodule "Tools/MemMapper"] 12 | path = Tools/MemMapper 13 | url = https://github.com/buu342/CPP-MemMapper.git 14 | branch = master 15 | ignore = dirty 16 | -------------------------------------------------------------------------------- /Docs/Code Style Conventions.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Docs/Code Style Conventions.docx -------------------------------------------------------------------------------- /Docs/Design Document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Docs/Design Document.pdf -------------------------------------------------------------------------------- /Engine/N64/MemoryMap_HD.json: -------------------------------------------------------------------------------- 1 | {"Items":[{"Alpha":128,"Color":[255,128,0,0],"Length":1048576,"Name":"Code","Start":1024,"TextColor":[0,0,0]},{"Alpha":128,"Color":[0,255,0,0],"Length":737280,"Name":"Framebuffer 1","Start":5554176,"TextColor":[0,0,0]},{"Alpha":128,"Color":[0,255,255,255],"Length":737280,"Name":"Framebuffer 2","Start":6602752,"TextColor":[0,0,0]},{"Alpha":128,"Color":[192,192,192,192],"Length":737280,"Name":"Z-Buffer","Start":7651328,"TextColor":[0,0,0]},{"Alpha":128,"Color":[255,255,255,255],"Length":62464,"Name":"Stacks","Start":1048576,"TextColor":[0,0,0]},{"Alpha":128,"Color":[212,190,236,236],"Length":524288,"Name":"Heap","Start":3485695,"TextColor":[0,0,0]}],"Settings":{"Mem Length":8388608,"Mem Segments":8,"Mem Start":0}} -------------------------------------------------------------------------------- /Engine/N64/MemoryMap_HD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Engine/N64/MemoryMap_HD.png -------------------------------------------------------------------------------- /Engine/N64/MemoryMap_SD.json: -------------------------------------------------------------------------------- 1 | {"Items":[{"Alpha":128,"Color":[255,128,0,0],"Length":1048576,"Name":"Code","Start":1024,"TextColor":[0,0,0]},{"Alpha":128,"Color":[0,255,0,0],"Length":184320,"Name":"Framebuffer 1","Start":1912832,"TextColor":[0,0,0]},{"Alpha":128,"Color":[0,255,255,255],"Length":184320,"Name":"Framebuffer 2","Start":2961408,"TextColor":[0,0,0]},{"Alpha":128,"Color":[192,192,192,192],"Length":184320,"Name":"Z-Buffer","Start":4009984,"TextColor":[0,0,0]},{"Alpha":128,"Color":[255,255,255,255],"Length":62464,"Name":"Stacks","Start":1048576,"TextColor":[0,0,0]},{"Alpha":128,"Color":[212,190,236,236],"Length":524288,"Name":"Heap","Start":3485695,"TextColor":[0,0,0]}],"Settings":{"Mem Length":4194304,"Mem Segments":4,"Mem Start":0}} -------------------------------------------------------------------------------- /Engine/N64/MemoryMap_SD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Engine/N64/MemoryMap_SD.png -------------------------------------------------------------------------------- /Engine/N64/audio.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | audio.c 3 | 4 | Handles audio 5 | ***************************************************************/ 6 | 7 | #include 8 | #include "debug.h" 9 | #include "osconfig.h" 10 | #include "audio.h" 11 | 12 | 13 | /********************************* 14 | Function Prototypes 15 | *********************************/ 16 | 17 | static void threadfunc_audio(void *arg); 18 | 19 | 20 | /********************************* 21 | Globals 22 | *********************************/ 23 | 24 | static OSThread s_threadstruct_audio; 25 | 26 | 27 | /*============================== 28 | audio_initialize 29 | Launches the audio thread 30 | ==============================*/ 31 | 32 | void audio_initialize() 33 | { 34 | // Start the audio thread 35 | osCreateThread(&s_threadstruct_audio, THREADID_AUDIO, threadfunc_audio, NULL, STACKREALSTART_AUDIO, THREADPRI_AUDIO); 36 | osStartThread(&s_threadstruct_audio); 37 | } 38 | 39 | 40 | /*============================== 41 | thread_audio 42 | The audio thread 43 | @param Argument passed to the thread 44 | ==============================*/ 45 | 46 | static void threadfunc_audio(void *arg) 47 | { 48 | debug_printf("Created audio thread\n"); 49 | 50 | // Spin this thread forever 51 | while (1) 52 | { 53 | debug_printf("Audio thread loop start\n"); 54 | 55 | debug_printf("Stopping audio thread\n"); 56 | osStopThread(&s_threadstruct_audio); 57 | } 58 | } 59 | 60 | 61 | /*============================== 62 | audio_stopthread 63 | Stops the audio thread 64 | ==============================*/ 65 | 66 | void audio_stopthread() 67 | { 68 | osStopThread(&s_threadstruct_audio); 69 | } -------------------------------------------------------------------------------- /Engine/N64/audio.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_AUDIO_H 2 | #define PLATFORM64_AUDIO_H 3 | 4 | void audio_initialize(); 5 | void audio_stopthread(); 6 | 7 | #endif -------------------------------------------------------------------------------- /Engine/N64/controller.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | controller.c 3 | 4 | Handles controller I/O and provides helper functions for reading 5 | player inputs. 6 | ***************************************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "debug.h" 12 | #include "types.h" 13 | #include "helper.h" 14 | #include "osconfig.h" 15 | #include "controller.h" 16 | 17 | 18 | /********************************* 19 | Definitions 20 | *********************************/ 21 | 22 | #define SIZE_MSGQUEUE_SI 1 23 | #define SIZE_MSGQUEUE_CONTROLLER 8*MAXCONTROLLERS 24 | 25 | // Enable this to see how the controller thread is behaving with prints 26 | #define VERBOSE FALSE 27 | 28 | // Controller messages 29 | #define MSG_CONTROLLER_QUERY 1 30 | #define MSG_CONTROLLER_READ 2 31 | #define MSG_CONTROLLER_RESET 3 32 | #define MSG_CONTROLLER_RUMBLE_INIT 4 33 | #define MSG_CONTROLLER_RUMBLE_P1 5 34 | #define MSG_CONTROLLER_RUMBLE_P2 6 35 | #define MSG_CONTROLLER_RUMBLE_P3 7 36 | #define MSG_CONTROLLER_RUMBLE_P4 8 37 | 38 | // Controller distances 39 | #define CONTROLLER_DEFAULT_MIN {{0, 5}, {3, 3}, {4, 0}, {3, -3}, {0, -5}, {-3, -3}, {-4, 0}, {-3, 3}} 40 | #define CONTROLLER_DEFAULT_MAX {{0, 83}, {64, 64}, {74, 0}, {64, -64}, {0, -83}, {-64, -64}, {-74, 0}, {-64, 64}} // My personal controller profile 41 | //#define CONTROLLER_DEFAULT_MAX {{0, 63}, {46, 46}, {61, 0}, {46, -46}, {0, -63}, {-46, -46}, {-61, 0}, {-46, 46}} // Nintendo recommended values 42 | 43 | // Rumble flags 44 | #define RUMBLE_ERR 0 45 | #define RUMBLE_ON 1 46 | #define RUMBLE_OFF 2 47 | 48 | 49 | /********************************* 50 | Structs 51 | *********************************/ 52 | 53 | typedef struct 54 | { 55 | s8 portindex; 56 | u8 rumblestat; 57 | u16 actions[MAX_ACTIONS]; 58 | Vector2D stick; 59 | Octagon stickprof_min; 60 | Octagon stickprof_max; 61 | OSPfs rumble; 62 | OSTimer rumbletimer; 63 | f32 trauma; 64 | } PlayerCont; 65 | 66 | 67 | /********************************* 68 | Function Prototypes 69 | *********************************/ 70 | 71 | static void threadfunc_controller(void *arg); 72 | static void controller_calcstick(plynum player); 73 | 74 | 75 | /********************************* 76 | Globals 77 | *********************************/ 78 | 79 | // Semaphores to stop queue overfilling 80 | static bool s_reading; 81 | static bool s_querying; 82 | 83 | // Raw controller data 84 | static OSContPad s_contdata[MAXCONTROLLERS]; 85 | static OSContPad s_contdata_old[MAXCONTROLLERS]; 86 | static OSContStatus s_contstat[MAXCONTROLLERS]; 87 | 88 | // Thread structure 89 | static OSThread s_threadstruct_controller; 90 | 91 | // Message queues for thread communication 92 | static OSMesgQueue s_msgqueue_cont; 93 | static OSMesg s_msgbuffer_cont[SIZE_MSGQUEUE_CONTROLLER]; 94 | static OSMesgQueue s_msgqueue_si; 95 | static OSMesg s_msgbuffer_si[SIZE_MSGQUEUE_SI]; 96 | 97 | // Player data 98 | static u8 s_playercount = 0; 99 | static PlayerCont s_playercont[MAXCONTROLLERS]; 100 | 101 | 102 | /*============================== 103 | controller_initialize 104 | Initializes the controller 105 | and launches a thread. 106 | ==============================*/ 107 | 108 | void controller_initialize() 109 | { 110 | // Initialize the serial interface and its message queue 111 | osCreateMesgQueue(&s_msgqueue_si, s_msgbuffer_si, SIZE_MSGQUEUE_SI); 112 | osSetEventMesg(OS_EVENT_SI, &s_msgqueue_si, (OSMesg)1); 113 | 114 | // Start the controller thread 115 | osCreateThread(&s_threadstruct_controller, THREADID_CONTROLLER, threadfunc_controller, NULL, STACKREALSTART_CONTROLLER, THREADPRI_CONTROLLER); 116 | osStartThread(&s_threadstruct_controller); 117 | } 118 | 119 | 120 | /*============================== 121 | thread_controller 122 | The controller thread 123 | @param Argument passed to the thread 124 | ==============================*/ 125 | 126 | static void threadfunc_controller(void *arg) 127 | { 128 | int i; 129 | u8 l_pattern; 130 | debug_printf("Created Controller thread\n"); 131 | 132 | // Initialize the thread's message queue 133 | osCreateMesgQueue(&s_msgqueue_cont, s_msgbuffer_cont, SIZE_MSGQUEUE_CONTROLLER); 134 | s_reading = FALSE; 135 | s_querying = FALSE; 136 | 137 | // Initialize the controllers 138 | osContInit(&s_msgqueue_si, &l_pattern, s_contstat); 139 | memset(s_playercont, 0, sizeof(PlayerCont)*MAXCONTROLLERS); 140 | s_playercount = 0; 141 | 142 | // Find out what player corresponds to what controller 143 | #if VERBOSE 144 | debug_printf("Controller Thread: Querying controllers.\n"); 145 | #endif 146 | for (i=0; i 0 && (s_contdata[l_contindex].stick_x != s_contdata_old[l_contindex].stick_x || s_contdata[l_contindex].stick_y != s_contdata_old[l_contindex].stick_y)) 292 | controller_calcstick(l_ply); 293 | } 294 | s_reading = FALSE; 295 | break; 296 | case MSG_CONTROLLER_RESET: 297 | 298 | // Reset the controllers 299 | osContReset(&s_msgqueue_si, s_contstat); 300 | memset(s_playercont, 0, sizeof(PlayerCont)*MAXCONTROLLERS); 301 | s_playercount = 0; 302 | 303 | // Find out what player corresponds to what controller 304 | #if VERBOSE 305 | debug_printf("Controller Thread: Querying controllers.\n"); 306 | #endif 307 | for (i=0; i 0.0f || s_playercont[l_ply].rumblestat == RUMBLE_ON) 355 | { 356 | osStopTimer(&s_playercont[l_ply].rumbletimer); 357 | if (s_playercont[l_ply].rumblestat == RUMBLE_ON && s_playercont[l_ply].trauma > 0.0f) 358 | { 359 | s_playercont[l_ply].trauma -= 0.1f; 360 | if (s_playercont[l_ply].trauma > 0.01f) 361 | osSetTimer(&s_playercont[l_ply].rumbletimer, OS_USEC_TO_CYCLES((u32)(100000.0f - s_playercont[l_ply].trauma*100000.0f)), 0, &s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_P1+l_ply)); 362 | else 363 | s_playercont[l_ply].trauma = 0.0f; 364 | s_playercont[l_ply].rumblestat = RUMBLE_OFF; 365 | osMotorStop(&s_playercont[l_ply].rumble); 366 | #if VERBOSE 367 | debug_printf("Controller Thread: Rumble stopped\n"); 368 | #endif 369 | } 370 | else 371 | { 372 | osSetTimer(&s_playercont[l_ply].rumbletimer, OS_USEC_TO_CYCLES((u32)(s_playercont[l_ply].trauma*100000.0f)), 0, &s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_P1+l_ply)); 373 | s_playercont[l_ply].rumblestat = RUMBLE_ON; 374 | osMotorStart(&s_playercont[l_ply].rumble); 375 | #if VERBOSE 376 | debug_printf("Controller Thread: Rumble started\n"); 377 | #endif 378 | } 379 | } 380 | 381 | // Handle rumble motor shutdown 382 | // The rumble pak must be shut down 3 times or more in order to guarantee it stopped 383 | if (s_playercont[l_ply].rumblestat != RUMBLE_ERR && s_playercont[l_ply].trauma == 0) 384 | { 385 | if (s_playercont[l_ply].rumblestat >= RUMBLE_OFF && s_playercont[l_ply].rumblestat < RUMBLE_OFF+3) 386 | { 387 | s_playercont[l_ply].rumblestat++; 388 | osMotorStop(&s_playercont[l_ply].rumble); 389 | osStopTimer(&s_playercont[l_ply].rumbletimer); 390 | osSetTimer(&s_playercont[l_ply].rumbletimer, OS_USEC_TO_CYCLES(100000.0f), 0, &s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_P1+l_ply)); 391 | #if VERBOSE 392 | debug_printf("Controller Thread: Rumble shutdown %d/3\n", s_playercont[l_ply].rumblestat-RUMBLE_OFF); 393 | #endif 394 | } 395 | } 396 | break; 397 | default: 398 | #if VERBOSE 399 | debug_printf("Controller Thread: Bad message '0x%2x' received\n", (s32)l_msg); 400 | #endif 401 | break; 402 | } 403 | } 404 | } 405 | 406 | 407 | /*============================== 408 | controller_reinitialize_all 409 | Reinitializes all the controllers 410 | ==============================*/ 411 | 412 | void controller_reinitialize_all() 413 | { 414 | osSendMesg(&s_msgqueue_cont, (OSMesg)MSG_CONTROLLER_RESET, OS_MESG_BLOCK); 415 | } 416 | 417 | 418 | /*============================== 419 | controller_query_all 420 | Queries all controllers 421 | ==============================*/ 422 | 423 | void controller_query_all() 424 | { 425 | if (s_querying) 426 | return; 427 | osSendMesg(&s_msgqueue_cont, (OSMesg)MSG_CONTROLLER_QUERY, OS_MESG_BLOCK); 428 | s_querying = TRUE; 429 | } 430 | 431 | 432 | /*============================== 433 | controller_read_all 434 | Reads all controllers 435 | ==============================*/ 436 | 437 | void controller_read_all() 438 | { 439 | if (s_reading) 440 | return; 441 | osSendMesg(&s_msgqueue_cont, (OSMesg)MSG_CONTROLLER_READ, OS_MESG_BLOCK); 442 | s_reading = TRUE; 443 | } 444 | 445 | 446 | /*============================== 447 | controller_playercount 448 | Gives you the player count 449 | (ie the number of connected controllers) 450 | @returns The number of players 451 | ==============================*/ 452 | 453 | inline s32 controller_playercount() 454 | { 455 | return s_playercount; 456 | } 457 | 458 | 459 | /*============================== 460 | controller_register_action 461 | Registers an action to a specific set of buttons 462 | on a player's controller. 463 | @param The player to register the action. 464 | @param The action to register 465 | @param The buttons to register. This should be a combination of 466 | Libultra button macros, like A_BUTTON. 467 | ==============================*/ 468 | 469 | void controller_register_action(plynum player, u8 action, u16 buttons) 470 | { 471 | s_playercont[player].actions[action] |= buttons; 472 | } 473 | 474 | 475 | /*============================== 476 | controller_unregister_action 477 | Unregisters an action from a specific set of buttons 478 | on a player's controller. 479 | @param The player to unregister the action. 480 | @param The action to unregister 481 | @param The buttons to unregister. This should be a combination of 482 | Libultra button macros, like A_BUTTON. 483 | ==============================*/ 484 | 485 | void controller_unregister_action(plynum player, u8 action, u16 buttons) 486 | { 487 | s_playercont[player].actions[action] &= ~buttons; 488 | } 489 | 490 | 491 | /*============================== 492 | controller_action_pressed 493 | Checks if a specific action button was pressed *this frame* 494 | on a player's controller. 495 | @param The player to check. 496 | @param The action to check 497 | @returns If the action is being pressed 498 | ==============================*/ 499 | 500 | bool controller_action_pressed(plynum player, u8 action) 501 | { 502 | s8 l_index = s_playercont[player].portindex-1; 503 | u16 l_action = s_playercont[player].actions[action]; 504 | if (l_index < 0) 505 | return FALSE; 506 | return (s_contdata[l_index].button & l_action) != 0 && (s_contdata_old[l_index].button & l_action) == 0; 507 | } 508 | 509 | 510 | /*============================== 511 | controller_action_down 512 | Checks if a specific action button is down on a player's 513 | controller. 514 | @param The player to check 515 | @param The action to check 516 | @returns If the action is being held down 517 | ==============================*/ 518 | 519 | bool controller_action_down(plynum player, u8 action) 520 | { 521 | s8 l_index = s_playercont[player].portindex-1; 522 | if (l_index < 0) 523 | return FALSE; 524 | return (s_contdata[l_index].button & s_playercont[player].actions[action]) != 0; 525 | } 526 | 527 | 528 | /*============================== 529 | controller_action_released 530 | Checks if a specific action button was released *this frame* 531 | on a player's controller. 532 | @param The player to check 533 | @param The action to check 534 | @returns If the action is being released 535 | ==============================*/ 536 | 537 | bool controller_action_released(plynum player, u8 action) 538 | { 539 | s8 l_index = s_playercont[player].portindex-1; 540 | u16 l_action = s_playercont[player].actions[action]; 541 | if (l_index < 0) 542 | return FALSE; 543 | return (s_contdata[l_index].button & l_action) == 0 && (s_contdata_old[l_index].button & l_action) != 0; 544 | } 545 | 546 | 547 | /*============================== 548 | controller_set_stickmin 549 | Sets a player's stick deadzone profile 550 | @param The player whos profile we want to modify. 551 | @param The octagon that represents the deadzone 552 | ==============================*/ 553 | 554 | void controller_set_stickmin(plynum player, Octagon oct) 555 | { 556 | s_playercont[player].stickprof_min = oct; 557 | } 558 | 559 | 560 | /*============================== 561 | controller_set_stickmax 562 | Sets a player's stick maximum range profile 563 | @param The player whos profile we want to modify. 564 | @param The octagon that represents the maximum range. 565 | ==============================*/ 566 | 567 | void controller_set_stickmax(plynum player, Octagon oct) 568 | { 569 | s_playercont[player].stickprof_max = oct; 570 | } 571 | 572 | 573 | /*============================== 574 | controller_set_stickmax 575 | Normalizes a player's stick coordinates to fit between [-1, 1], 576 | using their preconfigured stick deadzone and maximum range 577 | profiles. 578 | @param The player who's stick we should normalize 579 | ==============================*/ 580 | 581 | static void controller_calcstick(plynum player) 582 | { 583 | s32 l_x, l_y, l_xp, l_yp; 584 | u32 l_xa, l_ya; 585 | s32 l_minx1, l_minx2, l_miny1, l_miny2; 586 | s32 l_maxx1, l_maxx2, l_maxy1, l_maxy2; 587 | s32 l_quadrant = 0, l_octant = 0, l_octantnext = 0; 588 | f32 l_detmin, l_detmax, l_intmin_x, l_intmin_y, l_intmax_x, l_intmax_y; 589 | f32 l_ang; 590 | 591 | // Populate our helper variables 592 | l_x = s_contdata[s_playercont[player].portindex-1].stick_x; 593 | l_y = s_contdata[s_playercont[player].portindex-1].stick_y; 594 | if (l_x == 0 && l_y == 0) 595 | { 596 | s_playercont[player].stick.x = 0; 597 | s_playercont[player].stick.y = 0; 598 | return; 599 | } 600 | l_xp = (l_x >> 31) & 0x01; 601 | l_yp = (l_y >> 31) & 0x01; 602 | l_xa = (l_x >= 0) ? l_x : -l_x; 603 | l_ya = (l_y >= 0) ? l_y : -l_y; 604 | 605 | // Find the octant on the cartesian plane 606 | l_quadrant = (!l_xp) ? (l_yp) : (3 - l_yp); 607 | if ((l_quadrant & 0x01) == 1) 608 | l_octant = (l_xa <= l_ya) ? (l_quadrant*2 + 1) : (l_quadrant*2); 609 | else 610 | l_octant = (l_xa <= l_ya) ? (l_quadrant*2) : (l_quadrant*2 + 1); 611 | 612 | // Now we know which array values we need from our player zones 613 | l_minx1 = ((OctArray)s_playercont[player].stickprof_min).array[l_octant*2]; 614 | l_miny1 = ((OctArray)s_playercont[player].stickprof_min).array[l_octant*2+1]; 615 | l_maxx1 = ((OctArray)s_playercont[player].stickprof_max).array[l_octant*2]; 616 | l_maxy1 = ((OctArray)s_playercont[player].stickprof_max).array[l_octant*2+1]; 617 | l_octantnext = l_octant+1; 618 | if (l_octantnext > 7) 619 | l_octantnext = 0; 620 | l_minx2 = ((OctArray)s_playercont[player].stickprof_min).array[l_octantnext*2]; 621 | l_miny2 = ((OctArray)s_playercont[player].stickprof_min).array[l_octantnext*2+1]; 622 | l_maxx2 = ((OctArray)s_playercont[player].stickprof_max).array[l_octantnext*2]; 623 | l_maxy2 = ((OctArray)s_playercont[player].stickprof_max).array[l_octantnext*2+1]; 624 | 625 | // Ok, so now comes the actual math 626 | // We project a line from (0,0) to our point, and we find the interceptions with the min and max of our octant 627 | l_detmin = (l_minx1*l_miny2 - l_miny1*l_minx2)/((f32)((l_minx1 - l_minx2)*(0 - l_y) - (l_miny1 - l_miny2)*(0 - l_x))); 628 | l_detmax = (l_maxx1*l_maxy2 - l_maxy1*l_maxx2)/((f32)((l_maxx1 - l_maxx2)*(0 - l_y) - (l_maxy1 - l_maxy2)*(0 - l_x))); 629 | l_intmin_x = (0 - l_x)*l_detmin; 630 | l_intmin_y = (0 - l_y)*l_detmin; 631 | l_intmax_x = (0 - l_x)*l_detmax; 632 | l_intmax_y = (0 - l_y)*l_detmax; 633 | 634 | // We need to find the angle of the line, which we will apply to get the final X Y 635 | l_ang = atan2(l_y, l_x); 636 | 637 | // We know that the distance between the min and max point needs to have a length of 1 when remapped to the unit circle 638 | // So divide our point by the maximum value (with the minimum subtracted as well) 639 | // That gives us how far the X and Y values are from the circumference of the circle (as a percentage) 640 | // Then multiply by the angle to get the final XY value mapped to [-1, 1] 641 | if (l_intmax_x - l_intmin_x != 0) 642 | s_playercont[player].stick.x = clampf(((f32)l_x - l_intmin_x)/(l_intmax_x - l_intmin_x), 0, 1)*cosf(l_ang); 643 | else 644 | s_playercont[player].stick.x = 0; 645 | if (l_intmax_y - l_intmin_y != 0) 646 | s_playercont[player].stick.y = clampf(((f32)l_y - l_intmin_y)/(l_intmax_y - l_intmin_y), 0, 1)*sinf(l_ang); 647 | else 648 | s_playercont[player].stick.y = 0; 649 | } 650 | 651 | 652 | /*============================== 653 | controller_get_x 654 | Gets the X value of a player's stick, normalized 655 | to -1 and 1 based on their stick profile. 656 | @param The player to get the stick X of. 657 | @returns The normalized stick X value. 658 | ==============================*/ 659 | 660 | f32 controller_get_x(plynum player) 661 | { 662 | return s_playercont[player].stick.x; 663 | } 664 | 665 | 666 | /*============================== 667 | controller_get_y 668 | Gets the Y value of a player's stick, normalized 669 | to -1 and 1 based on their stick profile. 670 | @param The player to get the stick Y of. 671 | @returns The normalized stick Y value. 672 | ==============================*/ 673 | 674 | f32 controller_get_y(plynum player) 675 | { 676 | return s_playercont[player].stick.y; 677 | } 678 | 679 | 680 | /*============================== 681 | controller_rumble_init 682 | Initializes the Rumble Pak on all controllers 683 | ==============================*/ 684 | 685 | void controller_rumble_init() 686 | { 687 | osSendMesg(&s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_INIT), OS_MESG_BLOCK); 688 | } 689 | 690 | 691 | /*============================== 692 | controller_rumble_check 693 | Checks if the rumble pak is connected. 694 | Should be called some miliseconds after rumble_init, 695 | not right after. Controller stuff takes time. 696 | @param The player to check the Rumble Pak of. 697 | @returns Any errors that ocurred, or zero 698 | ==============================*/ 699 | 700 | s32 controller_rumble_check(plynum player) 701 | { 702 | s8 l_index = s_playercont[player].portindex-1; 703 | if (l_index < 0) 704 | return PFS_ERR_CONTRFAIL; 705 | if (s_playercont[player].rumblestat == RUMBLE_ERR) 706 | return PFS_ERR_NOPACK; 707 | return 0; 708 | } 709 | 710 | 711 | /*============================== 712 | controller_rumble_addtrauma 713 | Adds trauma to a player's controller 714 | @param The player who's controller we want to add trauma to 715 | @param The amount of trauma to add (from 0 to 1) 716 | ==============================*/ 717 | 718 | void controller_rumble_addtrauma(plynum player, f32 trauma) 719 | { 720 | if (s_playercont[player].rumblestat == RUMBLE_ERR) 721 | return; 722 | s_playercont[player].trauma = clampf(s_playercont[player].trauma + trauma, 0.0f, 1.0f); 723 | osSendMesg(&s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_P1+player), OS_MESG_BLOCK); 724 | } 725 | 726 | 727 | /*============================== 728 | controller_rumble_settrauma 729 | Sets the trauma on a player's controller 730 | @param The player who's controller we want to set the trauma of 731 | @param The trauma value to set (from 0 to 1) 732 | ==============================*/ 733 | 734 | void controller_rumble_settrauma(plynum player, f32 trauma) 735 | { 736 | if (s_playercont[player].rumblestat == RUMBLE_ERR) 737 | return; 738 | s_playercont[player].trauma = clampf(trauma, 0.0f, 1.0f); 739 | if (s_playercont[player].trauma == 0) 740 | s_playercont[player].rumblestat = RUMBLE_OFF; 741 | osSendMesg(&s_msgqueue_cont, (OSMesg)(MSG_CONTROLLER_RUMBLE_P1+player), OS_MESG_BLOCK); 742 | } -------------------------------------------------------------------------------- /Engine/N64/controller.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_CONTROLLER_H 2 | #define PLATFORM64_CONTROLLER_H 3 | 4 | /********************************* 5 | Definitions 6 | *********************************/ 7 | 8 | // Max number of supported players in this game 9 | #define MAXPLAYERS 2 10 | 11 | // The total number of actions 12 | #define MAX_ACTIONS 1 13 | 14 | // The list of registerable actions 15 | #define ACTION_JUMP 0 16 | 17 | 18 | /********************************* 19 | Typedefs 20 | *********************************/ 21 | 22 | // Player numbers 23 | typedef enum { 24 | PLAYER_1 = 0, 25 | PLAYER_2 = 1, 26 | PLAYER_3 = 2, 27 | PLAYER_4 = 3 28 | } plynum; 29 | 30 | 31 | /********************************* 32 | Function Prototypes 33 | *********************************/ 34 | 35 | void controller_initialize(); 36 | void controller_reinitialize_all(); 37 | void controller_query_all(); 38 | void controller_read_all(); 39 | 40 | inline s32 controller_playercount(); 41 | 42 | void controller_register_action(plynum player, u8 action, u16 buttons); 43 | void controller_unregister_action(plynum player, u8 action, u16 buttons); 44 | bool controller_action_pressed(plynum player, u8 action); 45 | bool controller_action_down(plynum player, u8 action); 46 | bool controller_action_released(plynum player, u8 action); 47 | void controller_set_stickmin(plynum player, Octagon oct); 48 | void controller_set_stickmax(plynum player, Octagon oct); 49 | f32 controller_get_x(plynum player); 50 | f32 controller_get_y(plynum player); 51 | 52 | void controller_rumble_init(); 53 | s32 controller_rumble_check(plynum player); 54 | void controller_rumble_addtrauma(plynum player, f32 trauma); 55 | void controller_rumble_settrauma(plynum player, f32 trauma); 56 | 57 | #endif -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/bool.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_BOOL_H 2 | #define PLATFORM64_BOOL_H 3 | 4 | #define FALSE 0 5 | #define TRUE 1 6 | 7 | typedef u8 bool; 8 | 9 | #endif -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/color.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../debug.h" 3 | #include "../../types.h" 4 | #include "color.h" 5 | 6 | 7 | /*============================== 8 | color_initialize 9 | Initializes a color struct 10 | @param The red value 11 | @param The green value 12 | @param The blue value 13 | @param The alpha value 14 | @return The initialized color struct 15 | ==============================*/ 16 | 17 | inline Color color_initialize(u8 red, u8 green, u8 blue, u8 alpha) 18 | { 19 | Color c = {.red = red, .green = green, .blue = blue, .alpha = alpha}; 20 | return c; 21 | } -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/color.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_COLOR_H 2 | #define PLATFORM64_COLOR_H 3 | 4 | typedef struct 5 | { 6 | u8 red; 7 | u8 green; 8 | u8 blue; 9 | u8 alpha; 10 | } Color; 11 | 12 | inline Color color_initialize(u8 red, u8 green, u8 blue, u8 alpha); 13 | 14 | # endif -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/transform2d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../debug.h" 3 | #include "../../types.h" 4 | #include "../../engine.h" 5 | #include "transform2d.h" 6 | 7 | 8 | /*============================== 9 | transform2d_initialize 10 | Creates an initialized 2D transform struct 11 | @return an initialized 2D transform struct 12 | ==============================*/ 13 | 14 | inline Transform2D transform2d_initialize(Vector2D pos, f32 rot, Vector2D scale) 15 | { 16 | Transform2D t = { 17 | .pos = pos, .rot = rot, .scale = scale, 18 | .oldpos = pos, .oldrot = rot, .oldscale = scale, 19 | .transformtime = 0, .interpolate = TRUE 20 | }; 21 | return t; 22 | } 23 | 24 | 25 | /*============================== 26 | transform2d_updateold 27 | Updates the old values of a transform2d struct 28 | @param The 2D transform struct to update 29 | ==============================*/ 30 | 31 | static inline void transform2d_updateold(Transform2D* t) 32 | { 33 | if (engine_get_gametime() != t->transformtime) 34 | { 35 | t->transformtime = engine_get_gametime(); 36 | t->interpolate = TRUE; 37 | t->oldpos = t->pos; 38 | t->oldrot = t->rot; 39 | t->oldscale = t->scale; 40 | } 41 | } 42 | 43 | 44 | /*============================== 45 | transform2d_set_pos 46 | Sets the position of a 2D transform 47 | @param The 2D transform struct to modify 48 | @param The position to set 49 | ==============================*/ 50 | 51 | inline void transform2d_set_pos(Transform2D* t, Vector2D pos) 52 | { 53 | transform2d_updateold(t); 54 | t->pos = pos; 55 | } 56 | 57 | 58 | /*============================== 59 | transform2d_set_rot 60 | Sets the rotation of a 2D transform 61 | @param The 2D transform struct to modify 62 | @param The rotation to set 63 | ==============================*/ 64 | 65 | inline void transform2d_set_rot(Transform2D* t, f32 rotation) 66 | { 67 | transform2d_updateold(t); 68 | t->rot = rotation; 69 | } 70 | 71 | 72 | /*============================== 73 | transform2d_set_scale 74 | Sets the scale of a 2D transform 75 | @param The 2D transform struct to modify 76 | @param The scale to set 77 | ==============================*/ 78 | 79 | inline void transform2d_set_scale(Transform2D* t, Vector2D scale) 80 | { 81 | transform2d_updateold(t); 82 | t->scale = scale; 83 | } 84 | 85 | 86 | /*============================== 87 | transform2d_force_pos 88 | Forces the position of a 2D transform, disabling interpolation 89 | @param The 2D transform struct to modify 90 | @param The position to force 91 | ==============================*/ 92 | 93 | inline void transform2d_force_pos(Transform2D* t, Vector2D pos) 94 | { 95 | transform2d_updateold(t); 96 | t->pos = pos; 97 | t->interpolate = FALSE; 98 | } 99 | 100 | 101 | /*============================== 102 | transform2d_force_rot 103 | Forces the rotation of a 2D transform, disabling interpolation 104 | @param The 2D transform struct to modify 105 | @param The rotation to force 106 | ==============================*/ 107 | 108 | inline void transform2d_force_rot(Transform2D* t, f32 rotation) 109 | { 110 | transform2d_updateold(t); 111 | t->rot = rotation; 112 | t->interpolate = FALSE; 113 | } 114 | 115 | 116 | /*============================== 117 | transform2d_force_scale 118 | Forces the scale of a 2D transform, disabling interpolation 119 | @param The 2D transform struct to modify 120 | @param The scale to force 121 | ==============================*/ 122 | 123 | inline void transform2d_force_scale(Transform2D* t, Vector2D scale) 124 | { 125 | transform2d_updateold(t); 126 | t->scale = scale; 127 | t->interpolate = FALSE; 128 | } 129 | 130 | 131 | /*============================== 132 | transform2d_get_pos 133 | Gets the current position of a 2D transform 134 | @param The 2D transform to get the current position of 135 | @return The current position as a 2D vector 136 | ==============================*/ 137 | 138 | inline Vector2D transform2d_get_pos(Transform2D* t) 139 | { 140 | return t->pos; 141 | } 142 | 143 | 144 | /*============================== 145 | transform2d_get_rot 146 | Gets the current rotation of a 2D transform 147 | @param The 2D transform to get the current rotation of 148 | @return The current rotation as an angle 149 | ==============================*/ 150 | 151 | inline f32 transform2d_get_rot(Transform2D* t) 152 | { 153 | return t->rot; 154 | } 155 | 156 | 157 | /*============================== 158 | transform2d_get_scale 159 | Gets the current scale of a 2D transform 160 | @param The 2D transform to get the current scale of 161 | @return The current scale as a 2D vector 162 | ==============================*/ 163 | 164 | inline Vector2D transform2d_get_scale(Transform2D* t) 165 | { 166 | return t->scale; 167 | } 168 | 169 | 170 | /*============================== 171 | transform2d_get_oldpos 172 | Gets the old position of a 2D transform 173 | @param The 2D transform to get the old position of 174 | @return The old position as a 2D vector 175 | ==============================*/ 176 | 177 | inline Vector2D transform2d_get_oldpos(Transform2D* t) 178 | { 179 | return t->oldpos; 180 | } 181 | 182 | 183 | /*============================== 184 | transform2d_get_oldrot 185 | Gets the old rotation of a 2D transform 186 | @param The 2D transform to get the old rotation of 187 | @return The old rotation as an angle 188 | ==============================*/ 189 | 190 | inline f32 transform2d_get_oldrot(Transform2D* t) 191 | { 192 | return t->oldrot; 193 | } 194 | 195 | 196 | /*============================== 197 | transform2d_get_oldscale 198 | Gets the old scale of a 2D transform 199 | @param The 2D transform to get the old scale of 200 | @return The old scale as a 2D vector 201 | ==============================*/ 202 | 203 | inline Vector2D transform2d_get_oldscale(Transform2D* t) 204 | { 205 | return t->oldscale; 206 | } 207 | 208 | 209 | /*============================== 210 | transform2d_get_subpos 211 | Gets the subtick position of a 2D transform 212 | @param The 2D transform to get the subtick position of 213 | @return The subtick position as a 2D vector 214 | ==============================*/ 215 | 216 | inline Vector2D transform2d_get_subpos(Transform2D* t) 217 | { 218 | return vector2d_addvector(vector2d_mult(t->pos, engine_get_subtick()), vector2d_mult(t->oldpos, 1.0f-engine_get_subtick())); 219 | } 220 | 221 | 222 | /*============================== 223 | transform2d_get_subrot 224 | Gets the subtick rotation of a 2D transform 225 | @param The 2D transform to get the subtick rotation of 226 | @return The subtick rotation as an angle 227 | ==============================*/ 228 | 229 | inline f32 transform2d_get_subrot(Transform2D* t) 230 | { 231 | return t->rot*engine_get_subtick() + t->oldrot*(1.0f-engine_get_subtick()); 232 | } 233 | 234 | 235 | /*============================== 236 | transform2d_get_subscale 237 | Gets the subtick scale of a 2D transform 238 | @param The 2D transform to get the subtick scale of 239 | @return The subtick scale as a 2D vector 240 | ==============================*/ 241 | 242 | inline Vector2D transform2d_get_subscale(Transform2D* t) 243 | { 244 | return vector2d_addvector(vector2d_mult(t->scale, engine_get_subtick()), vector2d_mult(t->oldscale, 1.0f-engine_get_subtick())); 245 | } -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/transform2d.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_TRANSFORM2D_H 2 | #define PLATFORM64_TRANSFORM2D_H 3 | 4 | #include "bool.h" 5 | #include "../math/vector2d.h" 6 | 7 | typedef struct 8 | { 9 | Vector2D pos; 10 | Vector2D scale; 11 | f32 rot; 12 | Vector2D oldpos; 13 | Vector2D oldscale; 14 | f32 oldrot; 15 | u64 transformtime; 16 | bool interpolate; 17 | } Transform2D; 18 | 19 | inline Transform2D transform2d_initialize(Vector2D pos, f32 rot, Vector2D scale); 20 | inline void transform2d_set_pos(Transform2D* t, Vector2D pos); 21 | inline void transform2d_set_rot(Transform2D* t, f32 rotation); 22 | inline void transform2d_set_scale(Transform2D* t, Vector2D scale); 23 | inline void transform2d_force_pos(Transform2D* t, Vector2D pos); 24 | inline void transform2d_force_rot(Transform2D* t, f32 rotation); 25 | inline void transform2d_force_scale(Transform2D* t, Vector2D scale); 26 | inline Vector2D transform2d_get_pos(Transform2D* t); 27 | inline f32 transform2d_get_rot(Transform2D* t); 28 | inline Vector2D transform2d_get_scale(Transform2D* t); 29 | inline Vector2D transform2d_get_oldpos(Transform2D* t); 30 | inline f32 transform2d_get_oldrot(Transform2D* t); 31 | inline Vector2D transform2d_get_oldscale(Transform2D* t); 32 | inline Vector2D transform2d_get_subpos(Transform2D* t); 33 | inline f32 transform2d_get_subrot(Transform2D* t); 34 | inline Vector2D transform2d_get_subscale(Transform2D* t); 35 | 36 | # endif -------------------------------------------------------------------------------- /Engine/N64/datatype/engine/transform3d.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_TRANSFORM2D_H 2 | #define PLATFORM64_TRANSFORM2D_H 3 | 4 | #include "bool.h" 5 | #include "../math/vector3d.h" 6 | #include "../math/quaternion.h" 7 | 8 | typedef struct 9 | { 10 | Vector3D pos; 11 | Vector3D scale; 12 | Quaternion rot; 13 | Vector3D oldpos; 14 | Vector3D oldscale; 15 | Quaternion oldrot; 16 | u64 transformtime; 17 | bool interpolate; 18 | } Transform3D; 19 | 20 | inline Transform3D transform3d_initialize(Vector3D pos, Quaternion rot, Vector3D scale); 21 | inline void transform3d_set_pos(Transform3D* t, Vector3D pos); 22 | inline void transform3d_set_rot(Transform3D* t, Quaternion rotation); 23 | inline void transform3d_set_scale(Transform3D* t, Vector3D scale); 24 | inline void transform3d_force_pos(Transform3D* t, Vector3D pos); 25 | inline void transform3d_force_rot(Transform3D* t, Quaternion rotation); 26 | inline void transform3d_force_scale(Transform3D* t, Vector3D scale); 27 | inline Vector3D transform3d_get_pos(Transform3D* t); 28 | inline Quaternion transform3d_get_rot(Transform3D* t); 29 | inline Vector3D transform3d_get_scale(Transform3D* t); 30 | inline Vector3D transform3d_get_oldpos(Transform3D* t); 31 | inline Quaternion transform3d_get_oldrot(Transform3D* t); 32 | inline Vector3D transform3d_get_oldscale(Transform3D* t); 33 | inline Vector3D transform3d_get_subpos(Transform3D* t); 34 | inline Quaternion transform3d_get_subrot(Transform3D* t); 35 | inline Vector3D transform3d_get_subscale(Transform3D* t); 36 | 37 | # endif -------------------------------------------------------------------------------- /Engine/N64/datatype/math/octagon.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_OCTAGON_H 2 | #define PLATFORM64_OCTAGON_H 3 | 4 | typedef struct 5 | { 6 | Vector2D top; 7 | Vector2D topright; 8 | Vector2D right; 9 | Vector2D bottomright; 10 | Vector2D bottom; 11 | Vector2D bottomleft; 12 | Vector2D left; 13 | Vector2D topleft; 14 | } Octagon; 15 | 16 | typedef union 17 | { 18 | Octagon octagon; 19 | f32 array[2*8]; 20 | } OctArray; 21 | 22 | #endif -------------------------------------------------------------------------------- /Engine/N64/datatype/math/quaternion.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Engine/N64/datatype/math/quaternion.c -------------------------------------------------------------------------------- /Engine/N64/datatype/math/quaternion.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_QUATERNION_H 2 | #define PLATFORM64_QUATERNION_H 3 | 4 | typedef struct 5 | { 6 | f32 w; 7 | f32 x; 8 | f32 y; 9 | f32 z; 10 | } Quaternion; 11 | 12 | typedef union 13 | { 14 | Quaternion q; 15 | f32 a[4]; 16 | } U_Quaternion; 17 | 18 | #endif -------------------------------------------------------------------------------- /Engine/N64/datatype/math/vector2d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../debug.h" 3 | #include "../../types.h" 4 | #include "vector2d.h" 5 | 6 | 7 | /*============================== 8 | vector2d_initialize 9 | Returns an initialized 2D vector 10 | @param The initial X value 11 | @param The initial Y value 12 | @return An initialized 2D vector 13 | ==============================*/ 14 | 15 | inline Vector2D vector2d_initialize(f32 x, f32 y) 16 | { 17 | Vector2D v = {.x = x, .y = y}; 18 | return v; 19 | } 20 | 21 | 22 | /*============================== 23 | vector2d_add 24 | Adds a value to a 2D vector 25 | @param The vector to add to 26 | @param The value to add 27 | @return The resulting vector 28 | ==============================*/ 29 | 30 | inline Vector2D vector2d_add(Vector2D v, f32 val) 31 | { 32 | v.x += val; 33 | v.y += val; 34 | return v; 35 | } 36 | 37 | 38 | /*============================== 39 | vector2d_addvector 40 | Adds a 2D vector to a 2D vector 41 | @param The first vector 42 | @param The second vector 43 | @return The combined vector 44 | ==============================*/ 45 | 46 | inline Vector2D vector2d_addvector(Vector2D a, Vector2D b) 47 | { 48 | a.x += b.x; 49 | a.y += b.y; 50 | return a; 51 | } 52 | 53 | 54 | /*============================== 55 | vector2d_mult 56 | Multiplies a value to a 2D vector 57 | @param The vector to multiply to 58 | @param The value to multiply 59 | @return The resulting vector 60 | ==============================*/ 61 | 62 | inline Vector2D vector2d_mult(Vector2D v, f32 val) 63 | { 64 | v.x *= val; 65 | v.y *= val; 66 | return v; 67 | } 68 | 69 | 70 | /*============================== 71 | vector2d_multvector 72 | Multiplies a 2D vector to a 2D vector 73 | @param The first vector 74 | @param The second vector 75 | @return The combined vector 76 | ==============================*/ 77 | 78 | inline Vector2D vector2d_multvector(Vector2D a, Vector2D b) 79 | { 80 | a.x *= b.x; 81 | a.y *= b.y; 82 | return a; 83 | } -------------------------------------------------------------------------------- /Engine/N64/datatype/math/vector2d.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_VECTOR2D_H 2 | #define PLATFORM64_VECTOR2D_H 3 | 4 | typedef struct 5 | { 6 | f32 x; 7 | f32 y; 8 | } Vector2D; 9 | 10 | typedef union 11 | { 12 | Vector2D v; 13 | f32 a[2]; 14 | } U_Vector2D; 15 | 16 | inline Vector2D vector2d_initialize(f32 x, f32 y); 17 | inline Vector2D vector2d_add(Vector2D v, f32 val); 18 | inline Vector2D vector2d_addvector(Vector2D a, Vector2D b); 19 | inline Vector2D vector2d_mult(Vector2D v, f32 val); 20 | inline Vector2D vector2d_multvector(Vector2D a, Vector2D b); 21 | 22 | #endif -------------------------------------------------------------------------------- /Engine/N64/datatype/math/vector3d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../debug.h" 3 | #include "../../types.h" 4 | #include "vector3d.h" 5 | 6 | 7 | /*============================== 8 | vector3d_initialize 9 | Returns an initialized 3D vector 10 | @param The initial X value 11 | @param The initial Y value 12 | @param The initial Z value 13 | @return An initialized 3D vector 14 | ==============================*/ 15 | 16 | inline Vector3D vector3d_initialize(f32 x, f32 y, f32 z) 17 | { 18 | Vector3D v = {.x = x, .y = y, .z = z}; 19 | return v; 20 | } -------------------------------------------------------------------------------- /Engine/N64/datatype/math/vector3d.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_VECTOR3D_H 2 | #define PLATFORM64_VECTOR3D_H 3 | 4 | typedef struct 5 | { 6 | f32 x; 7 | f32 y; 8 | f32 z; 9 | } Vector3D; 10 | 11 | typedef union 12 | { 13 | Vector3D v; 14 | f32 a[3]; 15 | } U_Vector3D; 16 | 17 | #endif -------------------------------------------------------------------------------- /Engine/N64/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef UNFL_DEBUG_H 2 | #define UNFL_DEBUG_H 3 | 4 | /********************************* 5 | Settings macros 6 | *********************************/ 7 | 8 | // Enable/Disable debug 9 | #ifndef DEBUG_MODE 10 | #define DEBUG_MODE 1 // Enable/Disable debug mode 11 | #endif 12 | 13 | // Settings 14 | #define DEBUG_INIT_MSG 1 // Print a message when debug mode has initialized 15 | #define USE_FAULTTHREAD 1 // Create a fault detection thread (libultra only) 16 | #define OVERWRITE_OSPRINT 1 // Replaces osSyncPrintf calls with debug_printf (libultra only) 17 | #define MAX_COMMANDS 25 // The max amount of user defined commands possible 18 | 19 | // Fault thread definitions (libultra only) 20 | #define FAULT_THREAD_ID 13 21 | #define FAULT_THREAD_PRI 125 22 | #define FAULT_THREAD_STACK 0x2000 23 | 24 | // USB thread definitions (libultra only) 25 | #define USB_THREAD_ID 14 26 | #define USB_THREAD_PRI 126 27 | #define USB_THREAD_STACK 0x2000 28 | 29 | 30 | /********************************* 31 | Debug Functions 32 | *********************************/ 33 | 34 | #if DEBUG_MODE 35 | 36 | /*============================== 37 | debug_initialize 38 | Initializes the debug and USB library. 39 | ==============================*/ 40 | 41 | extern void debug_initialize(); 42 | 43 | 44 | /*============================== 45 | debug_printf 46 | Prints a formatted message to the developer's command prompt. 47 | Supports up to 256 characters. 48 | @param A string to print 49 | @param variadic arguments to print as well 50 | ==============================*/ 51 | 52 | extern void debug_printf(const char* message, ...); 53 | 54 | 55 | /*============================== 56 | debug_dumpbinary 57 | Dumps a binary file through USB 58 | @param The file to dump 59 | @param The size of the file 60 | ==============================*/ 61 | 62 | extern void debug_dumpbinary(void* file, int size); 63 | 64 | 65 | /*============================== 66 | debug_screenshot 67 | Sends the currently displayed framebuffer through USB. 68 | DOES NOT PAUSE DRAWING THREAD! Using outside the drawing 69 | thread may lead to a screenshot with visible tearing 70 | ==============================*/ 71 | 72 | extern void debug_screenshot(); 73 | 74 | 75 | /*============================== 76 | debug_assert 77 | Halts the program if the expression fails. 78 | @param The expression to test 79 | ==============================*/ 80 | 81 | #define debug_assert(expr) (expr) ? ((void)0) : _debug_assert(#expr, __FILE__, __LINE__) 82 | 83 | 84 | /*============================== 85 | debug_64drivebutton 86 | Assigns a function to be executed when the 64drive button is pressed. 87 | @param The function pointer to execute 88 | @param Whether or not to execute the function only on pressing (ignore holding the button down) 89 | ==============================*/ 90 | 91 | extern void debug_64drivebutton(void(*execute)(), char onpress); 92 | 93 | 94 | /*============================== 95 | debug_pollcommands 96 | Check the USB for incoming commands. 97 | ==============================*/ 98 | 99 | extern void debug_pollcommands(); 100 | 101 | 102 | /*============================== 103 | debug_addcommand 104 | Adds a command for the USB to read. 105 | @param The command name 106 | @param The command description 107 | @param The function pointer to execute 108 | ==============================*/ 109 | 110 | extern void debug_addcommand(char* command, char* description, char*(*execute)()); 111 | 112 | 113 | /*============================== 114 | debug_parsecommand 115 | Stores the next part of the incoming command into the provided buffer. 116 | Make sure the buffer can fit the amount of data from debug_sizecommand! 117 | If you pass NULL, it skips this command. 118 | @param The buffer to store the data in 119 | ==============================*/ 120 | 121 | extern void debug_parsecommand(void* buffer); 122 | 123 | 124 | /*============================== 125 | debug_sizecommand 126 | Returns the size of the data from this part of the command. 127 | @return The size of the data in bytes, or 0 128 | ==============================*/ 129 | 130 | extern int debug_sizecommand(); 131 | 132 | 133 | /*============================== 134 | debug_printcommands 135 | Prints a list of commands to the developer's command prompt. 136 | ==============================*/ 137 | 138 | extern void debug_printcommands(); 139 | 140 | 141 | // Ignore this, use the macro instead 142 | extern void _debug_assert(const char* expression, const char* file, int line); 143 | 144 | // Include usb.h automatically 145 | #include "usb.h" 146 | 147 | #else 148 | 149 | // Overwrite library functions with useless macros if debug mode is disabled 150 | #define debug_initialize() 151 | #define debug_printf (void) 152 | #define debug_screenshot(a, b, c) 153 | #define debug_assert(a) 154 | #define debug_pollcommands() 155 | #define debug_addcommand(a, b, c) 156 | #define debug_parsecommand(a) NULL 157 | #define debug_sizecommand() 0 158 | #define debug_printcommands() 159 | #define debug_64drivebutton(a, b) 160 | #define usb_initialize() 0 161 | #define usb_getcart() 0 162 | #define usb_write(a, b, c) 163 | #define usb_poll() 0 164 | #define usb_read(a, b) 165 | #define usb_skip(a) 166 | #define usb_rewind(a) 167 | #define usb_purge() 168 | 169 | #endif 170 | 171 | #endif -------------------------------------------------------------------------------- /Engine/N64/engine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "debug.h" 3 | #include "types.h" 4 | #include "osconfig.h" 5 | #include "scheduler.h" 6 | #include "graphics.h" 7 | #include "engine.h" 8 | #include "game/levels/levels.h" 9 | 10 | 11 | /********************************* 12 | Globals 13 | *********************************/ 14 | 15 | // Engine stuff 16 | static f32 s_timescale = 1.0f; 17 | static f32 s_deltatime_scaled = DELTATIME; 18 | static f32 s_subtick = 0.0f; 19 | static f32 s_frametime = 0.0f; 20 | static u64 s_gametime = 0; 21 | 22 | // Level stuff 23 | static levelid s_levelid = LEVEL_BOOT; 24 | static levelid s_levelid_old = LEVEL_BOOT; 25 | static bool s_changelevel = FALSE; 26 | 27 | 28 | 29 | /*============================== 30 | engine_level_start 31 | Starts a level 32 | ==============================*/ 33 | 34 | void engine_level_start() 35 | { 36 | s_changelevel = FALSE; 37 | if (levels_get_all()[s_levelid].start != NULL) 38 | levels_get_all()[s_levelid].start(); 39 | } 40 | 41 | 42 | /*============================== 43 | engine_level_update 44 | Updates the level by deltatime ticks 45 | ==============================*/ 46 | 47 | void engine_level_update() 48 | { 49 | if (levels_get_all()[s_levelid].update != NULL) 50 | levels_get_all()[s_levelid].update(); 51 | } 52 | 53 | 54 | /*============================== 55 | engine_level_render 56 | Renders the level 57 | ==============================*/ 58 | 59 | void engine_level_render() 60 | { 61 | int i; 62 | for (i=0; irender, task->usecpu, (i == levels_get_all()[s_levelid].drawcount-1)); 66 | } 67 | } 68 | 69 | 70 | /*============================== 71 | engine_level_end 72 | Ends the level 73 | ==============================*/ 74 | 75 | void engine_level_end() 76 | { 77 | if (levels_get_all()[s_levelid_old].end != NULL) 78 | levels_get_all()[s_levelid_old].end(); 79 | } 80 | 81 | 82 | /*============================== 83 | engine_level_change 84 | Handles level changing 85 | @param The levelid to switch to 86 | ==============================*/ 87 | 88 | void engine_level_change(u32 levelid) 89 | { 90 | s_levelid_old = s_levelid; 91 | s_levelid = levelid; 92 | s_changelevel = TRUE; 93 | } 94 | 95 | 96 | /*============================== 97 | engine_level_shouldchange 98 | Checks if the level should change 99 | @return Whether to change the level or not 100 | ==============================*/ 101 | 102 | bool engine_level_shouldchange(levelid id) 103 | { 104 | return s_changelevel; 105 | } 106 | 107 | 108 | /*============================== 109 | engine_set_timescale 110 | Sets the timescale for the engine 111 | Use for slowmotion 112 | @param The timescale 113 | ==============================*/ 114 | 115 | inline void engine_set_timescale(f32 timescale) 116 | { 117 | s_timescale = timescale; 118 | s_deltatime_scaled = DELTATIME*timescale; 119 | } 120 | 121 | 122 | /*============================== 123 | engine_set_subtick 124 | Sets the subtick for the engine 125 | Used to interpolate between frames 126 | @param The subtick 127 | ==============================*/ 128 | 129 | inline void engine_set_subtick(f32 subtick) 130 | { 131 | s_subtick = subtick; 132 | } 133 | 134 | 135 | /*============================== 136 | engine_set_frametime 137 | Sets the frametime for the engine 138 | Used for framerate independent animations 139 | @param The frametime 140 | ==============================*/ 141 | 142 | inline void engine_set_frametime(f32 frametime) 143 | { 144 | s_frametime = frametime; 145 | } 146 | 147 | 148 | /*============================== 149 | engine_increment_gametime 150 | Increments the game time 151 | ==============================*/ 152 | 153 | inline void engine_increment_gametime() 154 | { 155 | s_gametime++; 156 | } 157 | 158 | 159 | /*============================== 160 | engine_get_deltatime 161 | Gets the deltatime 162 | @return The deltatime 163 | ==============================*/ 164 | 165 | inline f32 engine_get_deltatime() 166 | { 167 | return s_deltatime_scaled; 168 | } 169 | 170 | 171 | /*============================== 172 | engine_get_deltatime_unscaled 173 | Gets the unscaled deltatime 174 | @return The unscaled deltatime 175 | ==============================*/ 176 | 177 | inline f32 engine_get_deltatime_unscaled() 178 | { 179 | return DELTATIME; 180 | } 181 | 182 | 183 | /*============================== 184 | engine_get_timescale 185 | Gets the timescale of the engine 186 | @return The timescale 187 | ==============================*/ 188 | 189 | inline f32 engine_get_timescale() 190 | { 191 | return s_timescale; 192 | } 193 | 194 | 195 | /*============================== 196 | engine_get_subtick 197 | Gets the subtick of the engine 198 | @return The subtick 199 | ==============================*/ 200 | 201 | inline f32 engine_get_subtick() 202 | { 203 | return s_subtick; 204 | } 205 | 206 | 207 | /*============================== 208 | engine_get_frametime 209 | Gets the frametime of the engine 210 | @return The frametime 211 | ==============================*/ 212 | 213 | inline f32 engine_get_frametime() 214 | { 215 | return s_frametime; 216 | } 217 | 218 | 219 | /*============================== 220 | engine_get_gametime 221 | Gets a counter that increments since 222 | the game booted 223 | @return The game time 224 | ==============================*/ 225 | 226 | inline u64 engine_get_gametime() 227 | { 228 | return s_gametime; 229 | } 230 | 231 | 232 | /*============================== 233 | engine_shouldchange 234 | Checks if the engine should change 235 | @return Returns FALSE for now 236 | ==============================*/ 237 | 238 | inline bool engine_shouldchange() 239 | { 240 | return FALSE; 241 | } -------------------------------------------------------------------------------- /Engine/N64/engine.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_SCENE_H 2 | #define PLATFORM64_SCENE_H 3 | 4 | void engine_level_start(); 5 | void engine_level_update(); 6 | void engine_level_render(); 7 | void engine_level_end(); 8 | 9 | void engine_level_change(u32 levelid); 10 | bool engine_level_shouldchange(); 11 | 12 | inline void scene_set_timescale(f32 timescale); 13 | inline void engine_set_subtick(f32 subtick); 14 | inline void engine_set_frametime(f32 frametime); 15 | inline void engine_increment_gametime(); 16 | 17 | inline f32 engine_get_deltatime(); 18 | inline f32 engine_get_deltatime_unscaled(); 19 | inline f32 engine_get_frametime(); 20 | inline f32 engine_get_subtick(); 21 | inline f32 engine_get_timescale(); 22 | inline u64 engine_get_gametime(); 23 | 24 | #endif -------------------------------------------------------------------------------- /Engine/N64/game/levels/level_boot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../debug.h" 3 | #include "../../types.h" 4 | #include "../../osconfig.h" 5 | #include "../../scheduler.h" 6 | #include "../../graphics.h" 7 | #include "../../rcp.h" 8 | #include "../../helper.h" 9 | #include "../../engine.h" 10 | #include "levels.h" 11 | 12 | 13 | /********************************* 14 | Macros 15 | *********************************/ 16 | 17 | #define RECTSIZE 64 18 | #define RECTSPEED 200*engine_get_deltatime() 19 | 20 | // Rectangle stuff 21 | static Transform2D s_rect_transform; 22 | static Color s_rect_color; 23 | static Vector2D s_rect_speed; 24 | 25 | 26 | /*============================== 27 | level_boot_start 28 | Starts the boot level 29 | ==============================*/ 30 | 31 | void level_boot_start() 32 | { 33 | s_rect_transform = transform2d_initialize(vector2d_initialize(64, 64), 0, vector2d_initialize(RECTSIZE, RECTSIZE)); 34 | s_rect_color = color_initialize(255, 0, 0, 255); 35 | s_rect_speed = vector2d_initialize(RECTSPEED, 0); 36 | } 37 | 38 | 39 | /*============================== 40 | level_boot_update 41 | Updates the boot level by deltatime ticks 42 | ==============================*/ 43 | 44 | void level_boot_update() 45 | { 46 | Vector2D l_rectpos = transform2d_get_pos(&s_rect_transform); 47 | Vector2D l_rectsize = transform2d_get_scale(&s_rect_transform); 48 | 49 | // Move the rectangle around 50 | l_rectpos.x += s_rect_speed.x; 51 | l_rectpos.y += s_rect_speed.y; 52 | 53 | // Prevent the rectangle from going out of bounds 54 | if (l_rectpos.x > graphics_get_screenw()-l_rectsize.x || l_rectpos.x <= 0) 55 | { 56 | s_rect_speed.x = -s_rect_speed.x; 57 | l_rectpos.x = clampf(l_rectpos.x, 0, graphics_get_screenw()-l_rectsize.x); 58 | } 59 | if (l_rectpos.y > graphics_get_screenh()-l_rectsize.y || l_rectpos.y <= 0) 60 | { 61 | s_rect_speed.y = -s_rect_speed.y; 62 | l_rectpos.y = clampf(l_rectpos.y, 0, graphics_get_screenh()-l_rectsize.y); 63 | } 64 | 65 | // Apply the transformations 66 | transform2d_set_pos(&s_rect_transform, l_rectpos); 67 | } 68 | 69 | 70 | /*============================== 71 | level_boot_render 72 | Renders the boot level 73 | ==============================*/ 74 | 75 | void level_boot_render() 76 | { 77 | Vector2D l_rectpos = transform2d_get_subpos(&s_rect_transform); 78 | Vector2D l_rectscale = transform2d_get_subscale(&s_rect_transform); 79 | 80 | // Clear the framebuffer with a horrible blue 81 | rcp_clearbuffers(0, 0, 255); 82 | 83 | // Draw a rectangle 84 | gDPSetCycleType(g_displistp++, G_CYC_FILL); 85 | gDPSetFillColor(g_displistp++, 86 | GPACK_RGBA5551(s_rect_color.red, s_rect_color.green, s_rect_color.blue, 1) << 16 | 87 | GPACK_RGBA5551(s_rect_color.red, s_rect_color.green, s_rect_color.blue, 1) 88 | ); 89 | gDPFillRectangle(g_displistp++, l_rectpos.x, l_rectpos.y, l_rectpos.x + l_rectscale.x, l_rectpos.y + l_rectscale.y); 90 | gDPPipeSync(g_displistp++); 91 | 92 | // Print some debug info 93 | #if DEBUG_MODE 94 | debug_printf("Frametime %fms. Subtick %f. Xpos %f\n", engine_get_frametime()*1000.0f, engine_get_subtick(), l_rectpos.x); 95 | #endif 96 | } -------------------------------------------------------------------------------- /Engine/N64/game/levels/levels.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../../types.h" 3 | #include "levels.h" 4 | 5 | LevelDef g_levels[] = { 6 | /*LEVEL_BOOT*/ {level_boot_start, level_boot_update, NULL, 1, {{FALSE, level_boot_render}}}, 7 | }; 8 | 9 | inline LevelDef* levels_get_all() 10 | { 11 | return g_levels; 12 | } -------------------------------------------------------------------------------- /Engine/N64/game/levels/levels.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_LEVELS_H 2 | #define PLATFORM64_LEVELS_H 3 | 4 | typedef struct { 5 | bool usecpu; 6 | void (*render)(); 7 | } DrawFuncs; 8 | 9 | typedef struct { 10 | void (*start)(); 11 | void (*update)(); 12 | void (*end)(); 13 | u32 drawcount; 14 | DrawFuncs drawarray[5]; 15 | } LevelDef; 16 | 17 | extern inline LevelDef* levels_get_all(); 18 | 19 | 20 | /* =============================== */ 21 | 22 | typedef enum { 23 | LEVEL_BOOT = 0, 24 | } levelid; 25 | 26 | extern void level_boot_start(); 27 | extern void level_boot_update(); 28 | extern void level_boot_render(); 29 | 30 | #endif -------------------------------------------------------------------------------- /Engine/N64/graphics.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | graphics.c 3 | 4 | Handles graphics rendering 5 | ***************************************************************/ 6 | 7 | #include 8 | #include "debug.h" 9 | #include "osconfig.h" 10 | #include "types.h" 11 | #include "helper.h" 12 | #include "scheduler.h" 13 | #include "graphics.h" 14 | #include "rcp.h" 15 | 16 | 17 | /********************************* 18 | Definitions 19 | *********************************/ 20 | 21 | // Enable this to see how the graphics thread is behaving with prints 22 | #define VERBOSE FALSE 23 | 24 | // Size of message buffer for thread communication 25 | #define MSGBUFF_SIZE (FRAMEBUFF_MAXCOUNT+1) 26 | 27 | 28 | /********************************* 29 | Structs 30 | *********************************/ 31 | 32 | // A struct which describes the render task from the main thread 33 | typedef struct 34 | { 35 | void (*func)(); 36 | bool usecpu; 37 | bool swapbuffer; 38 | } RenderMessage; 39 | 40 | 41 | /********************************* 42 | Function Prototypes 43 | *********************************/ 44 | 45 | static void threadfunc_graphics(void *arg); 46 | static void graphics_renderscene(FrameBuffer* fb, void (*func)()); 47 | 48 | 49 | /********************************* 50 | Globals 51 | *********************************/ 52 | 53 | // Framebuffers 54 | static FrameBuffer s_framebuffers_sd[FRAMEBUFF_MAXCOUNT] = {{NULL}, {NULL}, {NULL}}; 55 | static FrameBuffer s_framebuffers_hd[FRAMEBUFF_MAXCOUNT] = {{NULL}, {NULL}, {NULL}}; 56 | static FrameBuffer* s_lastrendered; 57 | static u8 s_framebuffcount_sd; 58 | static u8 s_framebuffcount_hd; 59 | static u32* s_zbuffer_sd; 60 | static u32* s_zbuffer_hd; 61 | static bool s_ishd; 62 | 63 | // Active framebuffer trackers 64 | static FrameBuffer* s_framebuffers_active; 65 | static u8 s_framebuffers_activecount; 66 | 67 | // Thread 68 | static OSThread s_threadstruct_graphics; 69 | 70 | // Message queues for thread communication 71 | static OSMesgQueue s_msgqueue_graphics; 72 | static OSMesg s_msgbuffer_graphics[FRAMEBUFF_MAXCOUNT]; 73 | static OSMesgQueue s_msgqueue_rdp; 74 | static OSMesg s_msgbuffer_rdp; 75 | static OSMesgQueue s_msgqueue_vsync; 76 | static OSMesg s_msgbuffer_vsync; 77 | 78 | // Other thread communication stuff 79 | static RenderMessage s_messages[MSGBUFF_SIZE]; 80 | static u8 s_message_index; 81 | 82 | // The scheduler 83 | static Scheduler* s_scheduler; 84 | 85 | // RCP hang detection timer 86 | #if DEBUG_MODE 87 | OSTimer s_rcptime; 88 | #endif 89 | 90 | 91 | /*============================== 92 | graphics_initialize 93 | Launches the graphics thread 94 | ==============================*/ 95 | 96 | void graphics_initialize(Scheduler* scheduler) 97 | { 98 | int i; 99 | 100 | // Initialize globals 101 | s_ishd = FALSE; 102 | s_lastrendered = NULL; 103 | s_scheduler = scheduler; 104 | s_framebuffcount_sd = 0; 105 | s_framebuffcount_hd = 0; 106 | s_framebuffers_active = s_framebuffers_sd; 107 | s_framebuffers_activecount = s_framebuffcount_sd; 108 | s_zbuffer_sd = NULL; 109 | s_zbuffer_hd = NULL; 110 | 111 | // Initialize framebuffers to their default state 112 | for (i=0; istatus == FBSTATUS_FREE || (l_fb->status == FBSTATUS_READY && l_fb != s_lastrendered)) 164 | { 165 | l_freebuff = l_fb; 166 | break; 167 | } 168 | } 169 | 170 | // If none was found, drop this render request 171 | if (l_freebuff == NULL) 172 | { 173 | #if VERBOSE 174 | debug_printf("Graphics Thread: No available buffer, dropping request.\n"); 175 | #endif 176 | continue; 177 | } 178 | } 179 | 180 | // Generate the display list for the scene 181 | if (!l_msgp->usecpu) 182 | { 183 | #if VERBOSE 184 | debug_printf("Graphics Thread: Found buffer '%d' at %p.\n", i, l_freebuff->address); 185 | #endif 186 | graphics_renderscene(l_freebuff, l_msgp->func); 187 | l_freebuff->status = FBSTATUS_RENDERING; 188 | 189 | // Wait for the render task to finish 190 | (void)osRecvMesg(&s_msgqueue_rdp, NULL, OS_MESG_BLOCK); 191 | #if VERBOSE 192 | debug_printf("Graphics Thread: Render task finished.\n"); 193 | #endif 194 | s_scheduler->task_gfx = NULL; 195 | 196 | // If we got here, the RCP did not hang, hooray! 197 | #if DEBUG_MODE 198 | osStopTimer(&s_rcptime); 199 | #endif 200 | } 201 | else 202 | { 203 | if (l_msgp->func != NULL) 204 | l_msgp->func(); 205 | } 206 | 207 | // If we're not meant to swap the framebuffer yet, then stop here 208 | // The next loop should reuse this framebuffer if needed 209 | if (!l_msgp->swapbuffer) 210 | { 211 | #if VERBOSE 212 | debug_printf("Graphics Thread: Don't swap buffer yet.\n"); 213 | #endif 214 | continue; 215 | } 216 | l_freebuff->status = FBSTATUS_READY; 217 | #if VERBOSE 218 | debug_printf("Graphics Thread: Framebuffer %d ready.\n", i); 219 | #endif 220 | 221 | // Mark the buffer as the last rendered 222 | s_lastrendered = l_freebuff; 223 | l_freebuff = NULL; 224 | } 225 | } 226 | 227 | 228 | /*============================== 229 | graphics_renderscene 230 | Creates a display list and render task for the RCP 231 | @param The framebuffer to use 232 | @param The render function 233 | ==============================*/ 234 | 235 | static void graphics_renderscene(FrameBuffer* fb, void (*func)()) 236 | { 237 | RenderTask l_task; 238 | 239 | // Initialize the render task 240 | l_task.displistp = fb->displist; 241 | l_task.framebuffer = fb->address; 242 | l_task.func = func; 243 | if (s_ishd) 244 | l_task.zbuffer = s_zbuffer_hd; 245 | else 246 | l_task.zbuffer = s_zbuffer_sd; 247 | #if (FRAMEBUFF_DEPTH == u16) 248 | l_task.bufferdepth = G_IM_SIZ_16b; 249 | #else 250 | l_task.bufferdepth = G_IM_SIZ_32b; 251 | #endif 252 | l_task.ishd = s_ishd; 253 | 254 | // Build the display list 255 | rcp_initialize(&l_task); 256 | if (func != NULL) 257 | l_task.func(); 258 | rcp_finish(&l_task); 259 | 260 | // If the framebuffer is still in use by the VI (the switch takes time), then wait for it to become available 261 | while (osViGetCurrentFramebuffer() == fb->address) 262 | { 263 | #if VERBOSE 264 | debug_printf("Graphics Thread: Framebuffer in use by VI. Waiting for VSync.\n"); 265 | #endif 266 | s_scheduler->gfx_notify = &s_msgqueue_vsync; 267 | osRecvMesg(&s_msgqueue_vsync, NULL, OS_MESG_BLOCK); 268 | } 269 | 270 | // Let the scheduler know the RCP is going to be busy 271 | s_scheduler->task_gfx = l_task.task; 272 | 273 | // Start a timer to see how long it took to render. If it took too long, the RCP is hung 274 | #if DEBUG_MODE 275 | osSetTimer(&s_rcptime, OS_USEC_TO_CYCLES(SEC_TO_USEC(RCP_HUNGIME)), 0, &s_scheduler->queue, (OSMesg)MSG_SCHEDULER_RCPHANG); 276 | #endif 277 | 278 | // Send the render task to the RCP 279 | #if VERBOSE 280 | debug_printf("Graphics Thread: Sending render task.\n"); 281 | #endif 282 | osSpTaskStart(l_task.task); 283 | } 284 | 285 | 286 | /*============================== 287 | graphics_requestrender 288 | Requests a scene render from the main thread 289 | @param The render function 290 | @param Whether to draw with the CPU 291 | @param Whether to swap the buffer at the end of this task 292 | ==============================*/ 293 | 294 | void graphics_requestrender(void (*func)(), bool usecpu, bool swapbuffer) 295 | { 296 | RenderMessage* l_msgp = &s_messages[s_message_index]; 297 | l_msgp->func = func; 298 | l_msgp->usecpu = usecpu; 299 | l_msgp->swapbuffer = swapbuffer; 300 | s_message_index = (s_message_index + 1)%MSGBUFF_SIZE; 301 | osSendMesg(&s_msgqueue_graphics, (OSMesg)l_msgp, OS_MESG_BLOCK); 302 | } 303 | 304 | 305 | /*============================== 306 | graphics_framebufferready 307 | Checks if a framebuffer is ready to be consumed 308 | by the VI 309 | @returns Whether a framebuffer is available 310 | ==============================*/ 311 | 312 | bool graphics_framebufferready() 313 | { 314 | return s_lastrendered != NULL; 315 | } 316 | 317 | 318 | /*============================== 319 | graphics_popframebuffer 320 | Pops the last rendered framebuffer from the queue 321 | of rendered buffers 322 | @returns The popped framebuffer 323 | ==============================*/ 324 | 325 | FrameBuffer* graphics_popframebuffer() 326 | { 327 | int i; 328 | FrameBuffer* l_consumed = s_lastrendered; 329 | 330 | // Mark the consumed framebuffer as displaying, and remove the last rendered buffer 331 | l_consumed->status = FBSTATUS_DISPLAYING; 332 | s_lastrendered = NULL; 333 | 334 | // See if we have another framebuffer marked as ready 335 | for (i=0; itvblack = TRUE; 573 | 574 | // Re-Initialize the framebuffers 575 | for (i=0; i 8 | #include "debug.h" 9 | #include "types.h" 10 | #include "helper.h" 11 | 12 | 13 | /*============================== 14 | clampf 15 | Clamps a value between two others 16 | @param The value to clamp 17 | @param The minimum value 18 | @param The maximum value 19 | @return The clamped value 20 | ==============================*/ 21 | 22 | f32 clampf(f32 val, f32 min, f32 max) 23 | { 24 | return MIN(MAX(val, min), max); 25 | } 26 | 27 | 28 | /*============================== 29 | lerpf 30 | Returns the linear interpolation of 31 | two values given a fraction 32 | @param The from value 33 | @param The target value 34 | @param The fraction 35 | @return The interpolated result 36 | ==============================*/ 37 | 38 | f32 lerpf(f32 from, f32 target, f32 fraction) 39 | { 40 | return from + (fraction*(target - from)); 41 | } 42 | 43 | 44 | /*============================== 45 | roundf 46 | Rounds a floating point number 47 | @param The value to round 48 | @return The rounded result 49 | ==============================*/ 50 | 51 | s32 roundf(f32 val) 52 | { 53 | if (val < 0.0f) 54 | return (s32)(val - 0.5f); 55 | else 56 | return (s32)(val + 0.5f); 57 | } -------------------------------------------------------------------------------- /Engine/N64/helper.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_HELPER_H 2 | #define PLATFORM64_HELPER_H 3 | 4 | 5 | /********************************* 6 | Function Macros 7 | *********************************/ 8 | 9 | // Time conversion 10 | #define SEC_TO_USEC(a) (((f64)a)*1000000.0f) 11 | #define MSEC_TO_USEC(a) (((f64)a)*1000.0f) 12 | #define USEC_TO_MSEC(a) (((f64)a)/1000.0f) 13 | #define USEC_TO_SEC(a) (((f64)a)/1000000.0f) 14 | 15 | 16 | /********************************* 17 | Function Prototypes 18 | *********************************/ 19 | 20 | f32 clampf(f32 val, f32 min, f32 max); 21 | f32 lerpf(f32 from, f32 target, f32 fraction); 22 | s32 roundf(f32 val); 23 | 24 | #endif -------------------------------------------------------------------------------- /Engine/N64/main.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | main.c 3 | 4 | Handles the boot process of the ROM. 5 | ***************************************************************/ 6 | 7 | #include 8 | #include 9 | #include "debug.h" 10 | #include "types.h" 11 | #include "osconfig.h" 12 | #include "controller.h" 13 | #include "scheduler.h" 14 | #include "graphics.h" 15 | #include "audio.h" 16 | #include "engine.h" 17 | #include "helper.h" 18 | 19 | 20 | /********************************* 21 | Function Prototypes 22 | *********************************/ 23 | 24 | static void threadfunc_idle(void *arg); 25 | static void threadfunc_main(void *arg); 26 | #if DEBUG_MODE 27 | static void toggle_lag(); 28 | #endif 29 | 30 | // Unexposed engine.c functions 31 | inline void engine_set_subtick(f32 subtick); 32 | inline void engine_set_frametime(f32 frametime); 33 | inline void engine_increment_gametime(); 34 | 35 | 36 | /********************************* 37 | Globals 38 | *********************************/ 39 | 40 | // Threads 41 | static OSThread s_threadstruct_idle; 42 | static OSThread s_threadstruct_main; 43 | 44 | // PI Messages 45 | static OSMesg s_pi_messages[NUM_PI_MSGS]; 46 | static OSMesgQueue s_pi_queue; 47 | 48 | // Lag switch for demonstrations 49 | static bool s_shouldlag = FALSE; 50 | 51 | 52 | /*============================== 53 | boot 54 | Initializes the hardware and 55 | prints Hello World 56 | ==============================*/ 57 | 58 | void boot() 59 | { 60 | // Initialize the hardware and software 61 | osInitialize(); 62 | 63 | // Start the idle thread 64 | osCreateThread(&s_threadstruct_idle, THREADID_IDLE, threadfunc_idle, NULL, STACKREALSTART_IDLE, THREADPRI_IDLE); 65 | osStartThread(&s_threadstruct_idle); 66 | } 67 | 68 | 69 | /*============================== 70 | threadfunc_idle 71 | The idle thread 72 | @param Argument passed to the thread 73 | ==============================*/ 74 | 75 | static void threadfunc_idle(void *arg) 76 | { 77 | // Create the PI manager 78 | osCreatePiManager((OSPri)OS_PRIORITY_PIMGR, &s_pi_queue, s_pi_messages, NUM_PI_MSGS); 79 | 80 | // Initialize debug mode 81 | debug_initialize(); 82 | debug_64drivebutton(toggle_lag, TRUE); 83 | 84 | // Start the main thread 85 | osCreateThread(&s_threadstruct_main, THREADID_MAIN, threadfunc_main, NULL, STACKREALSTART_MAIN, THREADPRI_MAIN); 86 | osStartThread(&s_threadstruct_main); 87 | 88 | // Reduce this thread's priority to the minimum possible, and spin forever 89 | osSetThreadPri(0, 0); 90 | while (1) 91 | { 92 | //debug_printf("Idle Thread: Spinning\n"); 93 | } 94 | } 95 | 96 | 97 | /*============================== 98 | threadfunc_main 99 | The main thread loop 100 | @param Argument passed to the thread 101 | ==============================*/ 102 | 103 | static void threadfunc_main(void *arg) 104 | { 105 | int i; 106 | Vector2D l_oldstick[MAXCONTROLLERS]; 107 | Scheduler* l_scheduler; 108 | debug_printf("Main Thread: Started\n"); 109 | 110 | // Initialize the rest of the game 111 | l_scheduler = scheduler_initialize(); 112 | graphics_initialize(l_scheduler); 113 | audio_initialize(); 114 | controller_initialize(); 115 | controller_rumble_init(); 116 | memset(l_oldstick, 0, sizeof(Vector2D)*MAXCONTROLLERS); 117 | 118 | // Register framebuffers we are going to use 119 | graphics_register_fbuffer(FALSE, FRAMEBUFF_ADDR1_SD); 120 | graphics_register_fbuffer(FALSE, FRAMEBUFF_ADDR2_SD); 121 | if (osGetMemSize() == 0x00800000) // Only register HD addresses if a memory pak is present 122 | { 123 | graphics_register_fbuffer(TRUE, FRAMEBUFF_ADDR1_HD); 124 | graphics_register_fbuffer(TRUE, FRAMEBUFF_ADDR2_HD); 125 | } 126 | 127 | // Register controller actions 128 | controller_register_action(PLAYER_1, ACTION_JUMP, A_BUTTON); 129 | controller_register_action(PLAYER_2, ACTION_JUMP, A_BUTTON); 130 | 131 | // And now, perform the game main 132 | while (1) 133 | { 134 | OSTime l_oldtime = 0; 135 | OSTime l_accumulator = 0; 136 | const OSTime l_dt = OS_USEC_TO_CYCLES(SEC_TO_USEC(DELTATIME)); 137 | 138 | // Initialize the level 139 | engine_level_start(); 140 | 141 | // Handle the engine loop 142 | while (!engine_level_shouldchange()) 143 | { 144 | OSTime l_curtime = osGetTime(); 145 | OSTime l_frametime = l_curtime - l_oldtime; 146 | engine_set_frametime(USEC_TO_SEC(OS_CYCLES_TO_USEC(l_frametime))); 147 | 148 | // In order to prevent problems if the game slows down significantly, we will clamp the maximum timestep the simulation can take 149 | if (l_frametime > OS_USEC_TO_CYCLES(SEC_TO_USEC(0.25f))) 150 | l_frametime = OS_USEC_TO_CYCLES(SEC_TO_USEC(0.25f)); 151 | l_oldtime = l_curtime; 152 | 153 | // Perform the update in discrete steps (ticks) 154 | l_accumulator += l_frametime; 155 | while (l_accumulator >= l_dt) 156 | { 157 | engine_level_update(); 158 | l_accumulator -= l_dt; 159 | } 160 | 161 | // Read control stick data 162 | controller_query_all(); 163 | controller_read_all(); 164 | 165 | // Render the engine 166 | engine_set_subtick(((f64)l_accumulator)/((f64)l_dt)); 167 | engine_level_render(); 168 | 169 | // Check if the flashcart has incoming debug data 170 | debug_pollcommands(); 171 | 172 | // If enabled, crunch some numbers for a while to create "lag" 173 | if (s_shouldlag) 174 | { 175 | for (i=0; i<700000; i++) 176 | ; 177 | } 178 | 179 | // Advance the game time 180 | engine_increment_gametime(); 181 | } 182 | 183 | // End the current level 184 | engine_level_end(); 185 | } 186 | } 187 | 188 | 189 | #if DEBUG_MODE 190 | /*============================== 191 | toggle_lag 192 | Toggles lag when called 193 | ==============================*/ 194 | 195 | static void toggle_lag() 196 | { 197 | s_shouldlag = !s_shouldlag; 198 | } 199 | #endif -------------------------------------------------------------------------------- /Engine/N64/osconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_OSCONFIG_H 2 | #define PLATFORM64_OSCONFIG_H 3 | 4 | /********************************* 5 | TV Config 6 | *********************************/ 7 | 8 | // TV mode ID's 9 | #define TV_NTSC 0 10 | #define TV_PAL 1 11 | #define TV_MPAL 2 12 | 13 | // The selected TV mode 14 | #define TVMODE TV_PAL 15 | 16 | // Target framerate and tickrate 17 | #if TVMODE == TV_PAL 18 | #define TARGET_FRAMERATE 50 19 | #else 20 | #define TARGET_FRAMERATE 60 21 | #endif 22 | #define TICKRATE 50 23 | #define DELTATIME (1.0f/(f64)TICKRATE) 24 | 25 | 26 | /********************************* 27 | Segments 28 | *********************************/ 29 | 30 | // Code segments 31 | #define SEGMENTSTART_CODE 0x80000400 32 | #define SEGMENTSIZE_CODE 0x00100000 33 | 34 | // RAM Bank Addresses 35 | #define RAMBANK_START 0x80000000 36 | #define RAMBANK_SIZE 0x00100000 37 | #define RAMBANK_1 (RAMBANK_START + RAMBANK_SIZE*0) 38 | #define RAMBANK_2 (RAMBANK_START + RAMBANK_SIZE*1) 39 | #define RAMBANK_3 (RAMBANK_START + RAMBANK_SIZE*2) 40 | #define RAMBANK_4 (RAMBANK_START + RAMBANK_SIZE*3) 41 | #define RAMBANK_5 (RAMBANK_START + RAMBANK_SIZE*4) 42 | #define RAMBANK_6 (RAMBANK_START + RAMBANK_SIZE*5) 43 | #define RAMBANK_7 (RAMBANK_START + RAMBANK_SIZE*6) 44 | #define RAMBANK_8 (RAMBANK_START + RAMBANK_SIZE*7) 45 | 46 | 47 | /********************************* 48 | Stacks 49 | *********************************/ 50 | 51 | // Boot stack 52 | #define STACKSTART_BOOT RAMBANK_2 53 | #define STACKSIZE_BOOT 0x2000 54 | 55 | // Idle thread stack 56 | #define STACKSTART_IDLE (STACKSTART_BOOT + STACKSIZE_BOOT) 57 | #define STACKSIZE_IDLE 0x2000 58 | 59 | // Main thread stack 60 | #define STACKSTART_MAIN (STACKSTART_IDLE + STACKSIZE_IDLE) 61 | #define STACKSIZE_MAIN 0x2000 62 | 63 | // Controller thread stack 64 | #define STACKSTART_CONTROLLER (STACKSTART_MAIN + STACKSIZE_MAIN) 65 | #define STACKSIZE_CONTROLLER 0x2000 66 | 67 | // Scheduler thread stack 68 | #define STACKSTART_SCHEDULER (STACKSTART_CONTROLLER + STACKSIZE_CONTROLLER) 69 | #define STACKSIZE_SCHEDULER 0x2000 70 | 71 | // Graphics thread stack 72 | #define STACKSTART_GRAPHICS (STACKSTART_SCHEDULER + STACKSIZE_SCHEDULER) 73 | #define STACKSIZE_GRAPHICS 0x4000 74 | 75 | // Audio thread stack 76 | #define STACKSTART_AUDIO (STACKSTART_GRAPHICS + STACKSIZE_GRAPHICS) 77 | #define STACKSIZE_AUDIO 0x2000 78 | 79 | // RCP DRAM stack 80 | #define STACKSTART_DRAM (STACKSTART_AUDIO + STACKSIZE_AUDIO) 81 | #define STACKSIZE_DRAM SP_DRAM_STACK_SIZE8 82 | 83 | // RDP FIFO buffer 84 | #define STACKSTART_RDPFIFO (STACKSTART_DRAM + STACKSIZE_DRAM) 85 | #define STACKSIZE_RDPFIFO 0x1000 86 | #define STACKEND_RDPFIFO (u64*)(STACKSTART_RDPFIFO + STACKSIZE_RDPFIFO) 87 | 88 | // Real stack starts (because the stacks grow backwards with the MIPS compiler tools) 89 | #define STACKREALSTART_BOOT (u64*)(STACKSTART_BOOT + STACKSIZE_BOOT/sizeof(u64)) 90 | #define STACKREALSTART_IDLE (u64*)(STACKSTART_IDLE + STACKSIZE_IDLE/sizeof(u64)) 91 | #define STACKREALSTART_MAIN (u64*)(STACKSTART_MAIN + STACKSIZE_MAIN/sizeof(u64)) 92 | #define STACKREALSTART_CONTROLLER (u64*)(STACKSTART_CONTROLLER + STACKSIZE_CONTROLLER/sizeof(u64)) 93 | #define STACKREALSTART_SCHEDULER (u64*)(STACKSTART_SCHEDULER + STACKSIZE_SCHEDULER/sizeof(u64)) 94 | #define STACKREALSTART_GRAPHICS (u64*)(STACKSTART_GRAPHICS + STACKSIZE_GRAPHICS/sizeof(u64)) 95 | #define STACKREALSTART_AUDIO (u64*)(STACKSTART_AUDIO + STACKSIZE_AUDIO/sizeof(u64)) 96 | #define STACKREALSTART_DRAM (u64*)STACKSTART_DRAM 97 | #define STACKREALSTART_RDPFIFO (u64*)STACKSTART_RDPFIFO 98 | 99 | 100 | /********************************* 101 | Framebuffers 102 | *********************************/ 103 | 104 | // The framebuffer size, based on the TV mode 105 | #if (TVMODE == TV_NTSC) 106 | #define SCREEN_WIDTH_SD 320 107 | #define SCREEN_HEIGHT_SD 240 108 | 109 | #define SCREEN_WIDTH_HD 640 110 | #define SCREEN_HEIGHT_HD 480 111 | #else 112 | #define SCREEN_WIDTH_SD 320 113 | #define SCREEN_HEIGHT_SD 288 114 | 115 | #define SCREEN_WIDTH_HD 640 116 | #define SCREEN_HEIGHT_HD 576 117 | #endif 118 | 119 | // Framebuffer depth and count 120 | #define FRAMEBUFF_DEPTH u16 121 | #define FRAMEBUFF_MAXCOUNT 3 122 | 123 | // Framebuffer size 124 | #define FRAMEBUFF_SIZE_SD (SCREEN_WIDTH_SD*SCREEN_WIDTH_SD*sizeof(FRAMEBUFF_DEPTH)) 125 | #define FRAMEBUFF_SIZE_HD (SCREEN_WIDTH_HD*SCREEN_WIDTH_HD*sizeof(FRAMEBUFF_DEPTH)) 126 | 127 | // Frambuffer addresses (Low res) 128 | #define FRAMEBUFF_ADDR1_SD ((FRAMEBUFF_DEPTH*)(RAMBANK_2 + RAMBANK_SIZE - (SCREEN_WIDTH_SD*SCREEN_HEIGHT_SD*sizeof(FRAMEBUFF_DEPTH)))) 129 | #define FRAMEBUFF_ADDR2_SD ((FRAMEBUFF_DEPTH*)(RAMBANK_3 + RAMBANK_SIZE - (SCREEN_WIDTH_SD*SCREEN_HEIGHT_SD*sizeof(FRAMEBUFF_DEPTH)))) 130 | #define FRAMEBUFF_ADDRZ_SD ((FRAMEBUFF_DEPTH*)(RAMBANK_4 + RAMBANK_SIZE - (SCREEN_WIDTH_SD*SCREEN_HEIGHT_SD*sizeof(FRAMEBUFF_DEPTH)))) 131 | 132 | // Frambuffer addresses (High res) 133 | #define FRAMEBUFF_ADDR1_HD ((FRAMEBUFF_DEPTH*)(RAMBANK_6 + RAMBANK_SIZE - (SCREEN_WIDTH_HD*SCREEN_HEIGHT_HD*sizeof(FRAMEBUFF_DEPTH)))) 134 | #define FRAMEBUFF_ADDR2_HD ((FRAMEBUFF_DEPTH*)(RAMBANK_7 + RAMBANK_SIZE - (SCREEN_WIDTH_HD*SCREEN_HEIGHT_HD*sizeof(FRAMEBUFF_DEPTH)))) 135 | #define FRAMEBUFF_ADDRZ_HD ((FRAMEBUFF_DEPTH*)(RAMBANK_8 + RAMBANK_SIZE - (SCREEN_WIDTH_HD*SCREEN_HEIGHT_HD*sizeof(FRAMEBUFF_DEPTH)))) 136 | 137 | 138 | /********************************* 139 | Threads 140 | *********************************/ 141 | 142 | // Thread ID's 143 | #define THREADID_IDLE 1 144 | #define THREADID_MAIN 2 145 | #define THREADID_CONTROLLER 3 146 | #define THREADID_SCHEDULER 4 147 | #define THREADID_GRAPHICS 5 148 | #define THREADID_AUDIO 6 149 | #define THREADID_FAULT 13 // From debug.h, included here for completion sake 150 | #define THREADID_USB 14 // From debug.h, included here for completion sake 151 | 152 | // Thread Priorities 153 | #define THREADPRI_IDLE 1 154 | #define THREADPRI_MAIN 10 155 | #define THREADPRI_CONTROLLER 15 156 | #define THREADPRI_SCHEDULER 100 157 | #define THREADPRI_GRAPHICS 20 158 | #define THREADPRI_AUDIO 25 159 | #define THREADPRI_FAULT 125 // From debug.h, included here for completion sake 160 | #define THREADPRI_USB 126 // From debug.h, included here for completion sake 161 | 162 | 163 | /********************************* 164 | Heap 165 | *********************************/ 166 | 167 | #define HEAP_START (FRAMEBUFF_ADDRZ_SD - 1) 168 | #define HEAP_SIZE 0x080000 // Half a megabyte of heap memory 169 | 170 | 171 | /********************************* 172 | PI 173 | *********************************/ 174 | 175 | #define NUM_PI_MSGS 32 176 | 177 | 178 | /********************************* 179 | Preprocessor assertions 180 | *********************************/ 181 | 182 | // Ensure a valid TV mode was chosen 183 | #if (TVMODE != TV_NTSC && TVMODE != TV_PAL && TVMODE != TV_MPAL) 184 | #error Invalid TV mode chosen 185 | #endif 186 | 187 | // Ensure the stacks are properly aligned in memory 188 | #if (STACKSTART_BOOT%8 != 0) 189 | #error The boot stack must be 64-bit aligned 190 | #endif 191 | #if (STACKSTART_IDLE%8 != 0) 192 | #error The idle thread stack must be 64-bit aligned 193 | #endif 194 | #if (STACKSTART_MAIN%8 != 0) 195 | #error The main thread stack must be 64-bit aligned 196 | #endif 197 | #if (STACKSTART_CONTROLLER%8 != 0) 198 | #error The controller thread stack must be 64-bit aligned 199 | #endif 200 | #if (STACKSTART_SCHEDULER%8 != 0) 201 | #error The scheduler thread stack must be 64-bit aligned 202 | #endif 203 | #if (STACKSTART_GRAPHICS%8 != 0) 204 | #error The graphics thread stack must be 64-bit aligned 205 | #endif 206 | #if (STACKSTART_AUDIO%8 != 0) 207 | #error The audio thread stack must be 64-bit aligned 208 | #endif 209 | #if (STACKSTART_DRAM%16 != 0) 210 | #error The DRAM stack must be 16-byte aligned 211 | #endif 212 | #if (STACKSTART_RDPFIFO%16 != 0) 213 | #error The RDP FIFO buffer must be 16-byte aligned 214 | #endif 215 | 216 | // Ensure the stack sizes are valid 217 | #if (STACKSIZE_BOOT < OS_MIN_STACKSIZE) 218 | #error The boot stack size must be larger than OS_MIN_STACKSIZE 219 | #endif 220 | #if (STACKSIZE_IDLE < OS_MIN_STACKSIZE) 221 | #error The idle thread stack size must be larger than OS_MIN_STACKSIZE 222 | #endif 223 | #if (STACKSIZE_MAIN < OS_MIN_STACKSIZE) 224 | #error The main thread stack size must be larger than OS_MIN_STACKSIZE 225 | #endif 226 | #if (STACKSIZE_CONTROLLER < OS_MIN_STACKSIZE) 227 | #error The controller thread stack size must be larger than OS_MIN_STACKSIZE 228 | #endif 229 | #if (STACKSIZE_SCHEDULER < OS_MIN_STACKSIZE) 230 | #error The scheduler thread stack size must be larger than OS_MIN_STACKSIZE 231 | #endif 232 | #if (STACKSIZE_GRAPHICS < OS_MIN_STACKSIZE) 233 | #error The graphics thread stack size must be larger than OS_MIN_STACKSIZE 234 | #endif 235 | #if (STACKSIZE_AUDIO < OS_MIN_STACKSIZE) 236 | #error The audio thread stack size must be larger than OS_MIN_STACKSIZE 237 | #endif 238 | #if (STACKSIZE_DRAM < SP_DRAM_STACK_SIZE8) 239 | #error The dram stack size must be larger than SP_DRAM_STACK_SIZE8 240 | #endif 241 | #if (STACKSIZE_RDPFIFO < 0x100) 242 | #error The RDP FIFO buffer size must be larger than 256 bytes 243 | #endif 244 | 245 | #endif -------------------------------------------------------------------------------- /Engine/N64/platform.nbp: -------------------------------------------------------------------------------- 1 | [N64Project] 2 | TargetName=platform.n64 3 | BuildFolder=build 4 | ROMHeader_Name=PLATFORM64 5 | ROMHeader_Manufacturer=B 6 | ROMHeader_ID=PF 7 | ROMHeader_Country=I 8 | Flags_GCC=-Wall -I. -IC:/ultra/usr/include/PR -IC:/ultra/usr/include -G 0 -DF3DEX_GBI_2 -DNOT_SPEC -D_MIPS_SZLONG=32 -D_MIPS_SZINT=32 9 | Flags_LD=-L. -LC:/ultra/usr/lib -LC:/ultra/usr/lib/PR -LC:/ultra/gcc/mipse/lib -lkmc 10 | Flags_MILD= 11 | -------------------------------------------------------------------------------- /Engine/N64/rcp.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | rcp.c 3 | 4 | Contains a bunch of display lists to help us initialize the 5 | RCP 6 | ***************************************************************/ 7 | 8 | #include 9 | #include "debug.h" 10 | #include "osconfig.h" 11 | #include "types.h" 12 | #include "scheduler.h" 13 | #include "graphics.h" 14 | 15 | 16 | /********************************* 17 | Globals 18 | *********************************/ 19 | 20 | // Display lists 21 | Gfx g_displists[FRAMEBUFF_MAXCOUNT][DISPLIST_SIZE]; 22 | Gfx* g_displistp; 23 | 24 | // RCP task 25 | static RenderTask* s_curtask = NULL; 26 | static OSTask s_rcptask_render = 27 | {{ 28 | M_GFXTASK, // Task type 29 | 0, // Task flags 30 | NULL, // RCP boot microcode pointer (fill in later) 31 | 0, // RCP boot microcode size (fill in later) 32 | NULL, // Task microcode pointer (fill in later) 33 | SP_UCODE_SIZE, // Task microcode size 34 | NULL, // Task microcode data pointer (fill in later) 35 | SP_UCODE_DATA_SIZE, // Task microcode data size 36 | STACKREALSTART_DRAM, // Task DRAM stack pointer 37 | STACKSIZE_DRAM, // Task DRAM stack size 38 | STACKREALSTART_RDPFIFO, // Task FIFO buffer start pointer 39 | STACKEND_RDPFIFO, // Task FIFO buffer end pointer 40 | NULL, // Task data pointer (fill in later) 41 | 0, // Task data size (fill in later) 42 | NULL, // Task yield buffer pointer (unused) 43 | 0 // Task yield buffer size (unused) 44 | }}; 45 | 46 | 47 | /********************************* 48 | Viewports 49 | *********************************/ 50 | 51 | static const Vp s_viewport_sd = {{ 52 | {SCREEN_WIDTH_SD*2, SCREEN_HEIGHT_SD*2, G_MAXZ/2, 0}, // Scale 53 | {SCREEN_WIDTH_SD*2, SCREEN_HEIGHT_SD*2, G_MAXZ/2, 0}, // Translation 54 | }}; 55 | 56 | static const Vp s_viewport_hd = {{ 57 | {SCREEN_WIDTH_HD*2, SCREEN_HEIGHT_HD*2, G_MAXZ/2, 0}, // Scale 58 | {SCREEN_WIDTH_HD*2, SCREEN_HEIGHT_HD*2, G_MAXZ/2, 0}, // Translation 59 | }}; 60 | 61 | 62 | /********************************* 63 | RSP 64 | *********************************/ 65 | 66 | static const Gfx s_dl_rspinit_sd[] = { 67 | gsSPViewport(&s_viewport_sd), 68 | gsSPClearGeometryMode(G_SHADE | G_SHADING_SMOOTH | G_CULL_BOTH | 69 | G_FOG | G_LIGHTING | G_TEXTURE_GEN | 70 | G_TEXTURE_GEN_LINEAR | G_LOD), 71 | gsSPTexture(0, 0, 0, 0, G_OFF), 72 | gsSPEndDisplayList(), 73 | }; 74 | 75 | static const Gfx s_dl_rspinit_hd[] = { 76 | gsSPViewport(&s_viewport_hd), 77 | gsSPClearGeometryMode(G_SHADE | G_SHADING_SMOOTH | G_CULL_BOTH | 78 | G_FOG | G_LIGHTING | G_TEXTURE_GEN | 79 | G_TEXTURE_GEN_LINEAR | G_LOD), 80 | gsSPTexture(0, 0, 0, 0, G_OFF), 81 | gsSPEndDisplayList(), 82 | }; 83 | 84 | 85 | /********************************* 86 | RDP 87 | *********************************/ 88 | 89 | static const Gfx s_dl_rdpinit_sd[] = { 90 | gsDPSetCycleType(G_CYC_1CYCLE), 91 | gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH_SD, SCREEN_HEIGHT_SD), 92 | gsDPSetCombineKey(G_CK_NONE), 93 | gsDPSetAlphaCompare(G_AC_NONE), 94 | gsDPSetRenderMode(G_RM_NOOP, G_RM_NOOP2), 95 | gsDPSetColorDither(G_CD_DISABLE), 96 | gsDPPipeSync(), 97 | gsSPEndDisplayList(), 98 | }; 99 | 100 | static const Gfx s_dl_rdpinit_hd[] = { 101 | gsDPSetCycleType(G_CYC_1CYCLE), 102 | gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH_HD, SCREEN_HEIGHT_HD), 103 | gsDPSetCombineKey(G_CK_NONE), 104 | gsDPSetAlphaCompare(G_AC_NONE), 105 | gsDPSetRenderMode(G_RM_NOOP, G_RM_NOOP2), 106 | gsDPSetColorDither(G_CD_DISABLE), 107 | gsDPPipeSync(), 108 | gsSPEndDisplayList(), 109 | }; 110 | 111 | 112 | /*============================== 113 | rcp_initialize 114 | Initializes the RCP for drawing 115 | @param A pointer to the render task struct to use 116 | ==============================*/ 117 | 118 | void rcp_initialize(RenderTask* task) 119 | { 120 | g_displistp = task->displistp; 121 | 122 | // Set the segment register to the first segment 123 | // The addresses passed to the RCP must be in segment addresses 124 | // The CPU uses virtual addresses, this will convert accordingly 125 | gSPSegment(g_displistp++, 0, 0x0); 126 | 127 | // Set the framebuffer that the RDP will draw onto 128 | if (task->ishd) 129 | { 130 | gDPSetColorImage(g_displistp++, G_IM_FMT_RGBA, task->bufferdepth, SCREEN_WIDTH_HD, OS_K0_TO_PHYSICAL(task->framebuffer)); 131 | } 132 | else 133 | { 134 | gDPSetColorImage(g_displistp++, G_IM_FMT_RGBA, task->bufferdepth, SCREEN_WIDTH_SD, OS_K0_TO_PHYSICAL(task->framebuffer)); 135 | } 136 | 137 | // Initialize the RSP and RDP with our initialization display lists 138 | if (task->ishd) 139 | { 140 | gSPDisplayList(g_displistp++, s_dl_rdpinit_hd); 141 | gSPDisplayList(g_displistp++, s_dl_rspinit_hd); 142 | } 143 | else 144 | { 145 | gSPDisplayList(g_displistp++, s_dl_rdpinit_sd); 146 | gSPDisplayList(g_displistp++, s_dl_rspinit_sd); 147 | } 148 | 149 | // Set the current task pointer so that we can use it elsewhere 150 | s_curtask = task; 151 | } 152 | 153 | 154 | /*============================== 155 | rcp_clearbuffers 156 | Clears the framebuffer and zbuffer 157 | @param The red color to clear the framebuffer with 158 | @param The green color to clear the framebuffer with 159 | @param The blue color to clear the framebuffer with 160 | ==============================*/ 161 | 162 | void rcp_clearbuffers(u8 red, u8 green, u8 blue) 163 | { 164 | // Clear the framebuffer 165 | gDPSetCycleType(g_displistp++, G_CYC_FILL); 166 | gDPSetFillColor(g_displistp++, GPACK_RGBA5551(red, green, blue, 1) << 16 | GPACK_RGBA5551(red, green, blue, 1)); 167 | if (s_curtask->ishd) 168 | { 169 | gDPFillRectangle(g_displistp++, 0, 0, SCREEN_WIDTH_HD-1, SCREEN_HEIGHT_HD-1); 170 | } 171 | else 172 | { 173 | gDPFillRectangle(g_displistp++, 0, 0, SCREEN_WIDTH_SD-1, SCREEN_HEIGHT_SD-1); 174 | } 175 | gDPPipeSync(g_displistp++); 176 | 177 | // Clear the Z-buffer 178 | if (s_curtask->zbuffer != NULL) 179 | { 180 | gDPSetDepthImage(g_displistp++, s_curtask->zbuffer); 181 | if (s_curtask->ishd) 182 | { 183 | gDPSetColorImage(g_displistp++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH_HD, s_curtask->zbuffer); 184 | gDPSetFillColor(g_displistp++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16 | GPACK_ZDZ(G_MAXFBZ, 0))); 185 | gDPFillRectangle(g_displistp++, 0, 0, SCREEN_WIDTH_HD-1, SCREEN_HEIGHT_HD-1); 186 | } 187 | else 188 | { 189 | gDPSetColorImage(g_displistp++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WIDTH_SD, s_curtask->zbuffer); 190 | gDPSetFillColor(g_displistp++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16 | GPACK_ZDZ(G_MAXFBZ, 0))); 191 | gDPFillRectangle(g_displistp++, 0, 0, SCREEN_WIDTH_SD-1, SCREEN_HEIGHT_SD-1); 192 | } 193 | } 194 | } 195 | 196 | 197 | /*============================== 198 | rcp_finish 199 | Finish a display list and writebacks data 200 | @param A pointer to the render task struct to use 201 | ==============================*/ 202 | 203 | void rcp_finish(RenderTask* task) 204 | { 205 | // Finish the display list 206 | gDPFullSync(g_displistp++); 207 | gSPEndDisplayList(g_displistp++); 208 | 209 | // Ensure we haven't gone over the display list limit 210 | debug_assert((g_displistp - task->displistp) < DISPLIST_SIZE); 211 | 212 | // Writeback cache lines so that the RCP can read the up-to-date data 213 | osWritebackDCacheAll(); 214 | 215 | // Setup the RCP task 216 | s_rcptask_render.t.ucode_boot = (u64*)rspbootTextStart; 217 | s_rcptask_render.t.ucode_boot_size = (u32)rspbootTextEnd-(u32)rspbootTextStart; 218 | s_rcptask_render.t.ucode = (u64*)gspF3DEX2_fifoTextStart; 219 | s_rcptask_render.t.ucode_data = (u64*)gspF3DEX2_fifoDataStart; 220 | s_rcptask_render.t.data_ptr = (u64*)task->displistp; 221 | s_rcptask_render.t.data_size = (u32)((g_displistp - task->displistp)*sizeof(Gfx)); 222 | task->task = &s_rcptask_render; 223 | } -------------------------------------------------------------------------------- /Engine/N64/rcp.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_RCP_H 2 | #define PLATFORM64_RCP_H 3 | 4 | /********************************* 5 | Definitions 6 | *********************************/ 7 | 8 | // Time (in seconds) for an RCP task to take before it's declared as hung 9 | #define RCP_HUNGIME 3 10 | 11 | 12 | /********************************* 13 | Function Prototypes 14 | *********************************/ 15 | 16 | void rcp_initialize(RenderTask* task); 17 | void rcp_clearbuffers(u8 red, u8 green, u8 blue); 18 | void rcp_finish(RenderTask* task); 19 | 20 | #endif -------------------------------------------------------------------------------- /Engine/N64/scheduler.c: -------------------------------------------------------------------------------- 1 | /*************************************************************** 2 | scheduler.c 3 | 4 | Handles the scheduler, which coordinates between graphics and 5 | audio tasks, as well as handles PreNMI interrupts (Reset Button) 6 | ***************************************************************/ 7 | 8 | #include 9 | #include "debug.h" 10 | #include "osconfig.h" 11 | #include "types.h" 12 | #include "scheduler.h" 13 | #include "graphics.h" 14 | #include "audio.h" 15 | 16 | 17 | /********************************* 18 | Definitions 19 | *********************************/ 20 | 21 | // Enable this to see how the scheduler is behaving with prints 22 | #define VERBOSE FALSE 23 | 24 | 25 | /********************************* 26 | Function Prototypes 27 | *********************************/ 28 | 29 | static void threadfunc_scheduler(void *arg); 30 | static void scheduler_handledisplay(); 31 | static void scheduler_handlenmi(); 32 | static void scheduler_doresetwipe(); 33 | 34 | // Unexposed graphics.c functions 35 | extern bool graphics_framebufferready(); 36 | extern FrameBuffer* graphics_popframebuffer(); 37 | 38 | 39 | /********************************* 40 | Globals 41 | *********************************/ 42 | 43 | static OSThread s_threadstruct_scheduler; // The thread stucture 44 | static Scheduler s_scheduler; // The scheduler itself 45 | static FrameBuffer* s_displayingfb; // The current displaying framebuffer 46 | 47 | 48 | /*============================== 49 | scheduler_initialize 50 | Launches the scheduler thread 51 | ==============================*/ 52 | 53 | Scheduler* scheduler_initialize() 54 | { 55 | // Initialize globals 56 | s_displayingfb = NULL; 57 | 58 | // Initialize the scheduler 59 | s_scheduler.tvblack = TRUE; 60 | s_scheduler.reset = FALSE; 61 | s_scheduler.task_gfx = NULL; 62 | s_scheduler.task_audio = NULL; 63 | s_scheduler.gfx_notify = NULL; 64 | osCreateMesgQueue(&s_scheduler.queue, s_scheduler.messages, SIZE_MSGQUEUE_SCHEDULER); 65 | 66 | // Initialize the TV 67 | osCreateViManager(OS_PRIORITY_VIMGR); 68 | #if (TVMODE == TV_NTSC) 69 | osViSetMode(&osViModeNtscLan1); 70 | #elif (TVMODE == TV_PAL) 71 | osViSetMode(&osViModeFpalLan1); 72 | #else 73 | osViSetMode(&osViModeMpalLan1); 74 | #endif 75 | osViBlack(TRUE); 76 | 77 | // Set the target framerate and register the event callbacks 78 | #if TVMODE == TV_PAL 79 | osViSetEvent(&s_scheduler.queue, (OSMesg)MSG_SCHEDULER_VSYNC, 50/TARGET_FRAMERATE); 80 | #else 81 | osViSetEvent(&s_scheduler.queue, (OSMesg)MSG_SCHEDULER_VSYNC, 60/TARGET_FRAMERATE); 82 | #endif 83 | osSetEventMesg(OS_EVENT_PRENMI, &s_scheduler.queue, (OSMesg)MSG_SCHEDULER_PRENMI); 84 | 85 | // Start the scheduler thread 86 | osCreateThread(&s_threadstruct_scheduler, THREADID_SCHEDULER, threadfunc_scheduler, NULL, STACKREALSTART_SCHEDULER, THREADPRI_SCHEDULER); 87 | osStartThread(&s_threadstruct_scheduler); 88 | 89 | // Return the scheduler object 90 | return &s_scheduler; 91 | } 92 | 93 | 94 | /*============================== 95 | thread_scheduler 96 | The scheduler thread 97 | @param Argument passed to the thread 98 | ==============================*/ 99 | 100 | static void threadfunc_scheduler(void *arg) 101 | { 102 | #if VERBOSE 103 | debug_printf("Scheduler Thread: Started\n"); 104 | #endif 105 | 106 | // Spin this thread forever 107 | while (1) 108 | { 109 | OSMesg l_msg; 110 | #if VERBOSE 111 | debug_printf("Scheduler Thread: Loop start, waiting for message\n"); 112 | #endif 113 | osRecvMesg(&s_scheduler.queue, (OSMesg *)&l_msg, OS_MESG_BLOCK); 114 | 115 | // At this point, a message has been received from another thread 116 | #if VERBOSE 117 | debug_printf("Scheduler Thread: Message '%d' received\n", (s32)l_msg); 118 | #endif 119 | 120 | // Pick what to do based on the message value 121 | switch ((s32)l_msg) 122 | { 123 | case MSG_SCHEDULER_VSYNC: 124 | if (s_scheduler.gfx_notify != NULL) 125 | { 126 | osSendMesg(s_scheduler.gfx_notify, NULL, OS_MESG_BLOCK); 127 | s_scheduler.gfx_notify = NULL; 128 | } 129 | scheduler_handledisplay(); 130 | break; 131 | case MSG_SCHEDULER_PRENMI: 132 | scheduler_handlenmi(); 133 | break; 134 | case MSG_SCHEDULER_RCPHANG: 135 | debug_printf("RCP is HUNG UP!!\noh! MY GOD!!\n"); 136 | debug_assert(FALSE); 137 | break; 138 | default: 139 | #if VERBOSE 140 | debug_printf("Scheduler Thread: Bad message '0x%2x' received\n", (s32)l_msg); 141 | #endif 142 | break; 143 | } 144 | } 145 | } 146 | 147 | 148 | /*============================== 149 | scheduler_handledisplay 150 | Handles switching framebuffers 151 | ==============================*/ 152 | 153 | static void scheduler_handledisplay() 154 | { 155 | FrameBuffer* l_fb; 156 | 157 | // Check if a framebuffer that is ready exists, if not then we have to wait for the next retrace 158 | if (!graphics_framebufferready()) 159 | { 160 | #if VERBOSE 161 | debug_printf("Scheduler Thread: No framebuffer available.\n"); 162 | #endif 163 | 164 | // If the reset button was pressed recently, we can do some silly screen wipe 165 | if (s_scheduler.reset) 166 | scheduler_doresetwipe(); 167 | return; 168 | } 169 | 170 | // We have a framebuffer available, pop it from the ready stack 171 | l_fb = graphics_popframebuffer(); 172 | #if VERBOSE 173 | debug_printf("Scheduler Thread: Popped a framebuffer at %p.\n", l_fb->address); 174 | #endif 175 | 176 | // Mark the old framebuffer as free, and swap with the new one 177 | if (s_displayingfb != NULL) 178 | s_displayingfb->status = FBSTATUS_FREE; 179 | s_displayingfb = l_fb; 180 | osViSwapBuffer(l_fb->address); 181 | #if VERBOSE 182 | debug_printf("Scheduler Thread: Swapped framebuffer.\n"); 183 | #endif 184 | 185 | // Turn the TV on if it isn't 186 | if (s_scheduler.tvblack) 187 | { 188 | #if VERBOSE 189 | debug_printf("Scheduler Thread: TV Turned on.\n"); 190 | #endif 191 | s_scheduler.tvblack = FALSE; 192 | osViBlack(FALSE); 193 | } 194 | } 195 | 196 | 197 | /*============================== 198 | scheduler_handlenmi 199 | Handles Pre-NMI (reset button). 200 | Reset process is described in Developer News 1.5 201 | ==============================*/ 202 | 203 | static void scheduler_handlenmi() 204 | { 205 | osViSetYScale(1.0); 206 | audio_stopthread(); 207 | graphics_stopthread(); 208 | osSpTaskYield(); 209 | osAfterPreNMI(); 210 | s_scheduler.reset = TRUE; 211 | } 212 | 213 | 214 | /*============================== 215 | scheduler_doresetwipe 216 | Do some fancy effect on the CPU to the framebuffer 217 | while the reset button is down 218 | ==============================*/ 219 | 220 | #define COLUMNWIDTH 2 221 | #define MELTSPEED 8 222 | 223 | static void scheduler_doresetwipe() 224 | { 225 | int i = 0; 226 | FRAMEBUFF_DEPTH* l_frame = s_displayingfb->address; 227 | static bool l_initialized = FALSE; 228 | static s32 l_columnstate[SCREEN_WIDTH_HD/COLUMNWIDTH]; 229 | const u32 l_screenw = graphics_get_screenw(); 230 | const u32 l_screenh = graphics_get_screenh(); 231 | #if VERBOSE 232 | debug_printf("Scheduler Thread: Doing fizzle\n"); 233 | #endif 234 | 235 | // Initialize the melt effect 236 | // This is done by initializing each column based on the previous value 237 | // If I were to use pure random, it'd look like garbage unfortunately 238 | if (!l_initialized) 239 | { 240 | l_columnstate[0] = MELTSPEED*(guRandom()%16); 241 | for (i=1; i0; j--) 261 | { 262 | for (k=0; k -l_columnstate[i] && (j-MELTSPEED) > 0) // Copy pixels above the melt effect 266 | l_frame[l_ipos + l_screenw*j] = l_frame[l_ipos + l_screenw*(j-MELTSPEED)]; 267 | else if (j < -l_columnstate[i]-MELTSPEED) // Blacken pixels which haven't been yet (no need to re-blacken) 268 | l_frame[l_ipos + l_screenw*j] = 0; 269 | } 270 | } 271 | } 272 | l_columnstate[i] -= MELTSPEED; 273 | } 274 | } -------------------------------------------------------------------------------- /Engine/N64/scheduler.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_SCHEDULER_H 2 | #define PLATFORM64_SCHEDULER_H 3 | 4 | /********************************* 5 | Definitions 6 | *********************************/ 7 | 8 | // Max number of messages for the scheduler message queue 9 | #define SIZE_MSGQUEUE_SCHEDULER 8 10 | 11 | // Scheduler messages 12 | #define MSG_SCHEDULER_VSYNC 1 13 | #define MSG_SCHEDULER_AUDIOREQ 2 14 | #define MSG_SCHEDULER_PRENMI 3 15 | #define MSG_SCHEDULER_RCPHANG 4 16 | 17 | 18 | /********************************* 19 | Structs 20 | *********************************/ 21 | 22 | typedef struct 23 | { 24 | bool tvblack; // Whether the TV is blacked or not 25 | bool reset; // Whether the reset button was recently pressed 26 | OSTask* task_gfx; // Current executing graphics task 27 | OSTask* task_audio; // Current executing audio task 28 | OSMesgQueue queue; 29 | OSMesg messages[SIZE_MSGQUEUE_SCHEDULER]; 30 | OSMesgQueue* gfx_notify; 31 | } Scheduler; 32 | 33 | 34 | /********************************* 35 | Functions 36 | *********************************/ 37 | 38 | Scheduler* scheduler_initialize(); 39 | 40 | #endif -------------------------------------------------------------------------------- /Engine/N64/spec: -------------------------------------------------------------------------------- 1 | #include "osconfig.h" 2 | 3 | beginseg 4 | name "code" 5 | flags BOOT OBJECT 6 | entry boot 7 | address SEGMENTSTART_CODE 8 | maxsize SEGMENTSIZE_CODE 9 | stack STACKSTART_BOOT + STACKSIZE_BOOT 10 | include $(CODESEGMENT) 11 | include "$(ROOT)/usr/lib/PR/rspboot.o" 12 | include "$(ROOT)/usr/lib/PR/gspF3DEX2.fifo.o" 13 | endseg 14 | 15 | beginwave 16 | name "platform64" 17 | include "code" 18 | endwave -------------------------------------------------------------------------------- /Engine/N64/types.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM64_TYPES_H 2 | #define PLATFORM64_TYPES_H 3 | 4 | // Basic data types 5 | #include "datatype/engine/bool.h" 6 | 7 | // Math includes 8 | #include "datatype/math/vector2d.h" 9 | #include "datatype/math/vector3d.h" 10 | #include "datatype/math/quaternion.h" 11 | #include "datatype/math/octagon.h" 12 | 13 | // Engine includes 14 | #include "datatype/engine/transform2d.h" 15 | #include "datatype/engine/transform3d.h" 16 | #include "datatype/engine/color.h" 17 | 18 | #endif -------------------------------------------------------------------------------- /Engine/N64/usb.h: -------------------------------------------------------------------------------- 1 | #ifndef UNFL_USB_H 2 | #define UNFL_USB_H 3 | 4 | /********************************* 5 | DataType macros 6 | *********************************/ 7 | 8 | // UNCOMMENT THE #DEFINE IF USING LIBDRAGON 9 | //#define LIBDRAGON 10 | 11 | // Settings 12 | #define USE_OSRAW 0 // Use if you're doing USB operations without the PI Manager (libultra only) 13 | #define DEBUG_ADDRESS_SIZE 8*1024*1024 // Max size of USB I/O. The bigger this value, the more ROM you lose! 14 | #define CHECK_EMULATOR 1 // Stops the USB library from working if it detects an emulator to prevent problems 15 | 16 | // Cart definitions 17 | #define CART_NONE 0 18 | #define CART_64DRIVE 1 19 | #define CART_EVERDRIVE 2 20 | #define CART_SC64 3 21 | 22 | // Data types defintions 23 | #define DATATYPE_TEXT 0x01 24 | #define DATATYPE_RAWBINARY 0x02 25 | #define DATATYPE_HEADER 0x03 26 | #define DATATYPE_SCREENSHOT 0x04 27 | #define DATATYPE_HEARTBEAT 0x05 28 | 29 | 30 | /********************************* 31 | Convenience macros 32 | *********************************/ 33 | 34 | // Use these to conveniently read the header from usb_poll() 35 | #define USBHEADER_GETTYPE(header) ((header & 0xFF000000) >> 24) 36 | #define USBHEADER_GETSIZE(header) ((header & 0x00FFFFFF)) 37 | 38 | 39 | /********************************* 40 | USB Functions 41 | *********************************/ 42 | 43 | /*============================== 44 | usb_initialize 45 | Initializes the USB buffers and pointers 46 | @return 1 if the USB initialization was successful, 0 if not 47 | ==============================*/ 48 | 49 | extern char usb_initialize(); 50 | 51 | 52 | /*============================== 53 | usb_getcart 54 | Returns which flashcart is currently connected 55 | @return The CART macro that corresponds to the identified flashcart 56 | ==============================*/ 57 | 58 | extern char usb_getcart(); 59 | 60 | 61 | /*============================== 62 | usb_write 63 | Writes data to the USB. 64 | Will not write if there is data to read from USB 65 | @param The DATATYPE that is being sent 66 | @param A buffer with the data to send 67 | @param The size of the data being sent 68 | ==============================*/ 69 | 70 | extern void usb_write(int datatype, const void* data, int size); 71 | 72 | 73 | /*============================== 74 | usb_poll 75 | Returns the header of data being received via USB 76 | The first byte contains the data type, the next 3 the number of bytes left to read 77 | @return The data header, or 0 78 | ==============================*/ 79 | 80 | extern unsigned long usb_poll(); 81 | 82 | 83 | /*============================== 84 | usb_read 85 | Reads bytes from USB into the provided buffer 86 | @param The buffer to put the read data in 87 | @param The number of bytes to read 88 | ==============================*/ 89 | 90 | extern void usb_read(void* buffer, int size); 91 | 92 | 93 | /*============================== 94 | usb_skip 95 | Skips a USB read by the specified amount of bytes 96 | @param The number of bytes to skip 97 | ==============================*/ 98 | 99 | extern void usb_skip(int nbytes); 100 | 101 | 102 | /*============================== 103 | usb_rewind 104 | Rewinds a USB read by the specified amount of bytes 105 | @param The number of bytes to rewind 106 | ==============================*/ 107 | 108 | extern void usb_rewind(int nbytes); 109 | 110 | 111 | /*============================== 112 | usb_purge 113 | Purges the incoming USB data 114 | ==============================*/ 115 | 116 | extern void usb_purge(); 117 | 118 | 119 | /*============================== 120 | usb_timedout 121 | Checks if the USB timed out recently 122 | @return 1 if the USB timed out, 0 if not 123 | ==============================*/ 124 | 125 | extern char usb_timedout(); 126 | 127 | 128 | /*============================== 129 | usb_sendheartbeat 130 | Sends a heartbeat packet to the PC 131 | This is done once automatically at initialization, 132 | but can be called manually to ensure that the 133 | host side tool is aware of the current USB protocol 134 | version. 135 | ==============================*/ 136 | 137 | extern void usb_sendheartbeat(); 138 | 139 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | --- 4 | [![Build Status](https://dev.azure.com/buu342/Platform64/_apis/build/status/buu342.N64-Platform64?branchName=master)](https://dev.azure.com/buu342/Platform64/_build/latest?definitionId=1&branchName=master) 5 | 6 | A free and open source 2.5D side-scrolling adventure game for the Nintendo 64. 7 | 8 | 9 | ## Compilation 10 | 11 | Below are instructions for compiling different parts of Platform64. 12 | 13 | ### Engine 14 |
N64 15 | 16 | 1) Ensure you have libultra installed. 17 | 2) If you haven't already, you must first compile the [Builder](Tools/Builder) tool, and preferably place it in the project's source directory. Launch the tool once and ensure it is configured to match your libultra install. 18 | 3) Execute `Builder.exe` and go to `Settings->Import project settings`. Load `platform.nbp`. 19 | 4) Press the compile button to generate the ROM. 20 |
21 | 22 | ### Tools 23 |
Builder 24 | 25 | Please consult the [Tools/Builder](Tools/Builder#builder) folder for compilation instructions. 26 |
27 | 28 |
MemMapper 29 | 30 | Please consult the [MemMapper](https://github.com/buu342/CPP-MemMapper) repository for compilation instructions. 31 |
32 | 33 |
NRDC 34 | 35 | Please consult the [NRDC](https://github.com/buu342/N64-NRDC) repository for compilation instructions. 36 |
37 | 38 |
UNFLoader 39 | 40 | Please consult the [UNFLoader](https://github.com/buu342/N64-UNFLoader) repository for compilation instructions. 41 |
-------------------------------------------------------------------------------- /Tools/Builder/Builder.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // Portuguese (Portugal) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTG) 19 | LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE 20 | #pragma code_page(1252) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_ICON1 ICON "resources\\prog.ico" 56 | MAINICON ICON "resources\\prog.ico" 57 | 58 | #endif // Portuguese (Portugal) resources 59 | ///////////////////////////////////////////////////////////////////////////// 60 | 61 | 62 | 63 | #ifndef APSTUDIO_INVOKED 64 | ///////////////////////////////////////////////////////////////////////////// 65 | // 66 | // Generated from the TEXTINCLUDE 3 resource. 67 | // 68 | 69 | 70 | ///////////////////////////////////////////////////////////////////////////// 71 | #endif // not APSTUDIO_INVOKED 72 | 73 | -------------------------------------------------------------------------------- /Tools/Builder/Builder.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30320.27 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Builder", "Builder.vcxproj", "{2331AEC1-B737-400F-9119-F3B0F113604A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {2331AEC1-B737-400F-9119-F3B0F113604A}.Debug|x86.ActiveCfg = Debug|Win32 15 | {2331AEC1-B737-400F-9119-F3B0F113604A}.Debug|x86.Build.0 = Debug|Win32 16 | {2331AEC1-B737-400F-9119-F3B0F113604A}.Release|x86.ActiveCfg = Release|Win32 17 | {2331AEC1-B737-400F-9119-F3B0F113604A}.Release|x86.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {C98A9AE4-DCBE-4657-9B15-B9CF700B2885} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Tools/Builder/Builder.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 16.0 51 | Win32Proj 52 | {2331aec1-b737-400f-9119-f3b0f113604a} 53 | Builder 54 | 10.0 55 | 56 | 57 | 58 | Application 59 | true 60 | v141_xp 61 | Unicode 62 | 63 | 64 | Application 65 | false 66 | v141_xp 67 | true 68 | Unicode 69 | 70 | 71 | Application 72 | true 73 | v142 74 | Unicode 75 | 76 | 77 | Application 78 | false 79 | v142 80 | true 81 | Unicode 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | true 103 | 104 | 105 | false 106 | 107 | 108 | true 109 | 110 | 111 | false 112 | 113 | 114 | 115 | Level3 116 | true 117 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 118 | true 119 | $(WXWIN)/include; $(WXWIN)/include/msvc 120 | 121 | 122 | Windows 123 | true 124 | $(WXWIN)/lib/vc_lib 125 | 126 | 127 | 128 | 129 | Level3 130 | true 131 | true 132 | true 133 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS; 134 | true 135 | $(WXWIN)/include; $(WXWIN)/include/msvc 136 | 137 | 138 | Windows 139 | true 140 | true 141 | true 142 | $(WXWIN)/lib/vc_lib 143 | 144 | 145 | 146 | 147 | Level3 148 | true 149 | _DEBUG;_WINDOWS;%(PreprocessorDefinitions) 150 | true 151 | 152 | 153 | Windows 154 | true 155 | 156 | 157 | 158 | 159 | Level3 160 | true 161 | true 162 | true 163 | NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 164 | true 165 | 166 | 167 | Windows 168 | true 169 | true 170 | true 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /Tools/Builder/Builder.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | 70 | 71 | Resource Files 72 | 73 | 74 | 75 | 76 | Resource Files 77 | 78 | 79 | Resource Files 80 | 81 | 82 | Resource Files 83 | 84 | 85 | -------------------------------------------------------------------------------- /Tools/Builder/Builder.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /Tools/Builder/README.md: -------------------------------------------------------------------------------- 1 | # Builder 2 | 3 | A C++ GUI application for compiling N64 projects. This tool was written to supersede the old batch files and buggy KMC make system used early in the project. 4 | 5 | ### Compilation 6 | 7 | If you are on Windows, ensure you have wxWidgets installed (instructions available [here](https://docs.wxwidgets.org/trunk/plat_msw_install.html)), and a copy of Visual Studio 2019 with [Platform Toolset v140_xp](https://stackoverflow.com/questions/58755564/visual-studio-2019-how-to-use-platform-toolset-v140-xp/58755565#58755565) installed. If all of that is set up, then simply open the solution file in Visual Studio and compile. 8 | 9 | ### Usage 10 | 11 | I recommend placing the executable in the same folder as your project's source, as that will make it so that the program loads the project from the get-go instead of requiring you to manually open the project folder. 12 | 13 | If you are using the tool for the first time, hover over to `Settings->Preferences` and ensure that the program config (which is the bottom half of the menu, where the Libultra path is stored) is set up correctly. 14 | 15 | If you are attempting to build someone else's project, you can hover over to `Settings->Import project settings` to load a .nbp file which contains the settings to use for that specific project. 16 | 17 | #### Segments 18 | 19 | By default, all objects are placed in the codesegment. This can be changed by double clicking C file in the project tree and changing the name of the segment. 20 | 21 | During compilation, each segment name will be stored as an environment variable, which you can use to point to the correct path in your spec file. For example, if I have a segment named `codesegment`, then the `CODESEGMENT` environment variable will be created which contains the path to the file. In your spec file, simply use `$(CODESEGMENT)` to have it use the path in the environment variable. 22 | 23 | #### Force ROM rebuild 24 | 25 | If you make changes to the spec file or to files which are linked into the final ROM through inclusion in the spec file, the tool will not detect these changes and thus will not rebuild the ROM (this can be fixed in the future). You can force just the creation of a new ROM (skipping the recompilation of unchanged objects) through the `Force ROM rebuild` option in the `Build` menu. 26 | 27 | ### Credits 28 | 29 | This application uses [wxWidgets](https://www.wxwidgets.org/) in order to make the GUI application cross-platform. 30 | -------------------------------------------------------------------------------- /Tools/Builder/app.cpp: -------------------------------------------------------------------------------- 1 | #include "app.h" 2 | #include 3 | 4 | // Icons 5 | #include "resources/icon_prog.h" 6 | #include "resources/icon_c.h" 7 | #include "resources/icon_h.h" 8 | #include "resources/icon_config.h" 9 | 10 | wxIMPLEMENT_APP(App); 11 | 12 | wxIcon iconbm_prog = wxNullIcon; 13 | wxBitmap iconbm_c = wxNullBitmap; 14 | wxBitmap iconbm_h = wxNullBitmap; 15 | wxIcon iconbm_config = wxNullIcon; 16 | 17 | App::App() 18 | { 19 | this->m_ProgramFrame = NULL; 20 | wxDir::Make(wxStandardPaths::Get().GetUserConfigDir() + "/N64" + PROGRAM_NAME + "/", wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL); 21 | global_configfile = new wxFileConfig(PROGRAM_NAME, "Buu342", wxStandardPaths::Get().GetUserConfigDir() + "/N64" + PROGRAM_NAME + "/Config.ini"); 22 | Config_DefaultProgramConfig(); 23 | Config_LoadProgramConfig(); 24 | global_projectconfig.ProjectPath = DEFAULT_PROJECTPATH; 25 | Config_DefaultProjectConfig(); 26 | Config_LoadProjectConfig(); 27 | } 28 | 29 | App::~App() 30 | { 31 | // Nothing 32 | } 33 | 34 | bool App::OnInit() 35 | { 36 | wxBitmap temp; 37 | if (!wxApp::OnInit()) 38 | return false; 39 | wxInitAllImageHandlers(); 40 | iconbm_prog.CopyFromBitmap(wxBITMAP_PNG_FROM_DATA(icon_prog)); 41 | iconbm_c = wxBITMAP_PNG_FROM_DATA(icon_c); 42 | iconbm_h = wxBITMAP_PNG_FROM_DATA(icon_h); 43 | iconbm_config.CopyFromBitmap(wxBITMAP_PNG_FROM_DATA(icon_config)); 44 | this->m_ProgramFrame = new Main(); 45 | this->m_ProgramFrame->SetIcon(iconbm_prog); 46 | this->m_ProgramFrame->Show(); 47 | SetTopWindow(this->m_ProgramFrame); 48 | return true; 49 | } -------------------------------------------------------------------------------- /Tools/Builder/app.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct IUnknown IUnknown; 4 | 5 | #include 6 | #include "main.h" 7 | #include "preferences.h" 8 | 9 | #define PROGRAM_NAME "Builder" 10 | 11 | // Icons 12 | extern wxIcon iconbm_prog; 13 | extern wxBitmap iconbm_c; 14 | extern wxBitmap iconbm_h; 15 | extern wxIcon iconbm_config; 16 | 17 | class App : public wxApp 18 | { 19 | private: 20 | Main* m_ProgramFrame; 21 | 22 | public: 23 | App(); 24 | ~App(); 25 | virtual bool OnInit(); 26 | }; -------------------------------------------------------------------------------- /Tools/Builder/compunit.cpp: -------------------------------------------------------------------------------- 1 | #include "compunit.h" 2 | #include "helper.h" 3 | #include "preferences.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | CompUnit::CompUnit(wxTreeListCtrl* tree, wxTreeListItem id) 11 | { 12 | wxTextFile file; 13 | wxString path = ""; 14 | wxString output = tree->GetItemText(id); 15 | wxTreeListItem curid = id; 16 | wxString segmentname = "codesegment"; 17 | wxFileName segmentpath; 18 | 19 | // First, generate the path 20 | while (tree->GetItemParent(curid) != NULL) 21 | { 22 | curid = tree->GetItemParent(curid); 23 | path.Prepend(tree->GetItemText(curid)+"/"); 24 | } 25 | 26 | // Now set the file paths 27 | output.Replace(".c", ".o"); 28 | this->m_File.Assign(global_projectconfig.ProjectPath + "/" + path + tree->GetItemText(id)); 29 | if (global_programconfig.Use_Build) 30 | this->m_Output.Assign(global_projectconfig.BuildFolder + "/" + path + output); 31 | else 32 | this->m_Output.Assign(global_projectconfig.ProjectPath + "/" + path + output); 33 | 34 | // Set the segment 35 | if (global_configfile->HasEntry("/Project_" + global_projectconfig.ProjectPath + "/SegmentList")) 36 | { 37 | std::vector segments = std::vector(); 38 | wxString parse = global_configfile->Read("/Project_" + global_projectconfig.ProjectPath + "/SegmentList"); 39 | while (parse.size() > 0) 40 | { 41 | parse = parse.AfterFirst('\"'); 42 | segments.push_back(parse.BeforeFirst('\"')); 43 | parse = parse.AfterFirst('\"'); 44 | parse = parse.AfterFirst(' '); 45 | } 46 | for (std::vector::iterator it = segments.begin(); it != segments.end(); ++it) 47 | { 48 | parse = global_configfile->Read("/Project_" + global_projectconfig.ProjectPath + "/Segment_" + (*it)); 49 | while (parse.size() > 0) 50 | { 51 | parse = parse.AfterFirst('\"'); 52 | if (parse.BeforeFirst('\"') == RelativeProjectPath(this->m_File.GetFullPath())) 53 | { 54 | segmentname = (*it); 55 | break; 56 | } 57 | parse = parse.AfterFirst('\"'); 58 | parse = parse.AfterFirst(' '); 59 | } 60 | } 61 | } 62 | if (global_programconfig.Use_Build) 63 | segmentpath = global_projectconfig.BuildFolder + "/" + segmentname + ".o"; 64 | else 65 | segmentpath = global_projectconfig.ProjectPath + "/" + segmentname + ".o"; 66 | this->m_Segment = segmentpath; 67 | 68 | // Check if we have a debug file 69 | if (this->m_File.GetFullName() == "debug.c" || this->m_File.GetFullName() == "usb.c") 70 | this->m_IsDebugFile = true; 71 | else 72 | this->m_IsDebugFile = false; 73 | 74 | // Finally, we need to read the file and check its dependencies 75 | file.Open(this->m_File.GetFullPath()); 76 | while (!file.Eof()) 77 | { 78 | wxString str = file.GetNextLine(); 79 | if (str.Contains("#include")) 80 | { 81 | wxString token; 82 | wxStringTokenizer tokenizer(str, "\""); 83 | tokenizer.GetNextToken(); 84 | token = tokenizer.GetNextToken(); 85 | if (token != "") 86 | { 87 | wxFileName finalpath(token); 88 | finalpath.Normalize(wxPATH_NORM_ALL, this->m_File.GetPath()); 89 | this->m_Dependencies.push_back(finalpath); 90 | } 91 | } 92 | } 93 | file.Close(); 94 | } 95 | 96 | CompUnit::~CompUnit() 97 | { 98 | 99 | } 100 | 101 | wxFileName CompUnit::GetFilePath() 102 | { 103 | return this->m_File; 104 | } 105 | 106 | wxFileName CompUnit::GetOutputPath(bool debug) 107 | { 108 | if (debug && global_programconfig.SeparateDebug) 109 | return this->m_Output.GetPath() + "/" + this->m_Output.GetName() + "_d." + this->m_Output.GetExt(); 110 | else 111 | return this->m_Output; 112 | } 113 | 114 | wxFileName CompUnit::GetSegment() 115 | { 116 | return this->m_Segment; 117 | } 118 | 119 | bool CompUnit::IsDebugFile() 120 | { 121 | return this->m_IsDebugFile; 122 | } 123 | 124 | void CompUnit::SetSegment(wxString segment) 125 | { 126 | this->m_Segment = this->m_Segment.GetPath() + "/" + segment + ".o"; 127 | } 128 | 129 | bool CompUnit::ShouldRebuild(bool debug) 130 | { 131 | wxStructStat stat_input; 132 | wxStructStat stat_output; 133 | wxFileName outputpath = this->GetOutputPath(debug); 134 | stat_input.st_mtime = LastModTime(this->m_File.GetFullPath()); 135 | stat_output.st_mtime = LastModTime(outputpath.GetFullPath()); 136 | 137 | // Check if the object file exists 138 | if (!wxFileExists(outputpath.GetFullPath())) 139 | { 140 | wxLogVerbose(outputpath.GetFullName() + " does not exist"); 141 | return true; 142 | } 143 | 144 | // Check if the modification date of the C file superscedes the object file 145 | if (wxDateTime(stat_input.st_mtime).IsLaterThan(wxDateTime(stat_output.st_mtime))) 146 | { 147 | wxLogVerbose(this->m_File.GetFullName() + " was modified"); 148 | return true; 149 | } 150 | 151 | // Check if header files superscene the object file 152 | for (std::vector::iterator it = this->m_Dependencies.begin(); it != this->m_Dependencies.end(); ++it) 153 | { 154 | stat_input.st_mtime = LastModTime((*it).GetFullPath()); 155 | if (wxDateTime(stat_input.st_mtime).IsLaterThan(wxDateTime(stat_output.st_mtime))) 156 | { 157 | wxLogVerbose((*it).GetFullName() + " was modified"); 158 | return true; 159 | } 160 | } 161 | return false; 162 | } 163 | 164 | void CompUnit::Compile(bool debug) 165 | { 166 | wxString command; 167 | wxArrayString output; 168 | wxString optimizer = "-g"; 169 | wxString lcdefs = "-DDEBUG -DDEBUG_MODE=1"; 170 | wxString exew32 = global_programconfig.Use_EXEW32 ? "exew32.exe " : ""; 171 | 172 | // Set optimizer flags 173 | if (!debug) 174 | { 175 | optimizer = "-O2"; 176 | lcdefs = "-D_FINALROM -DNDEBUG -DDEBUG_MODE=0"; 177 | } 178 | 179 | // Run GCC 180 | wxDir::Make(this->GetOutputPath(debug).GetPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL); 181 | command = global_programconfig.Path_Toolkit + "/" + exew32 + "gcc.exe " 182 | + lcdefs + " " 183 | + global_projectconfig.Flags_GCC + " " 184 | + optimizer 185 | + " -c " + this->m_File.GetFullPath() 186 | + " -o " + this->GetOutputPath(debug).GetFullPath(); 187 | wxLogVerbose("> " + command); 188 | wxExecute(command, output, wxEXEC_SYNC, &GetProgramEnvironment()); 189 | 190 | // Output warnings + errors 191 | for (size_t i=0; i 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class CompUnit 12 | { 13 | private: 14 | wxFileName m_File; 15 | std::vector m_Dependencies; 16 | wxFileName m_Output; 17 | wxFileName m_Segment; 18 | bool m_IsDebugFile; 19 | 20 | public: 21 | wxFileName GetFilePath(); 22 | wxFileName GetOutputPath(bool debug); 23 | wxFileName GetSegment(); 24 | bool IsDebugFile(); 25 | void SetSegment(wxString segment); 26 | bool ShouldRebuild(bool debug); 27 | void Compile(bool debug); 28 | CompUnit(wxTreeListCtrl* tree, wxTreeListItem id); 29 | ~CompUnit(); 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /Tools/Builder/helper.cpp: -------------------------------------------------------------------------------- 1 | #include "helper.h" 2 | #include "preferences.h" 3 | #include 4 | #ifndef LINUX 5 | #include 6 | #endif 7 | 8 | time_t LastModTime(const char* path) 9 | { 10 | struct stat finfo; 11 | if (!wxFileExists(path)) 12 | return 0; 13 | #ifndef LINUX 14 | LARGE_INTEGER lt; 15 | WIN32_FILE_ATTRIBUTE_DATA fdata; 16 | GetFileAttributesExA(path, GetFileExInfoStandard, &fdata); 17 | lt.LowPart = fdata.ftLastWriteTime.dwLowDateTime; 18 | lt.HighPart = (long)fdata.ftLastWriteTime.dwHighDateTime; 19 | finfo.st_mtime = (time_t)(lt.QuadPart * 1e-7); 20 | #else 21 | stat(path, &finfo); 22 | #endif 23 | return finfo.st_mtime; 24 | } 25 | 26 | unsigned int GetMBits(const char* path) 27 | { 28 | unsigned int v = 1; 29 | v--; 30 | v |= v >> 1; 31 | v |= v >> 2; 32 | v |= v >> 4; 33 | v |= v >> 8; 34 | v |= v >> 16; 35 | v++; 36 | return v; 37 | } 38 | 39 | wxExecuteEnv GetProgramEnvironment() 40 | { 41 | wxExecuteEnv env; 42 | wxEnvVariableHashMap vars; 43 | vars["ROOT"] = wxString(global_programconfig.Path_Libultra); 44 | vars["gccdir"] = wxString(global_programconfig.Path_Libultra) + wxString("/gcc"); 45 | vars["PATH"] = global_programconfig.Path_Toolkit + wxString(";") + global_programconfig.Path_Libultra + wxString("/usr/sbin;C:/WINDOWS/system32;"); 46 | vars["gccsw"] = wxString("-mips3 -mgp32 -mfp32 -funsigned-char -D_LANGUAGE_C -D_ULTRA64 -D__EXTENSIONS__"); 47 | vars["n64align"] = "on"; 48 | env.cwd = global_projectconfig.ProjectPath; 49 | env.env = vars; 50 | return env; 51 | } 52 | 53 | wxString RelativeProjectPath(wxFileName file) 54 | { 55 | file.MakeRelativeTo(global_projectconfig.ProjectPath); 56 | return file.GetFullPath(); 57 | } -------------------------------------------------------------------------------- /Tools/Builder/helper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct IUnknown IUnknown; 4 | 5 | #include "compunit.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | time_t LastModTime(const char* path); 14 | unsigned int GetMBits(const char* path); 15 | wxExecuteEnv GetProgramEnvironment(); 16 | wxString RelativeProjectPath(wxFileName file); -------------------------------------------------------------------------------- /Tools/Builder/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct IUnknown IUnknown; 4 | 5 | #include "compunit.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | class Main : public wxFrame 25 | { 26 | private: 27 | 28 | protected: 29 | wxChoice* m_Choice_BuildMode; 30 | wxImageList* m_treeIcons; 31 | wxTreeListCtrl* m_TreeCtrl_ProjectDir; 32 | wxButton* m_Button_Disassemble; 33 | wxButton* m_Button_Clean; 34 | wxButton* m_Button_Build; 35 | wxButton* m_Button_Upload; 36 | wxMenuBar* m_MenuBar; 37 | wxMenu * m_Menu_File; 38 | wxMenu* m_Menu_Build; 39 | wxMenu* m_Menu_Settings; 40 | wxLogWindow* m_LogWin; 41 | std::map* m_CompUnits; 42 | 43 | void m_TreeCtrl_ProjectDir_OnActivated(wxTreeListEvent& event); 44 | void m_Button_Disassemble_OnButtonClick(wxCommandEvent& event); 45 | void m_Button_Clean_OnButtonClick(wxCommandEvent& event); 46 | void m_Button_Build_OnButtonClick(wxCommandEvent& event); 47 | void m_Button_Upload_OnButtonClick(wxCommandEvent& event); 48 | void m_MenuItem_Open_OnSelection(wxCommandEvent& event); 49 | void m_MenuItem_Refresh_OnSelection(wxCommandEvent& event); 50 | void m_MenuItem_Exit_OnSelection(wxCommandEvent& event); 51 | void m_MenuItem_Build_OnSelection(wxCommandEvent& event); 52 | void m_MenuItem_Clean_OnSelection(wxCommandEvent& event); 53 | void m_MenuItem_Disassemble_OnSelection(wxCommandEvent& event); 54 | void m_MenuItem_Upload_OnSelection(wxCommandEvent& event); 55 | void m_MenuItem_ForceRebuild_OnSelection(wxCommandEvent& event); 56 | void m_MenuItem_Config_OnSelection(wxCommandEvent& event); 57 | void m_MenuItem_ImportProject_OnSelection(wxCommandEvent& event); 58 | void m_MenuItem_ExportProject_OnSelection(wxCommandEvent& event); 59 | void PopulateCompileChoices(); 60 | bool CheckDebugEnabled(); 61 | void CleanProject(); 62 | void BuildProject(); 63 | void BuildROM(); 64 | void DisassembleROM(); 65 | void RegisterROM(wxString target); 66 | void MoveROM(wxString target); 67 | void UploadROM(); 68 | 69 | public: 70 | void RefreshProjectTree(); 71 | Main(); 72 | ~Main(); 73 | }; -------------------------------------------------------------------------------- /Tools/Builder/preferences.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct IUnknown IUnknown; 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "helper.h" 25 | #include "compunit.h" 26 | 27 | // Default project config 28 | #define DEFAULT_PROJECTPATH (wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath()) 29 | #define DEFAULT_ROMNAME "homebrew.n64" 30 | #define DEFAULT_BUILDPATH global_projectconfig.ProjectPath+"/build" 31 | #define DEFAULT_ROMHEADER_NAME "MY HOMEBREW GAME" 32 | #define DEFAULT_ROMHEADER_MANUF "N" 33 | #define DEFAULT_ROMHEADER_ID "HB" 34 | #define DEFAULT_ROMHEADER_COUNTRY "E" 35 | #define DEFAULT_GCCFLAGS (wxString("-Wall ") \ 36 | +"-I. " \ 37 | +"-I"+global_programconfig.Path_Libultra+"/usr/include/PR " \ 38 | +"-I"+global_programconfig.Path_Libultra+"/usr/include " \ 39 | +"-G 0 " \ 40 | +"-DF3DEX_GBI_2 -DNOT_SPEC -D_MIPS_SZLONG=32 -D_MIPS_SZINT=32 ") 41 | #define DEFAULT_LDFLAGS (wxString("-L. ") \ 42 | +"-L"+global_programconfig.Path_Libultra+"/usr/lib " \ 43 | +"-L"+global_programconfig.Path_Libultra+"/usr/lib/PR " \ 44 | +"-L"+global_programconfig.Path_Libultra+"/gcc/mipse/lib -lkmc") 45 | #define DEFAULT_MILDFLAGS "" 46 | 47 | // Default program config 48 | #define DEFAULT_LIBULTRAPATH "C:/ultra" 49 | #define DEFAULT_TOOLKITPATH "C:/ultra/GCC/MIPSE/BIN" 50 | #define DEFAULT_MOVEPATH "Z:" 51 | #define DEFAULT_DISASSEMBLY "disassembly.txt" 52 | #define DEFAULT_USEEXEW32 true 53 | #define DEFAULT_SEPARATEDEBUG true 54 | #define DEFAULT_USEBUILD true 55 | #define DEFAULT_USENRDC true 56 | #define DEFAULT_USEMAKEMASK true 57 | #define DEFAULT_USEMOVE false 58 | #define DEFAULT_USEUPLOAD false 59 | #define DEFAULT_PROMPTMOVE true 60 | #define DEFAULT_PROMPTUPLOAD true 61 | #define DEFAULT_PROMPTDISASS false 62 | #define DEFAULT_PROMPTCLEAN true 63 | 64 | typedef struct 65 | { 66 | wxString ProjectPath; 67 | wxString TargetName; 68 | wxString BuildFolder; 69 | wxString ROMHeader_Name; 70 | wxString ROMHeader_Manufacturer; 71 | wxString ROMHeader_ID; 72 | wxString ROMHeader_Country; 73 | wxString Flags_GCC; 74 | wxString Flags_LD; 75 | wxString Flags_MILD; 76 | } ConfigProject; 77 | 78 | typedef struct 79 | { 80 | wxString Path_Libultra; 81 | wxString Path_Toolkit; 82 | wxString Path_Move; 83 | wxString DissamblyName; 84 | bool Use_EXEW32; 85 | bool SeparateDebug; 86 | bool Use_Build; 87 | bool Use_NRDC; 88 | bool Use_MakeMask; 89 | bool Use_Move; 90 | bool Use_Upload; 91 | bool Prompt_Move; 92 | bool Prompt_Upload; 93 | bool Prompt_Disassembly; 94 | bool Prompt_Clean; 95 | } ConfigProgram; 96 | 97 | extern wxFileConfig* global_configfile; 98 | extern ConfigProject global_projectconfig; 99 | extern ConfigProgram global_programconfig; 100 | 101 | void Config_SaveProgramConfig(); 102 | void Config_LoadProgramConfig(); 103 | void Config_DefaultProgramConfig(); 104 | 105 | void Config_SaveProjectConfig(); 106 | void Config_LoadProjectConfig(); 107 | void Config_DefaultProjectConfig(); 108 | void Config_SaveExternalProjectConfig(wxFileName path, std::map* compunits); 109 | void Config_LoadExternalProjectConfig(wxFileName path); 110 | 111 | class Preferences : public wxFrame 112 | { 113 | private: 114 | 115 | protected: 116 | wxWindowDisabler* m_Disabler; 117 | wxStaticText* m_Text_TargetName; 118 | wxTextCtrl* m_TextCtrl_TargetName; 119 | wxStaticText* m_Text_BuildFolder; 120 | wxTextCtrl* m_TextCtrl_BuildFolder; 121 | wxStaticText* m_Text_ROMHeader; 122 | wxTextCtrl* m_TextCtrl_ROMHeader_Title; 123 | wxTextCtrl* m_TextCtrl_ROMHeader_Manufacturer; 124 | wxTextCtrl* m_TextCtrl_ROMHeader_ID; 125 | wxTextCtrl* m_TextCtrl_ROMHeader_Country; 126 | wxStaticText* m_Text_GCCFlags; 127 | wxTextCtrl* m_TextCtrl_GCCFlags; 128 | wxStaticText* m_Text_LDFlags; 129 | wxTextCtrl* m_TextCtrl_LDFlags; 130 | wxStaticText* m_Text_MILDFlags; 131 | wxTextCtrl* m_TextCtrl_MILDFlags; 132 | wxStaticLine* m_StaticLine; 133 | wxStaticText* m_Text_LibultraPath; 134 | wxTextCtrl* m_TextCtrl_LibultraPath; 135 | wxStaticText* m_Text_ToolkitPath; 136 | wxTextCtrl* m_TextCtrl_ToolkitPath; 137 | wxStaticText* m_Text_MoveFolder; 138 | wxTextCtrl* m_TextCtrl_MoveFolder; 139 | wxStaticText* m_Text_DisassemblyName; 140 | wxTextCtrl* m_TextCtrl_DisassemblyName; 141 | wxCheckBox* m_CheckBox_UseEXEW32; 142 | wxCheckBox* m_CheckBox_SeparateDebug; 143 | wxCheckBox* m_CheckBox_UseBuild; 144 | wxCheckBox* m_CheckBox_UseNRDC; 145 | wxCheckBox* m_CheckBox_UseMakemask; 146 | wxCheckBox* m_CheckBox_MoveROM; 147 | wxCheckBox* m_CheckBox_PromptMoving; 148 | wxCheckBox* m_CheckBox_UploadEnabled; 149 | wxCheckBox* m_CheckBox_PromptUpload; 150 | wxCheckBox* m_CheckBox_PromptDisassembly; 151 | wxCheckBox* m_CheckBox_PromptClean; 152 | wxButton* m_Button_Close; 153 | 154 | void m_TextCtrl_TargetName_OnText(wxCommandEvent& event); 155 | void m_TextCtrl_BuildFolder_OnText(wxCommandEvent& event); 156 | void m_TextCtrl_ROMHeader_Title_OnText(wxCommandEvent& event); 157 | void m_TextCtrl_ROMHeader_Manufacturer_OnText(wxCommandEvent& event); 158 | void m_TextCtrl_ROMHeader_ID_OnText(wxCommandEvent& event); 159 | void m_TextCtrl_ROMHeader_Country_OnText(wxCommandEvent& event); 160 | void m_TextCtrl_GCCFlags_OnText(wxCommandEvent& event); 161 | void m_TextCtrl_LDFlags_OnText(wxCommandEvent& event); 162 | void m_TextCtrl_MILDFlags_OnText(wxCommandEvent& event); 163 | void m_TextCtrl_LibultraPath_OnText(wxCommandEvent& event); 164 | void m_TextCtrl_Toolkit_OnText(wxCommandEvent& event); 165 | void m_TextCtrl_MoveFolder_OnText(wxCommandEvent& event); 166 | void m_TextCtrl_DisassemblyName_OnText(wxCommandEvent& event); 167 | void m_CheckBox_UseEXEW32_OnCheckBox(wxCommandEvent& event); 168 | void m_CheckBox_SeparateDebug_OnCheckBox(wxCommandEvent& event); 169 | void m_CheckBox_UseBuild_OnCheckBox(wxCommandEvent& event); 170 | void m_CheckBox_UseNRDC_OnCheckBox(wxCommandEvent& event); 171 | void m_CheckBox_UseMakemask_OnCheckBox(wxCommandEvent& event); 172 | void m_CheckBox_MoveROM_OnCheckBox(wxCommandEvent& event); 173 | void m_CheckBox_PromptMoving_OnCheckBox(wxCommandEvent& event); 174 | void m_CheckBox_UploadEnabled_OnCheckBox(wxCommandEvent& event); 175 | void m_CheckBox_PromptUpload_OnCheckBox(wxCommandEvent& event); 176 | void m_CheckBox_PromptDisassembly_OnCheckBox(wxCommandEvent& event); 177 | void m_CheckBox_PromptClean_OnCheckBox(wxCommandEvent& event); 178 | void m_Button_Close_OnButtonClick(wxCommandEvent& event); 179 | 180 | public: 181 | Preferences(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Preferences"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(550, 550), long style = wxCAPTION | wxCLOSE_BOX | wxFRAME_NO_TASKBAR | wxRESIZE_BORDER | wxSTAY_ON_TOP | wxSYSTEM_MENU | wxTAB_TRAVERSAL); 182 | ~Preferences(); 183 | }; -------------------------------------------------------------------------------- /Tools/Builder/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Builder.rc 4 | // 5 | #define IDI_ICON1 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /Tools/Builder/resources/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Tools/Builder/resources/c.png -------------------------------------------------------------------------------- /Tools/Builder/resources/config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Tools/Builder/resources/config.png -------------------------------------------------------------------------------- /Tools/Builder/resources/generate.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | for %%f in (*.png) do ( 3 | if "%%~xf"==".png" bin2c.exe %%f icon_%%~nf.h icon_%%~nf_png 4 | ) -------------------------------------------------------------------------------- /Tools/Builder/resources/h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Tools/Builder/resources/h.png -------------------------------------------------------------------------------- /Tools/Builder/resources/icon_c.h: -------------------------------------------------------------------------------- 1 | static const unsigned char icon_c_png[699] = { 2 | 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 3 | 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 4 | 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 5 | 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 6 | 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 7 | 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 8 | 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc1, 0x00, 0x00, 0x0e, 9 | 0xc1, 0x01, 0xb8, 0x91, 0x6b, 0xed, 0x00, 0x00, 0x02, 0x50, 0x49, 10 | 0x44, 0x41, 0x54, 0x38, 0x4f, 0x63, 0xfc, 0xff, 0xff, 0x3f, 0x03, 11 | 0x25, 0x80, 0x09, 0x4a, 0x93, 0x0d, 0xe0, 0x2e, 0x60, 0x64, 0x64, 12 | 0x04, 0xd3, 0x20, 0xf0, 0xdd, 0xce, 0x4e, 0xe0, 0xf7, 0x93, 0x27, 13 | 0x8a, 0x3f, 0x05, 0x85, 0x14, 0xbe, 0xa8, 0xa8, 0x8a, 0xfe, 0xfc, 14 | 0xf6, 0xfd, 0xf5, 0x9f, 0x77, 0x6f, 0x1e, 0x7e, 0x7a, 0xfb, 0xe6, 15 | 0xe3, 0x3f, 0x43, 0x63, 0x2e, 0x06, 0x3b, 0xc7, 0xdb, 0xd6, 0x19, 16 | 0xc9, 0x3f, 0x40, 0x6a, 0x59, 0xc0, 0x3a, 0xa0, 0xe0, 0xdf, 0x89, 17 | 0x13, 0x8c, 0xff, 0xaa, 0xab, 0x65, 0x7e, 0x5e, 0xbb, 0x96, 0xff, 18 | 0x85, 0x99, 0xdd, 0xf9, 0x99, 0x90, 0x82, 0xe0, 0x6f, 0x21, 0xb9, 19 | 0x8b, 0x8c, 0x2c, 0xef, 0x5e, 0xfd, 0xfe, 0xf4, 0x9d, 0xe9, 0xf7, 20 | 0xab, 0x1b, 0xe2, 0x9f, 0x9f, 0xbc, 0x7a, 0xf3, 0xe3, 0xe3, 0x9f, 21 | 0x7a, 0xa0, 0xf2, 0x87, 0x20, 0x3d, 0xa8, 0x06, 0x54, 0x57, 0x8b, 22 | 0xff, 0xbd, 0x7c, 0xb9, 0xfc, 0xfb, 0xd7, 0x1f, 0x89, 0xb7, 0xad, 23 | 0x1c, 0xbe, 0xdd, 0x72, 0x08, 0x9a, 0xc2, 0xa6, 0x28, 0xbb, 0x84, 24 | 0xeb, 0xcd, 0xe3, 0xef, 0xcc, 0xdf, 0x76, 0x08, 0x31, 0xb0, 0x5e, 25 | 0x6f, 0x78, 0xff, 0x8b, 0x41, 0xe9, 0xe3, 0xa7, 0x3f, 0x1c, 0x50, 26 | 0x2d, 0x08, 0x03, 0xbe, 0x79, 0x78, 0x70, 0xff, 0xbc, 0x7c, 0x39, 27 | 0xf9, 0xcf, 0xfb, 0xf7, 0x71, 0xaf, 0xa4, 0x94, 0x19, 0xef, 0x98, 28 | 0xba, 0x2e, 0x7c, 0xa5, 0x6d, 0x3e, 0xb1, 0x3a, 0x40, 0xee, 0x03, 29 | 0x54, 0xc9, 0xb3, 0x79, 0x86, 0xb6, 0xcd, 0x9f, 0xc5, 0xa4, 0xe3, 30 | 0x7e, 0x32, 0xb3, 0xfc, 0x85, 0x8a, 0x21, 0x02, 0xf1, 0xf7, 0xdb, 31 | 0xb7, 0xe2, 0xbf, 0xbe, 0x7c, 0xb1, 0xfd, 0xf1, 0xe7, 0x0f, 0xf7, 32 | 0x47, 0x3e, 0xe1, 0xf7, 0xdf, 0x84, 0x25, 0x8f, 0x0b, 0xf1, 0x70, 33 | 0x7c, 0x82, 0x4a, 0x83, 0xc1, 0x6f, 0x1d, 0xe3, 0xdb, 0xbf, 0xf5, 34 | 0x2d, 0x96, 0xb2, 0x48, 0xc9, 0xbe, 0x85, 0x0a, 0x21, 0x19, 0xc0, 35 | 0xc4, 0x24, 0xfa, 0x93, 0x81, 0x41, 0xfe, 0xc7, 0xff, 0xff, 0x4c, 36 | 0xdf, 0xb9, 0xb8, 0x3f, 0x71, 0x71, 0xb1, 0x3e, 0xcb, 0x74, 0x11, 37 | 0xfb, 0x07, 0x95, 0x06, 0x83, 0xf4, 0xc5, 0x13, 0xbe, 0xb1, 0x1b, 38 | 0x5a, 0x5e, 0x14, 0x94, 0x93, 0x87, 0xb9, 0x0a, 0x61, 0xc0, 0x8f, 39 | 0x7f, 0xff, 0x98, 0xbf, 0x01, 0x35, 0x7f, 0x01, 0xb2, 0x99, 0xbf, 40 | 0xbc, 0xff, 0x27, 0xf8, 0xff, 0x33, 0xdc, 0x99, 0xc8, 0x20, 0x2f, 41 | 0x58, 0xff, 0x6f, 0x8a, 0xb7, 0x0e, 0x3c, 0xf1, 0xc0, 0x0d, 0xf8, 42 | 0xfa, 0xf3, 0xd7, 0x9b, 0x6f, 0xff, 0xfe, 0xbf, 0xf8, 0xce, 0xc0, 43 | 0xf0, 0xff, 0xf7, 0xe7, 0x0f, 0xdc, 0xef, 0x9f, 0x3e, 0x15, 0x84, 44 | 0x4a, 0xe1, 0x05, 0x08, 0x17, 0xf0, 0xf0, 0xbc, 0xfc, 0xc6, 0xce, 45 | 0x7e, 0xfa, 0x3b, 0x13, 0xd3, 0xcf, 0x1f, 0x5f, 0x3e, 0x72, 0xb3, 46 | 0x5f, 0x3b, 0x23, 0x7e, 0xf8, 0xc0, 0x31, 0x94, 0x58, 0x9a, 0x17, 47 | 0x12, 0xc2, 0x36, 0x17, 0x18, 0xd8, 0xd3, 0x1c, 0x1d, 0xe1, 0x89, 48 | 0x06, 0x9e, 0x90, 0x76, 0xba, 0xfb, 0x32, 0xfe, 0xba, 0x77, 0x4f, 49 | 0x8d, 0xe1, 0xd5, 0xf3, 0x8e, 0x5f, 0x3f, 0xbf, 0x7b, 0xfe, 0x11, 50 | 0x15, 0xdb, 0xf5, 0x4b, 0x58, 0xb8, 0xee, 0x13, 0x3f, 0xef, 0xed, 51 | 0x5f, 0xdf, 0xbf, 0x33, 0x31, 0x7e, 0xfd, 0x2a, 0xf4, 0x53, 0x40, 52 | 0x28, 0x56, 0xc8, 0xc0, 0xe4, 0x87, 0x8c, 0x8b, 0xc7, 0x6c, 0xcf, 53 | 0x40, 0xf7, 0x8f, 0x28, 0x06, 0x80, 0x52, 0xe2, 0x8c, 0xe8, 0x5c, 54 | 0x26, 0xb6, 0xf3, 0x27, 0xf5, 0xfe, 0x7e, 0x7e, 0x5f, 0xf5, 0xf7, 55 | 0xef, 0x1f, 0xa3, 0xef, 0xac, 0x2c, 0xb7, 0xff, 0xb2, 0x33, 0x5f, 56 | 0xf8, 0xcb, 0xcd, 0xcd, 0xca, 0x26, 0x2e, 0x25, 0xf5, 0x57, 0x5e, 57 | 0x95, 0x95, 0x41, 0xcd, 0x60, 0x31, 0xbf, 0x92, 0xc6, 0xae, 0x94, 58 | 0x00, 0x53, 0x70, 0x4a, 0xc4, 0x48, 0xca, 0x2d, 0x31, 0xb5, 0x8c, 59 | 0xcc, 0x1f, 0x9e, 0xca, 0xfe, 0xf9, 0xf1, 0xdd, 0xf4, 0x37, 0x23, 60 | 0xa3, 0x21, 0x3b, 0x1f, 0x97, 0x24, 0x03, 0x3f, 0xef, 0x2f, 0x4e, 61 | 0x49, 0xa9, 0x5b, 0x4c, 0x0a, 0x5a, 0x7b, 0x3f, 0xb2, 0x0a, 0xdc, 62 | 0xaa, 0x4f, 0xb0, 0x06, 0x46, 0x16, 0x54, 0x1f, 0x8c, 0x41, 0x2e, 63 | 0x80, 0x07, 0x22, 0x79, 0x80, 0x81, 0x01, 0x00, 0xc4, 0x5b, 0x04, 64 | 0x62, 0xa2, 0x91, 0x22, 0x18, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 65 | 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 66 | }; 67 | 68 | const int icon_c_png_length = 699; 69 | -------------------------------------------------------------------------------- /Tools/Builder/resources/icon_h.h: -------------------------------------------------------------------------------- 1 | static const unsigned char icon_h_png[586] = { 2 | 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 3 | 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 4 | 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 5 | 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 6 | 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 7 | 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 8 | 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc1, 0x00, 0x00, 0x0e, 9 | 0xc1, 0x01, 0xb8, 0x91, 0x6b, 0xed, 0x00, 0x00, 0x01, 0xdf, 0x49, 10 | 0x44, 0x41, 0x54, 0x38, 0x4f, 0xc5, 0x93, 0xcd, 0x6b, 0xd4, 0x40, 11 | 0x18, 0xc6, 0xe7, 0x23, 0x93, 0x6c, 0xb6, 0xdb, 0x6e, 0xbb, 0x1f, 12 | 0xad, 0xc5, 0x96, 0x42, 0x41, 0x28, 0xa5, 0x8a, 0xa0, 0xbd, 0x48, 13 | 0xa5, 0x37, 0xaf, 0x9e, 0xea, 0xdd, 0x9b, 0xd0, 0xbf, 0xa0, 0x05, 14 | 0x6f, 0xe2, 0x41, 0xf0, 0xea, 0x49, 0xef, 0x1e, 0x04, 0xfd, 0x13, 15 | 0x04, 0xa1, 0x37, 0x2b, 0xf5, 0xd6, 0x52, 0xa1, 0x58, 0x0a, 0x5b, 16 | 0xdd, 0x2d, 0xd9, 0x26, 0xf3, 0x95, 0x4d, 0x66, 0x3a, 0xb3, 0x4c, 17 | 0x17, 0xc6, 0xf6, 0xa4, 0x07, 0x1f, 0x98, 0x0c, 0x99, 0x3c, 0xef, 18 | 0x6f, 0x9e, 0x79, 0x93, 0x40, 0xad, 0x35, 0xf8, 0x17, 0x21, 0x37, 19 | 0xff, 0xbd, 0x6c, 0x82, 0xcb, 0x14, 0xe3, 0xf7, 0xe5, 0x4c, 0x7c, 20 | 0x27, 0x7d, 0x09, 0x16, 0x7b, 0x87, 0xf1, 0xca, 0xe9, 0xce, 0xfa, 21 | 0xb3, 0x5f, 0x8f, 0x37, 0x3f, 0xca, 0x6b, 0x37, 0xb9, 0xac, 0xf3, 22 | 0x1e, 0x3e, 0x7c, 0x94, 0xf5, 0xaa, 0x63, 0x6c, 0x17, 0x00, 0xb1, 23 | 0x10, 0x45, 0x72, 0xa5, 0xd1, 0x2a, 0xef, 0x36, 0x08, 0xc3, 0xee, 24 | 0xf1, 0xb5, 0xf2, 0x00, 0x5f, 0x3f, 0x67, 0xaa, 0x7f, 0xc6, 0xfa, 25 | 0x40, 0x71, 0x0d, 0xb5, 0x40, 0x10, 0x16, 0xe4, 0xe7, 0x41, 0x86, 26 | 0xc2, 0xa5, 0xdd, 0xa0, 0xfe, 0xe0, 0x3b, 0x74, 0x36, 0x4f, 0x1e, 27 | 0x40, 0x72, 0x06, 0xb4, 0x29, 0x06, 0x8a, 0x42, 0x55, 0x32, 0x74, 28 | 0x72, 0x94, 0x2e, 0xbe, 0x7f, 0xf3, 0xe3, 0x55, 0x41, 0xbb, 0x6f, 29 | 0x11, 0xed, 0x3e, 0xdd, 0x78, 0xb1, 0x5f, 0x73, 0xd6, 0x91, 0x3c, 30 | 0x80, 0x56, 0x02, 0x98, 0xdd, 0x21, 0xd0, 0x4c, 0x4b, 0x4e, 0x49, 31 | 0xd2, 0x13, 0xf7, 0x66, 0xe7, 0xc8, 0x1a, 0x82, 0xf2, 0x89, 0xa0, 32 | 0xe9, 0xf3, 0xe4, 0x54, 0xac, 0x6d, 0x7f, 0xe8, 0x10, 0x67, 0x1f, 33 | 0xea, 0x6a, 0x83, 0x94, 0x80, 0x16, 0x42, 0x48, 0xae, 0x96, 0x6e, 34 | 0x57, 0x0f, 0xdb, 0xb3, 0xf8, 0x1d, 0xd0, 0xbc, 0x33, 0x90, 0x74, 35 | 0x5e, 0x32, 0xbe, 0x8e, 0x31, 0xf1, 0x52, 0xf8, 0x00, 0x95, 0x99, 36 | 0x18, 0xd4, 0x24, 0xa0, 0x1a, 0x43, 0x31, 0xc0, 0xb8, 0xdc, 0xdb, 37 | 0xdf, 0x3b, 0xfe, 0x56, 0xe4, 0x29, 0x05, 0x05, 0x45, 0x18, 0x96, 38 | 0x37, 0x30, 0x56, 0x55, 0xe7, 0x1e, 0xca, 0x3f, 0x82, 0x2e, 0xcd, 39 | 0x45, 0x1a, 0x90, 0xed, 0x85, 0x30, 0xa3, 0x54, 0x26, 0x91, 0x79, 40 | 0x5f, 0xdc, 0x7c, 0x70, 0xcc, 0x38, 0x8a, 0x2b, 0x8d, 0xfc, 0x23, 41 | 0x81, 0x2d, 0x36, 0x7d, 0xb0, 0x05, 0x16, 0x30, 0x04, 0xe6, 0xf6, 42 | 0x48, 0x76, 0xcd, 0x0c, 0x7b, 0xef, 0xbc, 0x4e, 0x1e, 0x40, 0xd0, 43 | 0x73, 0x63, 0xa6, 0x15, 0x33, 0x80, 0x1a, 0x64, 0x30, 0x17, 0x3c, 44 | 0x54, 0x05, 0xab, 0x00, 0x9d, 0x05, 0x76, 0x2d, 0x97, 0x0c, 0x49, 45 | 0x31, 0x40, 0x5b, 0x9f, 0xba, 0xa3, 0x24, 0x1e, 0x00, 0xe3, 0xbc, 46 | 0x5e, 0x1b, 0x87, 0xcb, 0xcd, 0x99, 0x30, 0x99, 0x98, 0x42, 0xe2, 47 | 0x3c, 0xe9, 0xcf, 0x4d, 0x4c, 0x46, 0xab, 0x8d, 0x76, 0x8c, 0x9a, 48 | 0xd3, 0x71, 0x2a, 0x68, 0x32, 0x75, 0x74, 0xd0, 0x69, 0xf1, 0xa4, 49 | 0x1c, 0x01, 0x02, 0x37, 0x0f, 0x35, 0x7f, 0xab, 0xc1, 0x6f, 0x2e, 50 | 0xc4, 0x5f, 0x9a, 0xed, 0x98, 0xe3, 0x00, 0x86, 0x95, 0x6a, 0xf8, 51 | 0xbb, 0xde, 0x1c, 0x3b, 0x26, 0x41, 0xf1, 0x3a, 0x8a, 0x70, 0x9d, 52 | 0x44, 0xe1, 0xd9, 0x64, 0xab, 0x46, 0xc3, 0x10, 0x8e, 0x00, 0xff, 53 | 0xfb, 0x6f, 0x04, 0xe0, 0x02, 0x50, 0x70, 0xf0, 0xb6, 0xc5, 0x4b, 54 | 0xe1, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 55 | 0x42, 0x60, 0x82 56 | }; 57 | 58 | const int icon_h_png_length = 586; 59 | -------------------------------------------------------------------------------- /Tools/Builder/resources/icon_prog.h: -------------------------------------------------------------------------------- 1 | static const unsigned char icon_prog_png[4190] = { 2 | 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 3 | 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 4 | 0x00, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0xaa, 0x69, 0x71, 0xde, 5 | 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 6 | 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 7 | 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x09, 8 | 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0e, 0xc3, 0x00, 0x00, 0x0e, 9 | 0xc3, 0x01, 0xc7, 0x6f, 0xa8, 0x64, 0x00, 0x00, 0x0f, 0xf3, 0x49, 10 | 0x44, 0x41, 0x54, 0x78, 0x5e, 0xed, 0x9b, 0x09, 0x78, 0x14, 0x45, 11 | 0x16, 0xc7, 0x5f, 0xf7, 0xf4, 0x4c, 0x26, 0x21, 0x64, 0x02, 0x04, 12 | 0x0c, 0x08, 0x26, 0x9c, 0xca, 0x8d, 0x72, 0xc8, 0x27, 0x08, 0xb8, 13 | 0xe8, 0x1a, 0x54, 0x50, 0x51, 0x51, 0x3c, 0x21, 0xdc, 0x72, 0xac, 14 | 0x10, 0x4e, 0x25, 0xac, 0x1c, 0x2a, 0x28, 0xa7, 0x12, 0x20, 0x80, 15 | 0x41, 0x40, 0x51, 0xb9, 0x04, 0x05, 0x14, 0x45, 0x64, 0x97, 0x4b, 16 | 0x09, 0xe1, 0x08, 0x81, 0x10, 0x92, 0x40, 0x2e, 0x08, 0x49, 0x26, 17 | 0xd7, 0xdc, 0x57, 0x77, 0xef, 0x7b, 0x33, 0x43, 0x98, 0xc9, 0x74, 18 | 0xc2, 0x4c, 0x32, 0x61, 0xf9, 0xbe, 0xdd, 0xdf, 0xf7, 0xfd, 0x33, 19 | 0x5d, 0xd5, 0x67, 0xbd, 0xae, 0x7a, 0xf5, 0xaa, 0xba, 0x02, 0xff, 20 | 0xe7, 0x7f, 0x1c, 0xc6, 0xf9, 0xeb, 0x4f, 0x64, 0x28, 0xd6, 0xb1, 21 | 0x09, 0x02, 0x8a, 0x77, 0x6c, 0xde, 0x9b, 0xf8, 0xcb, 0x00, 0xcc, 22 | 0xa6, 0xdd, 0x47, 0x4f, 0x2b, 0x83, 0x02, 0xbb, 0x32, 0x22, 0xb0, 23 | 0xa2, 0x20, 0x82, 0xc9, 0x6c, 0x85, 0x9c, 0x9c, 0xec, 0xf3, 0x5f, 24 | 0xaf, 0xfb, 0x74, 0x61, 0xfa, 0xe5, 0xb3, 0xc7, 0xf0, 0x98, 0x42, 25 | 0x3a, 0x0e, 0x25, 0xd2, 0x09, 0xf7, 0x0a, 0xf4, 0xb6, 0x6a, 0xcd, 26 | 0x98, 0xf7, 0x16, 0x35, 0x6d, 0xdc, 0xb4, 0xe5, 0x52, 0x8b, 0x55, 27 | 0x64, 0x4f, 0xff, 0x16, 0xc8, 0xe4, 0x66, 0x70, 0x4c, 0xfe, 0x35, 28 | 0x05, 0x63, 0x28, 0x69, 0x12, 0xde, 0xba, 0xe5, 0x90, 0x61, 0x89, 29 | 0x89, 0xf1, 0xda, 0x37, 0x47, 0xc7, 0xe4, 0x4e, 0x9f, 0xb7, 0x34, 30 | 0x51, 0xaf, 0xd5, 0x9a, 0x32, 0xd3, 0x2f, 0x15, 0xe1, 0x69, 0x7a, 31 | 0x14, 0xd5, 0x90, 0xff, 0x2a, 0xb7, 0xaa, 0xaa, 0xd7, 0x7c, 0x16, 32 | 0xbf, 0xab, 0xe7, 0xb7, 0x3f, 0xfe, 0x95, 0xfb, 0xfa, 0xa8, 0x7f, 33 | 0xcc, 0xc1, 0x64, 0x3b, 0x94, 0xbc, 0x41, 0x78, 0x8b, 0x2e, 0x26, 34 | 0x2b, 0x0f, 0x06, 0x23, 0x0f, 0x2c, 0x5e, 0xd1, 0x5d, 0x2c, 0xbd, 35 | 0xf5, 0x88, 0x27, 0x9e, 0x7d, 0x39, 0xdd, 0x26, 0xca, 0x5a, 0x47, 36 | 0x0d, 0x9e, 0x15, 0x3f, 0x69, 0xd2, 0xd9, 0xab, 0xbd, 0x7a, 0x4d, 37 | 0x58, 0x84, 0xf9, 0xad, 0x50, 0x7e, 0x79, 0x09, 0x35, 0xc5, 0x97, 38 | 0x26, 0xc0, 0x7c, 0xb5, 0xe7, 0xe4, 0x31, 0x86, 0x95, 0x3d, 0x66, 39 | 0xc5, 0xc2, 0xe6, 0xa4, 0x2a, 0xe0, 0x66, 0x8e, 0x51, 0xb7, 0x7e, 40 | 0x7d, 0xdf, 0x77, 0x16, 0x7c, 0xb1, 0xbb, 0xbf, 0xaa, 0x61, 0x93, 41 | 0x29, 0xda, 0xa2, 0x00, 0x50, 0x67, 0x29, 0x9d, 0x87, 0xdf, 0xa6, 42 | 0xe9, 0x43, 0xe9, 0x46, 0x55, 0xc3, 0xa6, 0x81, 0x26, 0xb3, 0x00, 43 | 0x59, 0x49, 0x21, 0xce, 0x5c, 0x00, 0xab, 0xd5, 0x6c, 0x5e, 0xbb, 44 | 0xb6, 0xef, 0x28, 0x41, 0x30, 0xed, 0xc3, 0x64, 0xb9, 0x23, 0xf7, 45 | 0xee, 0xe2, 0x95, 0x01, 0xba, 0x77, 0xef, 0x2e, 0x9f, 0x18, 0x1b, 46 | 0x67, 0x14, 0x04, 0x90, 0x19, 0x8c, 0x54, 0x88, 0xfa, 0x98, 0xeb, 47 | 0x38, 0x35, 0x3d, 0xfd, 0x8f, 0xac, 0xa8, 0xd7, 0xba, 0x84, 0x09, 48 | 0xac, 0x3c, 0xf8, 0xe6, 0x95, 0x40, 0x30, 0x96, 0xcb, 0xed, 0xf9, 49 | 0xae, 0x74, 0xec, 0xab, 0x07, 0x83, 0x99, 0x87, 0x6b, 0x89, 0xb7, 50 | 0xcf, 0x73, 0x65, 0xf9, 0xf2, 0x4e, 0x1f, 0xe0, 0xcf, 0xe7, 0x28, 51 | 0x9d, 0x3d, 0xe3, 0x2e, 0xe2, 0x55, 0x13, 0x18, 0x36, 0x7e, 0x51, 52 | 0x92, 0x4e, 0x6f, 0x91, 0x95, 0x95, 0x00, 0x64, 0x9f, 0x09, 0x01, 53 | 0x86, 0x61, 0x50, 0x58, 0x14, 0x54, 0xbb, 0x76, 0x4f, 0x44, 0x9a, 54 | 0x0d, 0xc1, 0xc1, 0x94, 0x30, 0xeb, 0xb8, 0x8a, 0x7c, 0x57, 0x5d, 55 | 0x3a, 0x5e, 0x0f, 0xb2, 0x4e, 0xbb, 0x9f, 0x77, 0x4b, 0x79, 0x79, 56 | 0x7f, 0x19, 0xf1, 0x16, 0xf7, 0xa3, 0x30, 0x75, 0xf7, 0xf1, 0xaa, 57 | 0xfd, 0xd5, 0x0f, 0x69, 0x90, 0x73, 0x5f, 0xf3, 0x56, 0xaf, 0x6b, 58 | 0x6f, 0xaa, 0x80, 0xb7, 0x50, 0x21, 0xa9, 0x20, 0xb7, 0xa5, 0x2b, 59 | 0xe6, 0xa0, 0x3c, 0x3f, 0x00, 0x4b, 0xe0, 0x9e, 0xef, 0x8d, 0x36, 60 | 0x6c, 0x88, 0x4a, 0xc3, 0x5b, 0xac, 0x41, 0x5d, 0x43, 0xd1, 0x0b, 61 | 0xb9, 0xab, 0xdd, 0xa6, 0xb7, 0x56, 0x0f, 0xf9, 0x68, 0xdd, 0xfe, 62 | 0x72, 0x05, 0xd7, 0x00, 0xd4, 0xe9, 0xa1, 0xce, 0xac, 0xda, 0x53, 63 | 0x5c, 0x96, 0x65, 0x2d, 0x2a, 0xf9, 0xfe, 0xca, 0xab, 0x23, 0x27, 64 | 0x3d, 0xc4, 0xdb, 0x78, 0x36, 0x37, 0x37, 0xff, 0x6a, 0xec, 0x94, 65 | 0x97, 0xdf, 0xe5, 0x79, 0x9e, 0xba, 0x4d, 0x83, 0xe3, 0xa8, 0xba, 66 | 0xc5, 0x5b, 0x03, 0xb0, 0x8b, 0xd6, 0xee, 0xb3, 0xd6, 0x0b, 0x0e, 67 | 0x61, 0x8b, 0x52, 0x1b, 0x3b, 0xb3, 0x6a, 0x0f, 0xc3, 0x8a, 0xd0, 68 | 0xb6, 0xa7, 0x0e, 0x34, 0xa5, 0x0c, 0x14, 0x64, 0x06, 0x81, 0xc8, 69 | 0xb3, 0x50, 0x5e, 0x7e, 0x43, 0x17, 0x17, 0x37, 0x70, 0x04, 0xee, 70 | 0xfe, 0x01, 0x55, 0xe7, 0xdd, 0xa4, 0xa4, 0x0f, 0x88, 0x8e, 0x9e, 71 | 0x51, 0x7f, 0xd2, 0xb4, 0xf9, 0xaf, 0xe0, 0x66, 0x4b, 0x54, 0x00, 72 | 0x4a, 0xe0, 0xcd, 0xe6, 0xef, 0x19, 0xec, 0xd7, 0x38, 0x85, 0x20, 73 | 0xd1, 0xd5, 0xd5, 0x4c, 0xd8, 0x08, 0x20, 0x03, 0x1d, 0x63, 0x61, 74 | 0x06, 0xba, 0x10, 0x91, 0xb5, 0xe7, 0x35, 0x68, 0xd0, 0x2c, 0x38, 75 | 0x22, 0xa2, 0xd7, 0x04, 0xbc, 0x27, 0x75, 0x91, 0x75, 0x8e, 0x64, 76 | 0x0d, 0xd8, 0xb0, 0xe3, 0x78, 0xa9, 0x32, 0x40, 0x1e, 0x6a, 0xd6, 77 | 0x2b, 0x20, 0xf5, 0x5c, 0x59, 0x5a, 0x76, 0xde, 0xce, 0xcf, 0xa3, 78 | 0x5e, 0x7a, 0x73, 0xb5, 0xc9, 0x22, 0x32, 0xa5, 0x39, 0xc1, 0x60, 79 | 0xd5, 0x79, 0x7a, 0x7a, 0x77, 0x04, 0xd1, 0x62, 0xb1, 0x88, 0x5a, 80 | 0xad, 0xda, 0x1a, 0x1a, 0x1a, 0x2e, 0x97, 0xc9, 0x38, 0x2c, 0x9a, 81 | 0xf7, 0x88, 0x22, 0x2f, 0x2e, 0x5c, 0xd8, 0x71, 0x2a, 0x6e, 0x92, 82 | 0x6f, 0xb0, 0xda, 0x33, 0xeb, 0x08, 0x0f, 0x03, 0xcc, 0x5d, 0xbc, 83 | 0xb9, 0x7d, 0xb3, 0xc8, 0x36, 0x97, 0x78, 0xac, 0x7c, 0x25, 0xe9, 84 | 0x61, 0xce, 0x5c, 0x07, 0x9c, 0xd2, 0x06, 0x36, 0x13, 0xe7, 0x4c, 85 | 0x79, 0xa2, 0xd1, 0xa8, 0x6d, 0xab, 0x56, 0x3d, 0x99, 0x6e, 0xb3, 86 | 0x19, 0x2f, 0x60, 0xf2, 0x2c, 0x2a, 0x1b, 0xc5, 0x3c, 0xd4, 0xf5, 87 | 0xd1, 0x81, 0xaf, 0xbc, 0xba, 0x28, 0x9a, 0xb3, 0x3e, 0x40, 0x87, 88 | 0x79, 0xc5, 0xe2, 0xc5, 0x7d, 0x7e, 0x33, 0x1a, 0xd5, 0x63, 0x71, 89 | 0x33, 0xcb, 0x91, 0x53, 0x37, 0x78, 0xf4, 0x02, 0xc3, 0x46, 0x4c, 90 | 0x4d, 0x11, 0x19, 0x36, 0xd8, 0xac, 0x53, 0x00, 0x6f, 0x50, 0xba, 91 | 0x79, 0x6c, 0x91, 0x97, 0xb9, 0xa5, 0x5d, 0xb5, 0x7d, 0x7b, 0x4c, 92 | 0xe1, 0xde, 0xbd, 0xb3, 0x7f, 0x11, 0x04, 0xdb, 0x32, 0xbc, 0xcc, 93 | 0x7a, 0xd4, 0xef, 0xa8, 0x64, 0xd4, 0x05, 0x75, 0xc1, 0xf5, 0x3f, 94 | 0x4c, 0xd6, 0x62, 0x73, 0xbb, 0x1e, 0x0f, 0x0c, 0x60, 0xcd, 0x8d, 95 | 0x25, 0xcf, 0xaf, 0xac, 0x43, 0x87, 0x56, 0x68, 0xb0, 0x26, 0x1c, 96 | 0xc5, 0xf3, 0x73, 0x51, 0x75, 0x86, 0x5b, 0xd5, 0x6c, 0x13, 0x15, 97 | 0x15, 0x60, 0x15, 0xc4, 0xfb, 0x78, 0x1c, 0xcc, 0x58, 0xd4, 0x2a, 98 | 0x90, 0xc9, 0x18, 0xaf, 0xb4, 0x72, 0xe5, 0x53, 0x39, 0x29, 0x29, 99 | 0xfb, 0xbe, 0xc6, 0x4b, 0xcc, 0x46, 0x51, 0x54, 0x47, 0xb1, 0xbe, 100 | 0x6b, 0x77, 0xa6, 0x3d, 0xf5, 0xef, 0x03, 0x4b, 0x8b, 0x8b, 0xf2, 101 | 0x2f, 0xc8, 0x9b, 0x66, 0x4b, 0x5e, 0xc3, 0x55, 0xf3, 0xe7, 0x77, 102 | 0x4d, 0x13, 0x04, 0xcb, 0x37, 0x78, 0x5e, 0x8a, 0xe3, 0xf4, 0xba, 103 | 0xc3, 0xcd, 0x00, 0x7f, 0xeb, 0xf6, 0xd4, 0x13, 0xc5, 0xea, 0x02, 104 | 0x30, 0xe8, 0xf4, 0xe8, 0x90, 0xc8, 0x29, 0x31, 0x77, 0x54, 0x42, 105 | 0xc2, 0x3b, 0x37, 0x8b, 0x8b, 0xb3, 0x77, 0xe1, 0xe9, 0x9f, 0xa1, 106 | 0xae, 0xa2, 0xaa, 0x1a, 0xed, 0xe9, 0xe3, 0x97, 0x4c, 0x1d, 0x62, 107 | 0xb5, 0x98, 0x40, 0xd1, 0xa8, 0x5c, 0xf2, 0x5a, 0xd4, 0xfa, 0x63, 108 | 0x63, 0x3b, 0xa5, 0x61, 0x13, 0xda, 0x80, 0x89, 0x8d, 0x28, 0x0d, 109 | 0x9d, 0x58, 0x97, 0xb8, 0x19, 0x60, 0xfd, 0xe2, 0x98, 0x23, 0x71, 110 | 0x0b, 0x27, 0x8f, 0x2b, 0x56, 0xe7, 0x0b, 0x32, 0x6c, 0x1c, 0x52, 111 | 0x6f, 0xc7, 0x55, 0xf9, 0xf9, 0x97, 0x2c, 0x19, 0x19, 0x27, 0xa8, 112 | 0xcf, 0x5e, 0x8d, 0xba, 0x69, 0xbf, 0x48, 0x35, 0x98, 0xcd, 0xe6, 113 | 0x5c, 0x9b, 0xcd, 0xa2, 0x65, 0x94, 0x3a, 0xc9, 0xeb, 0x1d, 0x3d, 114 | 0xba, 0x5e, 0xc3, 0xf3, 0xe6, 0x9f, 0xf0, 0xd0, 0x6d, 0xa8, 0xff, 115 | 0x5a, 0x1c, 0x40, 0xdd, 0x5e, 0xdf, 0xa9, 0x0b, 0xe2, 0x77, 0xde, 116 | 0x1f, 0xd2, 0x2f, 0x94, 0x15, 0x28, 0x29, 0xcd, 0xb4, 0x69, 0xad, 117 | 0xd1, 0xd9, 0x89, 0x34, 0x2a, 0x3c, 0x80, 0xf2, 0x6a, 0x9c, 0x3f, 118 | 0x39, 0x36, 0x6e, 0x41, 0x44, 0xeb, 0xf6, 0xb1, 0xac, 0x06, 0xa3, 119 | 0x5f, 0x5b, 0xa5, 0xde, 0x84, 0x11, 0x21, 0xec, 0x01, 0x2d, 0x58, 120 | 0x6c, 0x56, 0xb8, 0x59, 0x90, 0x97, 0xbe, 0xfb, 0xdb, 0xb5, 0x4b, 121 | 0xcf, 0x9c, 0xfc, 0xf5, 0x47, 0xdc, 0x73, 0x47, 0xe3, 0xd6, 0x14, 122 | 0xa9, 0xee, 0xc9, 0x8c, 0x3a, 0xbc, 0x62, 0xde, 0xb8, 0xfe, 0xb2, 123 | 0xb0, 0x22, 0x90, 0x85, 0x68, 0x81, 0xc5, 0xb7, 0x53, 0x59, 0xd9, 124 | 0xd9, 0x49, 0x78, 0x9c, 0x78, 0x02, 0x8f, 0xa5, 0x1a, 0xe0, 0xf5, 125 | 0x24, 0x47, 0x71, 0x61, 0xde, 0x41, 0x3a, 0x5a, 0x16, 0x8c, 0xcd, 126 | 0xac, 0xf2, 0x75, 0xd1, 0xf9, 0x15, 0x5c, 0x53, 0x42, 0xfe, 0xc5, 127 | 0x5c, 0xe8, 0x2b, 0x5f, 0xda, 0x76, 0x68, 0x8f, 0xfa, 0x6b, 0xf1, 128 | 0x94, 0x25, 0xa8, 0x2e, 0x28, 0xcf, 0x61, 0xa6, 0x1f, 0xa8, 0x5c, 129 | 0x03, 0x28, 0x1d, 0x30, 0x66, 0xe2, 0xdc, 0xb6, 0xbd, 0x07, 0x3c, 130 | 0xbd, 0xcd, 0x22, 0xca, 0x3b, 0xd9, 0x78, 0x7c, 0x5a, 0x75, 0x53, 131 | 0xc7, 0x5e, 0x17, 0x66, 0xcf, 0x7e, 0x24, 0x53, 0xaf, 0x2f, 0x99, 132 | 0x89, 0x9b, 0xbb, 0x1d, 0x39, 0xde, 0xd1, 0xff, 0xc5, 0x37, 0x9a, 133 | 0x0f, 0x7e, 0x7e, 0x54, 0xae, 0x5c, 0xa1, 0x04, 0xb6, 0xb8, 0x99, 134 | 0x3d, 0x8f, 0xe7, 0xad, 0xa0, 0xd7, 0x5c, 0x85, 0xae, 0x21, 0x71, 135 | 0xd0, 0xbf, 0xe5, 0x4f, 0x68, 0x08, 0x77, 0x7b, 0xde, 0x2c, 0x65, 136 | 0xca, 0x57, 0xec, 0x12, 0xf7, 0xac, 0xfe, 0x11, 0xa8, 0x79, 0x50, 137 | 0x17, 0x4b, 0xe3, 0x06, 0xbf, 0xc4, 0x07, 0x15, 0x06, 0xf8, 0x7c, 138 | 0xf3, 0xc1, 0x77, 0x1b, 0x35, 0x0a, 0x5d, 0xcd, 0xb2, 0x1c, 0x43, 139 | 0x85, 0x36, 0xe9, 0x39, 0x0c, 0x78, 0x02, 0x01, 0x2c, 0xd2, 0x86, 140 | 0x7f, 0xf7, 0xdd, 0x88, 0x3f, 0xf0, 0x67, 0x34, 0x8a, 0x1c, 0x9f, 141 | 0xd7, 0x0c, 0x79, 0x6d, 0x62, 0xb3, 0x01, 0xcf, 0x0c, 0xbb, 0xce, 142 | 0xc9, 0x15, 0xc0, 0x95, 0x36, 0x03, 0xab, 0xd5, 0x04, 0x17, 0x83, 143 | 0x7a, 0xc0, 0xc2, 0xc6, 0x3a, 0x08, 0xc6, 0xd0, 0xb8, 0x2a, 0x44, 144 | 0xdc, 0x75, 0x24, 0xb9, 0xbd, 0xf8, 0xf2, 0x02, 0xf9, 0xef, 0x26, 145 | 0x6b, 0xf2, 0x66, 0xcc, 0xfa, 0x1e, 0x55, 0x6b, 0x23, 0x54, 0x34, 146 | 0x01, 0xa3, 0x4d, 0x1c, 0x5d, 0xa6, 0xb3, 0x32, 0x65, 0x37, 0x83, 147 | 0xc0, 0x70, 0xa3, 0x09, 0x08, 0xe5, 0x0d, 0x41, 0xc6, 0x07, 0x4a, 148 | 0x3a, 0x2b, 0xab, 0x55, 0x47, 0x31, 0x7a, 0x26, 0x8a, 0xe6, 0xf9, 149 | 0x7c, 0xa2, 0x65, 0xfb, 0xce, 0x2d, 0x1c, 0x1e, 0xdf, 0xe1, 0x64, 150 | 0x4f, 0x9a, 0x16, 0x41, 0x92, 0xa0, 0x85, 0x67, 0x0a, 0x44, 0xe8, 151 | 0x97, 0x0f, 0xb0, 0x57, 0xcf, 0x82, 0xc5, 0xc5, 0x0e, 0x1a, 0x8c, 152 | 0x45, 0x26, 0xaf, 0x79, 0x1b, 0x82, 0x9f, 0x8f, 0x87, 0xe7, 0x62, 153 | 0xdf, 0x63, 0x4c, 0x56, 0x8e, 0xa2, 0xa9, 0xbe, 0x28, 0x95, 0xfd, 154 | 0x80, 0x5a, 0x52, 0x61, 0x00, 0x1b, 0x0f, 0x91, 0x66, 0x2b, 0xc6, 155 | 0xf9, 0x20, 0xf7, 0x28, 0x70, 0x65, 0x69, 0xb5, 0x45, 0x36, 0x3c, 156 | 0x25, 0x0f, 0x65, 0xb2, 0x9f, 0xec, 0x03, 0x8d, 0x1a, 0x36, 0xf9, 157 | 0x1b, 0x75, 0xb1, 0x8c, 0xc0, 0x81, 0xd1, 0x5c, 0x06, 0xe9, 0xaa, 158 | 0xad, 0xce, 0x3d, 0x0e, 0x96, 0x69, 0x04, 0x78, 0x12, 0x5d, 0xde, 159 | 0x6b, 0xf9, 0x72, 0x68, 0x33, 0xe2, 0x53, 0x68, 0xfa, 0xda, 0x2a, 160 | 0x48, 0xf8, 0xa5, 0x8f, 0x73, 0x6f, 0x05, 0x14, 0x8e, 0x4a, 0x39, 161 | 0x70, 0x57, 0xee, 0xb4, 0xdf, 0xce, 0x6d, 0x27, 0x28, 0x08, 0x06, 162 | 0xf4, 0x41, 0x20, 0xc3, 0x87, 0x93, 0x2a, 0xb4, 0xab, 0x0c, 0xc6, 163 | 0x32, 0x0a, 0x72, 0x68, 0x0a, 0xab, 0xba, 0xd1, 0x1a, 0x87, 0x0d, 164 | 0xa8, 0x99, 0x5c, 0x0e, 0x8f, 0xe0, 0x76, 0x7b, 0x54, 0x30, 0x65, 165 | 0x86, 0xa8, 0x1a, 0x4c, 0xa7, 0x48, 0x4f, 0xc1, 0xd7, 0x87, 0xc3, 166 | 0xd6, 0x69, 0x55, 0x3e, 0xe6, 0x91, 0x25, 0xd3, 0x21, 0xbf, 0xc4, 167 | 0xe7, 0x97, 0x4c, 0x57, 0x0b, 0x3b, 0xb2, 0x54, 0xb6, 0xbc, 0x73, 168 | 0x1b, 0x8e, 0x06, 0x54, 0x4f, 0xa1, 0x68, 0xb2, 0xa5, 0xca, 0x79, 169 | 0x8f, 0x0a, 0x03, 0x18, 0xf4, 0x9a, 0x1c, 0x8b, 0xd9, 0xe4, 0x08, 170 | 0x4a, 0xb0, 0x90, 0xd5, 0x29, 0x28, 0x30, 0x88, 0x6e, 0x24, 0x55, 171 | 0x78, 0xae, 0xed, 0x03, 0xd0, 0x6a, 0x7b, 0xac, 0x6c, 0x41, 0xe1, 172 | 0x0e, 0x50, 0x17, 0xed, 0x85, 0xeb, 0xa5, 0x3b, 0x21, 0xe9, 0xda, 173 | 0x16, 0xe6, 0xd4, 0x88, 0xbf, 0xc3, 0x17, 0xb8, 0x7f, 0x68, 0x69, 174 | 0x71, 0x41, 0x43, 0x1b, 0x56, 0x37, 0x7d, 0x59, 0x09, 0x5c, 0x0f, 175 | 0x3e, 0xe4, 0x38, 0xab, 0x12, 0xd6, 0xe2, 0x30, 0xd0, 0x5e, 0x8d, 176 | 0x74, 0xa6, 0xbc, 0x42, 0x3e, 0x69, 0x30, 0xd7, 0x27, 0xe3, 0x2b, 177 | 0x36, 0x51, 0xbb, 0x07, 0x0a, 0x7b, 0xb6, 0xe3, 0xa7, 0xfe, 0xb9, 178 | 0xdc, 0x16, 0x57, 0xfe, 0x03, 0x1c, 0xdc, 0xf5, 0x4f, 0xf6, 0xe7, 179 | 0x0e, 0x2d, 0x60, 0x3a, 0x1e, 0x43, 0xd5, 0x88, 0x06, 0x37, 0x6e, 180 | 0x26, 0xaf, 0x48, 0x4c, 0x7c, 0x3f, 0x6e, 0x7d, 0x60, 0xbd, 0xa0, 181 | 0x31, 0x6d, 0xc2, 0x7b, 0x42, 0x70, 0x40, 0x43, 0x67, 0xae, 0x34, 182 | 0x3a, 0x5d, 0x39, 0x3f, 0x7e, 0x7c, 0xfb, 0x0f, 0x71, 0xf3, 0x13, 183 | 0x94, 0x3d, 0xe4, 0x9d, 0x30, 0x4f, 0xf5, 0xca, 0xa2, 0x2e, 0xe5, 184 | 0x1b, 0x95, 0x0a, 0xb8, 0x3d, 0xeb, 0x59, 0x09, 0x01, 0x4d, 0x76, 185 | 0x2a, 0x2b, 0x1c, 0x12, 0xce, 0x0f, 0x81, 0xec, 0x8e, 0x3f, 0x83, 186 | 0xb1, 0xbe, 0x74, 0x98, 0x7f, 0x7e, 0xda, 0x72, 0xb0, 0xe9, 0xeb, 187 | 0x39, 0x53, 0x95, 0x89, 0xbf, 0x02, 0x70, 0x86, 0xc6, 0x08, 0x14, 188 | 0x7f, 0x94, 0xec, 0xf9, 0x90, 0x9b, 0xd6, 0xaf, 0x93, 0xed, 0xc3, 189 | 0x00, 0x05, 0x04, 0xd9, 0x77, 0x57, 0x81, 0xc1, 0x04, 0xb6, 0x67, 190 | 0xe6, 0x75, 0x39, 0x90, 0x78, 0x39, 0x39, 0x01, 0x93, 0x14, 0xb7, 191 | 0xd8, 0x1d, 0x68, 0x45, 0xd5, 0x48, 0x3c, 0x7a, 0xe0, 0xd8, 0x89, 192 | 0xc3, 0x7b, 0xf3, 0x32, 0xaf, 0x9e, 0xe7, 0x1e, 0x6c, 0xdb, 0xbd, 193 | 0xb1, 0x4a, 0xd5, 0x28, 0xc0, 0x35, 0x4c, 0x75, 0x95, 0x52, 0xa9, 194 | 0x64, 0x77, 0xed, 0x5a, 0x46, 0x4e, 0xf0, 0x30, 0xca, 0x82, 0x62, 195 | 0x0c, 0x3d, 0xc4, 0x99, 0xdf, 0x05, 0xf1, 0xbd, 0xce, 0x59, 0x58, 196 | 0xe8, 0x8d, 0xb1, 0x53, 0xa0, 0x44, 0x84, 0x21, 0x1a, 0x19, 0x50, 197 | 0x6d, 0xe3, 0xa0, 0xff, 0xcf, 0x69, 0xb0, 0xe3, 0x99, 0x02, 0xc0, 198 | 0xb1, 0x95, 0x07, 0x9a, 0xe4, 0x87, 0x41, 0x7d, 0xfc, 0x31, 0x67, 199 | 0x4a, 0x8a, 0xa4, 0x62, 0x80, 0xfc, 0x1c, 0xdc, 0xf8, 0xd7, 0x23, 200 | 0xab, 0x99, 0x8c, 0xd3, 0xa1, 0xc2, 0x0b, 0xf7, 0x29, 0x64, 0xf2, 201 | 0x56, 0x9c, 0x88, 0xdd, 0xa7, 0xe3, 0x08, 0x57, 0xca, 0xf4, 0x41, 202 | 0xf0, 0xc6, 0xe2, 0xf1, 0x30, 0x6e, 0x55, 0x34, 0x5b, 0x58, 0x26, 203 | 0x6b, 0x28, 0x08, 0x49, 0xd8, 0x32, 0x21, 0x09, 0x55, 0x4a, 0xfb, 204 | 0x5d, 0x1f, 0x93, 0x32, 0xd6, 0xa5, 0xa6, 0x1c, 0x7f, 0x2b, 0x26, 205 | 0xe6, 0xf1, 0x27, 0x87, 0x0f, 0x6f, 0x3a, 0x3a, 0x39, 0xfb, 0x70, 206 | 0xa1, 0x91, 0xd1, 0x60, 0xbb, 0x27, 0xbf, 0xe0, 0xae, 0xc8, 0xc8, 207 | 0x0e, 0x9d, 0xf0, 0x78, 0x6a, 0x5f, 0x0e, 0x6c, 0x8c, 0x82, 0x7e, 208 | 0xce, 0x5a, 0x04, 0x78, 0xbe, 0x50, 0x84, 0x28, 0x74, 0x64, 0x87, 209 | 0x8d, 0xac, 0xbd, 0xfb, 0x32, 0x27, 0x07, 0x40, 0xf1, 0xa8, 0x30, 210 | 0x28, 0x19, 0x19, 0x06, 0x96, 0x93, 0x72, 0xfb, 0x68, 0x6f, 0xe6, 211 | 0x26, 0xe9, 0xa9, 0xb5, 0xf4, 0x38, 0x1a, 0x01, 0xdf, 0x11, 0xb6, 212 | 0xdb, 0x32, 0xe6, 0x14, 0x23, 0x17, 0x1b, 0x1b, 0xf0, 0xfa, 0x9f, 213 | 0xa0, 0x4b, 0x7a, 0x02, 0xef, 0x37, 0xb2, 0x88, 0x81, 0x2c, 0xab, 214 | 0xc3, 0x0a, 0xbf, 0x9f, 0xeb, 0x08, 0x2d, 0xde, 0x58, 0x06, 0xf7, 215 | 0x0f, 0x5f, 0x01, 0xbf, 0x9c, 0xa6, 0x47, 0xad, 0xb0, 0x0e, 0xd5, 216 | 0x94, 0x8a, 0x31, 0x7d, 0xe5, 0xf7, 0x44, 0xde, 0x9d, 0xba, 0xb6, 217 | 0x44, 0xd4, 0xe6, 0xe6, 0x91, 0x91, 0x18, 0xaf, 0x95, 0x02, 0xcf, 218 | 0x9a, 0xb1, 0xd0, 0xee, 0x8e, 0x70, 0x6e, 0xec, 0xce, 0xee, 0x78, 219 | 0x0c, 0x75, 0x47, 0x92, 0x0e, 0x86, 0x1e, 0xec, 0xc3, 0x32, 0x01, 220 | 0x9e, 0xcb, 0x64, 0x41, 0xfb, 0x51, 0x08, 0x88, 0x3a, 0xf7, 0xd7, 221 | 0xf3, 0xc8, 0x25, 0x0e, 0x7b, 0x02, 0x67, 0xc2, 0x49, 0xce, 0x97, 222 | 0xe3, 0xf1, 0xef, 0xad, 0x47, 0xa2, 0xbe, 0xd0, 0xa5, 0x3f, 0x74, 223 | 0xa1, 0xe3, 0x7c, 0x78, 0x49, 0x16, 0x2c, 0x36, 0x77, 0x26, 0x2b, 224 | 0xc8, 0xb4, 0x89, 0xf0, 0xb6, 0x5a, 0x84, 0x88, 0x8f, 0x47, 0xc3, 225 | 0x90, 0x79, 0x53, 0xa0, 0x44, 0x6b, 0xf7, 0xbb, 0xd5, 0x22, 0x51, 226 | 0x51, 0x1d, 0x9f, 0xba, 0xb6, 0xfe, 0x94, 0x68, 0x96, 0xcb, 0xb9, 227 | 0x20, 0x8e, 0xe1, 0x20, 0x90, 0x53, 0x7a, 0x18, 0x20, 0xac, 0x51, 228 | 0x63, 0x45, 0xef, 0xde, 0x83, 0xde, 0xc4, 0xc3, 0x5b, 0x3b, 0xce, 229 | 0x92, 0x46, 0x5b, 0x4f, 0x80, 0xf4, 0x08, 0xe9, 0x89, 0xde, 0x39, 230 | 0x9b, 0x1a, 0x38, 0xb7, 0xd0, 0x3f, 0x18, 0x03, 0xa1, 0xe8, 0x54, 231 | 0x37, 0x50, 0xd5, 0x33, 0xc2, 0xae, 0x79, 0x71, 0xa0, 0xdb, 0x3b, 232 | 0x1e, 0xb4, 0x7b, 0x26, 0xc0, 0xa6, 0x98, 0x4d, 0xa0, 0x54, 0xdc, 233 | 0x8e, 0x77, 0x1e, 0x9c, 0x95, 0xdf, 0x52, 0x19, 0x5e, 0xb5, 0x9f, 234 | 0xf1, 0x15, 0x0f, 0x03, 0x7c, 0xb1, 0xf5, 0xd7, 0xe5, 0x7d, 0x06, 235 | 0xfc, 0xfd, 0x86, 0xc1, 0xc4, 0xb3, 0xf5, 0xd9, 0xc6, 0xd0, 0x3c, 236 | 0x28, 0x12, 0x0b, 0x4c, 0xd5, 0xde, 0xdd, 0x00, 0xa4, 0x0f, 0x3e, 237 | 0xd8, 0x3a, 0x20, 0x3c, 0x3c, 0x62, 0x32, 0x9e, 0x16, 0xee, 0x38, 238 | 0x5b, 0x9a, 0xf9, 0x13, 0xca, 0x24, 0xdf, 0x65, 0xf7, 0x0b, 0x1c, 239 | 0xc8, 0x9d, 0x55, 0xb6, 0xc5, 0xa1, 0xa1, 0x50, 0xba, 0x7b, 0x22, 240 | 0x5c, 0xdf, 0xf6, 0x1e, 0x44, 0xf5, 0x48, 0xc6, 0x66, 0x82, 0x0f, 241 | 0x87, 0x91, 0xe1, 0xb0, 0xfe, 0x7f, 0x82, 0x7a, 0xc7, 0x24, 0x28, 242 | 0xf8, 0xfe, 0x1f, 0xf0, 0xec, 0xf4, 0x35, 0x10, 0xdc, 0x0a, 0x03, 243 | 0x04, 0x3f, 0x52, 0xd9, 0x00, 0x9c, 0xce, 0x28, 0x4e, 0x2d, 0xd5, 244 | 0x9a, 0xb0, 0xe0, 0x6d, 0x20, 0x24, 0x40, 0x25, 0xd9, 0x0d, 0xba, 245 | 0xea, 0xcb, 0x84, 0x33, 0x93, 0xc6, 0x8e, 0xfd, 0x64, 0xbd, 0x55, 246 | 0x2f, 0x34, 0x72, 0x5e, 0xc3, 0x03, 0x83, 0x52, 0x80, 0xac, 0xe6, 247 | 0x9e, 0xbd, 0x26, 0x15, 0x7d, 0xf2, 0x6e, 0x15, 0x24, 0x84, 0xb1, 248 | 0xf0, 0xed, 0xd8, 0x6f, 0x40, 0xc1, 0xf1, 0xf6, 0x82, 0x57, 0x86, 249 | 0xf2, 0x82, 0x03, 0x4d, 0xb0, 0xbd, 0xdf, 0x79, 0x58, 0x6b, 0x69, 250 | 0x0e, 0x86, 0x2b, 0x0f, 0x3a, 0xf7, 0xd4, 0x1e, 0x0f, 0x1f, 0x90, 251 | 0x79, 0xf9, 0x5c, 0xbc, 0xd1, 0xa0, 0x73, 0xbc, 0x65, 0x74, 0xab, 252 | 0xde, 0xe8, 0x85, 0x17, 0xc6, 0x3c, 0xd7, 0xb3, 0xcd, 0x8b, 0x14, 253 | 0x74, 0x54, 0xc9, 0x8c, 0xa9, 0xe8, 0xbc, 0x25, 0x68, 0x54, 0xc4, 254 | 0x42, 0xb4, 0x5a, 0x80, 0x81, 0x18, 0x06, 0x6f, 0xd4, 0xca, 0xec, 255 | 0x4e, 0xb3, 0x32, 0x94, 0xf7, 0xe9, 0x8e, 0xe7, 0xa0, 0xe1, 0x4b, 256 | 0x5f, 0x40, 0xaf, 0xc9, 0xb1, 0x90, 0xba, 0xfc, 0x3d, 0x10, 0x05, 257 | 0xc9, 0xd6, 0xeb, 0x33, 0x1e, 0x57, 0xd9, 0xb8, 0x7c, 0xd6, 0x5c, 258 | 0x83, 0x4e, 0x23, 0x66, 0x14, 0x5d, 0xf1, 0xa8, 0xf2, 0xd5, 0x89, 259 | 0x3c, 0x7b, 0x75, 0x08, 0xe8, 0x2a, 0xcf, 0xb5, 0x27, 0x1f, 0x2b, 260 | 0x0d, 0xb5, 0xf2, 0x2d, 0x3a, 0x1e, 0xfa, 0xa3, 0x37, 0x1f, 0xa7, 261 | 0x66, 0x21, 0x1f, 0x0f, 0xcd, 0x2b, 0x6a, 0x00, 0x4f, 0xbf, 0x3f, 262 | 0x13, 0xc7, 0x01, 0xeb, 0x60, 0xfe, 0xd6, 0xc1, 0x60, 0xb6, 0xda, 263 | 0x3b, 0x1a, 0xb4, 0x08, 0x0b, 0xa9, 0xff, 0x5c, 0xe0, 0xd8, 0xae, 264 | 0x25, 0x52, 0x66, 0x2c, 0x4e, 0x3c, 0xfa, 0xcb, 0xf4, 0xec, 0xdc, 265 | 0x34, 0xac, 0x7b, 0x82, 0x64, 0x61, 0xa5, 0x74, 0x87, 0xf2, 0xdb, 266 | 0x59, 0x32, 0xa2, 0xcc, 0xb9, 0x55, 0x3d, 0xa9, 0x38, 0x26, 0x79, 267 | 0xb5, 0x08, 0x1d, 0xde, 0xa8, 0xc5, 0x70, 0x2c, 0x85, 0x7c, 0xac, 268 | 0xe7, 0xc5, 0x8d, 0x85, 0x8d, 0x41, 0xfd, 0xc7, 0x93, 0xce, 0x54, 269 | 0xcd, 0x91, 0x32, 0x80, 0x78, 0x70, 0xcf, 0x57, 0xeb, 0x97, 0xcd, 270 | 0x8d, 0x9e, 0xb2, 0x22, 0x6e, 0xe6, 0xa5, 0xaf, 0xb6, 0x7e, 0x92, 271 | 0x3b, 0x61, 0x42, 0xff, 0xe4, 0x81, 0x03, 0xc3, 0x0e, 0x9f, 0xbf, 272 | 0x9e, 0x02, 0x57, 0xd4, 0x19, 0x92, 0xbe, 0xc0, 0x1b, 0x03, 0x98, 273 | 0x03, 0x44, 0x48, 0xec, 0x5c, 0x75, 0x2d, 0xf0, 0x95, 0xec, 0xef, 274 | 0x5e, 0x06, 0xbe, 0xca, 0x88, 0xd1, 0x3b, 0xaa, 0x6a, 0x48, 0x3a, 275 | 0x41, 0x10, 0xe2, 0x0f, 0xfc, 0xf0, 0xe5, 0xe0, 0x2d, 0x9b, 0x96, 276 | 0xbc, 0x95, 0x96, 0x76, 0xfe, 0xed, 0x8f, 0xd6, 0xec, 0x34, 0x2b, 277 | 0xe4, 0x1c, 0xf0, 0x22, 0xd6, 0x0a, 0x09, 0x3f, 0xe0, 0x8d, 0x01, 278 | 0x88, 0xc5, 0x23, 0xed, 0x01, 0x98, 0x9f, 0x60, 0xe0, 0xc2, 0xfb, 279 | 0x1f, 0x55, 0x15, 0x2e, 0x78, 0x45, 0x75, 0x9e, 0x84, 0x42, 0x5c, 280 | 0x9a, 0xec, 0xf8, 0x17, 0xea, 0x42, 0x48, 0x68, 0xd8, 0x20, 0x01, 281 | 0x0b, 0xdf, 0x21, 0xbc, 0x95, 0x64, 0x0d, 0xf0, 0xd6, 0x02, 0xd8, 282 | 0x7c, 0xe1, 0x58, 0x77, 0xbf, 0x4c, 0xe6, 0xd8, 0xe1, 0x4d, 0x81, 283 | 0x90, 0xb3, 0x25, 0xda, 0x99, 0xf2, 0x9d, 0xea, 0x0c, 0x50, 0xc1, 284 | 0x8c, 0x25, 0x5b, 0xc7, 0x97, 0x14, 0x17, 0x83, 0xd1, 0x60, 0x80, 285 | 0xc0, 0x00, 0x0c, 0x8a, 0x24, 0x6a, 0x80, 0xde, 0x44, 0x4b, 0x7e, 286 | 0xbc, 0x63, 0xd5, 0xeb, 0xd2, 0x71, 0x41, 0x4d, 0x29, 0x3a, 0xf1, 287 | 0x28, 0x98, 0xf2, 0x5a, 0x38, 0x53, 0xbe, 0xe1, 0x95, 0x01, 0x3e, 288 | 0x9b, 0xf5, 0xd6, 0xb7, 0x87, 0xf6, 0x6c, 0xfe, 0x46, 0x66, 0xb3, 289 | 0x4a, 0xbe, 0xfd, 0xe8, 0x51, 0x03, 0x6e, 0x18, 0x2d, 0xd2, 0x73, 290 | 0x23, 0xa2, 0xe0, 0x59, 0x33, 0x68, 0x10, 0x74, 0xf0, 0x71, 0xaa, 291 | 0x60, 0xfe, 0xe3, 0xe2, 0xa2, 0x39, 0x92, 0xf7, 0xba, 0x13, 0x5e, 292 | 0x19, 0x00, 0x29, 0xfd, 0xf7, 0xa1, 0xdd, 0x93, 0x63, 0xc6, 0x0d, 293 | 0x7a, 0xf3, 0xe3, 0x65, 0x33, 0x2e, 0x59, 0xad, 0x26, 0x11, 0x83, 294 | 0x43, 0x7c, 0xf3, 0x00, 0xd1, 0x23, 0x07, 0xdc, 0xb8, 0x9c, 0x7a, 295 | 0x66, 0xb7, 0x88, 0xcd, 0x43, 0x8a, 0xab, 0x4b, 0x63, 0x9d, 0x5b, 296 | 0xee, 0x6c, 0x18, 0xea, 0xe7, 0x25, 0x41, 0xa2, 0x0c, 0xd2, 0x16, 297 | 0xd3, 0x4a, 0x1b, 0xdf, 0xf0, 0xd6, 0x00, 0x04, 0x79, 0xaf, 0xef, 298 | 0xf6, 0x7c, 0xb7, 0x66, 0x50, 0x9f, 0xc7, 0x1a, 0x8d, 0x18, 0x36, 299 | 0xbc, 0xcf, 0xee, 0x98, 0x98, 0x57, 0x53, 0x53, 0x52, 0x12, 0x69, 300 | 0x56, 0x78, 0x99, 0xcd, 0x22, 0xfd, 0x46, 0xf5, 0x79, 0xf7, 0xdb, 301 | 0x27, 0x38, 0x2a, 0x23, 0xe2, 0xcb, 0xda, 0xf9, 0xb4, 0xcf, 0x33, 302 | 0x6a, 0x76, 0x62, 0x02, 0x68, 0x14, 0xee, 0x89, 0x3e, 0xbb, 0x05, 303 | 0x94, 0x25, 0x3e, 0xea, 0x4c, 0x79, 0x87, 0x2f, 0x06, 0x20, 0x68, 304 | 0x54, 0x43, 0x63, 0xf1, 0xaf, 0x33, 0xaf, 0x9c, 0x1b, 0x73, 0xe4, 305 | 0xc8, 0xbe, 0xd7, 0x71, 0xfb, 0x63, 0xca, 0xcb, 0x52, 0xff, 0xf9, 306 | 0x1b, 0xfe, 0x4a, 0x92, 0xf6, 0xd9, 0x0c, 0x49, 0x4f, 0xbd, 0x2d, 307 | 0x4a, 0x0b, 0x35, 0xa8, 0xb5, 0x30, 0x99, 0x3d, 0x0c, 0x6d, 0x65, 308 | 0xf4, 0xf9, 0xd1, 0x93, 0xcc, 0x8d, 0x23, 0x41, 0x30, 0x7b, 0xff, 309 | 0x09, 0xc1, 0x57, 0x03, 0xdc, 0x82, 0xea, 0x7b, 0x09, 0xea, 0x1c, 310 | 0x0a, 0x83, 0x58, 0x74, 0xee, 0x81, 0x0c, 0xa5, 0x25, 0x31, 0x97, 311 | 0x86, 0x82, 0xe9, 0x86, 0x84, 0x93, 0xa2, 0x5a, 0x10, 0xe5, 0x7b, 312 | 0x2d, 0x20, 0x9b, 0xfd, 0xaa, 0xf8, 0x1c, 0xc7, 0xe1, 0x52, 0xcd, 313 | 0x8e, 0x81, 0x92, 0xb3, 0x9d, 0x9d, 0xdb, 0x77, 0xa6, 0xa6, 0x06, 314 | 0xf0, 0x00, 0x7b, 0x82, 0x6a, 0x1d, 0xfb, 0xc5, 0x05, 0xef, 0x4b, 315 | 0xd6, 0x82, 0xf3, 0xad, 0x6b, 0xf6, 0x09, 0x90, 0xc5, 0x8b, 0x9d, 316 | 0x0d, 0xa4, 0x19, 0xb9, 0xda, 0xf5, 0x27, 0x7e, 0x33, 0xc0, 0x9d, 317 | 0x61, 0xa1, 0xf4, 0x64, 0x3f, 0xe7, 0xb6, 0x7f, 0x50, 0x81, 0x11, 318 | 0x56, 0x2a, 0x7d, 0xfa, 0x30, 0xe5, 0xc1, 0x5d, 0x34, 0x00, 0xc0, 319 | 0xb5, 0xad, 0xc3, 0x6b, 0xfb, 0xc2, 0x3c, 0x78, 0x81, 0x39, 0x0b, 320 | 0x7d, 0xe5, 0x3e, 0x7d, 0x9c, 0x72, 0xe3, 0xae, 0x1a, 0x80, 0x86, 321 | 0xb0, 0x05, 0x3f, 0x0d, 0x75, 0xa6, 0x6a, 0x4e, 0xb6, 0x68, 0xa3, 322 | 0xc5, 0x95, 0x76, 0xc8, 0x1f, 0x7c, 0xc3, 0x25, 0x40, 0x08, 0x53, 323 | 0x91, 0xe5, 0x13, 0x77, 0xd5, 0x00, 0x44, 0xde, 0xfe, 0xa7, 0xd1, 324 | 0x85, 0xd6, 0xee, 0xb6, 0x03, 0x4c, 0xa5, 0x29, 0x18, 0x4c, 0xbb, 325 | 0xd5, 0xa5, 0x53, 0xca, 0x25, 0x68, 0x0c, 0xdf, 0xab, 0x97, 0xdf, 326 | 0x0c, 0x20, 0xd8, 0x44, 0xe9, 0x89, 0x3f, 0x09, 0xae, 0xad, 0x9d, 327 | 0x52, 0xab, 0x86, 0x80, 0xbe, 0x5f, 0x1c, 0x64, 0x2e, 0xa6, 0x45, 328 | 0x58, 0x15, 0x04, 0x82, 0x0d, 0xf6, 0x04, 0xd2, 0xd2, 0xa4, 0xea, 329 | 0xb0, 0x79, 0xdc, 0xd7, 0x6f, 0x06, 0xb8, 0x1c, 0x67, 0xd9, 0x99, 330 | 0x3c, 0x83, 0x39, 0x5e, 0x76, 0x8e, 0x55, 0x4b, 0xcd, 0xea, 0x10, 331 | 0x0c, 0x63, 0xe6, 0x59, 0x76, 0xfd, 0x95, 0x92, 0xe4, 0x95, 0xa7, 332 | 0x6d, 0x26, 0xfb, 0x0c, 0x74, 0x8d, 0x49, 0x17, 0x84, 0xcb, 0x11, 333 | 0xc6, 0xa2, 0x1f, 0x46, 0x58, 0x34, 0xa9, 0x79, 0x8c, 0x60, 0xef, 334 | 0x4b, 0xbb, 0x41, 0x2e, 0x8c, 0x55, 0xd0, 0x92, 0x05, 0x77, 0x38, 335 | 0x2e, 0xbd, 0x8c, 0x61, 0xe6, 0x9c, 0xb3, 0xd9, 0x12, 0x68, 0xc5, 336 | 0x19, 0x4d, 0x4d, 0x55, 0xf4, 0xbd, 0x92, 0x53, 0xda, 0x35, 0x44, 337 | 0x2d, 0x98, 0xa1, 0xbc, 0xf4, 0xb4, 0xa8, 0xcd, 0xdf, 0x07, 0x5a, 338 | 0xbe, 0x4c, 0xc6, 0xd7, 0x6b, 0x27, 0xaa, 0x8a, 0x7e, 0x7b, 0x96, 339 | 0x61, 0x99, 0x3c, 0xbd, 0x28, 0xc6, 0x5e, 0x10, 0xc5, 0x7d, 0xd7, 340 | 0x45, 0x31, 0x9f, 0xe2, 0x85, 0x8b, 0xba, 0x54, 0xe6, 0x66, 0xd8, 341 | 0xe3, 0x50, 0xed, 0xe4, 0x5e, 0xfe, 0xbe, 0xc1, 0xce, 0xad, 0xca, 342 | 0xec, 0xbb, 0x8e, 0x7f, 0x28, 0xf0, 0xda, 0x97, 0x25, 0xf2, 0x9a, 343 | 0x04, 0xab, 0x51, 0xbd, 0xd2, 0x66, 0x28, 0xbf, 0x22, 0x0a, 0xc6, 344 | 0x59, 0x5c, 0x96, 0xea, 0x80, 0xf0, 0xb0, 0x4c, 0x23, 0x72, 0x02, 345 | 0xc7, 0xed, 0xcf, 0x11, 0x84, 0xe5, 0x68, 0xab, 0x13, 0x6a, 0x00, 346 | 0x23, 0x9d, 0x73, 0x1c, 0xb5, 0x17, 0x45, 0x6b, 0x0c, 0xec, 0xd4, 347 | 0x20, 0x0e, 0xab, 0x16, 0xaa, 0x51, 0x4d, 0x50, 0xdd, 0x50, 0xbd, 348 | 0x51, 0x0f, 0x3b, 0xd3, 0x04, 0x3e, 0x04, 0x9c, 0x41, 0xfd, 0x89, 349 | 0xa2, 0xea, 0xfb, 0x70, 0x97, 0x25, 0xb0, 0x5d, 0x1e, 0xea, 0xf8, 350 | 0x68, 0x2a, 0x45, 0xd2, 0xb8, 0x78, 0xe7, 0x56, 0x65, 0xc6, 0x9d, 351 | 0xc2, 0x3f, 0xb4, 0x8e, 0x88, 0xbe, 0x37, 0xd2, 0x1a, 0x1e, 0xfa, 352 | 0x46, 0x40, 0xab, 0x48, 0xba, 0xa2, 0xe8, 0x2b, 0x08, 0xdd, 0x93, 353 | 0x66, 0x8f, 0x69, 0xb5, 0x0b, 0x7d, 0xc1, 0xa2, 0xe3, 0xff, 0x42, 354 | 0xd1, 0xc2, 0x6c, 0xb7, 0x61, 0xab, 0xbf, 0x0d, 0xe0, 0x0a, 0x7d, 355 | 0x82, 0xea, 0x80, 0xa2, 0x07, 0x22, 0xc3, 0xd0, 0x92, 0xb7, 0x8b, 356 | 0xa8, 0x5b, 0x91, 0x4f, 0x88, 0x5c, 0x05, 0xb3, 0x3b, 0x2f, 0x81, 357 | 0x39, 0x55, 0x4d, 0x25, 0x78, 0x69, 0x00, 0xd7, 0x70, 0x90, 0xee, 358 | 0x49, 0x73, 0x68, 0x1d, 0x51, 0xf7, 0xa1, 0xe8, 0xe3, 0x23, 0x19, 359 | 0x9b, 0xc2, 0x77, 0xc9, 0xd1, 0x9a, 0xdf, 0x7c, 0x80, 0x04, 0xd4, 360 | 0x2f, 0xd1, 0x37, 0x38, 0x5a, 0x00, 0x40, 0x2b, 0x3a, 0xe8, 0x6b, 361 | 0x93, 0x6b, 0xd8, 0xa7, 0xb1, 0x96, 0xc3, 0x7e, 0x53, 0x16, 0x43, 362 | 0xa1, 0xb4, 0xbf, 0xa0, 0x7b, 0x92, 0xa1, 0x69, 0xf5, 0x08, 0x2d, 363 | 0xb3, 0xa5, 0x05, 0xd7, 0xd4, 0xee, 0x25, 0x0b, 0x4f, 0xd4, 0xa5, 364 | 0x01, 0x6e, 0x41, 0x37, 0xaf, 0xea, 0x01, 0x92, 0x2e, 0x2d, 0x15, 365 | 0x57, 0x62, 0xff, 0x51, 0xab, 0x5e, 0xa1, 0x0a, 0xbc, 0x72, 0xb2, 366 | 0xfe, 0x74, 0x82, 0x35, 0xc1, 0x86, 0xa6, 0xd1, 0xe6, 0xef, 0x87, 367 | 0x00, 0x43, 0x36, 0xab, 0x0c, 0xe9, 0x00, 0x2a, 0x46, 0x0e, 0xb2, 368 | 0x5b, 0x4d, 0xe2, 0xb6, 0x13, 0x14, 0xb1, 0x07, 0x31, 0xd9, 0x64, 369 | 0xb2, 0x2d, 0x19, 0xa2, 0x18, 0x4f, 0x61, 0x1f, 0x8d, 0xbd, 0xed, 370 | 0x53, 0x75, 0xb4, 0xb7, 0x36, 0xd4, 0xa5, 0x0f, 0xf0, 0x85, 0x1e, 371 | 0xa8, 0x81, 0xa8, 0xee, 0x6c, 0x3d, 0x88, 0x68, 0x15, 0xcd, 0xb6, 372 | 0x09, 0xe9, 0x28, 0x34, 0x3c, 0x33, 0x7e, 0x1d, 0xc8, 0x64, 0x57, 373 | 0x35, 0x82, 0xb0, 0x36, 0x53, 0x14, 0xb5, 0x34, 0x91, 0x48, 0x0e, 374 | 0x8c, 0x1c, 0x19, 0xf5, 0x75, 0x3f, 0xa3, 0xc8, 0xb1, 0xd6, 0x8a, 375 | 0x7b, 0xc5, 0x00, 0x04, 0x79, 0x73, 0x72, 0x60, 0xbd, 0x50, 0x3d, 376 | 0x51, 0xb4, 0xac, 0x86, 0xe6, 0xbc, 0xa9, 0x79, 0x14, 0xa0, 0xc8, 377 | 0x99, 0x91, 0x27, 0xa7, 0x5f, 0x4a, 0xfb, 0xa5, 0xd9, 0xdc, 0x4b, 378 | 0x06, 0xb8, 0x05, 0xf9, 0x25, 0xfa, 0xb7, 0x14, 0xea, 0x4a, 0xc9, 379 | 0x08, 0x5a, 0x14, 0x15, 0xfa, 0x32, 0xea, 0xae, 0x2c, 0x9f, 0xbd, 380 | 0x97, 0xa0, 0x85, 0x0c, 0x77, 0xc3, 0x51, 0xff, 0xaf, 0x02, 0xf0, 381 | 0x1f, 0x59, 0x3f, 0xf1, 0x6d, 0xd3, 0x45, 0x00, 0xc2, 0x00, 0x00, 382 | 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 383 | }; 384 | 385 | const int icon_prog_png_length = 4190; 386 | -------------------------------------------------------------------------------- /Tools/Builder/resources/prog.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/buu342/N64-Platform64/28928e31a8e649f150c2dfa7a05f23921a31c77b/Tools/Builder/resources/prog.ico -------------------------------------------------------------------------------- /Tools/Builder/traverser.cpp: -------------------------------------------------------------------------------- 1 | #include "traverser.h" 2 | #include "preferences.h" 3 | #include "helper.h" 4 | #include 5 | #include 6 | 7 | Traverser::Traverser(wxString path, wxTreeListCtrl* tree, wxTreeListItem root, std::map* map, std::vector extensions) 8 | { 9 | this->m_CurDir = path; 10 | this->m_Tree = tree; 11 | this->m_CurNode = root; 12 | this->m_Map = map; 13 | this->m_Extensions = extensions; 14 | } 15 | 16 | Traverser::~Traverser() 17 | { 18 | 19 | } 20 | 21 | bool Traverser::IsWhitelistedExtension(wxString ext) 22 | { 23 | for (std::vector::iterator it = this->m_Extensions.begin(); it != this->m_Extensions.end(); ++it) 24 | if (ext == (*it)) 25 | return true; 26 | return false; 27 | } 28 | 29 | wxDirTraverseResult Traverser::OnFile(const wxString& filename) 30 | { 31 | wxFileName name(filename); 32 | if (this->IsWhitelistedExtension(name.GetExt())) 33 | { 34 | if (name.GetExt() == "c") 35 | { 36 | wxTreeListItem id = this->m_Tree->AppendItem(this->m_CurNode, name.GetFullName(), 1); 37 | if (this->m_Map != NULL) 38 | { 39 | CompUnit* unit = new CompUnit(this->m_Tree, id); 40 | this->m_Map->insert(std::pair(id, unit)); 41 | this->m_Tree->SetItemText(id, 1, unit->GetSegment().GetName()); 42 | } 43 | } 44 | else 45 | this->m_Tree->AppendItem(this->m_CurNode, name.GetFullName(), 2); 46 | } 47 | return wxDIR_CONTINUE; 48 | } 49 | 50 | wxDirTraverseResult Traverser::OnDir(const wxString& dirname) 51 | { 52 | wxDir dir(dirname); 53 | wxTreeListItem oldnode = this->m_CurNode; 54 | 55 | // Check for errors 56 | if (!dir.IsOpened()) 57 | return wxDIR_IGNORE; 58 | this->m_CurNode = this->m_Tree->AppendItem(this->m_CurNode, wxFileName(dirname).GetName(), 0); 59 | 60 | // Traverse recursively 61 | Traverser traverser(dirname, this->m_Tree, this->m_CurNode, this->m_Map, this->m_Extensions); 62 | dir.Traverse(traverser); 63 | dir.Close(); 64 | 65 | // Remove the node if it's empty 66 | if (!this->m_Tree->GetFirstChild(this->m_CurNode).IsOk()) 67 | { 68 | this->m_Tree->DeleteItem(this->m_CurNode); 69 | this->m_CurNode = oldnode; 70 | } 71 | else 72 | this->m_CurNode = this->m_Tree->GetItemParent(this->m_CurNode); 73 | 74 | // Done 75 | return wxDIR_IGNORE; 76 | } 77 | 78 | void Traverser::DeleteFiles(wxTreeListItem node) 79 | { 80 | wxString name = this->m_Tree->GetItemText(node); 81 | wxTreeListItem child = this->m_Tree->GetFirstChild(node); 82 | 83 | // Recursively find the child node 84 | while (child.IsOk()) 85 | { 86 | this->DeleteFiles(child); 87 | child = this->m_Tree->GetNextItem(child); 88 | } 89 | 90 | // Do the delete 91 | child = node; 92 | if (this->IsWhitelistedExtension(((wxFileName)name).GetExt())) 93 | { 94 | while (this->m_Tree->GetItemParent(child) != NULL) 95 | { 96 | child = this->m_Tree->GetItemParent(child); 97 | name.Prepend(this->m_Tree->GetItemText(child) + "/"); 98 | } 99 | wxRemoveFile(((wxFileName)name).GetFullPath()); 100 | } 101 | } -------------------------------------------------------------------------------- /Tools/Builder/traverser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct IUnknown IUnknown; 4 | 5 | #include "compunit.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class Traverser : public wxDirTraverser 13 | { 14 | protected: 15 | wxTreeListCtrl* m_Tree; 16 | wxTreeListItem m_CurNode; 17 | wxString m_CurDir; 18 | std::vector m_Extensions; 19 | std::map* m_Map; 20 | 21 | public: 22 | wxDirTraverseResult OnFile(const wxString& filename); 23 | wxDirTraverseResult OnDir(const wxString& dirname); 24 | bool IsWhitelistedExtension(wxString ext); 25 | void DeleteFiles(wxTreeListItem node); 26 | Traverser(wxString path, wxTreeListCtrl* tree, wxTreeListItem root, std::map* map, std::vector extensions); 27 | ~Traverser(); 28 | }; -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: ["master", "develop*", "release*", "refs/tags/*" ] 4 | paths: 5 | exclude: [ "doc", "*.md", ".gitignore" ] 6 | 7 | jobs: 8 | - job: Building_Toolkit 9 | pool: 10 | vmImage: 'windows-2019' 11 | steps: 12 | - script: | 13 | pip install gdown 14 | gdown --fuzzy https://drive.google.com/u/0/uc?id=1Dg5BZtatClyEX0zPYXjYKiNGHGMkbQ4G&export=download 15 | ren *.zip wxWidgets.zip 16 | 7z x wxWidgets.zip -oD:/ 17 | dir 18 | cd D:/ 19 | dir 20 | displayName: Download wxWidgets 21 | 22 | - task: VSBuild@1 23 | displayName: Build VSCode Tools 24 | env: 25 | WXWIN: D:/wxWidgets/ 26 | inputs: 27 | configuration: 'release' 28 | solution: '**\*.sln' 29 | vsVersion: '16.0' # Optional. Options: latest, 16.0, 15.0, 14.0, 12.0, 11.0 30 | msbuildArchitecture: 'x86' # Optional. Options: x86, x64 31 | 32 | - script: | 33 | cd Tools 34 | cd NRDC 35 | makeme.bat 36 | displayName: Build GCC Tools 37 | 38 | - script: | 39 | cd Tools 40 | mkdir ToolsRelease 41 | for /r . %%x in (*.exe) do copy "%%x" "ToolsRelease" 42 | cd ToolsRelease 43 | dir 44 | del /q /f bin2c.exe 45 | displayName: Move Executables 46 | 47 | - task: PublishBuildArtifacts@1 48 | displayName: Publish Build Artifacts 49 | inputs: 50 | pathtoPublish: '$(Build.SourcesDirectory)/Tools/ToolsRelease/' 51 | artifactName: 'tools-windows' 52 | --------------------------------------------------------------------------------