Integrated RT64 (not included in repo), sign extended addresses

This commit is contained in:
Mr-Wiseguy 2022-11-19 18:12:47 -05:00
parent 39b67c8468
commit d0c3eb73ec
17 changed files with 185 additions and 92 deletions

5
.gitignore vendored
View file

@ -38,4 +38,7 @@ bld/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
.vs/
# RT64 (since it's not public yet)
test/RT64

View file

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

View file

@ -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:
{

View file

@ -76,7 +76,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
@ -91,7 +91,7 @@
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(ProjectDir)..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
@ -104,21 +104,28 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>$(ProjectDir)..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>$(ProjectDir)RT64\Debug\RT64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>XCOPY "$(ProjectDir)RT64\$(Configuration)\*" "$(TargetDir)" /S /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>$(ProjectDir)..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)thirdparty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
<PostBuildEvent>
<Command>XCOPY "$(ProjectDir)RT64\$(Configuration)\*" "$(TargetDir)" /S /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="funcs\adjust_texture_table.c" />
@ -2005,6 +2012,7 @@
<ClCompile Include="portultra\task_pthreads.cpp" />
<ClCompile Include="portultra\task_win32.cpp" />
<ClCompile Include="portultra\threads.cpp" />
<ClCompile Include="RT64\rt64_layer.cpp" />
<ClCompile Include="src\ai.cpp" />
<ClCompile Include="src\cont.cpp" />
<ClCompile Include="src\dp.cpp" />
@ -2020,7 +2028,11 @@
<ClInclude Include="..\recomp.h" />
<ClInclude Include="portultra\multilibultra.hpp" />
<ClInclude Include="portultra\platform_specific.h" />
<ClInclude Include="RT64\rt64_layer.h" />
<ClInclude Include="portultra\ultra64.h" />
<ClInclude Include="thirdparty\blockingconcurrentqueue.h" />
<ClInclude Include="thirdparty\concurrentqueue.h" />
<ClInclude Include="thirdparty\lightweightsemaphore.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -5700,6 +5700,9 @@
<ClCompile Include="portultra\events.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RT64\rt64_layer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="portultra\platform_specific.h">
@ -5714,5 +5717,17 @@
<ClInclude Include="..\recomp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RT64\rt64_layer.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="thirdparty\blockingconcurrentqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thirdparty\concurrentqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lightweightsemaphore.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -2,11 +2,25 @@
#include <atomic>
#include <chrono>
#include <cinttypes>
#include <variant>
#include <Windows.h>
#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<SpTaskAction, SwapBuffersAction>;
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> 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<std::chrono::microseconds>(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<SpTaskAction>(&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<SwapBuffersAction>(&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 };
}
events_context.sp.thread = std::thread{ gfx_thread_func, rdram, rom };
}

View file

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

View file

@ -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];
}

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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) {
;
}
ctx->r2 = 0x80000000;
}

View file

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

View file

@ -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_);

View file

@ -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<uint8_t[]> 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<uint32_t*>(rom.get() + 0x8));
int32_t entrypoint = byteswap(*reinterpret_cast<uint32_t*>(rom.get() + 0x8));
// Allocate rdram_buffer
std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(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);

View file

@ -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);
}

View file

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