diff --git a/.gitignore b/.gitignore index f7679ff..0608ad8 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,7 @@ bld/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory -.vs/ \ No newline at end of file +.vs/ + +# RT64 (since it's not public yet) +test/RT64 diff --git a/recomp.h b/recomp.h index 0019229..3568bed 100644 --- a/recomp.h +++ b/recomp.h @@ -24,25 +24,35 @@ typedef uint64_t gpr; ((gpr)(int32_t)((a) - (b))) #define MEM_W(offset, reg) \ - (*(int32_t*)(rdram + ((((reg) + (offset))) & 0x3FFFFFF))) + (*(int32_t*)(rdram + ((((reg) + (offset))) - 0xFFFFFFFF80000000))) + //(*(int32_t*)(rdram + ((((reg) + (offset))) & 0x3FFFFFF))) #define MEM_H(offset, reg) \ - (*(int16_t*)(rdram + ((((reg) + (offset)) ^ 2) & 0x3FFFFFF))) + (*(int16_t*)(rdram + ((((reg) + (offset)) ^ 2) - 0xFFFFFFFF80000000))) + //(*(int16_t*)(rdram + ((((reg) + (offset)) ^ 2) & 0x3FFFFFF))) #define MEM_B(offset, reg) \ - (*(int8_t*)(rdram + ((((reg) + (offset)) ^ 3) & 0x3FFFFFF))) + (*(int8_t*)(rdram + ((((reg) + (offset)) ^ 3) - 0xFFFFFFFF80000000))) + //(*(int8_t*)(rdram + ((((reg) + (offset)) ^ 3) & 0x3FFFFFF))) #define MEM_HU(offset, reg) \ - (*(uint16_t*)(rdram + ((((reg) + (offset)) ^ 2) & 0x3FFFFFF))) + (*(uint16_t*)(rdram + ((((reg) + (offset)) ^ 2) - 0xFFFFFFFF80000000))) + //(*(uint16_t*)(rdram + ((((reg) + (offset)) ^ 2) & 0x3FFFFFF))) #define MEM_BU(offset, reg) \ - (*(uint8_t*)(rdram + ((((reg) + (offset)) ^ 3) & 0x3FFFFFF))) + (*(uint8_t*)(rdram + ((((reg) + (offset)) ^ 3) - 0xFFFFFFFF80000000))) + //(*(uint8_t*)(rdram + ((((reg) + (offset)) ^ 3) & 0x3FFFFFF))) #define SD(val, offset, reg) { \ - *(uint32_t*)(rdram + ((((reg) + (offset) + 4)) & 0x3FFFFFF)) = (uint32_t)((val) >> 32); \ - *(uint32_t*)(rdram + ((((reg) + (offset) + 0)) & 0x3FFFFFF)) = (uint32_t)((val) >> 0); \ + *(uint32_t*)(rdram + ((((reg) + (offset) + 4)) - 0xFFFFFFFF80000000)) = (uint32_t)((val) >> 0); \ + *(uint32_t*)(rdram + ((((reg) + (offset) + 0)) - 0xFFFFFFFF80000000)) = (uint32_t)((val) >> 32); \ } +//#define SD(val, offset, reg) { \ +// *(uint32_t*)(rdram + ((((reg) + (offset) + 4)) & 0x3FFFFFF)) = (uint32_t)((val) >> 32); \ +// *(uint32_t*)(rdram + ((((reg) + (offset) + 0)) & 0x3FFFFFF)) = (uint32_t)((val) >> 0); \ +//} + static inline uint64_t load_doubleword(uint8_t* rdram, gpr reg, gpr offset) { uint64_t ret = 0; uint64_t lo = (uint64_t)(uint32_t)MEM_W(reg, offset + 4); @@ -56,7 +66,8 @@ static inline uint64_t load_doubleword(uint8_t* rdram, gpr reg, gpr offset) { // TODO proper lwl/lwr/swl/swr #define MEM_WL(offset, reg) \ - (*(int32_t*)(rdram + ((((reg) + (offset))) & 0x3FFFFFF))) + (*(int32_t*)(rdram + ((((reg) + (offset))) - 0xFFFFFFFF80000000))) + //(*(int32_t*)(rdram + ((((reg) + (offset))) & 0x3FFFFFF))) #define S32(val) \ ((int32_t)(val)) @@ -103,6 +114,8 @@ static inline uint64_t load_doubleword(uint8_t* rdram, gpr reg, gpr offset) { #define NAN_CHECK(val) \ assert(val == val) +//#define NAN_CHECK(val) + typedef union { double d; struct { diff --git a/src/recompilation.cpp b/src/recompilation.cpp index b8a53cf..505bb78 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -104,7 +104,7 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::F break; // Arithmetic case InstrId::cpu_lui: - print_line("{}{} = {:#X} << 16", ctx_gpr_prefix(rt), rt, imm); + print_line("{}{} = S32({:#X} << 16)", ctx_gpr_prefix(rt), rt, imm); break; case InstrId::cpu_addu: { diff --git a/test/RecompTest.vcxproj b/test/RecompTest.vcxproj index 4142293..679a28a 100644 --- a/test/RecompTest.vcxproj +++ b/test/RecompTest.vcxproj @@ -76,7 +76,7 @@ Level3 ProgramDatabase Disabled - $(ProjectDir)..;%(AdditionalIncludeDirectories) + $(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories) stdcpp20 @@ -91,7 +91,7 @@ MultiThreadedDLL Level3 ProgramDatabase - $(ProjectDir)..;%(AdditionalIncludeDirectories) + $(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories) stdcpp20 @@ -104,21 +104,28 @@ - $(ProjectDir)..;%(AdditionalIncludeDirectories) + $(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories) stdcpp20 Console + $(ProjectDir)RT64\Debug\RT64.lib;%(AdditionalDependencies) + + XCOPY "$(ProjectDir)RT64\$(Configuration)\*" "$(TargetDir)" /S /Y + - $(ProjectDir)..;%(AdditionalIncludeDirectories) + $(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories) stdcpp20 Console + + XCOPY "$(ProjectDir)RT64\$(Configuration)\*" "$(TargetDir)" /S /Y + @@ -2005,6 +2012,7 @@ + @@ -2020,7 +2028,11 @@ + + + + diff --git a/test/RecompTest.vcxproj.filters b/test/RecompTest.vcxproj.filters index fd40093..2e37f19 100644 --- a/test/RecompTest.vcxproj.filters +++ b/test/RecompTest.vcxproj.filters @@ -5700,6 +5700,9 @@ Source Files + + Source Files + @@ -5714,5 +5717,17 @@ Header Files + + Source Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/test/portultra/events.cpp b/test/portultra/events.cpp index e77fb9c..0bdac12 100644 --- a/test/portultra/events.cpp +++ b/test/portultra/events.cpp @@ -2,11 +2,25 @@ #include #include #include +#include + +#include +#include "blockingconcurrentqueue.h" #include "ultra64.h" #include "multilibultra.hpp" #include "recomp.h" +struct SpTaskAction { + OSTask task; +}; + +struct SwapBuffersAction { + int32_t origin; +}; + +using Action = std::variant; + static struct { struct { std::thread thread; @@ -18,8 +32,6 @@ static struct { std::thread thread; PTR(OSMesgQueue) mq = NULLPTR; OSMesg msg = (OSMesg)0; - OSTask task; - std::atomic_flag task_queued; } sp; struct { std::thread thread; @@ -35,12 +47,12 @@ static struct { std::thread thread; PTR(OSMesgQueue) mq = NULLPTR; OSMesg msg = (OSMesg)0; - std::atomic_flag read_queued; } si; // The same message queue may be used for multiple events, so share a mutex for all of them std::mutex message_mutex; uint8_t* rdram; std::chrono::system_clock::time_point start; + moodycamel::BlockingConcurrentQueue action_queue{}; } events_context{}; extern "C" void osSetEventMesg(RDRAM_ARG OSEvent event_id, PTR(OSMesgQueue) mq_, OSMesg msg) { @@ -73,8 +85,10 @@ extern "C" void osViSetEvent(RDRAM_ARG PTR(OSMesgQueue) mq_, OSMesg msg, u32 ret events_context.vi.retrace_count = retrace_count; } +constexpr uint32_t speed_multiplier = 10; + // N64 CPU counter ticks per millisecond -constexpr uint32_t counter_per_ms = 46'875; +constexpr uint32_t counter_per_ms = 46'875 * speed_multiplier; uint64_t duration_to_count(std::chrono::system_clock::duration duration) { uint64_t delta_micros = std::chrono::duration_cast(duration).count(); @@ -107,7 +121,7 @@ void vi_thread_func() { while (true) { // Determine the next VI time (more accurate than adding 16ms each VI interrupt) - auto next = events_context.start + (total_vis * 1000000us) / 60; + auto next = events_context.start + (total_vis * 1000000us) / (60 * speed_multiplier); //if (next > std::chrono::system_clock::now()) { // printf("Sleeping for %" PRIu64 " us to get from %" PRIu64 " us to %" PRIu64 " us \n", // (next - std::chrono::system_clock::now()) / 1us, @@ -118,22 +132,29 @@ void vi_thread_func() { //} std::this_thread::sleep_until(next); // Calculate how many VIs have passed - uint64_t new_total_vis = ((std::chrono::system_clock::now() - events_context.start) * 60 / 1000ms) + 1; + uint64_t new_total_vis = ((std::chrono::system_clock::now() - events_context.start) * (60 * speed_multiplier) / 1000ms) + 1; if (new_total_vis > total_vis + 1) { - printf("Skipped % " PRId64 " frames in VI interupt thread!\n", new_total_vis - total_vis - 1); + //printf("Skipped % " PRId64 " frames in VI interupt thread!\n", new_total_vis - total_vis - 1); } total_vis = new_total_vis; remaining_retraces--; - if (remaining_retraces == 0) { + { std::lock_guard lock{ events_context.message_mutex }; - remaining_retraces = events_context.vi.retrace_count; uint8_t* rdram = events_context.rdram; + if (remaining_retraces == 0) { + remaining_retraces = events_context.vi.retrace_count; - if (events_context.vi.mq != NULLPTR) { - if (osSendMesg(PASS_RDRAM events_context.vi.mq, events_context.vi.msg, OS_MESG_NOBLOCK) == -1) { - //printf("Game skipped a VI frame!\n"); + if (events_context.vi.mq != NULLPTR) { + if (osSendMesg(PASS_RDRAM events_context.vi.mq, events_context.vi.msg, OS_MESG_NOBLOCK) == -1) { + //printf("Game skipped a VI frame!\n"); + } + } + } + if (events_context.ai.mq != NULLPTR) { + if (osSendMesg(PASS_RDRAM events_context.ai.mq, events_context.ai.msg, OS_MESG_NOBLOCK) == -1) { + //printf("Game skipped a AI frame!\n"); } } } @@ -152,41 +173,49 @@ void dp_complete() { osSendMesg(PASS_RDRAM events_context.dp.mq, events_context.dp.msg, OS_MESG_NOBLOCK); } -void gfx_thread_func() { +void RT64Init(uint8_t* rom, uint8_t* rdram); +void RT64SendDL(uint8_t* rdram, const OSTask* task); +void RT64UpdateScreen(uint32_t vi_origin); +void RT64PumpEvents(); + +void gfx_thread_func(uint8_t* rdram, uint8_t* rom) { + using namespace std::chrono_literals; + RT64Init(rom, rdram); + while (true) { - // Wait for a sp task to be queued - events_context.sp.task_queued.wait(false); - - // Grab the task and inform the game that it's free to queue up a new task - OSTask current_task = events_context.sp.task; - events_context.sp.task_queued.clear(); - events_context.sp.task_queued.notify_all(); - - // Process the task - if (current_task.t.type = M_GFXTASK) { - // TODO interface with RT64 here - - // (TODO let RT64 do this) Tell the game that the RSP and RDP tasks are complete - sp_complete(); - dp_complete(); - } else if (current_task.t.type == M_AUDTASK) { - sp_complete(); - } else { - fprintf(stderr, "Unknown task type: %" PRIu32 "\n", current_task.t.type); - std::exit(EXIT_FAILURE); + // Try to pull an action from the queue + Action action; + if (events_context.action_queue.wait_dequeue_timed(action, 1ms)) { + // Determine the action type and act on it + if (const auto* task_action = std::get_if(&action)) { + if (task_action->task.t.type == M_GFXTASK) { + // (TODO let RT64 do this) Tell the game that the RSP and RDP tasks are complete + RT64SendDL(rdram, &task_action->task); + sp_complete(); + dp_complete(); + } else if (task_action->task.t.type == M_AUDTASK) { + sp_complete(); + } else { + fprintf(stderr, "Unknown task type: %" PRIu32 "\n", task_action->task.t.type); + std::exit(EXIT_FAILURE); + } + } else if (const auto* swap_action = std::get_if(&action)) { + RT64UpdateScreen(swap_action->origin); + } } + + // Handle events + RT64PumpEvents(); } } +extern "C" void osViSwapBuffer(RDRAM_ARG PTR(void) frameBufPtr) { + events_context.action_queue.enqueue(SwapBuffersAction{ frameBufPtr + 640 }); +} + void Multilibultra::submit_rsp_task(RDRAM_ARG PTR(OSTask) task_) { OSTask* task = TO_PTR(OSTask, task_); - // Wait for the sp thread clear the old task - events_context.sp.task_queued.wait(true); - // Make a full copy of the task instead of just recording a pointer to it, since that's what osSpTaskLoad does - events_context.sp.task = *task; - - events_context.sp.task_queued.test_and_set(); - events_context.sp.task_queued.notify_all(); + events_context.action_queue.enqueue(SpTaskAction{ *task }); } void Multilibultra::send_si_message() { @@ -194,8 +223,8 @@ void Multilibultra::send_si_message() { osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK); } -void Multilibultra::init_events(uint8_t* rdram) { +void Multilibultra::init_events(uint8_t* rdram, uint8_t* rom) { events_context.rdram = rdram; events_context.vi.thread = std::thread{ vi_thread_func }; - events_context.sp.thread = std::thread{ gfx_thread_func }; -} \ No newline at end of file + events_context.sp.thread = std::thread{ gfx_thread_func, rdram, rom }; +} diff --git a/test/portultra/init.cpp b/test/portultra/init.cpp index 74af0b7..2086db6 100644 --- a/test/portultra/init.cpp +++ b/test/portultra/init.cpp @@ -1,9 +1,9 @@ #include "ultra64.h" #include "multilibultra.hpp" -void Multilibultra::preinit(uint8_t* rdram) { +void Multilibultra::preinit(uint8_t* rdram, uint8_t* rom) { Multilibultra::set_main_thread(); - Multilibultra::init_events(rdram); + Multilibultra::init_events(rdram, rom); } extern "C" void osInitialize() { diff --git a/test/portultra/mesgqueue.cpp b/test/portultra/mesgqueue.cpp index a55acf0..fd7a0bb 100644 --- a/test/portultra/mesgqueue.cpp +++ b/test/portultra/mesgqueue.cpp @@ -167,7 +167,7 @@ extern "C" s32 osRecvMesg(RDRAM_ARG PTR(OSMesgQueue) mq_, PTR(OSMesg) msg_, s32 } } - if (msg != nullptr) { + if (msg_ != NULLPTR) { *msg = TO_PTR(OSMesg, mq->msg)[mq->first]; } diff --git a/test/portultra/multilibultra.hpp b/test/portultra/multilibultra.hpp index 26d0682..3efd71d 100644 --- a/test/portultra/multilibultra.hpp +++ b/test/portultra/multilibultra.hpp @@ -17,10 +17,10 @@ struct UltraThreadContext { namespace Multilibultra { -void preinit(uint8_t* rdram); +void preinit(uint8_t* rdram, uint8_t* rom); void native_init(); void init_scheduler(); -void init_events(uint8_t* rdram); +void init_events(uint8_t* rdram, uint8_t* rom); void native_thread_init(OSThread *t); void set_self_paused(RDRAM_ARG1); void wait_for_resumed(RDRAM_ARG1); diff --git a/test/portultra/threads.cpp b/test/portultra/threads.cpp index 09089d3..8e67f2a 100644 --- a/test/portultra/threads.cpp +++ b/test/portultra/threads.cpp @@ -29,7 +29,7 @@ int main(int argc, char** argv) { #endif #if 1 -void run_thread_function(uint8_t* rdram, uint32_t addr, uint32_t sp, uint32_t arg); +void run_thread_function(uint8_t* rdram, uint64_t addr, uint64_t sp, uint64_t arg); #else #define run_thread_function(func, sp, arg) func(arg) #endif @@ -66,7 +66,7 @@ extern "C" void osStartThread(RDRAM_ARG PTR(OSThread) t_) { OSThread* t = TO_PTR(OSThread, t_); debug_printf("[os] Start Thread %d\n", t->id); - // Wait until the thread is initialized to indicate that it's task_queued to be started. + // Wait until the thread is initialized to indicate that it's action_queued to be started. t->context->initialized.wait(false); debug_printf("[os] Thread %d is ready to be started\n", t->id); diff --git a/test/portultra/ultra64.h b/test/portultra/ultra64.h index c00b261..c5d88eb 100644 --- a/test/portultra/ultra64.h +++ b/test/portultra/ultra64.h @@ -25,12 +25,12 @@ typedef uint16_t u16; typedef int8_t s8; typedef uint8_t u8; -#define PTR(x) uint32_t +#define PTR(x) int32_t #define RDRAM_ARG uint8_t *rdram, #define RDRAM_ARG1 uint8_t *rdram #define PASS_RDRAM rdram, #define PASS_RDRAM1 rdram -#define TO_PTR(type, var) ((type*)(&rdram[var & 0x3FFFFFF])) +#define TO_PTR(type, var) ((type*)(&rdram[(uint64_t)var - 0xFFFFFFFF80000000])) #ifdef __cplusplus #define NULLPTR (PTR(void))0 #endif @@ -89,7 +89,7 @@ typedef struct OSThread_t { OSId id; int32_t pad3; UltraThreadContext* context; // An actual pointer regardless of platform - uint32_t sp; + int32_t sp; } OSThread; typedef u32 OSEvent; @@ -161,6 +161,7 @@ s32 osJamMesg(RDRAM_ARG PTR(OSMesgQueue), OSMesg, s32); s32 osRecvMesg(RDRAM_ARG PTR(OSMesgQueue), PTR(OSMesg), s32); void osSetEventMesg(RDRAM_ARG OSEvent, PTR(OSMesgQueue), OSMesg); void osViSetEvent(RDRAM_ARG PTR(OSMesgQueue), OSMesg, u32); +void osViSwapBuffer(RDRAM_ARG PTR(void) frameBufPtr); u32 osGetCount(); OSTime osGetTime(); diff --git a/test/src/ai.cpp b/test/src/ai.cpp index f3a8343..65954b2 100644 --- a/test/src/ai.cpp +++ b/test/src/ai.cpp @@ -1,17 +1,20 @@ #include "recomp.h" extern "C" void osAiSetFrequency_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; + ctx->r2 = ctx->r4; } +static uint32_t ai_length = 0; + extern "C" void osAiSetNextBuffer_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; + ai_length = (uint32_t)ctx->r5; + ctx->r2 = 0; } extern "C" void osAiGetLength_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; + ctx->r2 = ai_length; } extern "C" void osAiGetStatus_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; -} \ No newline at end of file + ctx->r2 = 0x80000000; +} diff --git a/test/src/cont.cpp b/test/src/cont.cpp index f4fc07a..ffa11e9 100644 --- a/test/src/cont.cpp +++ b/test/src/cont.cpp @@ -9,8 +9,24 @@ extern "C" void osContStartReadData_recomp(uint8_t* restrict rdram, recomp_conte Multilibultra::send_si_message(); } +struct OSContPad { + u16 button; + s8 stick_x; /* -80 <= stick_x <= 80 */ + s8 stick_y; /* -80 <= stick_y <= 80 */ + u8 errno_; +}; + extern "C" void osContGetReadData_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; + int32_t pad = (uint32_t)ctx->r4; + + // button + MEM_H(0, pad) = 0; + // stick_x + MEM_B(2, pad) = 0; + // stick_y + MEM_B(3, pad) = 0; + // errno + MEM_B(4, pad) = 0; } extern "C" void osMotorInit_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { diff --git a/test/src/pi.cpp b/test/src/pi.cpp index 1adcca9..68d5abd 100644 --- a/test/src/pi.cpp +++ b/test/src/pi.cpp @@ -16,7 +16,7 @@ extern "C" void osCreatePiManager_recomp(uint8_t* restrict rdram, recomp_context constexpr uint32_t rom_base = 0xB0000000; -void do_rom_read(uint8_t* rdram, uint32_t ram_address, uint32_t dev_address, size_t num_bytes) { +void do_rom_read(uint8_t* rdram, int32_t ram_address, uint32_t dev_address, size_t num_bytes) { // TODO use word copies when possible uint8_t* rom_addr = rom.get() + (dev_address | rom_base) - rom_base; for (size_t i = 0; i < num_bytes; i++) { @@ -30,7 +30,7 @@ extern "C" void osPiStartDma_recomp(uint8_t* restrict rdram, recomp_context* res uint32_t pri = ctx->r5; uint32_t direction = ctx->r6; uint32_t devAddr = ctx->r7; - uint32_t dramAddr = MEM_W(0x10, ctx->r29); + int32_t dramAddr = MEM_W(0x10, ctx->r29); uint32_t size = MEM_W(0x14, ctx->r29); uint32_t mq_ = MEM_W(0x18, ctx->r29); OSMesgQueue* mq = TO_PTR(OSMesgQueue, mq_); diff --git a/test/src/recomp.cpp b/test/src/recomp.cpp index 0c023ce..5a5a63f 100644 --- a/test/src/recomp.cpp +++ b/test/src/recomp.cpp @@ -35,8 +35,8 @@ extern "C" recomp_func_t* get_function(uint32_t addr) { } extern "C" void bzero(uint8_t* restrict rdram, recomp_context* restrict ctx) { - uint32_t start_addr = ctx->r4; - uint32_t size = ctx->r5; + gpr start_addr = ctx->r4; + gpr size = ctx->r5; for (uint32_t i = 0; i < size; i++) { MEM_B(start_addr, i) = 0; @@ -53,7 +53,7 @@ extern "C" void do_break(uint32_t vram) { exit(EXIT_FAILURE); } -void run_thread_function(uint8_t* rdram, uint32_t addr, uint32_t sp, uint32_t arg) { +void run_thread_function(uint8_t* rdram, uint64_t addr, uint64_t sp, uint64_t arg) { recomp_context ctx{}; ctx.r29 = sp; ctx.r4 = arg; @@ -62,7 +62,7 @@ void run_thread_function(uint8_t* rdram, uint32_t addr, uint32_t sp, uint32_t ar } extern "C" void game_init(uint8_t* restrict rdram, recomp_context* restrict ctx); -void do_rom_read(uint8_t* rdram, uint32_t ram_address, uint32_t dev_address, size_t num_bytes); +void do_rom_read(uint8_t* rdram, int32_t ram_address, uint32_t dev_address, size_t num_bytes); std::unique_ptr rom; size_t rom_size; @@ -105,7 +105,7 @@ int main(int argc, char **argv) { // Get entrypoint from ROM // TODO fix this for other IPL3 versions - uint32_t entrypoint = byteswap(*reinterpret_cast(rom.get() + 0x8)); + int32_t entrypoint = byteswap(*reinterpret_cast(rom.get() + 0x8)); // Allocate rdram_buffer std::unique_ptr rdram_buffer = std::make_unique(8 * 1024 * 1024); @@ -134,17 +134,17 @@ int main(int argc, char **argv) { #endif // Set up stack pointer - context.r29 = 0x803FFFF0u; + context.r29 = 0xFFFFFFFF803FFFF0u; // Initialize variables normally set by IPL3 - constexpr uint32_t osTvType = 0x80000300; - constexpr uint32_t osRomType = 0x80000304; - constexpr uint32_t osRomBase = 0x80000308; - constexpr uint32_t osResetType = 0x8000030c; - constexpr uint32_t osCicId = 0x80000310; - constexpr uint32_t osVersion = 0x80000314; - constexpr uint32_t osMemSize = 0x80000318; - constexpr uint32_t osAppNMIBuffer = 0x8000031c; + constexpr int32_t osTvType = 0x80000300; + constexpr int32_t osRomType = 0x80000304; + constexpr int32_t osRomBase = 0x80000308; + constexpr int32_t osResetType = 0x8000030c; + constexpr int32_t osCicId = 0x80000310; + constexpr int32_t osVersion = 0x80000314; + constexpr int32_t osMemSize = 0x80000318; + constexpr int32_t osAppNMIBuffer = 0x8000031c; uint8_t *rdram = rdram_buffer.get(); MEM_W(osTvType, 0) = 1; // NTSC MEM_W(osRomBase, 0) = 0xB0000000u; // standard rom base @@ -157,7 +157,7 @@ int main(int argc, char **argv) { debug_printf("[Recomp] Starting\n"); - Multilibultra::preinit(rdram_buffer.get()); + Multilibultra::preinit(rdram_buffer.get(), rom.get()); game_init(rdram_buffer.get(), &context); diff --git a/test/src/sp.cpp b/test/src/sp.cpp index 370a8e2..fb8ce76 100644 --- a/test/src/sp.cpp +++ b/test/src/sp.cpp @@ -10,7 +10,7 @@ extern "C" void osSpTaskStartGo_recomp(uint8_t* restrict rdram, recomp_context* //printf("[sp] osSpTaskStartGo(0x%08X)\n", (uint32_t)ctx->r4); OSTask* task = TO_PTR(OSTask, ctx->r4); if (task->t.type == M_GFXTASK) { - printf("[sp] Gfx task: %08X\n", (uint32_t)ctx->r4); + //printf("[sp] Gfx task: %08X\n", (uint32_t)ctx->r4); } else if (task->t.type == M_AUDTASK) { printf("[sp] Audio task: %08X\n", (uint32_t)ctx->r4); } diff --git a/test/src/vi.cpp b/test/src/vi.cpp index d5f31e1..910ebc5 100644 --- a/test/src/vi.cpp +++ b/test/src/vi.cpp @@ -1,3 +1,4 @@ +#include "../portultra/multilibultra.hpp" #include "recomp.h" extern "C" void osCreateViManager_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { @@ -21,7 +22,7 @@ extern "C" void osViGetNextFramebuffer_recomp(uint8_t* restrict rdram, recomp_co } extern "C" void osViSwapBuffer_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) { - ; + osViSwapBuffer(rdram, ctx->r4); } extern "C" void osViSetMode_recomp(uint8_t* restrict rdram, recomp_context* restrict ctx) {