mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-27 00:10:31 +00:00
[jak3] A bunch of small fixes to get game.cgo
to load (#3435)
The `test-play` macro is back, though it doesn't call `play` yet. We can at least load all of `game.cgo`, which involves loading a lot of the code we've decompiled, loading/linking objects files compiled by OpenGOAL (like dir-tpages), and loading/linking Jak's art-groups (for jak 3 they are stored v5 format that I added to the linker). There were no major issues - just a few forgotten mips2c entries and minor bugs/functions that needed stubs. Most of the work was updating the linker. Hopefully I'll never have to touch that code again - I think it supports everything we need for jak 3!
This commit is contained in:
parent
9b4b54978a
commit
ee015e3b22
@ -1799,7 +1799,7 @@
|
||||
some, but not all, functions assume that a matrix is an affine transform.
|
||||
others assume that the rotation has no scale or shear (and that its inverse is its transpose)."
|
||||
((data float 16 :offset-assert 0 :score -2) ;; guessed by decompiler
|
||||
(vector vector 4 :offset 0 :score -1) ;; guessed by decompiler
|
||||
(vector vector 4 :inline :offset 0 :score -1) ;; guessed by decompiler
|
||||
(quad uint128 4 :offset 0) ;; guessed by decompiler
|
||||
(rvec vector :inline :offset 0 :score 1)
|
||||
(uvec vector :inline :offset 16 :score 1)
|
||||
@ -30761,7 +30761,6 @@
|
||||
;; sparticle-launcher ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
#|
|
||||
(deftype sp-queued-launch-particles (structure)
|
||||
((sp-system sparticle-system :offset-assert 0) ;; guessed by decompiler
|
||||
(sp-launcher sparticle-launcher :offset-assert 4) ;; guessed by decompiler
|
||||
@ -30771,34 +30770,28 @@
|
||||
:size-assert #x20
|
||||
:flag-assert #x900000020
|
||||
)
|
||||
|#
|
||||
|
||||
#|
|
||||
(deftype sp-launch-queue (basic)
|
||||
((in-use int32 :offset-assert 4)
|
||||
(queue sp-queued-launch-particles 256 :offset-assert 16) ;; guessed by decompiler
|
||||
(queue sp-queued-launch-particles 256 :inline :offset-assert 16) ;; guessed by decompiler
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x2010
|
||||
:flag-assert #x900002010
|
||||
)
|
||||
|#
|
||||
|
||||
#|
|
||||
(deftype particle-adgif-cache (basic)
|
||||
((used int32 :offset-assert 4)
|
||||
(last uint16 :offset-assert 8)
|
||||
(lastgif adgif-shader :offset-assert 12)
|
||||
(tidhash uint16 80 :offset-assert 16) ;; guessed by decompiler
|
||||
(spadgif adgif-shader 80 :offset-assert 176) ;; guessed by decompiler
|
||||
(spadgif adgif-shader 80 :inline :offset-assert 176) ;; guessed by decompiler
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x19b0
|
||||
:flag-assert #x9000019b0
|
||||
)
|
||||
|#
|
||||
|
||||
#|
|
||||
(deftype sp-launch-stack (structure)
|
||||
((ra basic :offset-assert 0)
|
||||
(dummy0 basic :offset-assert 4)
|
||||
@ -30822,23 +30815,22 @@
|
||||
:flag-assert #x900000130
|
||||
;; field ra uses ~A with a signed load. field dummy0 uses ~A with a signed load. field dummy1 uses ~A with a signed load. field b-spfic uses ~A with a signed load. field l-spfic uses ~A with a signed load.
|
||||
)
|
||||
|#
|
||||
|
||||
;; sparticle-launcher is already defined!
|
||||
|
||||
(define-extern *part-id-table* (array sparticle-launcher))
|
||||
(define-extern *part-group-id-table* (array sparticle-launch-group))
|
||||
;; (define-extern *sp-temp* object) ;; float
|
||||
(define-extern *sp-temp* float)
|
||||
;; (define-extern lookup-part-group-by-name function) ;; (function string sparticle-launch-group)
|
||||
(define-extern lookup-part-group-pointer-by-name (function string (pointer object)))
|
||||
(define-extern part-group-pointer? (function pointer symbol))
|
||||
(define-extern unlink-part-group-by-heap (function kheap int))
|
||||
;; (define-extern sp-init-fields! function) ;; (function (pointer float) (inline-array sp-field-init-spec) sp-field-id sp-field-id symbol (inline-array sp-field-init-spec))
|
||||
;; (define-extern *sp-launcher-lock* object) ;; symbol
|
||||
;; (define-extern *sp-launch-queue* object) ;; sp-launch-queue
|
||||
;; (define-extern *sp-launcher-enable* object) ;; symbol
|
||||
(define-extern *sp-launcher-lock* symbol)
|
||||
(define-extern *sp-launch-queue* sp-launch-queue)
|
||||
(define-extern *sp-launcher-enable* symbol)
|
||||
;; (define-extern particle-setup-adgif function) ;; (function adgif-shader int none)
|
||||
;; (define-extern *particle-adgif-cache* object) ;; particle-adgif-cache
|
||||
(define-extern *particle-adgif-cache* particle-adgif-cache)
|
||||
(define-extern particle-adgif-cache-flush (function none))
|
||||
;; (define-extern particle-adgif function) ;; (function adgif-shader texture-id none)
|
||||
;; (define-extern particle-adgif-callback function) ;; (function adgif-shader texture-id none)
|
||||
@ -30847,7 +30839,7 @@
|
||||
;; (define-extern sp-euler-convert function) ;; (function sparticle-launchinfo sparticle-cpuinfo none)
|
||||
;; (define-extern sp-rotate-system function) ;; (function sparticle-launchinfo sparticle-cpuinfo transformq none)
|
||||
(define-extern sp-launch-particles-var (function sparticle-system sparticle-launcher matrix sparticle-launch-state sparticle-launch-control float none))
|
||||
;; (define-extern *death-adgif* object) ;; adgif-shader
|
||||
(define-extern *death-adgif* adgif-shader)
|
||||
;; (define-extern sp-launch-particles-death function) ;; (function sparticle-system sparticle-launcher vector none)
|
||||
;; (define-extern sp-clear-queue function) ;; (function none)
|
||||
;; (define-extern sp-relaunch-setup-fields function) ;; (function object sparticle-launcher sparticle-cpuinfo sprite-vec-data-3d none)
|
||||
@ -30865,7 +30857,7 @@
|
||||
;; (define-extern birth-func-clean function)
|
||||
;; (define-extern birth-func-process-clock function)
|
||||
;; (define-extern birth-func-copy-rot-color function) ;; (function sparticle-system sparticle-cpuinfo sprite-vec-data-3d sparticle-launcher sparticle-launch-state none)
|
||||
;; (define-extern *global-toggle* object) ;; int
|
||||
(define-extern *global-toggle* int)
|
||||
;; (define-extern birth-func-copy2-rot-color function) ;; (function sparticle-system sparticle-cpuinfo sprite-vec-data-3d sparticle-launcher sparticle-launch-state none)
|
||||
;; (define-extern birth-func-copy-omega-to-z function) ;; (function sparticle-system sparticle-cpuinfo sprite-vec-data-3d sparticle-launcher sparticle-launch-state none)
|
||||
;; (define-extern birth-func-random-next-time function) ;; (function sparticle-system sparticle-cpuinfo sprite-vec-data-3d sparticle-launcher sparticle-launch-state none)
|
||||
|
@ -188,10 +188,13 @@ set(RUNTIME_SOURCE
|
||||
mips2c/jak3_functions/collide_func.cpp
|
||||
mips2c/jak3_functions/debug.cpp
|
||||
mips2c/jak3_functions/font.cpp
|
||||
mips2c/jak3_functions/foreground.cpp
|
||||
mips2c/jak3_functions/generic_effect.cpp
|
||||
mips2c/jak3_functions/joint.cpp
|
||||
mips2c/jak3_functions/lights.cpp
|
||||
mips2c/jak3_functions/prim.cpp
|
||||
mips2c/jak3_functions/sky.cpp
|
||||
mips2c/jak3_functions/texture.cpp
|
||||
mips2c/mips2c_table.cpp
|
||||
overlord/common/dma.cpp
|
||||
overlord/common/fake_iso.cpp
|
||||
|
@ -32,6 +32,13 @@ struct ObjectFileHeader {
|
||||
uint32_t link_block_length;
|
||||
};
|
||||
|
||||
struct SegmentInfoV5 {
|
||||
uint32_t relocs; // offset of relocation table
|
||||
uint32_t data; // offset of segment data
|
||||
uint32_t size; // segment data size (0 if segment doesn't exist)
|
||||
uint32_t magic; // always 0
|
||||
};
|
||||
|
||||
void klink_init_globals();
|
||||
/*!
|
||||
* Stores the state of the linker. Used for multi-threaded linking, so it can be suspended.
|
||||
@ -65,6 +72,8 @@ struct link_control {
|
||||
bool m_on_global_heap = false;
|
||||
LinkHeaderV5Core* m_link_hdr = nullptr;
|
||||
bool m_moved_link_block = false;
|
||||
int m_n_segments = 0;
|
||||
SegmentInfoV5* m_link_segments_table = nullptr;
|
||||
|
||||
void jak1_jak2_begin(Ptr<uint8_t> object_file,
|
||||
const char* name,
|
||||
@ -89,6 +98,7 @@ struct link_control {
|
||||
uint32_t jak2_work_v3();
|
||||
uint32_t jak2_work_v2();
|
||||
|
||||
uint32_t jak3_work_v2_v4();
|
||||
uint32_t jak3_work_v5();
|
||||
uint32_t jak3_work_opengoal();
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "game/kernel/common/fileio.h"
|
||||
#include "game/kernel/common/klink.h"
|
||||
#include "game/kernel/common/kprint.h"
|
||||
#include "game/kernel/common/memory_layout.h"
|
||||
#include "game/kernel/jak3/kmalloc.h"
|
||||
#include "game/kernel/jak3/kscheme.h"
|
||||
#include "game/mips2c/mips2c_table.h"
|
||||
@ -145,19 +146,27 @@ void link_control::jak3_begin(Ptr<uint8_t> object_file,
|
||||
LinkHeaderV5* l_hdr = (LinkHeaderV5*)m_object_data.c();
|
||||
m_flags = flags;
|
||||
u16 version = l_hdr->core.version;
|
||||
ASSERT(version == 5); // I think, since there's only a work v5.
|
||||
|
||||
if (version == 4) {
|
||||
// it's a v4 produced by opengoal... lets just try using jak2's linker
|
||||
m_version = 4;
|
||||
printf("got version 4, falling back to jak1/jak2\n");
|
||||
jak1_jak2_begin(object_file, name, size, heap, flags);
|
||||
return;
|
||||
}
|
||||
ASSERT(version == 5);
|
||||
m_heap_top = heap->top;
|
||||
// this->unk_init1 = 1; TODO
|
||||
m_busy = true;
|
||||
m_heap = heap;
|
||||
// this->m_unk_init0_0 = 0; TODO
|
||||
m_entry.offset = 0;
|
||||
m_keep_debug = false;
|
||||
m_link_hdr = &l_hdr->core; // m_hdr_ptr
|
||||
m_code_size = 0;
|
||||
// this->m_ptr_2 = l_hdr; just used for cache flush, so skip it! not really the right thing??
|
||||
// this->m_unk_init0_3 = 0; TODO
|
||||
// this->m_unk_init0_4 = 0; TODO
|
||||
// this->m_unk_init0_5 = 0; TODO
|
||||
m_state = 0;
|
||||
m_segment_process = 0;
|
||||
m_moved_link_block = 0;
|
||||
if (version == 4) {
|
||||
ASSERT_NOT_REACHED();
|
||||
} else {
|
||||
@ -183,7 +192,17 @@ void link_control::jak3_begin(Ptr<uint8_t> object_file,
|
||||
m_heap->current = m_object_data;
|
||||
}
|
||||
} else {
|
||||
// the link block is in the heap. This is problematic because we don't want to hang
|
||||
// on to this long term, but executing the top-level may allocate on this heap, causing
|
||||
// stuff to get added after the hole left by the link data.
|
||||
// So, we make a temporary allocation on the top and move it there.
|
||||
|
||||
m_moved_link_block = true;
|
||||
Ptr<u8> new_link_block_mem;
|
||||
u8* link_block_move_dst;
|
||||
u8* old_link_block;
|
||||
u32 link_block_move_size;
|
||||
|
||||
if (m_link_hdr->version == 5) {
|
||||
// the link block is inside our heap, but we'd like to avoid this.
|
||||
// we'll copy the link block, and the header to the temporary part of our heap:
|
||||
@ -191,9 +210,9 @@ void link_control::jak3_begin(Ptr<uint8_t> object_file,
|
||||
// where we loaded the link data:
|
||||
auto offset_to_link_data = m_link_hdr->length_to_get_to_link;
|
||||
|
||||
// allocate memory for link data, and header
|
||||
auto new_link_block_mem = kmalloc(m_heap, m_link_hdr->link_length + sizeof(LinkHeaderV5),
|
||||
KMALLOC_TOP, "link-block");
|
||||
// allocate memory for link data, and header (pvVar5)
|
||||
new_link_block_mem = kmalloc(m_heap, m_link_hdr->link_length + sizeof(LinkHeaderV5),
|
||||
KMALLOC_TOP, "link-block");
|
||||
|
||||
// we'll place the header and link block back to back in the newly alloated block,
|
||||
// so patch up the offset for this new layout before copying
|
||||
@ -202,30 +221,38 @@ void link_control::jak3_begin(Ptr<uint8_t> object_file,
|
||||
// move header!
|
||||
memmove(new_link_block_mem.c(), object_file.c(), sizeof(LinkHeaderV5));
|
||||
|
||||
// move link data!
|
||||
auto old_link_block = object_file.c() + offset_to_link_data;
|
||||
memmove(new_link_block_mem.c() + sizeof(LinkHeaderV5), old_link_block,
|
||||
m_link_hdr->link_length);
|
||||
// dst: pvVar6
|
||||
link_block_move_dst = new_link_block_mem.c() + sizeof(LinkHeaderV5);
|
||||
|
||||
// update our pointer to the link header core.
|
||||
m_link_hdr = &((LinkHeaderV5*)new_link_block_mem.c())->core;
|
||||
// move link data! (pcVar8)
|
||||
old_link_block = object_file.c() + offset_to_link_data;
|
||||
|
||||
// scary: update the heap to kick out all the link data (and likely the actual data too).
|
||||
// we'll be relying on the linking process to copy the data as needed.l
|
||||
if (old_link_block < m_heap->current.c()) {
|
||||
if (link_debug_printfs) {
|
||||
printf("Kick out old link block\n");
|
||||
}
|
||||
m_heap->current.offset = old_link_block - g_ee_main_mem;
|
||||
}
|
||||
link_block_move_size = m_link_hdr->link_length;
|
||||
} else {
|
||||
// hm, maybe only possible with version 2 or 3??
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
memmove(link_block_move_dst, old_link_block, link_block_move_size);
|
||||
|
||||
// update our pointer to the link header core.
|
||||
m_link_hdr = &((LinkHeaderV5*)new_link_block_mem.c())->core;
|
||||
|
||||
// scary: update the heap to kick out all the link data (and likely the actual data too).
|
||||
// we'll be relying on the linking process to copy the data as needed.l
|
||||
if (old_link_block < m_heap->current.c()) {
|
||||
if (link_debug_printfs) {
|
||||
printf("Kick out old link block\n");
|
||||
}
|
||||
m_heap->current.offset = old_link_block - g_ee_main_mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((m_flags & LINK_FLAG_FORCE_DEBUG) && MasterDebug && !DiskBoot) {
|
||||
m_keep_debug = true;
|
||||
}
|
||||
// hack:
|
||||
m_version = m_link_hdr->version;
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +275,11 @@ uint32_t link_control::jak3_work() {
|
||||
ASSERT(!m_opengoal);
|
||||
*(u32*)(((u8*)m_link_hdr) - 4) = *((s7 + jak3_symbols::FIX_SYM_LINK_BLOCK - 1).cast<u32>());
|
||||
rv = jak3_work_v5();
|
||||
} else if (m_version == 4) {
|
||||
// Note: this is a bit of a hack. Jak 3 doesn't support v2/v4. But, OpenGOAL generates data
|
||||
// objects in this format. We will just try reusing the jak 2 v2/v4 linker here and see if it
|
||||
// works. See corresponding call to jak1_jak2_begin in begin.
|
||||
rv = jak3_work_v2_v4();
|
||||
} else {
|
||||
ASSERT_MSG(false, fmt::format("UNHANDLED OBJECT FILE VERSION {} IN WORK!", m_version));
|
||||
return 0;
|
||||
@ -257,9 +289,175 @@ uint32_t link_control::jak3_work() {
|
||||
return rv;
|
||||
}
|
||||
|
||||
namespace jak3 {
|
||||
void ultimate_memcpy(void* dst, void* src, uint32_t size);
|
||||
}
|
||||
|
||||
uint32_t link_control::jak3_work_v5() {
|
||||
ASSERT_NOT_REACHED(); // save this for another day...
|
||||
// TODO: there are some missing vars in begin. I just commented them out for now.
|
||||
if (m_state == 0) {
|
||||
// here, we change length_to_get_to_link to an actual pointer to the link table.
|
||||
// since we need 32-bits, we'll store offset from g_ee_mem.
|
||||
u8* link_data = ((u8*)m_link_hdr) - 4 + m_link_hdr->length_to_get_to_link;
|
||||
m_link_hdr->length_to_get_to_link = link_data - g_ee_main_mem;
|
||||
|
||||
m_n_segments = m_link_hdr->n_segments;
|
||||
|
||||
// the link segments table is just at the start of the link data:
|
||||
m_link_segments_table = (SegmentInfoV5*)link_data;
|
||||
/*
|
||||
for (int i = 0; i < m_n_segments; i++) {
|
||||
printf(" %d: reloc %d, data %d, size %d, magic %d\n", i, m_link_segments_table[i].relocs,
|
||||
m_link_segments_table[i].data, m_link_segments_table[i].size,
|
||||
m_link_segments_table[i].magic);
|
||||
}
|
||||
*/
|
||||
// for now, only supporting 1 segment
|
||||
ASSERT(m_n_segments == 1);
|
||||
|
||||
// fixup the relocs/data offsets into addresses (again, offsets from g_ee_main_mem)
|
||||
// relocs is relative to this link data
|
||||
m_link_segments_table[0].relocs += (link_data - g_ee_main_mem);
|
||||
// data is relative to usual object_data
|
||||
m_link_segments_table[0].data += m_object_data.offset;
|
||||
ASSERT(m_link_segments_table[0].magic == 1);
|
||||
|
||||
// see if there's even data
|
||||
if (m_link_segments_table[0].size == 0) {
|
||||
// no data.
|
||||
m_link_segments_table[0].data = 0;
|
||||
} else {
|
||||
// check if we need to move the main segment.
|
||||
if (!m_moved_link_block ||
|
||||
((m_link_hdr->link_length + 0x50) <= m_link_hdr->length_to_get_to_code)) {
|
||||
// printf(" v5 linker allocating for main segment... (%d)\n", m_moved_link_block);
|
||||
auto old_data_offset = m_link_segments_table[0].data; // 25
|
||||
auto new_data = kmalloc(m_heap, m_link_segments_table[0].size, 0, "main-segment");
|
||||
m_link_segments_table[0].data = new_data.offset;
|
||||
if (!new_data.offset) {
|
||||
MsgErr("dkernel: unable to malloc %d bytes for main-segment\n",
|
||||
m_link_segments_table[0].size);
|
||||
return 1;
|
||||
}
|
||||
jak3::ultimate_memcpy(new_data.c(), old_data_offset + g_ee_main_mem,
|
||||
m_link_segments_table[0].size);
|
||||
} else {
|
||||
m_heap->current = m_object_data + m_code_size;
|
||||
if (m_heap->top.offset <= m_heap->current.offset) {
|
||||
MsgErr("dkernel: heap overflow\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_segment_process = 0;
|
||||
m_state = 1;
|
||||
m_object_data.offset = m_link_segments_table[0].data;
|
||||
|
||||
Ptr<u8> base_ptr(m_link_segments_table[0].data);
|
||||
Ptr<u8> data_ptr = base_ptr - 4;
|
||||
Ptr<u8> link_ptr(m_link_segments_table[0].relocs);
|
||||
|
||||
bool fixing = false;
|
||||
if (*link_ptr) {
|
||||
// we have pointers
|
||||
while (true) {
|
||||
while (true) {
|
||||
if (!fixing) {
|
||||
// seeking
|
||||
data_ptr.offset += 4 * (*link_ptr);
|
||||
} else {
|
||||
// fixing.
|
||||
for (uint32_t i = 0; i < *link_ptr; i++) {
|
||||
// uint32_t old_code = *(const uint32_t*)(&data.at(data_ptr));
|
||||
u32 old_code = *data_ptr.cast<u32>();
|
||||
if ((old_code >> 24) == 0) {
|
||||
// printf("modifying pointer at 0x%x (old 0x%x) : now ", data_ptr.offset,
|
||||
// *data_ptr.cast<u32>());
|
||||
*data_ptr.cast<u32>() += base_ptr.offset;
|
||||
// printf("0x%x\n", *data_ptr.cast<u32>());
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
/*
|
||||
f.stats.v3_split_pointers++;
|
||||
auto dest_seg = (old_code >> 8) & 0xf;
|
||||
auto lo_hi_offset = (old_code >> 12) & 0xf;
|
||||
ASSERT(lo_hi_offset);
|
||||
ASSERT(dest_seg < 3);
|
||||
auto offset_upper = old_code & 0xff;
|
||||
uint32_t low_code = *(const uint32_t*)(&data.at(data_ptr + 4 * lo_hi_offset));
|
||||
uint32_t offset = low_code & 0xffff;
|
||||
if (offset_upper) {
|
||||
offset += (offset_upper << 16);
|
||||
}
|
||||
f.pointer_link_split_word(seg_id, data_ptr - base_ptr,
|
||||
data_ptr + 4 * lo_hi_offset - base_ptr, dest_seg, offset);
|
||||
*/
|
||||
}
|
||||
data_ptr.offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (*link_ptr != 0xff)
|
||||
break;
|
||||
link_ptr.offset++;
|
||||
if (*link_ptr == 0) {
|
||||
link_ptr.offset++;
|
||||
fixing = !fixing;
|
||||
}
|
||||
}
|
||||
|
||||
link_ptr.offset++;
|
||||
fixing = !fixing;
|
||||
if (*link_ptr == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
link_ptr.offset++;
|
||||
|
||||
// symbol linking.
|
||||
if (*link_ptr) {
|
||||
auto sub_link_ptr = link_ptr;
|
||||
|
||||
while (true) {
|
||||
auto reloc = *sub_link_ptr;
|
||||
auto next_link_ptr = sub_link_ptr + 1;
|
||||
link_ptr = next_link_ptr;
|
||||
|
||||
if ((reloc & 0x80) == 0) {
|
||||
link_ptr = sub_link_ptr + 3; //
|
||||
const char* sname = link_ptr.cast<char>().c();
|
||||
link_ptr.offset += strlen(sname) + 1;
|
||||
// printf("linking symbol %s\n", sname);
|
||||
auto goalObj = jak3::intern_from_c(-1, 0, sname);
|
||||
link_ptr = c_symlink2(m_object_data, goalObj.cast<u8>(), link_ptr);
|
||||
|
||||
} else if ((reloc & 0x3f) == 0x3f) {
|
||||
ASSERT(false); // todo, does this ever get hit?
|
||||
} else {
|
||||
int n_methods_base = reloc & 0x3f;
|
||||
int n_methods = n_methods_base * 4;
|
||||
if (n_methods_base) {
|
||||
n_methods += 3;
|
||||
}
|
||||
link_ptr.offset +=
|
||||
2; // ghidra misses some aliasing here and would have you think this is +1!
|
||||
const char* sname = link_ptr.cast<char>().c();
|
||||
// printf("linking type %s\n", sname);
|
||||
link_ptr.offset += strlen(sname) + 1;
|
||||
auto goalObj = jak3::intern_type_from_c(-1, 0, sname, n_methods);
|
||||
link_ptr = c_symlink2(m_object_data, goalObj.cast<u8>(), link_ptr);
|
||||
}
|
||||
|
||||
sub_link_ptr = link_ptr;
|
||||
if (!*sub_link_ptr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_entry = m_object_data + 4;
|
||||
return 1;
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -567,7 +765,17 @@ void link_control::jak3_finish(bool jump_from_c_to_goal) {
|
||||
output_segment_load(m_object_name, m_link_block_ptr, m_flags);
|
||||
}
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
if (m_flags & LINK_FLAG_EXECUTE) {
|
||||
auto entry = m_entry;
|
||||
auto name = basename_goal(m_object_name);
|
||||
strcpy(Ptr<char>(LINK_CONTROL_NAME_ADDR).c(), name);
|
||||
// printf(" about to call... (0x%x)\n", entry.offset);
|
||||
Ptr<jak3::Type> type(*((entry - 4).cast<u32>()));
|
||||
// printf(" type is %s\n", jak3::sym_to_cstring(type->symbol));
|
||||
jak3::call_method_of_type_arg2(entry.offset, type, GOAL_RELOC_METHOD, m_heap.offset,
|
||||
Ptr<char>(LINK_CONTROL_NAME_ADDR).offset);
|
||||
// printf(" done with call!\n");
|
||||
}
|
||||
}
|
||||
|
||||
*EnableMethodSet = *EnableMethodSet - this->m_keep_debug;
|
||||
@ -654,3 +862,214 @@ void ultimate_memcpy(void* dst, void* src, uint32_t size) {
|
||||
}
|
||||
|
||||
} // namespace jak3
|
||||
|
||||
#define LINK_V2_STATE_INIT_COPY 0
|
||||
#define LINK_V2_STATE_OFFSETS 1
|
||||
#define LINK_V2_STATE_SYMBOL_TABLE 2
|
||||
#define OBJ_V2_CLOSE_ENOUGH 0x90
|
||||
#define OBJ_V2_MAX_TRANSFER 0x80000
|
||||
|
||||
uint32_t link_control::jak3_work_v2_v4() {
|
||||
// u32 startCycle = kernel.read_clock(); todo
|
||||
|
||||
if (m_state == LINK_V2_STATE_INIT_COPY) { // initialization and copying to heap
|
||||
// we move the data segment to eliminate gaps
|
||||
// very small gaps can be tolerated, as it is not worth the time penalty to move large objects
|
||||
// many bytes. if this requires copying a large amount of data, we will do it in smaller chunks,
|
||||
// allowing the copy to be spread over multiple game frames
|
||||
|
||||
// state initialization
|
||||
if (m_segment_process == 0) {
|
||||
m_heap_gap =
|
||||
m_object_data - m_heap->current; // distance between end of heap and start of object
|
||||
}
|
||||
|
||||
if (m_heap_gap <
|
||||
OBJ_V2_CLOSE_ENOUGH) { // close enough, don't relocate the object, just expand the heap
|
||||
if (link_debug_printfs) {
|
||||
printf("[work_v2] close enough, not moving\n");
|
||||
}
|
||||
m_heap->current = m_object_data + m_code_size;
|
||||
if (m_heap->top.offset <= m_heap->current.offset) {
|
||||
MsgErr("dkernel: heap overflow\n"); // game has ~% instead of \n :P
|
||||
return 1;
|
||||
}
|
||||
|
||||
// added in jak 2, move the link block to the top of the heap so we can allocate on
|
||||
// the level heap during linking without overwriting link data. this is used for level types
|
||||
u32 link_block_size = *m_link_block_ptr.cast<u32>();
|
||||
auto new_link_block = kmalloc(m_heap, link_block_size, KMALLOC_TOP, "link-block");
|
||||
memmove(new_link_block.c(), m_link_block_ptr.c() - 4, link_block_size);
|
||||
m_link_block_ptr = Ptr<uint8_t>(new_link_block.offset + 4); // basic offset
|
||||
|
||||
} else { // not close enough, need to move the object
|
||||
// on the first run of this state...
|
||||
if (m_segment_process == 0) {
|
||||
m_original_object_location = m_object_data;
|
||||
// allocate on heap, will have no gap
|
||||
m_object_data = kmalloc(m_heap, m_code_size, 0, "data-segment");
|
||||
if (link_debug_printfs) {
|
||||
printf("[work_v2] moving from 0x%x to 0x%x\n", m_original_object_location.offset,
|
||||
m_object_data.offset);
|
||||
}
|
||||
if (!m_object_data.offset) {
|
||||
MsgErr("dkernel: unable to malloc %d bytes for data-segment\n", m_code_size);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// the actual copy
|
||||
Ptr<u8> source = m_original_object_location + m_segment_process;
|
||||
u32 size = m_code_size - m_segment_process;
|
||||
|
||||
if (size > OBJ_V2_MAX_TRANSFER) { // around .5 MB
|
||||
jak3::ultimate_memcpy((m_object_data + m_segment_process).c(), source.c(),
|
||||
OBJ_V2_MAX_TRANSFER);
|
||||
m_segment_process += OBJ_V2_MAX_TRANSFER;
|
||||
return 0; // return, don't want to take too long.
|
||||
}
|
||||
|
||||
// if we have bytes to copy, but they are less than the max transfer, do it in one shot!
|
||||
if (size) {
|
||||
jak3::ultimate_memcpy((m_object_data + m_segment_process).c(), source.c(), size);
|
||||
if (m_segment_process > 0) { // if we did a previous copy, we return now....
|
||||
m_state = LINK_V2_STATE_OFFSETS;
|
||||
m_segment_process = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise go straight into the next state.
|
||||
m_state = LINK_V2_STATE_OFFSETS;
|
||||
m_segment_process = 0;
|
||||
}
|
||||
|
||||
// init offset phase
|
||||
if (m_state == LINK_V2_STATE_OFFSETS && m_segment_process == 0) {
|
||||
m_reloc_ptr = m_link_block_ptr + 8; // seek to link table
|
||||
if (*m_reloc_ptr == 0) { // do we have pointer links to do?
|
||||
m_reloc_ptr.offset++; // if not, seek past the \0, and go to next state
|
||||
m_state = LINK_V2_STATE_SYMBOL_TABLE;
|
||||
m_segment_process = 0;
|
||||
} else {
|
||||
m_base_ptr = m_object_data; // base address for offsetting.
|
||||
m_loc_ptr = m_object_data; // pointer which seeks thru the code
|
||||
m_table_toggle = 0; // are we seeking or fixing?
|
||||
m_segment_process = 1; // we've done first time setup
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state == LINK_V2_STATE_OFFSETS) { // pointer fixup
|
||||
// this state reads through a table. Values alternate between "seek amount" and "number of
|
||||
// consecutive 4-byte
|
||||
// words to fix up". The counts are encoded using a variable length encoding scheme. They use
|
||||
// a very stupid
|
||||
// method of encoding values which requires O(n) bytes to store the value n.
|
||||
|
||||
// to avoid dropping a frame, we check every 0x400 relocations to see if 0.5 milliseconds have
|
||||
// elapsed.
|
||||
u32 relocCounter = 0x400;
|
||||
while (true) { // loop over entire table
|
||||
while (true) { // loop over current mode
|
||||
|
||||
// read and seek table
|
||||
u8 count = *m_reloc_ptr;
|
||||
m_reloc_ptr.offset++;
|
||||
|
||||
if (!m_table_toggle) { // seek mode
|
||||
m_loc_ptr.offset +=
|
||||
4 *
|
||||
count; // perform seek (MIPS instructions are 4 bytes, so we >> 2 the seek amount)
|
||||
} else { // offset mode
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
if (m_loc_ptr.offset % 4) {
|
||||
ASSERT(false);
|
||||
}
|
||||
u32 code = *(m_loc_ptr.cast<u32>());
|
||||
code += m_base_ptr.offset;
|
||||
*(m_loc_ptr.cast<u32>()) = code;
|
||||
m_loc_ptr.offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (count != 0xff) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (*m_reloc_ptr == 0) {
|
||||
m_reloc_ptr.offset++;
|
||||
m_table_toggle = m_table_toggle ^ 1;
|
||||
}
|
||||
}
|
||||
|
||||
// reached the end of the tableToggle mode
|
||||
m_table_toggle = m_table_toggle ^ 1;
|
||||
if (*m_reloc_ptr == 0) {
|
||||
break; // end of the state
|
||||
}
|
||||
relocCounter--;
|
||||
if (relocCounter == 0) {
|
||||
// u32 clock_value = kernel.read_clock();
|
||||
// if(clock_value - startCycle > 150000) { // 0.5 milliseconds
|
||||
// return 0;
|
||||
// }
|
||||
relocCounter = 0x400;
|
||||
}
|
||||
}
|
||||
m_reloc_ptr.offset++;
|
||||
m_state = 2;
|
||||
m_segment_process = 0;
|
||||
}
|
||||
|
||||
if (m_state == 2) { // GOAL object fixup
|
||||
if (*m_reloc_ptr == 0) {
|
||||
m_state = 3;
|
||||
m_segment_process = 0;
|
||||
} else {
|
||||
while (true) {
|
||||
u32 relocation = *m_reloc_ptr;
|
||||
m_reloc_ptr.offset++;
|
||||
Ptr<u8> goalObj;
|
||||
char* name;
|
||||
if ((relocation & 0x80) == 0) {
|
||||
// symbol!
|
||||
if (relocation > 9) {
|
||||
m_reloc_ptr.offset--; // no idea what this is.
|
||||
}
|
||||
name = m_reloc_ptr.cast<char>().c();
|
||||
if (link_debug_printfs) {
|
||||
printf("[work_v2] symlink: %s\n", name);
|
||||
}
|
||||
goalObj = jak3::intern_from_c(-1, 0, name).cast<u8>();
|
||||
} else {
|
||||
// type!
|
||||
u8 nMethods = relocation & 0x7f;
|
||||
if (nMethods == 0) {
|
||||
nMethods = 1;
|
||||
}
|
||||
name = m_reloc_ptr.cast<char>().c();
|
||||
if (link_debug_printfs) {
|
||||
printf("[work_v2] symlink -type: %s\n", name);
|
||||
}
|
||||
goalObj = jak3::intern_type_from_c(-1, 0, name, nMethods).cast<u8>();
|
||||
}
|
||||
m_reloc_ptr.offset += strlen(name) + 1;
|
||||
// DECOMPILER->hookStartSymlinkV3(_state - 1, _objectData, std::string(name));
|
||||
m_reloc_ptr = c_symlink2(m_object_data, goalObj, m_reloc_ptr);
|
||||
// DECOMPILER->hookFinishSymlinkV3();
|
||||
if (*m_reloc_ptr == 0) {
|
||||
break; // done
|
||||
}
|
||||
// u32 currentCycle = kernel.read_clock();
|
||||
// if(currentCycle - startCycle > 150000) {
|
||||
// return 0;
|
||||
// }
|
||||
}
|
||||
m_state = 3;
|
||||
m_segment_process = 0;
|
||||
}
|
||||
}
|
||||
m_entry = m_object_data + 4;
|
||||
return 1;
|
||||
}
|
||||
|
@ -54,11 +54,11 @@ void kscheme_init_globals() {
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
u32 u32_in_fixed_sym(u32 offset) {
|
||||
return Ptr<Symbol4<u32>>(s7.offset + offset)->value();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void fixed_sym_set(u32 offset, u32 value) {
|
||||
Ptr<Symbol4<u32>>(s7.offset + offset)->value() = value;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ struct Type {
|
||||
};
|
||||
|
||||
s64 load_and_link(const char* filename, char* decode_name, kheapinfo* heap, u32 flags);
|
||||
u32 u32_in_fixed_sym(u32 offset);
|
||||
Ptr<Symbol4<u32>> intern_from_c(int sym_id, int flags, const char* name);
|
||||
u64 load(u32 /*file_name_in*/, u32 /*heap_in*/);
|
||||
u64 loadb(u32 /*file_name_in*/, u32 /*heap_in*/, u32 /*param3*/);
|
||||
@ -56,7 +57,9 @@ u64 call_method_of_type(u32 arg, Ptr<Type> type, u32 method_id);
|
||||
u64 new_pair(u32 heap, u32 type, u32 car, u32 cdr);
|
||||
u64 call_goal_function_by_name(const char* name);
|
||||
Ptr<Type> intern_type_from_c(int a, int b, const char* name, u64 methods);
|
||||
u64 alloc_heap_object(u32 heap, u32 type, u32 size, u32 pp);
|
||||
int InitHeapAndSymbol();
|
||||
u64 call_method_of_type_arg2(u32 arg, Ptr<Type> type, u32 method_id, u32 a1, u32 a2);
|
||||
template <typename T>
|
||||
Ptr<Ptr<String>> sym_to_string_ptr(Ptr<Symbol4<T>> in) {
|
||||
return Ptr<Ptr<String>>(SymbolString.offset + in.offset - s7.offset);
|
||||
|
@ -241,7 +241,6 @@ void link() {
|
||||
} // namespace Mips2C
|
||||
// add moving_sphere_triangle_intersect::link to the link callback table for the object file.
|
||||
// FWD DEC:
|
||||
namespace moving_sphere_triangle_intersect { extern void link(); }
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
// clang-format off
|
||||
@ -503,4 +502,3 @@ void link() {
|
||||
} // namespace Mips2C
|
||||
// add collide_do_primitives::link to the link callback table for the object file.
|
||||
// FWD DEC:
|
||||
namespace collide_do_primitives { extern void link(); }
|
@ -149,8 +149,6 @@ struct Cache {
|
||||
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->load_symbol2(v1, cache.math_camera); // lw v1, *math-camera*(s7)
|
||||
c->load_symbol2(a0, cache.sky_work); // lw a0, *sky-work*(s7)
|
||||
c->daddiu(a0, a0, 1088); // daddiu a0, a0, 1088
|
||||
@ -215,7 +213,7 @@ struct Cache {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
// u32 call_addr = 0;
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddiu(sp, sp, -8); // daddiu sp, sp, -8
|
||||
// nop // sll r0, r0, 0
|
||||
@ -223,7 +221,7 @@ u64 execute(void* ctxt) {
|
||||
c->load_symbol2(t9, cache.clip_polygon_against_positive_hyperplane);// lw t9, clip-polygon-against-positive-hyperplane(s7)
|
||||
c->mov64(a2, t4); // or a2, t4, r0
|
||||
c->mov64(a3, t5); // or a3, t5, r0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
// call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->daddu(t2, a2, r0); // daddu t2, a2, r0
|
||||
// c->jalr(call_addr); // jalr ra, t9
|
||||
clip_polygon_against_positive_hyperplane::execute(ctxt);
|
||||
@ -233,7 +231,7 @@ u64 execute(void* ctxt) {
|
||||
|
||||
c->mov64(a2, t5); // or a2, t5, r0
|
||||
c->mov64(a3, t4); // or a3, t4, r0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
// call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->daddiu(t2, a2, 4); // daddiu t2, a2, 4
|
||||
// c->jalr(call_addr); // jalr ra, t9
|
||||
clip_polygon_against_positive_hyperplane::execute(ctxt);
|
||||
@ -243,7 +241,7 @@ u64 execute(void* ctxt) {
|
||||
|
||||
c->mov64(a2, t4); // or a2, t4, r0
|
||||
c->mov64(a3, t5); // or a3, t5, r0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
// call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->daddu(t2, a2, r0); // daddu t2, a2, r0
|
||||
// c->jalr(call_addr); // jalr ra, t9
|
||||
clip_polygon_against_negative_hyperplane::execute(ctxt);
|
||||
@ -253,7 +251,7 @@ u64 execute(void* ctxt) {
|
||||
|
||||
c->mov64(a2, t5); // or a2, t5, r0
|
||||
c->mov64(a3, t4); // or a3, t4, r0
|
||||
call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
// call_addr = c->gprs[t9].du32[0]; // function call:
|
||||
c->daddiu(t2, a2, 4); // daddiu t2, a2, 4
|
||||
// c->jalr(call_addr); // jalr ra, t9
|
||||
clip_polygon_against_negative_hyperplane::execute(ctxt);
|
||||
@ -355,7 +353,6 @@ u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
c->copy_vfs_from_other(&sky_regs_vfs);
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->mov64(v1, a0); // or v1, a0, r0
|
||||
c->load_symbol2(v1, cache.math_camera); // lw v1, *math-camera*(s7)
|
||||
c->lqc2(vf14, 780, v1); // lqc2 vf14, 780(v1)
|
||||
@ -493,7 +490,6 @@ u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
c->copy_vfs_from_other(&sky_regs_vfs);
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->mov64(v1, a0); // or v1, a0, r0
|
||||
get_fake_spad_addr2(t4, cache.fake_scratchpad_data, 0, c);// lui t4, 28672
|
||||
c->ori(t4, t4, 12288); // ori t4, t4, 12288
|
||||
|
1300
game/mips2c/jak3_functions/foreground.cpp
Normal file
1300
game/mips2c/jak3_functions/foreground.cpp
Normal file
File diff suppressed because it is too large
Load Diff
162
game/mips2c/jak3_functions/joint.cpp
Normal file
162
game/mips2c/jak3_functions/joint.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
|
||||
//--------------------------MIPS2C---------------------
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
|
||||
namespace Mips2C::jak3 {
|
||||
// main function for (parent bone, transformq) -> child bone
|
||||
// this is used to compute world-space bones, used for collision and similar.
|
||||
// This includes the weird w divisor thing
|
||||
// This does not take into account the bind pose for mesh drawing.
|
||||
// (that's handled in bones.gc, which combines this with the bind pose to get the merc/pris matrix)
|
||||
namespace cspace_parented_transformq_joint {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a3, 0, a0); // lw a3, 0(a0)
|
||||
c->lui(v1, 16256); // lui v1, 16256
|
||||
c->lqc2(vf5, 16, a1); // lqc2 vf5, 16(a1)
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->lw(t0, 16, a3); // lw t0, 16(a3)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lw(a2, 16, a0); // lw a2, 16(a0)
|
||||
c->vadd(DEST::xyzw, vf6, vf5, vf5); // vadd.xyzw vf6, vf5, vf5
|
||||
c->lwc1(f1, 64, t0); // lwc1 f1, 64(t0)
|
||||
c->vadd_bc(DEST::x, BC::w, vf2, vf0, vf5); // vaddw.x vf2, vf0, vf5
|
||||
c->lqc2(vf15, 0, a1); // lqc2 vf15, 0(a1)
|
||||
c->vadd_bc(DEST::y, BC::z, vf2, vf0, vf5); // vaddz.y vf2, vf0, vf5
|
||||
c->lqc2(vf1, 32, a1); // lqc2 vf1, 32(a1)
|
||||
c->divs_accurate(f4, f0, f1); // div.s f4, f0, f1
|
||||
c->lqc2(vf7, 0, t0); // lqc2 vf7, 0(t0)
|
||||
c->vsub_bc(DEST::z, BC::y, vf2, vf0, vf5); // vsuby.z vf2, vf0, vf5
|
||||
c->lqc2(vf8, 16, t0); // lqc2 vf8, 16(t0)
|
||||
// sets vf2.w to 0
|
||||
c->vsub_bc(DEST::w, BC::w, vf2, vf0, vf0); // vsubw.w vf2, vf0, vf0
|
||||
c->lqc2(vf9, 32, t0); // lqc2 vf9, 32(t0)
|
||||
c->vsub_bc(DEST::x, BC::z, vf3, vf0, vf5); // vsubz.x vf3, vf0, vf5
|
||||
c->lqc2(vf10, 48, t0); // lqc2 vf10, 48(t0)
|
||||
c->vadd_bc(DEST::y, BC::w, vf3, vf0, vf5); // vaddw.y vf3, vf0, vf5
|
||||
c->lwc1(f2, 68, t0); // lwc1 f2, 68(t0)
|
||||
c->vadd_bc(DEST::z, BC::x, vf3, vf0, vf5); // vaddx.z vf3, vf0, vf5
|
||||
c->sqc2(vf1, 64, a2); // sqc2 vf1, 64(a2)
|
||||
c->vsub_bc(DEST::w, BC::w, vf3, vf0, vf0); // vsubw.w vf3, vf0, vf0
|
||||
c->lwc1(f3, 72, t0); // lwc1 f3, 72(t0)
|
||||
c->vadd_bc(DEST::x, BC::y, vf4, vf0, vf5); // vaddy.x vf4, vf0, vf5
|
||||
c->lw(v1, 76, t0); // lw v1, 76(t0)
|
||||
c->vsub_bc(DEST::y, BC::x, vf4, vf0, vf5); // vsubx.y vf4, vf0, vf5
|
||||
c->mfc1(t1, f4); // mfc1 t1, f4
|
||||
c->vadd_bc(DEST::z, BC::w, vf4, vf0, vf5); // vaddw.z vf4, vf0, vf5
|
||||
c->divs_accurate(f4, f0, f2); // div.s f4, f0, f2
|
||||
c->vsub_bc(DEST::w, BC::w, vf4, vf0, vf0); // vsubw.w vf4, vf0, vf0
|
||||
c->vopmula(vf6, vf2); // vopmula.xyz acc, vf6, vf2
|
||||
c->vopmsub(vf2, vf2, vf6); // vopmsub.xyz vf2, vf2, vf6
|
||||
c->vopmula(vf6, vf3); // vopmula.xyz acc, vf6, vf3
|
||||
c->vopmsub(vf3, vf3, vf6); // vopmsub.xyz vf3, vf3, vf6
|
||||
c->vopmula(vf6, vf4); // vopmula.xyz acc, vf6, vf4
|
||||
c->vopmsub(vf4, vf4, vf6); // vopmsub.xyz vf4, vf4, vf6
|
||||
c->vadd_bc(DEST::x, BC::w, vf2, vf2, vf0); // vaddw.x vf2, vf2, vf0
|
||||
c->vadd_bc(DEST::y, BC::w, vf3, vf3, vf0); // vaddw.y vf3, vf3, vf0
|
||||
c->vadd_bc(DEST::z, BC::w, vf4, vf4, vf0); // vaddw.z vf4, vf4, vf0
|
||||
c->mfc1(t2, f4); // mfc1 t2, f4
|
||||
bc = c->sgpr64(v1) != 0; // bne v1, r0, L50
|
||||
c->divs_accurate(f4, f0, f3); // div.s f4, f0, f3
|
||||
if (bc) {
|
||||
goto block_2;
|
||||
} // branch non-likely
|
||||
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf2, vf2, vf1); // vmulx.xyzw vf2, vf2, vf1
|
||||
c->vmul_bc(DEST::xyzw, BC::y, vf3, vf3, vf1); // vmuly.xyzw vf3, vf3, vf1
|
||||
c->vmul_bc(DEST::xyzw, BC::z, vf4, vf4, vf1); // vmulz.xyzw vf4, vf4, vf1
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf2); // vmulax.xyzw acc, vf7, vf2
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf2); // vmadday.xyzw acc, vf8, vf2
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf2); // vmaddaz.xyzw acc, vf9, vf2
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf11, vf10, vf2); // vmaddw.xyzw vf11, vf10, vf2
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf3); // vmulax.xyzw acc, vf7, vf3
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf3); // vmadday.xyzw acc, vf8, vf3
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf3); // vmaddaz.xyzw acc, vf9, vf3
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf12, vf10, vf3); // vmaddw.xyzw vf12, vf10, vf3
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf4); // vmulax.xyzw acc, vf7, vf4
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf4); // vmadday.xyzw acc, vf8, vf4
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf4); // vmaddaz.xyzw acc, vf9, vf4
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf13, vf10, vf4); // vmaddw.xyzw vf13, vf10, vf4
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf15); // vmulax.xyzw acc, vf7, vf15
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf15); // vmadday.xyzw acc, vf8, vf15
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf15); // vmaddaz.xyzw acc, vf9, vf15
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf14, vf10, vf0); // vmaddw.xyzw vf14, vf10, vf0
|
||||
c->sqc2(vf11, 0, a2); // sqc2 vf11, 0(a2)
|
||||
c->sqc2(vf12, 16, a2); // sqc2 vf12, 16(a2)
|
||||
c->sqc2(vf13, 32, a2); // sqc2 vf13, 32(a2)
|
||||
c->sqc2(vf14, 48, a2); // sqc2 vf14, 48(a2)
|
||||
// jr ra // jr ra
|
||||
// nop // sll r0, r0, 0
|
||||
goto end_of_function; // return
|
||||
|
||||
block_2:
|
||||
c->pextlw(t1, t2, t1); // pextlw t1, t2, t1
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf2, vf2, vf1); // vmulx.xyzw vf2, vf2, vf1
|
||||
c->vmul_bc(DEST::xyzw, BC::y, vf3, vf3, vf1); // vmuly.xyzw vf3, vf3, vf1
|
||||
c->vmul_bc(DEST::xyzw, BC::z, vf4, vf4, vf1); // vmulz.xyzw vf4, vf4, vf1
|
||||
// here, f4 is 1/scale. Sometimes the scale out of the joint compression code is slightly negative
|
||||
// this leads to mfc1 sign extending 1's into the upper 32 bits of t3 (this is weirdly how the ps2
|
||||
// does it).
|
||||
c->mfc1(t3, f4); // mfc1 t3, f4
|
||||
// and this brings those ones into bits 96-128
|
||||
c->pcpyld(t1, t3, t1); // pcpyld t1, t3, t1
|
||||
// so here, vf16.w is usually 0, except for when the scale is negative, then it's 0xffff'ffff
|
||||
// (NaN on x86, -BIG on PS2)
|
||||
c->mov128_vf_gpr(vf16, t1); // qmtc2.i vf16, t1
|
||||
// here, vf2/3/4's w's are all 0. On PS2, this always keeps them as 0.
|
||||
// but on x86, this propagates NaNs: 0 * NaN = NaN.
|
||||
// so:
|
||||
c->vfs[vf16].vf.w() = 0; // PATCH to clear invalid float that will be multiplied by 0 below
|
||||
// (this might seem weird because the multiplication sequence could have 3 instructions removed
|
||||
// because we know that vf2/3/4.w are all 0. But maybe this is just copy-pasted, or it didn't
|
||||
// really matter because it would have stalled in place of that 1 cycle instruction because
|
||||
// multiplication latency is 4).
|
||||
|
||||
c->vmul(DEST::xyzw, vf2, vf2, vf16); // vmul.xyzw vf2, vf2, vf16
|
||||
c->vmul(DEST::xyzw, vf3, vf3, vf16); // vmul.xyzw vf3, vf3, vf16
|
||||
c->vmul(DEST::xyzw, vf4, vf4, vf16); // vmul.xyzw vf4, vf4, vf16
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf2); // vmulax.xyzw acc, vf7, vf2
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf2); // vmadday.xyzw acc, vf8, vf2
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf2); // vmaddaz.xyzw acc, vf9, vf2
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf11, vf10, vf2); // vmaddw.xyzw vf11, vf10, vf2
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf3); // vmulax.xyzw acc, vf7, vf3
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf3); // vmadday.xyzw acc, vf8, vf3
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf3); // vmaddaz.xyzw acc, vf9, vf3
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf12, vf10, vf3); // vmaddw.xyzw vf12, vf10, vf3
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf4); // vmulax.xyzw acc, vf7, vf4
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf4); // vmadday.xyzw acc, vf8, vf4
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf4); // vmaddaz.xyzw acc, vf9, vf4
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf13, vf10, vf4); // vmaddw.xyzw vf13, vf10, vf4
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf7, vf15); // vmulax.xyzw acc, vf7, vf15
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf8, vf15); // vmadday.xyzw acc, vf8, vf15
|
||||
c->vmadda_bc(DEST::xyzw, BC::z, vf9, vf15); // vmaddaz.xyzw acc, vf9, vf15
|
||||
c->vmadd_bc(DEST::xyzw, BC::w, vf14, vf10, vf0); // vmaddw.xyzw vf14, vf10, vf0
|
||||
c->sqc2(vf11, 0, a2); // sqc2 vf11, 0(a2)
|
||||
c->sqc2(vf12, 16, a2); // sqc2 vf12, 16(a2)
|
||||
c->sqc2(vf13, 32, a2); // sqc2 vf13, 32(a2)
|
||||
c->sqc2(vf14, 48, a2); // sqc2 vf14, 48(a2)
|
||||
// jr ra // jr ra
|
||||
// nop // sll r0, r0, 0
|
||||
goto end_of_function; // return
|
||||
|
||||
// jr ra // jr ra
|
||||
c->daddu(sp, sp, r0); // daddu sp, sp, r0
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
gLinkedFunctionTable.reg("cspace<-parented-transformq-joint!", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace cspace_parented_transformq_joint
|
||||
} // namespace Mips2C::jak3
|
||||
// add cspace<_parented_transformq_joint::link to the link callback table for the object file.
|
||||
// FWD DEC:
|
@ -12,7 +12,6 @@ struct Cache {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->daddiu(sp, sp, -48); // daddiu sp, sp, -48
|
||||
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
||||
c->daddiu(t0, sp, 16); // daddiu t0, sp, 16
|
||||
@ -158,7 +157,6 @@ struct Cache {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->daddiu(sp, sp, -48); // daddiu sp, sp, -48
|
||||
c->daddiu(v1, sp, 16); // daddiu v1, sp, 16
|
||||
// nop // sll r0, r0, 0
|
||||
@ -294,7 +292,6 @@ namespace add_light_sphere_to_light_group {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
bool cop1_bc = false;
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
@ -700,7 +697,6 @@ namespace light_hash_get_bucket_index {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->daddiu(sp, sp, -32); // daddiu sp, sp, -32
|
||||
c->daddiu(v1, sp, 16); // daddiu v1, sp, 16
|
||||
// nop // sll r0, r0, 0
|
||||
|
188
game/mips2c/jak3_functions/texture.cpp
Normal file
188
game/mips2c/jak3_functions/texture.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
//--------------------------MIPS2C---------------------
|
||||
// clang-format off
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/jak3/kscheme.h"
|
||||
using ::jak3::intern_from_c;
|
||||
namespace Mips2C::jak3 {
|
||||
namespace adgif_shader_texture_with_update {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
c->ld(a2, 16, a0); // ld a2, 16(a0)
|
||||
c->addiu(v1, r0, 256); // addiu v1, r0, 256
|
||||
c->andi(a2, a2, 513); // andi a2, a2, 513
|
||||
c->mtc1(f0, v1); // mtc1 f0, v1
|
||||
c->cvtsw(f0, f0); // cvt.s.w f0, f0
|
||||
c->lbu(v1, 4, a1); // lbu v1, 4(a1)
|
||||
c->lwc1(f1, 44, a1); // lwc1 f1, 44(a1)
|
||||
c->daddiu(v1, v1, -1); // daddiu v1, v1, -1
|
||||
c->divs(f0, f0, f1); // div.s f0, f0, f1
|
||||
c->dsll(v1, v1, 2); // dsll v1, v1, 2
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->lbu(v1, 7, a1); // lbu v1, 7(a1)
|
||||
c->dsll(v1, v1, 19); // dsll v1, v1, 19
|
||||
c->lbu(a3, 5, a1); // lbu a3, 5(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll(a3, a3, 5); // dsll a3, a3, 5
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->ld(t1, 0, a0); // ld t1, 0(a0)
|
||||
c->dsll(t1, t1, 27); // dsll t1, t1, 27
|
||||
c->lbu(v1, 6, a1); // lbu v1, 6(a1)
|
||||
c->dsra32(t1, t1, 30); // dsra32 t1, t1, 30
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->dsll32(t1, t1, 3); // dsll32 t1, t1, 3
|
||||
c->lhu(a3, 10, a1); // lhu a3, 10(a1)
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lbu(v1, 26, a1); // lbu v1, 26(a1)
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->dsll(v1, v1, 14); // dsll v1, v1, 14
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lhu(v1, 0, a1); // lhu v1, 0(a1)
|
||||
c->plzcw(v1, v1); // plzcw v1, v1
|
||||
c->addiu(t0, r0, 30); // addiu t0, r0, 30
|
||||
c->subu(v1, t0, v1); // subu v1, t0, v1
|
||||
c->lhu(a3, 2, a1); // lhu a3, 2(a1)
|
||||
c->dsll(v1, v1, 26); // dsll v1, v1, 26
|
||||
c->plzcw(a3, a3); // plzcw a3, a3
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->subu(a3, t0, a3); // subu a3, t0, a3
|
||||
c->dsll(a3, a3, 30); // dsll a3, a3, 30
|
||||
c->addiu(v1, r0, 1); // addiu v1, r0, 1
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->dsll32(v1, v1, 2); // dsll32 v1, v1, 2
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->lhu(v1, 24, a1); // lhu v1, 24(a1)
|
||||
c->dsll32(v1, v1, 5); // dsll32 v1, v1, 5
|
||||
c->lhu(a3, 8, a1); // lhu a3, 8(a1)
|
||||
c->dsll32(a3, a3, 19); // dsll32 a3, a3, 19
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->or_(t1, t1, a3); // or t1, t1, a3
|
||||
c->addiu(v1, r0, 1); // addiu v1, r0, 1
|
||||
c->dsll32(v1, v1, 29); // dsll32 v1, v1, 29
|
||||
c->cvtws(f0, f0); // cvt.w.s f0, f0
|
||||
c->or_(t1, t1, v1); // or t1, t1, v1
|
||||
c->mfc1(v1, f0); // mfc1 v1, f0
|
||||
c->sd(t1, 0, a0); // sd t1, 0(a0)
|
||||
c->plzcw(a3, v1); // plzcw a3, v1
|
||||
c->subu(a3, t0, a3); // subu a3, t0, a3
|
||||
c->lbu(t0, 7, a1); // lbu t0, 7(a1)
|
||||
c->daddiu(t0, t0, -1); // daddiu t0, t0, -1
|
||||
// nop // sll r0, r0, 0
|
||||
bc = c->sgpr64(t0) == 0; // beq t0, r0, L43
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
c->daddiu(t0, a3, -4); // daddiu t0, a3, -4
|
||||
c->dsll(a3, a3, 4); // dsll a3, a3, 4
|
||||
bc = ((s64)c->sgpr64(t0)) < 0; // bltz t0, L41
|
||||
c->daddiu(a3, a3, -175); // daddiu a3, a3, -175
|
||||
if (bc) {goto block_3;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L42 // beq r0, r0, L42
|
||||
c->dsrav(t0, v1, t0); // dsrav t0, v1, t0
|
||||
goto block_4; // branch always
|
||||
|
||||
|
||||
block_3:
|
||||
c->dsubu(t0, r0, t0); // dsubu t0, r0, t0
|
||||
c->dsllv(t0, v1, t0); // dsllv t0, v1, t0
|
||||
|
||||
block_4:
|
||||
c->andi(t0, t0, 15); // andi t0, t0, 15
|
||||
// nop // sll r0, r0, 0
|
||||
//beq r0, r0, L46 // beq r0, r0, L46
|
||||
c->daddu(a3, a3, t0); // daddu a3, a3, t0
|
||||
goto block_9; // branch always
|
||||
|
||||
|
||||
block_5:
|
||||
c->daddiu(t0, a3, -5); // daddiu t0, a3, -5
|
||||
c->dsll(a3, a3, 5); // dsll a3, a3, 5
|
||||
bc = ((s64)c->sgpr64(t0)) < 0; // bltz t0, L44
|
||||
c->daddiu(a3, a3, -350); // daddiu a3, a3, -350
|
||||
if (bc) {goto block_7;} // branch non-likely
|
||||
|
||||
//beq r0, r0, L45 // beq r0, r0, L45
|
||||
c->dsrav(t0, v1, t0); // dsrav t0, v1, t0
|
||||
goto block_8; // branch always
|
||||
|
||||
|
||||
block_7:
|
||||
c->dsubu(t0, r0, t0); // dsubu t0, r0, t0
|
||||
c->dsllv(t0, v1, t0); // dsllv t0, v1, t0
|
||||
|
||||
block_8:
|
||||
c->andi(t0, t0, 31); // andi t0, t0, 31
|
||||
// nop // sll r0, r0, 0
|
||||
c->daddu(a3, a3, t0); // daddu a3, a3, t0
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_9:
|
||||
c->andi(a3, a3, 4095); // andi a3, a3, 4095
|
||||
c->lhu(t1, 12, a1); // lhu t1, 12(a1)
|
||||
c->dsll32(a3, a3, 0); // dsll32 a3, a3, 0
|
||||
c->lbu(v1, 27, a1); // lbu v1, 27(a1)
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->dsll(v1, v1, 14); // dsll v1, v1, 14
|
||||
c->sd(a2, 16, a0); // sd a2, 16(a0)
|
||||
c->or_(a2, t1, v1); // or a2, t1, v1
|
||||
c->lhu(v1, 14, a1); // lhu v1, 14(a1)
|
||||
// nop // sll r0, r0, 0
|
||||
c->lbu(a3, 28, a1); // lbu a3, 28(a1)
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 2); // dsll32 a3, a3, 2
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 16, a1); // lhu v1, 16(a1)
|
||||
c->lbu(a3, 29, a1); // lbu a3, 29(a1)
|
||||
c->dsll32(v1, v1, 8); // dsll32 v1, v1, 8
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 22); // dsll32 a3, a3, 22
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lbu(t0, 4, a1); // lbu t0, 4(a1)
|
||||
c->daddiu(t0, t0, -5); // daddiu t0, t0, -5
|
||||
c->sd(a2, 32, a0); // sd a2, 32(a0)
|
||||
bc = ((s64)c->sgpr64(t0)) < 0; // bltz t0, L47
|
||||
c->lbu(a3, 30, a1); // lbu a3, 30(a1)
|
||||
if (bc) {goto block_11;} // branch non-likely
|
||||
|
||||
c->lhu(a2, 18, a1); // lhu a2, 18(a1)
|
||||
c->dsll(a3, a3, 14); // dsll a3, a3, 14
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 20, a1); // lhu v1, 20(a1)
|
||||
c->dsll(v1, v1, 20); // dsll v1, v1, 20
|
||||
c->lbu(a3, 31, a1); // lbu a3, 31(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 2); // dsll32 a3, a3, 2
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->lhu(v1, 22, a1); // lhu v1, 22(a1)
|
||||
c->dsll32(v1, v1, 8); // dsll32 v1, v1, 8
|
||||
c->lbu(a3, 32, a1); // lbu a3, 32(a1)
|
||||
c->or_(a2, a2, v1); // or a2, a2, v1
|
||||
c->dsll32(a3, a3, 22); // dsll32 a3, a3, 22
|
||||
c->or_(a2, a2, a3); // or a2, a2, a3
|
||||
c->addiu(v1, r0, 54); // addiu v1, r0, 54
|
||||
c->sd(a2, 64, a0); // sd a2, 64(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
c->sw(v1, 72, a0); // sw v1, 72(a0)
|
||||
// nop // sll r0, r0, 0
|
||||
|
||||
block_11:
|
||||
c->mov64(v0, a0); // or v0, a0, r0
|
||||
//jr ra // jr ra
|
||||
c->daddu(sp, sp, r0); // daddu sp, sp, r0
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
gLinkedFunctionTable.reg("adgif-shader<-texture-with-update!", execute, 128);
|
||||
}
|
||||
|
||||
} // namespace adgif_shader<_texture_with_update
|
||||
} // namespace Mips2C
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "game/kernel/common/kscheme.h"
|
||||
#include "game/kernel/jak1/kscheme.h"
|
||||
#include "game/kernel/jak2/kscheme.h"
|
||||
#include "game/kernel/jak3/kscheme.h"
|
||||
#include "game/runtime.h"
|
||||
|
||||
extern "C" {
|
||||
@ -281,6 +282,14 @@ namespace method_9_font_work { extern void link(); }
|
||||
namespace draw_string_asm { extern void link(); }
|
||||
namespace get_string_length { extern void link(); }
|
||||
namespace method_9_prim_strip { extern void link(); }
|
||||
namespace adgif_shader_texture_with_update { extern void link(); }
|
||||
namespace moving_sphere_triangle_intersect { extern void link(); }
|
||||
namespace collide_do_primitives { extern void link(); }
|
||||
namespace cspace_parented_transformq_joint { extern void link(); }
|
||||
namespace foreground_check_longest_edge_asm { extern void link(); }
|
||||
namespace foreground_merc { extern void link(); }
|
||||
namespace foreground_generic_merc { extern void link(); }
|
||||
|
||||
|
||||
}
|
||||
// clang-format on
|
||||
@ -466,7 +475,14 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
|
||||
jak3::generic_no_light_proc::link}},
|
||||
{"font",
|
||||
{jak3::method_9_font_work::link, jak3::draw_string_asm::link, jak3::get_string_length::link}},
|
||||
{"prim", {jak3::method_9_prim_strip::link}}}};
|
||||
{"texture", {jak3::adgif_shader_texture_with_update::link}},
|
||||
{"collide-func",
|
||||
{jak3::moving_sphere_triangle_intersect::link, jak3::collide_do_primitives::link}},
|
||||
{"prim", {jak3::method_9_prim_strip::link}},
|
||||
{"joint", {jak3::cspace_parented_transformq_joint::link}},
|
||||
{"foreground",
|
||||
{jak3::foreground_check_longest_edge_asm::link, jak3::foreground_generic_merc::link,
|
||||
jak3::foreground_merc::link}}}};
|
||||
|
||||
void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 stack_size) {
|
||||
const auto& it = m_executes.insert({name, {exec, Ptr<u8>()}});
|
||||
@ -488,6 +504,11 @@ void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 s
|
||||
s7.offset + jak2_symbols::FIX_SYM_GLOBAL_HEAP,
|
||||
::jak2::u32_in_fixed_sym(jak2_symbols::FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP));
|
||||
break;
|
||||
case GameVersion::Jak3:
|
||||
jump_to_asm = Ptr<u8>(::jak3::alloc_heap_object(
|
||||
s7.offset + jak3_symbols::FIX_SYM_GLOBAL_HEAP,
|
||||
::jak3::u32_in_fixed_sym(jak3_symbols::FIX_SYM_FUNCTION_TYPE), 0x40, UNKNOWN_PP));
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
|
@ -2223,7 +2223,7 @@
|
||||
;; make-joint-jump-tables: not needed
|
||||
;; calc-animation-from-spr: not needed
|
||||
|
||||
(def-mips2c calc-animation-from-spr (function joint-anim-frame int none))
|
||||
;; (def-mips2c calc-animation-from-spr (function joint-anim-frame int none))
|
||||
|
||||
(defun create-interpolated-joint-animation-frame ((dst joint-anim-frame) (num-joints int) (jc joint-control))
|
||||
"Compute the entire joint frame by evaluating the blend tree, decompressing animations, and blending them."
|
||||
|
@ -45,4 +45,6 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
(cam-start #f)
|
||||
(format 0 "Skipping cam-start!!~%")
|
||||
(format #t "Skipping cam-start!!~%")
|
||||
;; (cam-start #f)
|
||||
|
@ -13,6 +13,13 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; TODO: remove this - just a stub.
|
||||
(defun find-free-eye-index ((a int) (b string) (c int))
|
||||
0)
|
||||
(defun get-eye-block ((a int) (c int))
|
||||
0)
|
||||
|
||||
|
||||
(deftype eye (structure)
|
||||
"Data for a single eye."
|
||||
((data vector 2 :inline)
|
||||
|
@ -8,3 +8,8 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; TODO: remove these stubs
|
||||
(defun clear-mood-context ((arg0 mood-context))
|
||||
(format 0 "no clear-mood-context~%")
|
||||
#f
|
||||
)
|
@ -35,3 +35,9 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; TODO: stub
|
||||
(kmemopen global "part-tables")
|
||||
(define *part-id-table* (new 'global 'boxed-array sparticle-launcher 5500))
|
||||
(define *part-group-id-table* (new 'global 'boxed-array sparticle-launch-group 1700))
|
||||
(define *sp-temp* 0.0)
|
||||
(kmemclose)
|
@ -1520,6 +1520,8 @@
|
||||
|
||||
(defmethod upload-now! ((this texture-page) (mode tex-upload-mode))
|
||||
"Upload a texture to VRAM immediately, wait for DMA to finish."
|
||||
|
||||
(format 0 "TODO: upload-now!~%")
|
||||
(let ((gp-0 *txt-dma-list*))
|
||||
(let ((v1-0 gp-0))
|
||||
(set! (-> v1-0 base) (-> v1-0 data))
|
||||
@ -1534,7 +1536,10 @@
|
||||
(set! (-> (the-as (pointer uint64) a0-7) 1) (the-as uint 0))
|
||||
(set! (-> v1-6 base) (&+ a0-7 16))
|
||||
)
|
||||
(dma-buffer-send-chain (the-as dma-bank-source #x1000a000) gp-0)
|
||||
;; the actual send
|
||||
(#unless PC_PORT
|
||||
(dma-buffer-send-chain (the-as dma-bank-source #x1000a000) gp-0)
|
||||
)
|
||||
)
|
||||
(dma-sync (the-as pointer #x1000a000) 0 0)
|
||||
(none)
|
||||
|
@ -20,7 +20,7 @@
|
||||
(define *kernel-boot-message* 'play)
|
||||
(start-debug "loading GAME.DGO~%")
|
||||
(load-package "game" global)
|
||||
(play-boot)
|
||||
;; (play-boot)
|
||||
)
|
||||
)
|
||||
|
||||
@ -3744,6 +3744,8 @@
|
||||
(none)
|
||||
)
|
||||
|
||||
(format 0 "about to start level stuff...~%")
|
||||
|
||||
(when (zero? (-> *level* level0 art-group))
|
||||
(kmemopen global "level-struct")
|
||||
(let ((gp-0 *level*))
|
||||
@ -3789,3 +3791,5 @@
|
||||
)
|
||||
(kmemclose)
|
||||
)
|
||||
|
||||
(format 0 "done level stuff...~%")
|
||||
|
@ -23,7 +23,7 @@
|
||||
some, but not all, functions assume that a matrix is an affine transform.
|
||||
others assume that the rotation has no scale or shear (and that its inverse is its transpose)."
|
||||
((data float 16)
|
||||
(vector vector 4 :overlay-at (-> data 0))
|
||||
(vector vector 4 :inline :overlay-at (-> data 0))
|
||||
(quad uint128 4 :overlay-at (-> data 0))
|
||||
(rvec vector :inline :overlay-at (-> data 0))
|
||||
(uvec vector :inline :overlay-at (-> data 4))
|
||||
|
@ -793,8 +793,6 @@ void Debugger::read_symbol_table_jak3() {
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("got %s\n", str.c_str());
|
||||
|
||||
// update maps
|
||||
if (m_symbol_name_to_offset_map.find(str) != m_symbol_name_to_offset_map.end()) {
|
||||
if (str == "asize-of-basic-func") {
|
||||
|
16
test/decompiler/reference/jak3/engine/math/matrix-h_REF.gc
generated
vendored
16
test/decompiler/reference/jak3/engine/math/matrix-h_REF.gc
generated
vendored
@ -7,12 +7,12 @@
|
||||
some, but not all, functions assume that a matrix is an affine transform.
|
||||
others assume that the rotation has no scale or shear (and that its inverse is its transpose)."
|
||||
((data float 16)
|
||||
(vector vector 4 :overlay-at (-> data 0))
|
||||
(quad uint128 4 :overlay-at (-> data 0))
|
||||
(rvec vector :inline :overlay-at (-> data 0))
|
||||
(uvec vector :inline :overlay-at (-> data 4))
|
||||
(fvec vector :inline :overlay-at (-> data 8))
|
||||
(trans vector :inline :overlay-at (-> data 12))
|
||||
(vector vector 4 :inline :overlay-at (-> data 0))
|
||||
(quad uint128 4 :overlay-at (-> data 0))
|
||||
(rvec vector :inline :overlay-at (-> data 0))
|
||||
(uvec vector :inline :overlay-at (-> data 4))
|
||||
(fvec vector :inline :overlay-at (-> data 8))
|
||||
(trans vector :inline :overlay-at (-> data 12))
|
||||
)
|
||||
(:methods
|
||||
(transform-vectors! (_type_ (inline-array vector) (inline-array vector) int) none)
|
||||
@ -145,7 +145,3 @@ and how they were originally packed (for example, in tie/shrub)."
|
||||
|
||||
;; failed to figure out what this is:
|
||||
0
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user