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) {